Compare commits
88 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b7b5fc3835 | |||
| 4bb05d23eb | |||
| 4998ad615e | |||
| 05f11943a5 | |||
| b7a1258ce0 | |||
| 867a215180 | |||
| 822b06be3d | |||
| 2b72657ec0 | |||
| d76d052456 | |||
| e778e7aa95 | |||
| 451d9077ea | |||
| 8cee8e1df7 | |||
| 400db191ce | |||
| d25439183b | |||
| a9d93bb206 | |||
| 286424bfde | |||
| e75cdee67b | |||
| 28de0099b5 | |||
| 084e6b0be1 | |||
| df84903745 | |||
| d30ba7a34d | |||
| be5f4eb86d | |||
| 4678472326 | |||
| 80f25e569a | |||
| 584c5c8714 | |||
| f3361bfb4e | |||
| dc6b670db5 | |||
| 212716afbd | |||
| e952f2f906 | |||
| 664d3ff2a1 | |||
| 59da6c6b96 | |||
| 5bd0c54a0a | |||
| 2f5e737fa1 | |||
| cfdac70756 | |||
| c4ffe13477 | |||
| 987f276ef1 | |||
| 6fa01de5f9 | |||
| 90a2f64ba4 | |||
| 25bbfd5ac2 | |||
| ac0e6b566e | |||
| a362d9938a | |||
| 9ce36cf42d | |||
| b1e78bc4cc | |||
| 9502ef56b4 | |||
| fc3a66d8da | |||
| 8b7c6896d5 | |||
| b73f6cd823 | |||
| 3b56fc906b | |||
| 7a2e369709 | |||
| 6fc320177d | |||
| 4155267c45 | |||
| 15b5e9916b | |||
| 21f59235e1 | |||
| a3a5edcdb0 | |||
| 4856f06869 | |||
| 639f4082c8 | |||
| 2fc2629637 | |||
| db35297c53 | |||
| cbce387a8c | |||
| 9406105014 | |||
| be2022527b | |||
| c37c8f9026 | |||
| 8327545821 | |||
| fc1e1531b8 | |||
| 2496e60aea | |||
| 9b4cf761c6 | |||
| 830e26774d | |||
| 2bccffb8c5 | |||
| 06b285a8ba | |||
| 8e9c3906f2 | |||
| 6482cf65b9 | |||
| e17574e706 | |||
| 9833b0d13c | |||
| 5d1e9a188f | |||
| 8895adf24c | |||
| 67ff700dfc | |||
| ac039b311d | |||
| 6d6da7545c | |||
| 3410828736 | |||
| 21039dd60e | |||
| 94cd4b9b83 | |||
| 3a1449c5e0 | |||
| 2b34d0bb0c | |||
| c1396ef127 | |||
| 8cc45d39c3 | |||
| 212b6b8747 | |||
| c5acee173c | |||
| 41020d78d8 |
@@ -0,0 +1,172 @@
|
||||
---
|
||||
name: harness
|
||||
description: Use when planning agentic implementation phases, creating phases/index.json and self-contained step files, or running the Harness step executor.
|
||||
---
|
||||
|
||||
# Harness Workflow
|
||||
|
||||
이 프로젝트는 Harness 프레임워크를 사용한다. 아래 워크플로에 따라 작업한다.
|
||||
|
||||
## A. 탐색
|
||||
|
||||
`AGENTS.md`와 `docs/` 하위 문서(PRD, ARCHITECTURE, ADR 등)를 읽고 프로젝트의 기획,
|
||||
아키텍처, 설계 의도를 파악한다. 병렬 탐색이 실제로 유용하고 현재 세션에서 허용될
|
||||
때만 Codex subagent를 선택적으로 사용한다.
|
||||
|
||||
## B. 논의
|
||||
|
||||
구현을 위해 구체화하거나 기술적으로 결정해야 할 사항이 있으면 사용자에게 한 번에
|
||||
하나씩 제시하고 논의한다.
|
||||
|
||||
## C. Step 설계
|
||||
|
||||
사용자가 구현 계획 작성을 지시하면 여러 step으로 나뉜 초안을 작성해 피드백을
|
||||
요청한다.
|
||||
|
||||
설계 원칙:
|
||||
|
||||
1. **Scope 최소화** — 하나의 step에서 하나의 레이어 또는 모듈만 다룬다. 여러
|
||||
모듈을 동시에 수정해야 하면 step을 쪼갠다.
|
||||
2. **자기완결성** — 각 step 파일은 독립된 Codex 실행에서 사용된다. 외부 대화
|
||||
참조를 금지하고 필요한 정보를 모두 파일 안에 적는다.
|
||||
3. **사전 준비 강제** — 관련 문서와 이전 step에서 생성하거나 수정한 파일 경로를
|
||||
명시한다.
|
||||
4. **시그니처 수준 지시** — 함수와 클래스의 인터페이스를 제시하고 내부 구현은
|
||||
Codex 재량에 맡긴다. 멱등성, 보안, 데이터 무결성 같은 핵심 규칙은 명시한다.
|
||||
5. **AC는 실행 가능한 command** — 추상적 조건 대신 실제 빌드와 테스트 command를
|
||||
포함한다.
|
||||
6. **주의사항은 구체적으로** — "X를 하지 마라. 이유: Y" 형식으로 적는다.
|
||||
7. **네이밍** — step name은 핵심 작업을 표현하는 kebab-case slug로 정한다.
|
||||
|
||||
## D. 파일 생성
|
||||
|
||||
사용자가 초안을 승인한 후에만 다음 파일을 생성한다.
|
||||
|
||||
### D-1. `phases/index.json`
|
||||
|
||||
여러 task를 관리하는 top-level 인덱스다. 이미 존재하면 `phases` 배열에 새 항목을
|
||||
추가한다.
|
||||
|
||||
```json
|
||||
{
|
||||
"phases": [
|
||||
{
|
||||
"dir": "0-mvp",
|
||||
"status": "pending"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
- `dir`: task 디렉터리명
|
||||
- `status`: `pending` | `completed` | `error` | `blocked`
|
||||
- timestamp는 executor가 상태를 바꿀 때 기록하므로 생성 시 넣지 않는다.
|
||||
|
||||
### D-2. `phases/{task-name}/index.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"project": "<프로젝트명>",
|
||||
"phase": "<task-name>",
|
||||
"steps": [
|
||||
{ "step": 0, "name": "project-setup", "status": "pending" },
|
||||
{ "step": 1, "name": "core-types", "status": "pending" },
|
||||
{ "step": 2, "name": "api-layer", "status": "pending" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
필드 규칙:
|
||||
|
||||
- `project`: `AGENTS.md`에 정의된 프로젝트명
|
||||
- `phase`: task 이름이며 디렉터리명과 일치
|
||||
- `steps[].step`: 0부터 시작하는 순번
|
||||
- `steps[].name`: kebab-case slug
|
||||
- `steps[].status`: 초기값 `pending`
|
||||
|
||||
상태와 기록 주체:
|
||||
|
||||
| 전이 | 기록 필드 | 기록 주체 |
|
||||
|------|-----------|-----------|
|
||||
| `completed` | `summary`, `completed_at` | Codex가 summary, executor가 timestamp |
|
||||
| `error` | `error_message`, `failed_at` | Codex가 message, executor가 timestamp |
|
||||
| `blocked` | `blocked_reason`, `blocked_at` | Codex가 reason, executor가 timestamp |
|
||||
|
||||
`summary`에는 다음 step에 유용한 생성 파일과 핵심 결정을 한 줄로 적는다.
|
||||
task `created_at`과 step `started_at`은 executor가 기록하므로 생성 시 넣지 않는다.
|
||||
|
||||
### D-3. `phases/{task-name}/step{N}.md`
|
||||
|
||||
````markdown
|
||||
# Step {N}: {이름}
|
||||
|
||||
## 읽어야 할 파일
|
||||
|
||||
먼저 아래 파일을 읽고 프로젝트의 아키텍처와 설계 의도를 파악하라:
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/ARCHITECTURE.md`
|
||||
- `/docs/ADR.md`
|
||||
- 이전 step에서 생성하거나 수정한 파일 경로
|
||||
|
||||
이전 step의 코드를 꼼꼼히 읽고 설계 의도를 이해한 뒤 작업하라.
|
||||
|
||||
## 작업
|
||||
|
||||
구체적인 구현 지시를 파일 경로, 클래스와 함수 시그니처, 로직 설명과 함께 적는다.
|
||||
구현체는 Codex에 맡기되 설계 의도에서 벗어나면 안 되는 핵심 규칙은 명시한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
프로젝트 형식에 맞는 명령을 사용한다. `.harness/config.json`이 있으면 해당 preset,
|
||||
solution, configuration, platform, test command를 우선한다.
|
||||
|
||||
```powershell
|
||||
# CMake
|
||||
cmake --build .harness/build --config Debug
|
||||
ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
|
||||
# 직접 MSBuild
|
||||
MSBuild.exe MyProject.sln /m /p:Configuration=Debug /p:Platform=x64
|
||||
.\build\tests\Debug\MyProjectTests.exe
|
||||
```
|
||||
|
||||
## 검증 절차
|
||||
|
||||
1. Acceptance Criteria command를 실행한다.
|
||||
2. ARCHITECTURE 디렉터리 구조를 따르는지 확인한다.
|
||||
3. ADR 기술 스택과 `AGENTS.md` CRITICAL 규칙을 확인한다.
|
||||
4. 결과에 따라 task index의 해당 step을 갱신한다.
|
||||
- 성공: `status`를 `completed`로 바꾸고 한 줄 `summary` 기록
|
||||
- 수정 3회 후 실패: `status`를 `error`로 바꾸고 `error_message` 기록
|
||||
- 사용자 개입 필요: `status`를 `blocked`로 바꾸고 `blocked_reason` 기록 후 중단
|
||||
|
||||
## 금지사항
|
||||
|
||||
- 이 step의 범위 밖 기능을 추가하지 마라. 이유: step의 독립성을 깨뜨린다.
|
||||
- 기존 테스트를 깨뜨리지 마라. 이유: 이전 동작을 회귀시킨다.
|
||||
````
|
||||
|
||||
## E. 실행
|
||||
|
||||
```bash
|
||||
python scripts/execute.py {task-name}
|
||||
python scripts/execute.py {task-name} --push
|
||||
```
|
||||
|
||||
환경에서 Python 3 실행 명령이 `python3`이면 그 명령을 대신 사용한다.
|
||||
|
||||
executor가 처리하는 작업:
|
||||
|
||||
- `feat-{task-name}` 브랜치 생성 또는 checkout
|
||||
- `AGENTS.md`와 `docs/*.md` guardrail 주입
|
||||
- 완료 step의 summary를 다음 prompt에 누적
|
||||
- 실패 시 최대 3회 재시도하며 이전 오류를 prompt에 전달
|
||||
- 코드 변경과 metadata를 분리해 commit
|
||||
- `started_at`, `completed_at`, `failed_at`, `blocked_at` 기록
|
||||
|
||||
에러 복구:
|
||||
|
||||
- `error`: 해당 status를 `pending`으로 바꾸고 `error_message`를 삭제한 뒤 재실행
|
||||
- `blocked`: 원인을 해결하고 status를 `pending`으로 바꾸고 `blocked_reason`을 삭제한
|
||||
뒤 재실행
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
name: review
|
||||
description: Use when reviewing repository changes against AGENTS.md, architecture decisions, tests, and build requirements.
|
||||
---
|
||||
|
||||
# Repository Review
|
||||
|
||||
먼저 다음 문서를 읽는다.
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/ARCHITECTURE.md`
|
||||
- `/docs/ADR.md`
|
||||
|
||||
사용자가 범위를 지정하지 않으면 현재 작업 트리의 변경을 리뷰한다. 관련 diff를
|
||||
확인하고 가능한 빌드와 테스트 command를 실제로 실행한다.
|
||||
|
||||
## 체크리스트
|
||||
|
||||
1. MSVC toolset와 C++ 표준이 AGENTS.md/ADR과 일치하는가?
|
||||
2. CMake 또는 MSBuild Debug/x64 빌드가 통과하는가?
|
||||
3. CTest 또는 `.harness/config.json`의 명시적 test command가 통과하는가?
|
||||
4. 새 C/C++ 소스와 헤더에 대응 테스트가 있는가?
|
||||
5. CRITICAL 아키텍처 규칙과 public header 경계를 지키는가?
|
||||
|
||||
## 출력 형식
|
||||
|
||||
실제 결함을 심각도순으로 먼저 제시한다. 각 finding에 파일과 줄 번호, 영향,
|
||||
재현 또는 근거, 구체적인 수정 방안을 포함한다.
|
||||
|
||||
그 뒤 다음 표를 제공한다.
|
||||
|
||||
| 항목 | 결과 | 비고 |
|
||||
|------|------|------|
|
||||
| 아키텍처 준수 | ✅/❌/미검증 | 상세 |
|
||||
| 기술 스택 준수 | ✅/❌/미검증 | 상세 |
|
||||
| 테스트 존재 | ✅/❌/미검증 | 상세 |
|
||||
| CRITICAL 규칙 | ✅/❌/미검증 | 상세 |
|
||||
| 빌드 가능 | ✅/❌/미검증 | 상세 |
|
||||
|
||||
실행할 수 없는 검사는 성공으로 추정하지 말고 `미검증`과 이유를 적는다. finding이
|
||||
없으면 발견된 문제가 없다고 명시하고 남아 있는 검증 공백을 설명한다.
|
||||
@@ -10,7 +10,7 @@ Mission:
|
||||
- Run build and test validation only after Implementation Agent work.
|
||||
- Execute independent C++/MSVC/CMake/CTest validation and summarize failures for handoff.
|
||||
- Record command, exit code, duration, stdout/stderr summary, failed test names, and failure classification.
|
||||
- Keep the output aligned with AGENTS.md, docs/SOLVER_AGENT_DESIGN.md, scripts/validate_workspace.py, and the implementation plan/report.
|
||||
- Keep the output aligned with AGENTS.md, docs/HARNESS_WORKFLOW.md, docs/SOLVER_AGENT_DESIGN.md, `.harness/config.json` when present, and the implementation plan/report.
|
||||
|
||||
Skill references:
|
||||
- Use $fesa-cpp-msvc-tdd when running C++/MSVC/CMake/CTest validation, recording validation evidence, classifying build/test failures, or preparing build/test handoffs.
|
||||
@@ -32,23 +32,26 @@ Input priorities:
|
||||
2. Implementation Agent report.
|
||||
3. docs/implementation-plans/<feature-id>-implementation-plan.md.
|
||||
4. AGENTS.md and docs/SOLVER_AGENT_DESIGN.md.
|
||||
5. scripts/validate_workspace.py.
|
||||
6. CMakePresets.json, CMakeLists.txt, CMake files, and CTest metadata when present.
|
||||
5. `.harness/config.json` when present.
|
||||
6. CMakePresets.json, CMakeLists.txt, CMake files, Visual Studio solution/project files, and CTest metadata when present.
|
||||
7. Related docs/reference-models/<feature-id>-reference-models.md when present.
|
||||
8. Stored reference artifacts when present, read-only.
|
||||
|
||||
Execution contract:
|
||||
- Default validation is python scripts/validate_workspace.py.
|
||||
- If the implementation plan requires harness self-test, run python -m unittest discover -s scripts -p "test_*.py" first.
|
||||
- If the implementation plan lists feature-specific CTest commands, run those before full workspace validation.
|
||||
- Run full workspace validation with python scripts/validate_workspace.py last.
|
||||
- scripts/validate_workspace.py resolves HARNESS_VALIDATION_COMMANDS, CMakePresets.json msvc-debug, or CMake/MSVC x64 Debug commands.
|
||||
- The default CMake/MSVC x64 Debug commands are:
|
||||
1. cmake -S . -B build/msvc-debug -G "Visual Studio 17 2022" -A x64
|
||||
2. cmake --build build/msvc-debug --config Debug
|
||||
3. ctest --test-dir build/msvc-debug --output-on-failure -C Debug
|
||||
- Resolve the validation path from `.harness/config.json` first, then Harness project auto detection.
|
||||
- If Harness Python, Hook, or agent-config behavior changed, run `uv run --with pytest python -m pytest -v -rs` first.
|
||||
- Configure and build before running feature-specific and full tests.
|
||||
- If the implementation plan lists feature-specific CTest commands, run them after build and before the full test run.
|
||||
- For a non-preset CMake project, run:
|
||||
1. cmake -S . -B .harness/build -A x64
|
||||
2. cmake --build .harness/build --config Debug
|
||||
3. ctest --test-dir .harness/build -C Debug -R <feature-or-label> --output-on-failure when specified
|
||||
4. ctest --test-dir .harness/build -C Debug --show-only=json-v1
|
||||
5. ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
- If `.harness/config.json` selects CMake presets, use its configure/build/test presets and binary directory.
|
||||
- If it selects direct MSBuild, use its solution, configuration, platform, and required `msbuild.testCommand`.
|
||||
- Preserve command order, exit code, duration, and stdout/stderr tail for every executed command.
|
||||
- For no-CMake workspaces, record the scripts/validate_workspace.py informational success path instead of treating it as a failure.
|
||||
- Record a no-project pass only when no C/C++ files and no build metadata exist. C/C++ files without build metadata are an error.
|
||||
- Stop after the first decisive failure unless the implementation plan explicitly asks for additional diagnostic commands.
|
||||
|
||||
Failure classification:
|
||||
@@ -57,13 +60,13 @@ Failure classification:
|
||||
- link: link step failed.
|
||||
- test: CTest or unit/integration tests failed.
|
||||
- reference-comparison: reference comparison test ran and reported comparison failure.
|
||||
- harness: Python harness self-test or validation script failed.
|
||||
- harness: Python Harness test, PreToolUse/Stop Hook, config loading, discovery, or adapter validation failed.
|
||||
- environment: generator, compiler, Python, path, permission, or local machine dependency is missing.
|
||||
- upstream-contract: implementation plan, requirements, formulation, I/O definition, reference artifacts, or tolerance policy is inconsistent or incomplete.
|
||||
|
||||
Required Build/Test Report sections:
|
||||
1. Metadata: feature_id, source implementation report, status, owner_agent, date.
|
||||
2. Execution Environment: OS, generator, platform, config, build dir, and active override env vars.
|
||||
2. Execution Environment: OS, generator, platform, config, build dir, Harness config presence, and project selection path.
|
||||
3. Command Log Summary: command, exit code, duration, stdout/stderr tail.
|
||||
4. Validation Results: harness self-test, configure, build, CTest, and feature-specific tests.
|
||||
5. Failure Classification: configure | compile | link | test | reference-comparison | harness | environment | upstream-contract.
|
||||
|
||||
@@ -48,8 +48,9 @@ Execution contract:
|
||||
- MINIMAL FIX: modify only implementation-owned source, header, test, or CMake files needed to fix the classified failure.
|
||||
- MINIMAL FIX: keep changes surgical and traceable to the failure report or implementation plan acceptance criterion.
|
||||
- VERIFY: rerun the targeted command that reproduced the failure first.
|
||||
- VERIFY: run python scripts/validate_workspace.py after the targeted command.
|
||||
- VERIFY: run python -m unittest discover -s scripts -p "test_*.py" when harness, hook, or agent config behavior is involved.
|
||||
- VERIFY: run the full MSVC build/test commands resolved from `.harness/config.json` or Harness auto detection after the targeted command.
|
||||
- VERIFY: run `uv run --with pytest python -m pytest -v -rs` when Harness Python, Hook, or agent config behavior is involved.
|
||||
- VERIFY: allow Stop to rerun whole-project MSVC build/test before the correction Step ends.
|
||||
- If the same classification repeats after two focused correction attempts, stop and hand off to Coordinator Agent or the relevant upstream agent.
|
||||
- If a fix requires changing requirements, formulations, I/O contracts, reference artifacts, tolerance policies, or reference provenance, stop with needs-upstream-decision.
|
||||
- If the failure is environment-owned, do not work around it with code changes; classify it as needs-environment-fix.
|
||||
@@ -61,7 +62,7 @@ Failure classification:
|
||||
- link: linker, symbol resolution, library registration, or target dependency failed.
|
||||
- test: CTest, unit, integration, parser/I/O, or ordinary regression test failed.
|
||||
- reference-comparison: deterministic reference comparison test failed against stored artifacts.
|
||||
- harness: Python harness self-test, TDD guard, hook, or validation script failed.
|
||||
- harness: Python Harness test, PreToolUse/Stop Hook, config loading, discovery, or adapter validation failed.
|
||||
- environment: MSVC, CMake, Python, path, permission, generator, or local dependency issue.
|
||||
- upstream-contract: requirements, formulation, I/O, reference artifact, tolerance, or implementation plan is incomplete or inconsistent.
|
||||
|
||||
@@ -70,7 +71,7 @@ Required Correction Report sections:
|
||||
2. Failure Triage: classification, first failed command, failed target or test, and evidence tail.
|
||||
3. Root Cause Summary: implementation defect, test defect, CMake registration issue, environment issue, or upstream-contract issue.
|
||||
4. Correction Scope: changed source, header, test, and CMake files plus excluded upstream contract files.
|
||||
5. Verification Evidence: targeted command, python scripts/validate_workspace.py, and Python harness self-test when relevant.
|
||||
5. Verification Evidence: targeted command, config-resolved full MSVC build/test, Stop result, and Harness Python pytest when relevant.
|
||||
6. Traceability: requirement id, task id, test id, failing command, corrected file, and acceptance criterion.
|
||||
7. Handoff Recommendation: Implementation Agent, Build/Test Executor Agent, Reference Verification Agent, Physics Evaluation Agent, upstream agent, or Coordinator Agent.
|
||||
8. Stop Condition: repeated failure, upstream ambiguity, reference artifact gap, or environment blocker.
|
||||
|
||||
@@ -43,7 +43,9 @@ Execution contract:
|
||||
- RED: write the planned C++ unit, integration, parser/I/O, or reference-comparison test first.
|
||||
- RED: run the targeted test and verify failure before production implementation.
|
||||
- GREEN: implement the minimum code needed for the planned task and acceptance criterion.
|
||||
- VERIFY: run the targeted CTest command, then the workspace validation commands.
|
||||
- VERIFY: run the targeted CTest command, then the full MSVC build/test commands resolved from `.harness/config.json` or the Harness defaults.
|
||||
- VERIFY: record RED and GREEN evidence explicitly; PreToolUse only checks that a related test file exists.
|
||||
- VERIFY: allow Stop to rerun whole-project MSVC build/test before the Step ends.
|
||||
- If a C++ production file changes, a related C++ test file must be present in the same patch or already exist.
|
||||
- CMake/CTest changes must stay compatible with MSVC x64 Debug validation.
|
||||
- Abaqus reference CSV files are read-only verification inputs.
|
||||
@@ -69,15 +71,19 @@ Required Implementation Report sections:
|
||||
2. Implemented Scope: completed task ids, skipped task ids, and reason.
|
||||
3. Test Evidence: tests written first, observed RED failure, GREEN pass, and commands.
|
||||
4. Code Changes: source, header, test, and CMake/CTest change summary.
|
||||
5. Validation Evidence: ctest -C Debug, python scripts/validate_workspace.py, and python -m unittest discover -s scripts -p "test_*.py" when relevant.
|
||||
5. Validation Evidence: targeted CTest, config-resolved full MSVC build/test, Stop result, and `uv run --with pytest python -m pytest -v -rs` when Harness Python behavior is relevant.
|
||||
6. Traceability: requirement id, task id, test id, and acceptance criterion.
|
||||
7. Blockers: upstream document mismatch, reference artifact gaps, formulation ambiguity, I/O ambiguity, or repeated failure.
|
||||
8. Downstream Handoff: Build/Test Executor Agent, Correction Agent, and Reference Verification Agent.
|
||||
|
||||
Validation commands:
|
||||
- python -m unittest discover -s scripts -p "test_*.py"
|
||||
- python scripts/validate_workspace.py
|
||||
- ctest -C Debug -R <feature-or-label>
|
||||
- cmake -S . -B .harness/build -A x64
|
||||
- cmake --build .harness/build --config Debug
|
||||
- ctest --test-dir .harness/build -C Debug -R <feature-or-label> --output-on-failure
|
||||
- ctest --test-dir .harness/build -C Debug --show-only=json-v1
|
||||
- ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
- Use configured CMake presets or direct MSBuild commands instead when `.harness/config.json` selects them.
|
||||
- Run `uv run --with pytest python -m pytest -v -rs` when Harness Python, Hook, or agent-config behavior changes.
|
||||
|
||||
Status rules:
|
||||
- in-progress: implementation is underway.
|
||||
|
||||
@@ -55,11 +55,11 @@ Required Implementation Plan sections:
|
||||
3. Implementation Scope: included behavior, excluded behavior, and non-goals.
|
||||
4. Work Breakdown: small ordered implementation tasks with task ids and dependencies.
|
||||
5. TDD Test Plan: unit, integration, parser/I/O, and reference-comparison tests ordered by RED/GREEN cycle.
|
||||
6. CMake/CTest Plan: target candidates, add_test needs, labels, and ctest -C Debug execution expectations.
|
||||
6. CMake/CTest Plan: target candidates, add_test needs, labels, and `.harness/config.json` or default `.harness/build` execution expectations.
|
||||
7. Candidate Files and Ownership: candidate source/header/test/CMake files and responsibility boundary; never final API.
|
||||
8. Data Flow Contract: Abaqus .inp input, internal model, solver results.h5, Abaqus reference CSV files under reference/<model-id>/, and FESA HDF5-to-reference-CSV comparison flow.
|
||||
9. Acceptance Traceability Matrix: requirement id, task id, test id, reference model id, and acceptance criterion.
|
||||
10. Validation Commands: python -m unittest discover -s scripts -p \"test_*.py\", python scripts/validate_workspace.py, and feature-specific CTest commands.
|
||||
10. Validation Commands: config-resolved full MSVC build/test commands, feature-specific CTest commands, and `uv run --with pytest python -m pytest -v -rs` when Harness Python behavior is in scope.
|
||||
11. Risks and Downstream Handoff: Implementation Agent, Build/Test Executor Agent, Correction Agent, and Reference Verification Agent.
|
||||
12. Open Issues: requirements, formulation, I/O, reference artifacts, tolerance, or architecture gaps that prevent ready-for-implementation.
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ Required Release Report sections:
|
||||
2. Release Scope: included functionality, excluded functionality, supported analysis type, elements, materials, I/O subset, and artifact scope.
|
||||
3. Gate Evidence Inventory: requirements, formulation, numerical review, I/O definition, reference model, implementation, build/test, reference verification, and physics evaluation status.
|
||||
4. Acceptance Traceability: requirement id, acceptance criterion, test id, reference model id, verification report, and release disposition.
|
||||
5. Validation Evidence: python scripts/validate_workspace.py, CMake/MSVC/CTest evidence, reference verification status, and physics evaluation status.
|
||||
5. Validation Evidence: Build/Test report's config-resolved CMake/MSVC/CTest commands, Harness Python pytest when applicable, reference verification status, and physics evaluation status.
|
||||
6. Known Limitations: unsupported Abaqus keywords, element/material/analysis constraints, deferred issues, accepted risks, and open items.
|
||||
7. Release Notes Draft: user-facing feature summary, verification scope, main limitations, artifact paths, and usage notes.
|
||||
8. Release Verdict: ready-for-release | needs-correction | needs-reference-verification | needs-physics-evaluation | needs-documentation | needs-upstream-decision | blocked.
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
#:schema https://developers.openai.com/codex/config-schema.json
|
||||
|
||||
[features]
|
||||
codex_hooks = true
|
||||
hooks = true
|
||||
|
||||
+13
-9
@@ -1,25 +1,29 @@
|
||||
{
|
||||
"description": "Harness TDD, command safety, and MSVC C/C++ validation hooks.",
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "^Bash$",
|
||||
"matcher": "Bash|shell_command|PowerShell|apply_patch|Edit|MultiEdit|Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python -c \"import pathlib, runpy, subprocess; root = pathlib.Path(subprocess.check_output(['git', 'rev-parse', '--show-toplevel'], text=True).strip()); runpy.run_path(str(root / '.codex' / 'hooks' / 'pre_commit_checks.py'), run_name='__main__')\"",
|
||||
"timeout": 600,
|
||||
"statusMessage": "Running pre-commit checks"
|
||||
"command": "python3 -X utf8 \"$(git rev-parse --show-toplevel)/scripts/hooks/pre_tool_use.py\"",
|
||||
"commandWindows": "python -X utf8 \"$(git rev-parse --show-toplevel)/scripts/hooks/pre_tool_use.py\"",
|
||||
"timeout": 30,
|
||||
"statusMessage": "Checking Harness policies"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
],
|
||||
"Stop": [
|
||||
{
|
||||
"matcher": "^(apply_patch|Edit|Write)$",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python -c \"import pathlib, runpy, subprocess; root = pathlib.Path(subprocess.check_output(['git', 'rev-parse', '--show-toplevel'], text=True).strip()); runpy.run_path(str(root / '.codex' / 'hooks' / 'tdd-guard.py'), run_name='__main__')\"",
|
||||
"timeout": 30,
|
||||
"statusMessage": "Checking TDD guard"
|
||||
"command": "python3 -X utf8 \"$(git rev-parse --show-toplevel)/scripts/hooks/stop_validation.py\"",
|
||||
"commandWindows": "python -X utf8 \"$(git rev-parse --show-toplevel)/scripts/hooks/stop_validation.py\"",
|
||||
"timeout": 1800,
|
||||
"statusMessage": "Running MSVC build and tests"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def _repo_root(cwd: Path) -> Path:
|
||||
try:
|
||||
root = subprocess.check_output(
|
||||
["git", "rev-parse", "--show-toplevel"],
|
||||
cwd=cwd,
|
||||
text=True,
|
||||
stderr=subprocess.DEVNULL,
|
||||
).strip()
|
||||
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||
return cwd
|
||||
return Path(root)
|
||||
|
||||
|
||||
def _is_git_commit(command: str) -> bool:
|
||||
return re.search(
|
||||
r"^\s*git(?:\s+(?:-[A-Za-z]\s+\S+|--[A-Za-z0-9-]+(?:=\S+)?))*\s+commit\b",
|
||||
command,
|
||||
) is not None
|
||||
|
||||
|
||||
def _deny(reason: str) -> None:
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PreToolUse",
|
||||
"permissionDecision": "deny",
|
||||
"permissionDecisionReason": reason,
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def _tail(text: str, limit: int = 1200) -> str:
|
||||
text = text.strip()
|
||||
if len(text) <= limit:
|
||||
return text
|
||||
return text[-limit:]
|
||||
|
||||
|
||||
def _build_pre_commit_commands(root: Path) -> list[list[str]]:
|
||||
return [
|
||||
[sys.executable, "-m", "unittest", "discover", "-s", "scripts", "-p", "test_*.py"],
|
||||
[sys.executable, "scripts/validate_workspace.py"],
|
||||
]
|
||||
|
||||
|
||||
def _run_checks(root: Path) -> str | None:
|
||||
for command in _build_pre_commit_commands(root):
|
||||
result = subprocess.run(command, cwd=root, capture_output=True, text=True)
|
||||
if result.returncode != 0:
|
||||
details = _tail(result.stdout + "\n" + result.stderr)
|
||||
label = " ".join(command)
|
||||
if details:
|
||||
return f"{label} failed:\n{details}"
|
||||
return f"{label} failed with exit code {result.returncode}."
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def main() -> int:
|
||||
try:
|
||||
payload = json.load(sys.stdin)
|
||||
except json.JSONDecodeError:
|
||||
return 0
|
||||
|
||||
command = payload.get("tool_input", {}).get("command", "")
|
||||
if not isinstance(command, str) or not _is_git_commit(command):
|
||||
return 0
|
||||
|
||||
cwd = Path(payload.get("cwd") or Path.cwd())
|
||||
root = _repo_root(cwd)
|
||||
failure = _run_checks(root)
|
||||
if failure:
|
||||
_deny(f"PRE-COMMIT CHECKS: {failure}")
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -1,205 +0,0 @@
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
SOURCE_SUFFIXES = {".h", ".hpp", ".hh", ".hxx", ".c", ".cc", ".cpp", ".cxx", ".ixx"}
|
||||
TEST_SUFFIXES = {".h", ".hpp", ".hh", ".hxx", ".c", ".cc", ".cpp", ".cxx", ".ixx"}
|
||||
CONFIG_SUFFIXES = {".json", ".md", ".yml", ".yaml", ".txt", ".cmake"}
|
||||
|
||||
|
||||
def _repo_root(cwd: Path) -> Path:
|
||||
try:
|
||||
root = subprocess.check_output(
|
||||
["git", "rev-parse", "--show-toplevel"],
|
||||
cwd=cwd,
|
||||
text=True,
|
||||
stderr=subprocess.DEVNULL,
|
||||
).strip()
|
||||
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||
return cwd
|
||||
return Path(root)
|
||||
|
||||
|
||||
def _extract_patch_paths(command: str) -> list[str]:
|
||||
prefixes = (
|
||||
"*** Add File: ",
|
||||
"*** Update File: ",
|
||||
"*** Delete File: ",
|
||||
"*** Move to: ",
|
||||
)
|
||||
paths: list[str] = []
|
||||
for raw_line in command.splitlines():
|
||||
line = raw_line.strip()
|
||||
for prefix in prefixes:
|
||||
if line.startswith(prefix):
|
||||
paths.append(line[len(prefix) :].strip())
|
||||
break
|
||||
return paths
|
||||
|
||||
|
||||
def _touched_paths(payload: dict) -> list[str]:
|
||||
tool_input = payload.get("tool_input", {})
|
||||
if not isinstance(tool_input, dict):
|
||||
return []
|
||||
|
||||
file_path = tool_input.get("file_path")
|
||||
if isinstance(file_path, str) and file_path:
|
||||
return [file_path]
|
||||
|
||||
command = tool_input.get("command")
|
||||
if isinstance(command, str):
|
||||
return _extract_patch_paths(command)
|
||||
|
||||
return []
|
||||
|
||||
|
||||
def _normalize(path_text: str) -> str:
|
||||
return path_text.replace("\\", "/").lower()
|
||||
|
||||
|
||||
def _is_test_path(path_text: str) -> bool:
|
||||
normalized = _normalize(path_text)
|
||||
name = normalized.rsplit("/", 1)[-1]
|
||||
path = Path(path_text)
|
||||
return (
|
||||
"/tests/" in f"/{normalized}"
|
||||
or "/test/" in f"/{normalized}"
|
||||
or name.endswith("_test.cpp")
|
||||
or name.startswith("test_")
|
||||
or ".test." in name
|
||||
or ".spec." in name
|
||||
) and path.suffix.lower() in TEST_SUFFIXES
|
||||
|
||||
|
||||
def _token(text: str) -> str:
|
||||
return "".join(ch for ch in text.lower() if ch.isalnum())
|
||||
|
||||
|
||||
def _module_token(path: Path) -> str:
|
||||
parts = [part.lower() for part in path.parts]
|
||||
for marker in ("include", "src"):
|
||||
if marker not in parts:
|
||||
continue
|
||||
idx = parts.index(marker)
|
||||
if marker == "include" and idx + 2 < len(parts) and parts[idx + 1] == "fesa":
|
||||
return _token(parts[idx + 2])
|
||||
if marker == "src" and idx + 1 < len(parts):
|
||||
return _token(parts[idx + 1])
|
||||
return ""
|
||||
|
||||
|
||||
def _related_tokens(path: Path) -> set[str]:
|
||||
tokens = {_token(_base_name(path))}
|
||||
module = _module_token(path)
|
||||
if module:
|
||||
tokens.add(module)
|
||||
return {token for token in tokens if token}
|
||||
|
||||
|
||||
def _candidate_test_paths(paths: list[str], cwd: Path, root: Path) -> list[Path]:
|
||||
candidates: list[Path] = []
|
||||
for path_text in paths:
|
||||
resolved = _resolve_path(path_text, cwd)
|
||||
if _is_test_path(str(resolved)):
|
||||
candidates.append(resolved)
|
||||
|
||||
for test_root_name in ("tests", "test"):
|
||||
test_root = root / test_root_name
|
||||
if not test_root.is_dir():
|
||||
continue
|
||||
for suffix in TEST_SUFFIXES:
|
||||
candidates.extend(test_root.rglob(f"*{suffix}"))
|
||||
|
||||
return candidates
|
||||
|
||||
|
||||
def _has_related_test(path: Path, candidate_tests: list[Path]) -> bool:
|
||||
tokens = _related_tokens(path)
|
||||
for test_path in candidate_tests:
|
||||
test_token = _token(test_path.stem)
|
||||
if any(token and token in test_token for token in tokens):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _is_exempt(path_text: str) -> bool:
|
||||
normalized = _normalize(path_text)
|
||||
path = Path(path_text)
|
||||
name = path.name.lower()
|
||||
|
||||
if name == "cmakelists.txt":
|
||||
return True
|
||||
if _is_test_path(path_text):
|
||||
return True
|
||||
if path.suffix.lower() in CONFIG_SUFFIXES:
|
||||
return True
|
||||
if "/cmake/" in normalized:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def _resolve_path(path_text: str, cwd: Path) -> Path:
|
||||
path = Path(path_text)
|
||||
if path.is_absolute():
|
||||
return path
|
||||
return (cwd / path).resolve()
|
||||
|
||||
|
||||
def _base_name(path: Path) -> str:
|
||||
for suffix in sorted(SOURCE_SUFFIXES, key=len, reverse=True):
|
||||
if path.name.lower().endswith(suffix):
|
||||
return path.name[: -len(suffix)]
|
||||
return path.stem
|
||||
|
||||
|
||||
def _guarded_paths(paths: list[str], cwd: Path, root: Path) -> list[str]:
|
||||
missing_tests: list[str] = []
|
||||
candidate_tests = _candidate_test_paths(paths, cwd, root)
|
||||
for path_text in paths:
|
||||
if _is_exempt(path_text):
|
||||
continue
|
||||
|
||||
path = _resolve_path(path_text, cwd)
|
||||
if path.suffix.lower() not in SOURCE_SUFFIXES:
|
||||
continue
|
||||
if not _has_related_test(path, candidate_tests):
|
||||
missing_tests.append(_base_name(path))
|
||||
|
||||
return missing_tests
|
||||
|
||||
|
||||
def main() -> int:
|
||||
try:
|
||||
payload = json.load(sys.stdin)
|
||||
except json.JSONDecodeError:
|
||||
return 0
|
||||
|
||||
cwd = Path(payload.get("cwd") or Path.cwd())
|
||||
root = _repo_root(cwd)
|
||||
missing_tests = _guarded_paths(_touched_paths(payload), cwd, root)
|
||||
if not missing_tests:
|
||||
return 0
|
||||
|
||||
names = ", ".join(sorted(set(missing_tests)))
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PreToolUse",
|
||||
"permissionDecision": "deny",
|
||||
"permissionDecisionReason": (
|
||||
"TDD GUARD: missing test file for "
|
||||
f"{names}. Write or add the test first."
|
||||
),
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -1,3 +1,3 @@
|
||||
# FEM wiki vault root path.
|
||||
# Edit this per PC. Use an absolute path to the vault that contains wiki/ and .raw/.
|
||||
D:\Obsidian\MultiPhysicsVault
|
||||
C:\git\MultiPhysicsVault
|
||||
|
||||
@@ -26,10 +26,12 @@ Read these first:
|
||||
3. RED: write the planned unit, integration, parser/I/O, or reference-comparison test first.
|
||||
4. RED: run the targeted test and verify the expected failure before production code.
|
||||
5. GREEN: implement the minimum C++17/MSVC-compatible code needed for the task.
|
||||
6. VERIFY: run the targeted command, then `python scripts/validate_workspace.py`.
|
||||
6. VERIFY: run the targeted command, then the full MSVC build/test commands resolved from `.harness/config.json` or the Harness defaults.
|
||||
7. For C++ production changes, require a related C++ test file in the same patch or already present.
|
||||
8. For failure triage, classify as `configure | compile | link | test | reference-comparison | harness | environment | upstream-contract`.
|
||||
9. Fix implementation-owned failures only and keep changes traceable to the implementation plan.
|
||||
8. Treat PreToolUse as a test-file-existence guardrail, not proof that RED was observed. Record the RED and GREEN commands and results in the implementation report.
|
||||
9. Let Stop perform the final whole-project MSVC build/test before the Step ends.
|
||||
10. For failure triage, classify as `configure | compile | link | test | reference-comparison | harness | environment | upstream-contract`.
|
||||
11. Fix implementation-owned failures only and keep changes traceable to the implementation plan.
|
||||
|
||||
## Output Contract
|
||||
|
||||
@@ -43,17 +45,19 @@ Produce one of these, depending on role:
|
||||
Required validation commands:
|
||||
|
||||
```powershell
|
||||
python -m unittest discover -s scripts -p "test_*.py"
|
||||
python scripts/validate_workspace.py
|
||||
ctest -C Debug -R <feature-or-label>
|
||||
cmake -S . -B .harness/build -A x64
|
||||
cmake --build .harness/build --config Debug
|
||||
ctest --test-dir .harness/build -C Debug -R <feature-or-label> --output-on-failure
|
||||
ctest --test-dir .harness/build -C Debug --show-only=json-v1
|
||||
ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
```
|
||||
|
||||
Default MSVC path:
|
||||
Use configured CMake presets or direct MSBuild commands instead when
|
||||
`.harness/config.json` selects them. For Harness Python, Hook, or agent-config
|
||||
changes, also run:
|
||||
|
||||
```powershell
|
||||
cmake -S . -B build/msvc-debug -G "Visual Studio 17 2022" -A x64
|
||||
cmake --build build/msvc-debug --config Debug
|
||||
ctest --test-dir build/msvc-debug --output-on-failure -C Debug
|
||||
uv run --with pytest python -m pytest -v -rs
|
||||
```
|
||||
|
||||
## Boundaries
|
||||
@@ -73,6 +77,7 @@ ctest --test-dir build/msvc-debug --output-on-failure -C Debug
|
||||
- Every `must` requirement maps to at least one task and one test.
|
||||
- Each test has a clear RED condition, GREEN condition, linked task, and command.
|
||||
- CMake/CTest plans remain compatible with MSVC x64 Debug validation.
|
||||
- Stop validation is green for the whole discovered C/C++ project; a no-project pass is valid only when no C/C++ files and no build metadata exist.
|
||||
- Build/test reports record command, exit code, duration, stdout/stderr tail, and failure classification.
|
||||
- Correction attempts stop when repeated failure indicates upstream contract ambiguity.
|
||||
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
---
|
||||
name: harness-review
|
||||
description: Use when reviewing this C++/MSVC Harness repository: local changes, generated phase files, step outputs, implementation diffs, missing tests, MSVC build readiness, or compliance with AGENTS.md, docs/ARCHITECTURE.md, docs/ADR.md, and Harness acceptance criteria.
|
||||
---
|
||||
|
||||
# Harness Review
|
||||
|
||||
## Overview
|
||||
|
||||
Use this skill to review Harness work against the repository's persistent rules, architecture docs, C++/MSVC constraints, TDD guard policy, and executable verification requirements. Prioritize bugs, regressions, missing tests, and rule violations.
|
||||
|
||||
## Review Process
|
||||
|
||||
1. Read `/AGENTS.md`, `/docs/ARCHITECTURE.md`, and `/docs/ADR.md`.
|
||||
2. Inspect the changed files with `git status --short` and `git diff`.
|
||||
3. Check architecture, stack choices, C++ test coverage, critical rules, and MSVC/CMake readiness.
|
||||
4. Run relevant verification commands when feasible. If a command cannot be run, report that as residual risk.
|
||||
5. Lead with actionable findings. Keep summaries secondary.
|
||||
|
||||
## Checklist
|
||||
|
||||
| Item | Question |
|
||||
| --- | --- |
|
||||
| Architecture | Does the change follow `docs/ARCHITECTURE.md` ownership boundaries? |
|
||||
| Stack | Does the change stay within C++/MSVC/CMake decisions documented in `docs/ADR.md`? |
|
||||
| Tests | Are new or changed behaviors covered by Python Harness tests or C++ tests? |
|
||||
| TDD Guard | Would C++ production edits be blocked without related tests? |
|
||||
| Critical Rules | Does the change violate any `AGENTS.md` CRITICAL rule? |
|
||||
| Build | Do `python -m unittest discover -s scripts -p "test_*.py"` and `python scripts/validate_workspace.py` pass or provide an expected no-CMake message? |
|
||||
|
||||
## Output Format
|
||||
|
||||
If there are findings, list them first in severity order with file and line references when possible. Then include this table:
|
||||
|
||||
| 항목 | 결과 | 비고 |
|
||||
| --- | --- | --- |
|
||||
| 아키텍처 준수 | PASS/FAIL | {상세} |
|
||||
| 기술 스택 준수 | PASS/FAIL | {상세} |
|
||||
| 테스트 존재 | PASS/FAIL | {상세} |
|
||||
| TDD Guard | PASS/FAIL | {상세} |
|
||||
| CRITICAL 규칙 | PASS/FAIL | {상세} |
|
||||
| 빌드/검증 가능 | PASS/FAIL | {상세} |
|
||||
|
||||
When there are no findings, say that clearly, then mention any commands not run or remaining risk.
|
||||
@@ -1,4 +0,0 @@
|
||||
interface:
|
||||
display_name: "Harness Review"
|
||||
short_description: "Review Harness changes safely"
|
||||
default_prompt: "Use $harness-review to review Harness repository changes."
|
||||
@@ -1,130 +0,0 @@
|
||||
---
|
||||
name: harness-workflow
|
||||
description: Use when planning or running this C++/MSVC Harness framework: reading AGENTS.md and docs/*.md, discussing implementation scope, creating or updating phases/index.json, phases/{task}/index.json, phases/{task}/stepN.md, or invoking scripts/execute.py for staged Codex execution.
|
||||
---
|
||||
|
||||
# Harness Workflow
|
||||
|
||||
## Overview
|
||||
|
||||
Use this skill to turn a user-approved task into small, self-contained Harness steps that another Codex session can execute reliably. Keep every step grounded in repository docs, C++/MSVC constraints, TDD, and executable acceptance criteria.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Read `AGENTS.md` and relevant files under `docs/`, especially `docs/PRD.md`, `docs/ARCHITECTURE.md`, and `docs/ADR.md`.
|
||||
2. Discuss unresolved product or technical decisions with the user before writing phase files.
|
||||
3. When the user asks for an implementation plan, draft steps and get approval before creating files.
|
||||
4. Create or update `phases/index.json`, `phases/{task-name}/index.json`, and one `phases/{task-name}/stepN.md` per step.
|
||||
5. Run the phase with `python scripts/execute.py {task-name}` when asked to execute it. Use `--push` only when the user asks to push.
|
||||
|
||||
## Step Design Rules
|
||||
|
||||
- Scope each step to one layer or module. Split steps when multiple modules would otherwise change together.
|
||||
- Make every step self-contained. Do not rely on prior conversation; include all required context and file paths.
|
||||
- Force context gathering. Each step must tell Codex which docs and previous outputs to read before editing.
|
||||
- Specify interfaces and signatures, not full implementations, unless exact code is required for a constraint.
|
||||
- Put core invariants directly in the step: idempotency, numerical conventions, data integrity, API contracts, or other non-negotiables.
|
||||
- Use executable acceptance criteria such as `python scripts/validate_workspace.py`, not abstract statements.
|
||||
- For C++ behavior changes, require tests first and name the expected test file or test executable.
|
||||
- Name steps with kebab-case slugs such as `project-setup`, `core-types`, or `solver-validation`.
|
||||
|
||||
## Phase Files
|
||||
|
||||
Create or update `phases/index.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"phases": [
|
||||
{
|
||||
"dir": "0-mvp",
|
||||
"status": "pending"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Create `phases/{task-name}/index.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"project": "FESA Harness",
|
||||
"phase": "<task-name>",
|
||||
"steps": [
|
||||
{ "step": 0, "name": "project-setup", "status": "pending", "allowed_paths": ["CMakeLists.txt", "tests/"] },
|
||||
{ "step": 1, "name": "core-types", "status": "pending", "allowed_paths": ["src/fesa/core/", "tests/unit/"] },
|
||||
{ "step": 2, "name": "validation-path", "status": "pending", "allowed_paths": ["scripts/", "docs/"] }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- `project` comes from `AGENTS.md`.
|
||||
- `phase` matches the task directory name.
|
||||
- `steps[].step` starts at `0`.
|
||||
- Initial status is always `pending`.
|
||||
- Each step must declare non-empty `allowed_paths` using repository-relative paths, directory prefixes, or glob patterns.
|
||||
- Do not add timestamps when creating files. `scripts/execute.py` records `created_at`, `started_at`, `completed_at`, `failed_at`, and `blocked_at`.
|
||||
|
||||
## Step Template
|
||||
|
||||
```markdown
|
||||
# Step {N}: {name}
|
||||
|
||||
## 읽어야 할 파일
|
||||
|
||||
먼저 아래 파일들을 읽고 프로젝트의 아키텍처와 설계 의도를 파악하라:
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/ARCHITECTURE.md`
|
||||
- `/docs/ADR.md`
|
||||
- {previously created or modified files}
|
||||
|
||||
이전 step에서 만들어진 코드를 꼼꼼히 읽고, 설계 의도를 이해한 뒤 작업하라.
|
||||
|
||||
## 작업
|
||||
|
||||
{Concrete instructions with file paths, interfaces, signatures, and rules.}
|
||||
|
||||
## Tests To Write First
|
||||
|
||||
- {Exact C++ or Python test file and behavior to add before implementation.}
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
```bash
|
||||
python -m unittest discover -s scripts -p "test_*.py"
|
||||
python scripts/validate_workspace.py
|
||||
```
|
||||
|
||||
## 검증 절차
|
||||
|
||||
1. 위 AC 커맨드를 실행한다.
|
||||
2. 아키텍처 체크리스트를 확인한다:
|
||||
- ARCHITECTURE.md 디렉토리 구조를 따르는가?
|
||||
- ADR 기술 스택을 벗어나지 않았는가?
|
||||
- AGENTS.md CRITICAL 규칙을 위반하지 않았는가?
|
||||
- C++ 변경에는 관련 테스트가 존재하는가?
|
||||
3. 결과에 따라 `phases/{task-name}/index.json`의 해당 step을 업데이트한다:
|
||||
- 성공: `"status": "completed"`, `"summary": "산출물 한 줄 요약"`
|
||||
- 3회 수정 시도 후 실패: `"status": "error"`, `"error_message": "구체적 에러 내용"`
|
||||
- 사용자 개입 필요: `"status": "blocked"`, `"blocked_reason": "구체적 사유"` 후 중단
|
||||
|
||||
## 금지사항
|
||||
|
||||
- JavaScript/TypeScript/npm fallback을 추가하지 마라. Reason: 이 Harness는 C++/MSVC 전용이다.
|
||||
- 기존 테스트를 깨뜨리지 마라.
|
||||
```
|
||||
|
||||
## Execution And Recovery
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
python scripts/execute.py {task-name}
|
||||
python scripts/execute.py {task-name} --push
|
||||
```
|
||||
|
||||
`scripts/execute.py` creates or checks out `codex/{task-name}`, refuses dirty worktrees, requires per-step `allowed_paths`, stages only explicit allowed paths and runner housekeeping files, validates before every runner-created commit, injects `AGENTS.md` and `docs/*.md` into each prompt, carries completed step summaries forward, retries failed steps up to three times, and records timestamps.
|
||||
|
||||
If a step is `error`, set it back to `pending` and remove `error_message` after fixing the cause. If a step is `blocked`, resolve `blocked_reason`, set it back to `pending`, remove `blocked_reason`, and rerun.
|
||||
@@ -1,4 +0,0 @@
|
||||
interface:
|
||||
display_name: "Harness Workflow"
|
||||
short_description: "Plan staged Harness workflow steps"
|
||||
default_prompt: "Use $harness-workflow to plan Harness phases and step files."
|
||||
@@ -17,6 +17,11 @@ Testing/
|
||||
*.log
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.h5
|
||||
|
||||
# local Harness configuration and build outputs
|
||||
.harness/config.json
|
||||
.harness/build/
|
||||
|
||||
# phase execution outputs
|
||||
phases/**/phase*-output.json
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"version": 1,
|
||||
"projectType": "auto",
|
||||
"tdd": {
|
||||
"testRoots": [
|
||||
"tests",
|
||||
"test"
|
||||
],
|
||||
"testPatterns": [
|
||||
"{stem}_test.cpp",
|
||||
"{stem}_tests.cpp",
|
||||
"test_{stem}.cpp",
|
||||
"{stem}.test.cpp"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -10,38 +10,86 @@
|
||||
- Abaqus `.inp` keyword subset input
|
||||
|
||||
## 프로젝트 정체성
|
||||
- FESA는 유한요소법 기반 구조해석 솔버 개발 프로젝트이다.
|
||||
- Harness는 솔버 자체가 아니라 요구조건, TDD, phase 실행, 검증을 통제하는 개발 운영 인프라이다.
|
||||
- FESA는 유한요소법 기반 구조해석 솔버를 단계적으로 구축하고 검증하는 프로젝트이다. 목표는 Abaqus를 흉내 내는 parser를 만드는 것이 아니라, 승인된 입력 범위에서 물리적으로 설명 가능하고 재현 가능한 해석 결과를 만드는 것이다.
|
||||
- 새 기능은 입력 keyword만 인식하거나 element kernel만 존재한다고 완성된 것이 아니다. Semantic model, equation system, 해법, 결과 복구, HDF5 외부 계약과 독립 검증 evidence가 하나의 추적 가능한 기능을 이뤄야 한다.
|
||||
- 프로젝트의 배경, 목적, 사용자, 범위는 `docs/PRD.md`에서 확인한다.
|
||||
- 전체 아키텍처와 모듈별 책임은 `docs/ARCHITECTURE.md`에서 확인한다.
|
||||
- 주요 아키텍처 결정과 그 이유 및 트레이드오프는 `docs/ADR.md`에서 확인한다.
|
||||
- AI 에이전트는 설계나 구현 결정을 내리기 전에 PRD에서 제품 범위를, ARCHITECTURE에서 소유권과 데이터 흐름을, ADR에서 이미 결정된 트레이드오프를 먼저 확인한다. 기능별 의미는 `docs/requirements/`, `docs/formulations/`, `docs/io-definitions/`, `docs/reference-models/`의 승인 문서를 source of truth로 삼는다.
|
||||
- Harness는 솔버 자체가 아니라 요구조건, TDD, phase 실행, 검증을 통제하는 개발 운영 인프라이다. 전체 실행 흐름은 `docs/HARNESS_WORKFLOW.md`, 설치와 설정은 `docs/HARNESS.md`를 따른다.
|
||||
- 문서와 구현은 full Abaqus compatibility를 주장하지 않는다. 기능별로 승인된 Abaqus keyword subset만 지원한다.
|
||||
- 공식 solver output은 HDF5 `results.h5`이다.
|
||||
- reference 결과는 FESA와 같은 Abaqus `.inp` 모델을 Abaqus로 해석해 생성한 CSV 파일이다.
|
||||
- reference comparison은 FESA `results.h5`의 변위, 반력, 내력, 응력 dataset을 `reference/<model-id>/<model-id>_*.csv` 파일과 비교한다.
|
||||
- reference artifact의 정확한 경로와 파일명은 기능별 reference model contract를 따른다. 신규 모델은 `reference/<model-id>/<model-id>_*.csv` canonical 이름을 사용한다.
|
||||
- 승인된 B33 baseline은 예외적으로 `reference/cantilever beam/`의 기존 space-containing 파일명을 read-only legacy alias로 사용한다.
|
||||
- CSV는 FESA 공식 output이 아니며, FESA HDF5에서 추출한 deterministic CSV view는 비교 디버깅/검토용 보조 artifact로만 둔다.
|
||||
|
||||
## 아키텍처 규칙
|
||||
- CRITICAL: 기본 검증 경로는 `python scripts/validate_workspace.py`이다.
|
||||
## FESA 개발의 핵심 원칙
|
||||
|
||||
### 물리와 수치 계약
|
||||
|
||||
- CRITICAL: 구현보다 요구조건, 정식화, 부호, 단위, 좌표계, row identity와 tolerance 계약을 먼저 고정한다. 구현 편의를 위해 승인된 의미를 조용히 바꾸지 않는다.
|
||||
- CRITICAL: 해석 결과가 유한하고 선형계가 풀렸다는 사실만으로 correctness를 주장하지 않는다. Equilibrium, reaction, rigid-body mode, energy, symmetry와 reference identity를 기능에 맞게 검증한다.
|
||||
- Source label/instance identity와 internal index/equation index를 구분한다. Stable source identity는 진단, 결과, reference mapping 전 구간에서 보존한다.
|
||||
- 병렬 실행 여부와 관계없이 같은 입력은 같은 sparse structure, reduction order, result row order와 diagnostic order를 만들어야 한다.
|
||||
- Scale-aware validation은 formulation과 I/O 계약의 기준을 사용한다. 임의의 `max(1, ...)`, zero clamp, 누락 row 무시 또는 불일치 평균으로 오류를 숨기지 않는다.
|
||||
|
||||
### 소유권과 의존성
|
||||
|
||||
- CRITICAL: C++ 빌드는 CMake/MSVC/x64/Debug 기준으로 검증한다.
|
||||
- CRITICAL: 새 기능 또는 동작 변경은 테스트를 먼저 작성하고 실패를 확인한 뒤 구현한다.
|
||||
- CRITICAL: C++ production file을 바꿀 때는 관련 C++ test file이 있어야 한다.
|
||||
- CRITICAL: Abaqus reference artifact 생성, 수정, 복원은 명시적으로 요청된 phase에서만 수행한다.
|
||||
- CRITICAL: `harness-workflow` 스킬은 사용자가 명시적으로 허용하기 전까지 사용하지 않는다.
|
||||
- CRITICAL: public header와 implementation 의존성 방향을 역전하지 않는다.
|
||||
- CRITICAL: 사람이 계약과 수치식을 대조할 수 있는 단순한 코드를 작성한다. 주석은 코드가 이미 말하는 동작보다 부호, 수명, 순서, backend 제약처럼 비자명한 이유를 설명한다.
|
||||
- Domain은 입력 파일에서 생성된 전체 모델 정의를 소유하고, 파싱 이후 가능한 한 불변으로 취급한다.
|
||||
- AnalysisModel은 현재 step에서 활성화된 elements, loads, boundary conditions, properties/materials의 view를 제공하며 Domain을 복사하지 않는다.
|
||||
- AnalysisModel은 현재 step에서 활성화된 elements, loads, boundary conditions, properties/materials의 non-owning view를 제공하며 Domain을 복사하지 않는다. 따라서 Domain은 AnalysisModel보다 오래 살아야 한다.
|
||||
- DofManager는 node별 자유도 정의, constrained/free mapping, equation numbering, sparse pattern ownership을 전담한다. Node 또는 Element 내부에 equation id를 분산 저장하지 않는다.
|
||||
- AnalysisState는 displacement, velocity, acceleration, temperature, external/internal force, residual, time/increment/iteration, element state를 소유한다.
|
||||
- MKL, TBB, HDF5 API는 solver core에 직접 노출하지 않는다. `LinearSolver`, `ParallelFor`, `ResultsWriter`, `Vector`, `Matrix`, `SparseMatrix` adapter 경계 뒤에 둔다.
|
||||
- AnalysisState는 해당 procedure가 실제로 사용하는 mutable solution과 recovery row만 소유한다. V0는 full displacement/external/internal force/residual/reaction과 step/frame 및 beam recovery rows만 보관하며 미래 state를 미리 할당하지 않는다.
|
||||
- MKL, TBB, HDF5, Win32 API와 vendor type은 public solver core에 노출하지 않는다. `LinearSolver`, `ParallelFor`, `ResultsWriter`, `Vector`, `Matrix`, `SparseMatrix` 경계 뒤에 둔다.
|
||||
- 해석 단계는 실패할 수 있는 candidate를 완성하고 검증한 뒤 소유 state/output에 반영한다. 실패 시 기존 state와 기존 최종 HDF5를 가능한 계약 범위에서 보존한다.
|
||||
|
||||
### 선형 정적 해석 불변식
|
||||
|
||||
- `Analysis::run()`의 실제 단계와 객체별 책임은 `docs/ARCHITECTURE.md`의 해석 실행 흐름을 따른다.
|
||||
- Full stiffness를 stable free/constrained 순서로 `Kff/Kfc/Kcf/Kcc`에 분할하고, `Kff` factorization을 load assembly보다 먼저 수행한다.
|
||||
- Effective RHS는 `Ff - Kfc * dc`이며 substitution 뒤 full displacement를 복구한다. 모든 DOF가 constrained인 유효한 모델의 `0 x 0 Kff`를 singular error로 바꾸지 않는다.
|
||||
- Reaction과 free-equilibrium evidence는 조립된 full residual `K*d - F`에서 구한다. Constrained 성분은 physical reaction이고 free 성분은 residual evidence다.
|
||||
- Sparse assembly는 element-local contribution과 stable COO ordering, 고정된 reduction을 사용한다. 병렬 worker가 global CSR storage를 직접 갱신하지 않는다.
|
||||
- Element end action, positive-local-x section resultant, Gauss generalized result와 section-point stress는 서로 다른 identity와 부호 계약을 가진다. Station mismatch를 평균으로 합치지 않는다.
|
||||
|
||||
### 개발 운영 인프라
|
||||
|
||||
- Codex custom agent의 `model_reasoning_effort` 기본값은 `extra high`로 둔다.
|
||||
- Harness runner는 `scripts/execute.py`에 둔다.
|
||||
- `scripts/execute.py`는 `codex/<phase-name>` branch prefix만 사용한다.
|
||||
- `scripts/execute.py` 실행 전 worktree는 clean 상태여야 한다.
|
||||
- 각 phase step은 non-empty `allowed_paths`를 선언해야 한다.
|
||||
- runner는 explicit allowed path와 runner housekeeping file만 stage하며 broad staging을 사용하지 않는다.
|
||||
- runner가 만드는 모든 commit 전에는 Harness Python self-test와 `python scripts/validate_workspace.py`가 통과해야 한다.
|
||||
- Codex hook 정책은 `.codex/hooks/`에 둔다.
|
||||
- `scripts/execute.py`는 `feat-<phase-name>` branch prefix를 사용한다.
|
||||
- runner는 `git add -A`로 변경사항을 stage하므로 실행 전 clean worktree 또는 별도 Git worktree를 사용한다.
|
||||
- Hook 연결은 `.codex/hooks.json`, 구현은 `scripts/hooks/`와 `scripts/msvc_harness/`에 둔다.
|
||||
- PreToolUse는 위험 명령과 C++ production file의 대응 테스트 존재 여부를 검사하는 guardrail이며 RED 실행을 증명하지 않는다.
|
||||
- Stop은 `.harness/config.json` 또는 자동 감지 결과에 따라 MSVC build와 test를 모두 검증한다.
|
||||
- Generated phase execution outputs remain ignored under `phases/**/step*-output.json`.
|
||||
|
||||
## 현재 승인된 V0 기능 계약
|
||||
- `linear-static-3d-euler-beam`의 source of truth는 `docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md`이다. 관련 문서를 변경하거나 구현할 때 이 계약의 의미를 임의로 넓히지 않는다.
|
||||
- 입력 파일당 하나의 `*STEP, *STATIC`과 `TYPE=B33`만 지원한다. B31을 Euler 요소로 매핑하지 않고 `unsupported-element-formulation`으로 거부한다.
|
||||
- `*PART/*ASSEMBLY/*INSTANCE`는 identity instance와 stable source identity만 지원한다. instance transform과 nested assembly는 거부한다.
|
||||
- 선형 정적 실행 순서는 stiffness assembly와 constrained partition 뒤 `Kff`를 factorize하고, 그 다음 load vector와 effective RHS를 조립해 substitution하는 순서를 유지한다.
|
||||
- FESA는 output request와 무관하게 displacement, reaction, equilibrium end action, section resultant, generalized strain/resultant, axial `S11`을 HDF5에 기록한다. Beam stress의 Abaqus reference comparison은 N/A다.
|
||||
- B33 reference row는 component별 Abaqus scale로 `absolute_floor + 1e-6 * reference_scale`을 적용한다. Reference 값을 zero-clamp하거나 누락 row를 무시하지 않는다.
|
||||
- `reference/cantilever beam/` artifact는 rename, rewrite 또는 보정하지 않는다.
|
||||
|
||||
## 기능을 추가할 때의 판단 기준
|
||||
|
||||
- 새 element는 요구조건과 formulation을 승인한 뒤 semantic mapping, property/material 연결, DOF/scatter, local kernel, deterministic assembly, recovery, HDF5 row identity, reference/physics evidence를 함께 설계한다.
|
||||
- 새 load 또는 constraint는 parser 인식만 추가하지 않는다. Source target resolution, stable application order, full-space assembly, partition/effective RHS, diagnostic과 결과 의미까지 연결한다.
|
||||
- 새 analysis procedure는 기존 선형 정적 lifecycle에 조건문을 누적하지 않는다. 필요한 state, equation, solver lifecycle과 recovery contract를 별도 요구조건·ADR·formulation으로 정의한다.
|
||||
- 새 backend는 기존 public interface를 유지하고 vendor lifecycle, integer/index conversion, runtime dependency와 failure translation을 adapter 내부에 격리한다.
|
||||
- 새 output quantity는 계산식뿐 아니라 units, coordinate system, source/internal identity, HDF5 schema, mandatory 여부, reference projection과 tolerance를 동시에 정의한다.
|
||||
- Element API에 kernel이 존재하는 것과 Abaqus keyword/CLI에서 그 기능을 노출하는 것은 별도 계약이다. 예를 들어 V0의 line-load kernel은 `*DLOAD` 지원을 뜻하지 않는다.
|
||||
|
||||
## 개발 프로세스
|
||||
- TDD를 기본으로 한다. 구현은 `RED -> GREEN -> VERIFY` 순서를 따른다.
|
||||
- CRITICAL: 빌드 경고를 새로 추가하지 말 것.
|
||||
- 기능 개발은 다음 gate를 순서대로 통과해야 한다.
|
||||
1. 요구조건 분석
|
||||
2. 연구자료 조사
|
||||
@@ -54,12 +102,11 @@
|
||||
9. reference comparison
|
||||
10. physics sanity
|
||||
11. release readiness
|
||||
- 커밋 전 hook은 Harness Python self-test와 workspace validation을 실행해야 한다.
|
||||
- 커밋 메시지는 conventional commits 형식을 따른다: `feat:`, `fix:`, `docs:`, `refactor:`, `test:`.
|
||||
- Codex는 작업 완료 후 검증을 마치면 즉시 변경사항을 commit하고 push한다.
|
||||
- 계획이 필요한 장기 작업은 Harness phase로 나누고, 각 step은 독립 실행 가능해야 한다.
|
||||
- 커밋 메시지는 conventional commits 형식을 따른다: `feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:`.
|
||||
|
||||
## Agent/Skill Workflow
|
||||
AI 에이전트는 유한요소 구조해석 지식이 필요할 때 FEM wiki를 참조하기 위해 `.codex/skills/fem-theory-query` 스킬을 사용할 수 있다.
|
||||
|
||||
| 개발 과정 | Agent | Skill | 산출물 |
|
||||
| --- | --- | --- | --- |
|
||||
| 요구조건 분석 | `requirement-agent` | `fesa-requirements-baseline` | `docs/requirements/<feature-id>.md` |
|
||||
@@ -75,23 +122,39 @@
|
||||
| 물리 검토 | `physics-evaluation-agent` | `fesa-physics-sanity` | `docs/physics-evaluations/<feature-id>-physics-evaluation.md` |
|
||||
| 배포 준비 | `release-agent` | `fesa-release-readiness` | `docs/releases/<feature-id>-release.md` |
|
||||
|
||||
## 명령어
|
||||
```bash
|
||||
python -m unittest discover -s scripts -p "test_*.py"
|
||||
python scripts/validate_workspace.py
|
||||
python scripts/execute.py <phase-dir>
|
||||
python scripts/execute.py <phase-dir> --push
|
||||
## 최소 검증 진입점
|
||||
|
||||
세부 target graph, dependency normalization과 Windows runtime staging은 `docs/ARCHITECTURE.md`와 실제 CMake 파일을 따른다. `.harness/config.json`이 존재하면 그 설정을 우선한다.
|
||||
|
||||
### Harness Python 검증
|
||||
|
||||
```powershell
|
||||
uv run --with pytest python -m pytest -v -rs
|
||||
```
|
||||
|
||||
## MSVC 검증 기본값
|
||||
- Generator: `Visual Studio 17 2022`
|
||||
- Platform: `x64`
|
||||
- Config: `Debug`
|
||||
- Build directory: `build/msvc-debug`
|
||||
### Phase 실행
|
||||
|
||||
Override variables:
|
||||
- `HARNESS_VALIDATION_COMMANDS`
|
||||
- `HARNESS_CMAKE_GENERATOR`
|
||||
- `HARNESS_CMAKE_PLATFORM`
|
||||
- `HARNESS_CMAKE_CONFIG`
|
||||
- `HARNESS_BUILD_DIR`
|
||||
```powershell
|
||||
python scripts/execute.py <phase-name>
|
||||
python scripts/execute.py <phase-name> --push
|
||||
```
|
||||
|
||||
### CMake/CTest 프로젝트
|
||||
|
||||
```powershell
|
||||
$gtestSource = "C:/path/to/googletest"
|
||||
$mklDir = "C:/path/to/oneAPI/mkl/lib/cmake/mkl"
|
||||
$tbbDir = "C:/path/to/oneAPI/tbb/lib/cmake/tbb"
|
||||
$hdf5Dir = "C:/path/to/HDF5/cmake"
|
||||
|
||||
cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 `
|
||||
"-DFESA_GTEST_SOURCE_DIR=$gtestSource" `
|
||||
"-DMKL_DIR=$mklDir" `
|
||||
"-DTBB_DIR=$tbbDir" `
|
||||
"-DHDF5_DIR=$hdf5Dir"
|
||||
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
|
||||
```
|
||||
|
||||
`FESA_GTEST_SOURCE_DIR`는 approved local GoogleTest source checkout을 반드시 가리켜야 한다. MKL/TBB/HDF5가 기본 package search에서 발견되지 않는 환경에서는 나머지 세 config directory도 명시한다. FESA 제품 검증은 solution-only MSBuild가 아니라 CMake target과 CTest를 기준으로 한다.
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
cmake_minimum_required(VERSION 3.25)
|
||||
|
||||
project(FESA VERSION 0.1.0 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
include(cmake/FesaDependencies.cmake)
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_subdirectory(src/fesa)
|
||||
add_subdirectory(tests)
|
||||
@@ -0,0 +1,74 @@
|
||||
set(
|
||||
FESA_GTEST_SOURCE_DIR
|
||||
""
|
||||
CACHE PATH
|
||||
"Path to the approved local GoogleTest source checkout"
|
||||
)
|
||||
|
||||
if(NOT FESA_GTEST_SOURCE_DIR)
|
||||
message(FATAL_ERROR "FESA_GTEST_SOURCE_DIR must name a local GoogleTest source checkout")
|
||||
endif()
|
||||
|
||||
get_filename_component(
|
||||
_fesa_gtest_source_dir
|
||||
"${FESA_GTEST_SOURCE_DIR}"
|
||||
ABSOLUTE
|
||||
BASE_DIR "${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
if(NOT EXISTS "${_fesa_gtest_source_dir}/CMakeLists.txt")
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"FESA_GTEST_SOURCE_DIR does not contain a GoogleTest CMakeLists.txt: "
|
||||
"${_fesa_gtest_source_dir}"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Keep GoogleTest on the same MSVC runtime as FESA without changing its source tree.
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "Use the shared MSVC runtime for GoogleTest" FORCE)
|
||||
add_subdirectory(
|
||||
"${_fesa_gtest_source_dir}"
|
||||
"${CMAKE_BINARY_DIR}/_deps/googletest-build"
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
|
||||
find_package(MKL CONFIG REQUIRED)
|
||||
find_package(TBB CONFIG REQUIRED COMPONENTS tbb)
|
||||
find_package(HDF5 CONFIG REQUIRED)
|
||||
|
||||
if(NOT TARGET MKL::MKL)
|
||||
message(FATAL_ERROR "The oneMKL CONFIG package did not define MKL::MKL")
|
||||
endif()
|
||||
|
||||
if(NOT TARGET TBB::tbb)
|
||||
message(FATAL_ERROR "The oneTBB CONFIG package did not define TBB::tbb")
|
||||
endif()
|
||||
|
||||
# Prefer the packaged shared C runtime when both variants exist. The Windows
|
||||
# static archive may carry compiler-runtime requirements that are not part of
|
||||
# the HDF5 imported target's transitive link interface.
|
||||
if(TARGET hdf5::hdf5-shared)
|
||||
set(_fesa_hdf5_target hdf5::hdf5-shared)
|
||||
elseif(TARGET hdf5::hdf5-static)
|
||||
set(_fesa_hdf5_target hdf5::hdf5-static)
|
||||
elseif(TARGET HDF5::HDF5)
|
||||
set(_fesa_hdf5_target HDF5::HDF5)
|
||||
else()
|
||||
message(FATAL_ERROR "The HDF5 CONFIG package did not define a supported C target")
|
||||
endif()
|
||||
|
||||
# Stable FESA-owned targets keep package-specific target names out of later modules.
|
||||
add_library(fesa_dependency_mkl INTERFACE)
|
||||
target_link_libraries(fesa_dependency_mkl INTERFACE MKL::MKL)
|
||||
add_library(Fesa::MKL ALIAS fesa_dependency_mkl)
|
||||
|
||||
add_library(fesa_dependency_tbb INTERFACE)
|
||||
target_link_libraries(fesa_dependency_tbb INTERFACE TBB::tbb)
|
||||
add_library(Fesa::TBB ALIAS fesa_dependency_tbb)
|
||||
|
||||
add_library(fesa_dependency_hdf5 INTERFACE)
|
||||
target_link_libraries(fesa_dependency_hdf5 INTERFACE "${_fesa_hdf5_target}")
|
||||
add_library(Fesa::HDF5 ALIAS fesa_dependency_hdf5)
|
||||
|
||||
unset(_fesa_gtest_source_dir)
|
||||
unset(_fesa_hdf5_target)
|
||||
+117
-17
@@ -6,18 +6,26 @@ FESA의 architecture decision은 solver correctness, verification traceability,
|
||||
---
|
||||
|
||||
### ADR-001: FESA는 구조해석 솔버 프로젝트이고 Harness는 운영 인프라로 둔다
|
||||
**결정**: 저장소의 주 목적은 유한요소법 기반 구조해석 솔버 개발이다. Harness scaffold는 phase execution, TDD guard, commit validation, workspace validation을 제공하는 보조 계층으로 유지한다.
|
||||
**결정**: 저장소의 주 목적은 유한요소법 기반 구조해석 솔버 개발이다. Harness는 승인된 Step 계획, 독립 세션 실행, PreToolUse guardrail, Stop MSVC build/test 검증을 제공하는 보조 계층으로 유지한다.
|
||||
|
||||
**이유**: 기존 문서가 Harness 중심이면 agent가 solver architecture, FEM verification, Abaqus/HDF5 계약보다 운영 스크립트에 과도하게 맞춰 행동한다.
|
||||
|
||||
**트레이드오프**: Harness 문서의 비중은 낮아지지만, 검증 명령과 hook 정책은 계속 필수 운영 규칙으로 유지한다.
|
||||
**트레이드오프**: Harness 문서의 비중은 낮아지지만, `docs/HARNESS_WORKFLOW.md`의 실행 계약과 `.codex/hooks.json`의 검증 정책은 계속 필수 운영 규칙으로 유지한다.
|
||||
|
||||
### ADR-002: C++17/MSVC/CMake/CTest를 기본 구현 환경으로 둔다
|
||||
**결정**: 기본 solver 구현과 validation은 C++17 이상, Visual Studio 17 2022 generator, x64 platform, Debug config, CMake, CTest로 수행한다.
|
||||
**결정**: 기본 solver 구현과 validation은 C++17 이상, Visual Studio 17 2022 또는
|
||||
Visual Studio 18 2026 generator, x64 platform, Debug config, CMake, CTest로 수행한다.
|
||||
`.harness/config.json`이 없으면 CMake가 설치된 두 승인 generator 중 하나를 자동
|
||||
선택할 수 있으며, build/test evidence에는 실제 generator와 compiler version을 기록한다.
|
||||
|
||||
**이유**: FESA의 목표 환경은 Windows/MSVC 기반 C++이다. CMake/CTest는 solver source tree가 추가되거나 확장될 때 가장 일관된 build/test entry point다.
|
||||
**이유**: FESA의 목표 환경은 Windows/MSVC 기반 C++이다. CMake/CTest는 solver source tree가 추가되거나 확장될 때 가장 일관된 build/test entry point다. VS17과 VS18을
|
||||
승인하면 현재 지원되는 MSVC 개발 환경에서 같은 C++17/x64/Debug 계약을 검증할 수 있다.
|
||||
|
||||
**트레이드오프**: Visual Studio solution-only workflow는 기본 지원하지 않는다. 필요하면 `HARNESS_VALIDATION_COMMANDS`로 override한다.
|
||||
**트레이드오프**: FESA solver source는 CMake/CTest를 기본으로 유지한다. Generator별
|
||||
compiler 차이는 각 build/test report에 명시하고, 두 generator 중 하나에서만 관찰되는
|
||||
실패를 다른 generator의 성공으로 숨기지 않는다. Harness 자체는 `.harness/config.json`에
|
||||
solution과 test command를 명시한 직접 MSBuild 프로젝트도 검증할 수 있지만, 이는 FESA
|
||||
제품이 solution-only workflow를 지원한다는 의미가 아니다.
|
||||
|
||||
### ADR-003: Abaqus `.inp` full compatibility가 아니라 기능별 keyword subset을 지원한다
|
||||
**결정**: FESA parser는 Abaqus keyword/data/comment line 규칙을 따르되, 기능별로 승인된 keyword subset만 지원한다. 미지원 keyword는 명확한 diagnostic을 남긴다.
|
||||
@@ -31,26 +39,26 @@ FESA의 architecture decision은 solver correctness, verification traceability,
|
||||
|
||||
**이유**: 모델 정의, step activation, equation system, transient/nonlinear state가 섞이면 parser, assembler, solver, result writer가 강하게 결합된다. 분리된 상태 모델은 선형 정적 해석에서 시작해 비선형, 동적, thermal coupling으로 확장하기 쉽다.
|
||||
|
||||
**트레이드오프**: 초기 class 수가 늘어난다. Phase 1에서는 interface를 얇게 유지하고 displacement 중심 state부터 구현한다.
|
||||
**트레이드오프**: 초기 class 수가 늘어난다. V0에서는 interface를 얇게 유지하고 실제 선형 정적 frame에 필요한 state만 구현한다.
|
||||
|
||||
### ADR-005: 공식 결과 파일은 HDF5로 하고 reference 결과는 Abaqus CSV로 둔다
|
||||
**결정**: FESA solver의 authoritative result output은 `results.h5` HDF5이다. Abaqus reference results는 `reference/<model-id>/` 아래 CSV 파일로 저장하며, verification은 FESA HDF5 rows와 Abaqus reference CSV rows를 documented IDs, components, units, coordinate system, step/frame identity, tolerance 기준으로 비교한다.
|
||||
**결정**: FESA solver의 authoritative result output은 `results.h5` HDF5이다. Abaqus reference results는 기능별 reference model contract가 지정한 `reference/<model-id>/` 아래 CSV 파일로 저장하며, verification은 FESA HDF5 rows와 Abaqus reference CSV rows를 documented IDs, components, units, coordinate system, step/frame identity, tolerance 기준으로 비교한다. 신규 reference는 canonical 파일명을 사용하고, 승인된 기존 bundle의 legacy alias는 해당 기능 계약에 정확한 경로를 기록한 경우에만 허용한다.
|
||||
|
||||
**이유**: 구조해석 결과는 step/frame, field/history, node/element/integration point location, units, coordinate system, schema version을 함께 가져야 한다. HDF5는 이 계층 구조와 metadata를 안정적으로 표현한다.
|
||||
|
||||
**트레이드오프**: reference comparison은 FESA HDF5 dataset identity와 Abaqus CSV row identity를 모두 관리해야 한다. FESA HDF5에서 추출한 deterministic CSV view는 디버깅/검토용 보조 artifact로 허용하지만, 공식 solver output이나 reference artifact로 취급하지 않는다.
|
||||
|
||||
### ADR-006: 해석 알고리즘과 수치 backend는 Strategy와 Adapter 경계 뒤에 둔다
|
||||
**결정**: `Analysis`, `LinearSolver`, `TimeIntegrator`, `ConvergenceCriteria`는 Strategy로 구성하고, MKL, TBB, HDF5 API는 adapter 계층 뒤에 둔다.
|
||||
**결정**: `Analysis`, `LinearSolver`, `TimeIntegrator`, `ConvergenceCriteria`는 Strategy로 구성하고, MKL, TBB, HDF5 API는 adapter 계층 뒤에 둔다. `Vector`는 contiguous `double`, `Matrix`는 row-major contiguous `double`을 소유하고 dense 연산은 MKL CBLAS를 사용한다. `SparseMatrix`는 이들과 상속 관계가 없는 0-based CSR 전용 타입이며, PARDISO factorization과 substitution은 `LinearSolver` 경계 뒤에서 분리한다.
|
||||
|
||||
**이유**: 선형 정적, 비선형 정적, 동적, frequency, heat transfer 해석은 공통 흐름을 공유하지만 알고리즘과 backend가 다르다. 외부 API를 core에 노출하면 테스트 double, backend 교체, dependency review가 어려워진다.
|
||||
|
||||
**트레이드오프**: 단일 기능만 구현할 때는 adapter가 다소 장황해 보일 수 있다. 하지만 solver backend와 result writer는 장기적으로 교체 가능해야 한다.
|
||||
**트레이드오프**: 단일 기능만 구현할 때는 adapter가 다소 장황해 보일 수 있다. Row-major dense storage와 CSR sparse storage를 따로 유지해야 하지만 backend 의존성과 dense/sparse 의미가 core 모델에 섞이지 않는다.
|
||||
|
||||
### ADR-007: Analysis 실행 흐름은 Template Method로 고정한다
|
||||
**결정**: `Analysis::run()`은 `initialize -> buildAnalysisModel -> buildDofMap -> buildSparsePattern -> assemble -> applyBoundaryConditions -> solve -> updateState -> writeResults` 흐름을 고정한다.
|
||||
**결정**: `Analysis::run()`은 공통 lifecycle을 고정한다. 선형 정적 V0의 순서는 `parse input -> initialize Domain -> build AnalysisModel -> build DOF map/sparse pattern -> assemble stiffness -> partition constraints -> factorize Kff -> assemble load -> form effective RHS -> substitute -> reconstruct displacement -> recover results -> write HDF5`다. 강성행렬 factorization은 하중벡터 조립보다 먼저 수행하고, factorization과 substitution을 하나의 불투명한 solve 호출로 합치지 않는다.
|
||||
|
||||
**이유**: 해석 procedure가 늘어나도 공통 실행 순서가 유지되어야 검증, logging, result writing, failure classification이 일관된다.
|
||||
**이유**: 해석 procedure가 늘어나도 공통 실행 순서가 유지되어야 검증, logging, result writing, failure classification이 일관된다. Factorization과 substitution을 분리하면 동일 강성행렬에 여러 RHS를 적용할 수 있고 각 실패 단계를 구조화된 diagnostic으로 분류할 수 있다.
|
||||
|
||||
**트레이드오프**: 특수 해석 절차가 공통 흐름에 맞지 않는 경우 hook point가 필요하다. 초기에는 선형 정적 해석을 기준으로 최소 hook만 둔다.
|
||||
|
||||
@@ -69,15 +77,107 @@ FESA의 architecture decision은 solver correctness, verification traceability,
|
||||
**트레이드오프**: 초기 병렬화 범위가 제한된다. MKL 내부 thread와 TBB task arena의 oversubscription 정책을 별도로 문서화해야 한다.
|
||||
|
||||
### ADR-010: Abaqus reference artifact는 사람이 생성하거나 명시 승인된 절차로만 갱신한다
|
||||
**결정**: Agent는 Abaqus, Nastran 또는 reference solver를 직접 실행하지 않는다. reference artifact 생성, 수정, 복원은 명시 승인된 phase에서만 수행하고 provenance를 `metadata.json`에 기록한다.
|
||||
**결정**: Agent는 Abaqus, Nastran 또는 reference solver를 직접 실행하지 않는다. reference artifact 생성, 수정, 복원은 명시 승인된 phase에서만 수행한다. 신규 bundle의 provenance는 `metadata.json`에 기록한다. 승인된 `cantilever-beam-b33` legacy baseline은 source commit과 generator, units, coordinate system, schema, tolerance를 설계 및 Reference Model Contract가 대신 기록하므로 이 baseline에 한해서 `metadata.json`과 `README.md`가 N/A다.
|
||||
|
||||
**이유**: reference 결과는 solver correctness의 기준이다. 생성 절차가 불명확하면 구현 결함과 reference artifact 오류를 구분할 수 없다.
|
||||
|
||||
**트레이드오프**: reference 준비가 느려질 수 있다. 대신 검증 기준의 신뢰도와 감사 가능성이 높아진다.
|
||||
**트레이드오프**: reference 준비가 느려질 수 있다. Legacy 예외는 일반 artifact 규칙을 복잡하게 하지만 exact path와 source commit을 고정하고 read-only로 취급해 감사 가능성을 유지한다.
|
||||
|
||||
### ADR-011: C++ production 변경은 TDD guard와 workspace validation을 통과해야 한다
|
||||
**결정**: C++ production file 변경은 관련 C++ test file이 없으면 차단한다. 기본 검증은 `python -m unittest discover -s scripts -p "test_*.py"`와 `python scripts/validate_workspace.py`를 사용한다.
|
||||
### ADR-011: 구형 단일 검증 진입점 계약을 폐기한다
|
||||
|
||||
**이유**: FEM solver 결함은 작은 부호, DOF ordering, integration rule 오류에서도 발생한다. 테스트 없는 변경을 막아야 reference validation 이전 단계에서 회귀를 줄일 수 있다.
|
||||
**상태**: ADR-012로 대체됨.
|
||||
|
||||
**트레이드오프**: 초기 scaffolding 작업에서 guard가 엄격하게 느껴질 수 있다. 문서, CMake 설정, Harness metadata는 guard 대상에서 제외한다.
|
||||
**결정**: 삭제된 legacy validation entry point, legacy Python test discovery, 환경 변수 기반 command override를 Harness의 기본 검증 계약으로 사용하지 않는다.
|
||||
|
||||
### ADR-012: Harness는 계획, 실행, Hook 검증의 세 계층으로 운영한다
|
||||
|
||||
**결정**: 계획은 `.agents/skills/harness`, Step 실행과 Git 상태 관리는 `scripts/execute.py`, 도구 호출 전 정책과 종료 전 검증은 `.codex/hooks.json`에 연결된 `scripts/hooks/`가 담당한다. C++ production 변경은 관련 테스트 파일이 있어야 하며, 실제 RED 실패와 GREEN 성공은 같은 Step 안에서 확인한다. Stop은 `.harness/config.json` 또는 자동 감지 결과로 전체 MSVC build/test를 검증한다. Harness Python 변경은 `uv run --with pytest python -m pytest -v -rs`로 검증한다.
|
||||
|
||||
**이유**: 테스트 파일 존재 검사, TDD 실행 증거, 전체 build/test는 서로 다른 책임이다. 이를 분리하면 Hook이 보장하는 범위를 과장하지 않으면서 Step 종료 시 green 상태를 강제할 수 있다.
|
||||
|
||||
**트레이드오프**: PreToolUse만으로 구현 전 RED 실행을 증명할 수 없으므로 Implementation report에 RED/GREEN 명령과 결과를 기록해야 한다. C/C++가 없는 저장소는 Stop이 통과하므로 Harness Python 검증은 별도 acceptance command로 유지한다.
|
||||
|
||||
### ADR-013: V0 선형 정적 해석은 단일 step B33 Euler beam으로 제한한다
|
||||
|
||||
**결정**: 첫 end-to-end 제품 기능은 입력 파일당 하나의 `*STEP, *STATIC`을 해석하는 2절점 3D Euler–Bernoulli beam이다. Abaqus `TYPE=B33`만 이 요소로 매핑하고 B31은 `unsupported-element-formulation`으로 거부한다. `*PART/*ASSEMBLY/*INSTANCE`는 여러 identity instance와 stable source identity를 지원하지만 instance transform, nested assembly, 다중 step은 지원하지 않는다. Output-request keyword는 승인 allowlist에서 warning 후 no-op 처리하고 FESA 기본 HDF5 결과는 항상 생성한다.
|
||||
|
||||
**이유**: B31은 transverse shear deformation을 포함하므로 Euler–Bernoulli 정식화와 의미가 다르다. 단일 step과 identity instance로 범위를 제한하면 parser wrapper, source identity, assembly, 해법 및 결과 복구를 end-to-end로 검증하면서 의미를 왜곡하지 않는다.
|
||||
|
||||
**트레이드오프**: 기존 Abaqus 모델 중 B31, instance transform, 다중 step 또는 `*DLOAD`를 사용하는 입력은 거부된다. 이후 기능은 별도 요구조건과 formulation/reference gate를 거쳐 추가한다.
|
||||
|
||||
### ADR-014: B33 cantilever baseline은 component-scale 혼합 tolerance로 비교한다
|
||||
|
||||
**결정**: `reference/cantilever beam/`의 B33 input, displacement CSV, reaction CSV, elemental-force CSV를 V0 reference baseline으로 사용한다. Displacement와 reaction은 node identity로, section resultant는 CSV node station과 정규화된 FESA element endpoint로 비교한다. 같은 model, step/frame, quantity, component에 대해 `reference_scale = max(abs(reference rows))`를 계산하고 모든 row에 `absolute_floor + 1e-6 * reference_scale`을 적용한다. SI displacement/rotation absolute floor는 `1e-9`, force/moment floor는 `1e-3`이다. Beam stress는 출력하되 Abaqus stress reference comparison은 N/A다.
|
||||
|
||||
**이유**: 자유단 moment처럼 이론적으로 0인 값에는 행별 상대오차가 정의되지 않으며 Abaqus 결과에 작은 수치 잔차가 남을 수 있다. Component scale을 사용하면 전체 물리량 크기에 비해 작은 잔차를 허용하면서 각 row를 결정적으로 판정할 수 있다.
|
||||
|
||||
**트레이드오프**: 큰 component scale은 zero row의 허용폭을 넓힌다. 이를 완화하기 위해 quantity와 component를 섞지 않고 Abaqus 값만 scale에 사용하며, 모든 row의 absolute/normalized error와 worst row를 보고하고 누락·추가·nonfinite row를 tolerance 전에 실패시킨다.
|
||||
|
||||
### ADR-015: 외부 CMake target을 FESA 경계로 정규화하고 Windows runtime closure를 명시한다
|
||||
|
||||
**결정**: MKL, TBB, HDF5 CONFIG package가 제공하는 target은 dependency module에서
|
||||
`Fesa::MKL`, `Fesa::TBB`, `Fesa::HDF5`로 정규화한다. Product target은 이 경계만
|
||||
`PRIVATE` link하고 public header에 vendor/Win32 type을 노출하지 않는다. Approved Windows
|
||||
환경에서는 packaged shared HDF5 C target을 우선하며, CLI와 test executable 옆에 TBB,
|
||||
MKL, OpenMP, Intel math runtime, HDF5를 포함한 실제 runtime DLL closure를 POST_BUILD로
|
||||
stage한다.
|
||||
|
||||
**이유**: Package version이나 shared/static variant에 따라 imported target 이름과 숨은
|
||||
runtime dependency가 달라질 수 있다. Configure와 link 성공만 확인하면 GoogleTest
|
||||
discovery 또는 배포된 CLI가 `0xc0000135`로 실패할 수 있다. FESA-owned target과 명시적
|
||||
runtime closure는 module code와 실행 환경을 package 세부사항에서 분리한다.
|
||||
|
||||
**트레이드오프**: Windows staging CMake가 길어지고 새 dynamic dependency마다 runtime
|
||||
audit가 필요하다. 대신 개인 설치 경로를 source에 하드코딩하거나 developer `PATH`에
|
||||
의존하지 않고 build tree executable을 재현 가능하게 실행할 수 있다.
|
||||
|
||||
### ADR-016: 결정론과 failure atomicity를 correctness contract로 취급한다
|
||||
|
||||
**결정**: Parallel element 계산은 index별 독립 buffer만 쓰고, COO tuple ordering과
|
||||
floating-point sum은 join 이후 고정된 serial 순서로 수행한다. Result recovery, solver
|
||||
output, HDF5 writer는 candidate를 완성·검증한 뒤 caller-owned state 또는 final file에
|
||||
commit한다. HDF5는 same-directory temporary file을 checked close/reopen한 후에만 atomic
|
||||
finalization한다.
|
||||
|
||||
**이유**: Reference comparison과 물리 검토는 row identity와 작은 수치 차이에 민감하다.
|
||||
Thread scheduling 또는 중간 실패가 sparse bytes, result order, 이전 output을 바꾸면 같은
|
||||
입력에 대한 evidence를 신뢰할 수 없다.
|
||||
|
||||
**트레이드오프**: Serial reduction과 candidate copy가 throughput과 memory를 더 사용할 수
|
||||
있다. 성능 최적화는 동일한 ordering, failure preservation, reference 결과를 증명할 때만
|
||||
대체할 수 있으며, nondeterministic global sparse write는 허용하지 않는다.
|
||||
|
||||
### ADR-017: Essential constraint는 stable elimination으로 적용하고 reaction은 full residual로 정의한다
|
||||
|
||||
**결정**: V0는 DofManager의 stable free/constrained order로 full stiffness를
|
||||
`Kff/Kfc/Kcf/Kcc`로 분할하고 `Kff * df = Ff - Kfc * dc`를 푼 뒤 full displacement를
|
||||
복구한다. 모든 DOF가 constrained인 모델의 `0 x 0 Kff`는 유효한 trivial factorization과
|
||||
empty substitution이다. Recovery의 full residual `r = K*d - F`를 reaction vector로
|
||||
보존하며 constrained entry는 physical reaction, free entry는 equilibrium evidence다.
|
||||
|
||||
**이유**: Equation numbering과 prescribed displacement를 한 owner가 관리하면 nonzero
|
||||
constraint, no/all/mixed constraint가 같은 수식과 stable order를 사용한다. Full residual은
|
||||
element end action을 별도로 합산하는 경로보다 조립·하중·해법 전체의 equilibrium을 직접
|
||||
검증한다.
|
||||
|
||||
**트레이드오프**: Full K와 네 partition을 유지하는 메모리 비용이 있고 reaction vector의
|
||||
free entry가 정확한 0이라고 가정할 수 없다. V0에는 penalty, MPC, Lagrange multiplier를
|
||||
혼합하지 않으며, 추가 constraint policy는 별도 formulation과 equation/output 계약을
|
||||
요구한다.
|
||||
|
||||
### ADR-018: Kernel 존재와 제품 노출을 분리하고 계층형 검증을 요구한다
|
||||
|
||||
**결정**: Local element/load/recovery kernel이 존재해도 syntax, semantic Domain mapping,
|
||||
analysis orchestration, mandatory HDF5와 diagnostic 계약이 연결되지 않으면 CLI 지원으로
|
||||
간주하지 않는다. 검증은 unit, integration, reference comparison, physics sanity를 서로
|
||||
대체할 수 없는 계층으로 유지한다. Reference가 가능하지 않은 quantity는 명시적 N/A와
|
||||
analytical/schema/physics 대체 evidence를 요구한다.
|
||||
|
||||
**이유**: Unit test는 수식과 validation을, integration test는 lifetime과 호출 순서를,
|
||||
reference comparison은 외부 solver와의 수치 일치를, physics sanity는 공통-mode 오류와
|
||||
model adequacy를 검출한다. 한 계층의 성공만으로 parser exposure 또는 물리 correctness를
|
||||
추론하면 지원 범위와 검증 강도가 과장된다.
|
||||
|
||||
**트레이드오프**: 작은 기능도 여러 계약과 evidence를 함께 준비해야 하므로 개발 속도가
|
||||
느려진다. 대신 `*DLOAD`처럼 kernel은 있지만 입력에 노출되지 않은 기능, stress처럼
|
||||
mandatory output이지만 Abaqus reference가 N/A인 기능을 정확하게 표현할 수 있다.
|
||||
|
||||
+262
-175
@@ -9,206 +9,278 @@ FESA의 아키텍처 목표는 Abaqus `.inp` subset을 내부 semantic model로
|
||||
- sparse linear algebra backend isolation
|
||||
- deterministic verification
|
||||
- incremental feature addition
|
||||
- Harness 기반 TDD와 workspace validation
|
||||
- Harness 기반 TDD
|
||||
|
||||
## 디렉토리 구조
|
||||
현재 승인된 V0 end-to-end 기능은 `linear-static-3d-euler-beam`이다. 상세 계약의
|
||||
source of truth는
|
||||
`docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md`이며, 이 문서는
|
||||
그 계약을 전체 solver architecture의 모듈과 데이터 흐름에 배치한다. 아래에 나타난
|
||||
비선형, 동적, thermal 및 다른 element 계층은 장기 확장 경계이며 V0 지원 범위가 아니다.
|
||||
|
||||
## 현재 구현된 디렉토리 구조
|
||||
```text
|
||||
include/fesa/ # backend-neutral public C++ API
|
||||
src/
|
||||
fesa/
|
||||
core/ # ids, status, diagnostics, units, small value types
|
||||
analysis/ # Analysis lifecycle, V0 LinearStaticAnalysis
|
||||
app/ # CLI application and main
|
||||
assembly/ # deterministic stiffness/load assembly, ParallelFor adapter
|
||||
constraints/ # essential-constraint elimination and reconstruction
|
||||
core/ # source identity, status, diagnostics
|
||||
elements/ # V0 EulerBeam3D kernel and recovery
|
||||
fem/ # DOF/equation numbering and sparse pattern
|
||||
io/
|
||||
abaqus/ # .inp lexer/parser, keyword subset, include policy
|
||||
hdf5/ # HDF5 result writer/reader, schema versioning
|
||||
model/ # semantic model: nodes, elements, sets, materials, sections, steps
|
||||
fem/ # DOF space, equation numbering, quadrature, shape functions
|
||||
elements/ # truss/bar, beam, plane, solid, shell element routines
|
||||
materials/ # elastic/plastic material contracts and state variables
|
||||
assembly/ # local-to-global mapping, sparse pattern, COO/CSR assembly
|
||||
constraints/ # essential BC, MPC, penalty or elimination policies
|
||||
abaqus/ # .inp syntax reader and semantic Domain mapper
|
||||
hdf5/ # private HDF5 writer and atomic finalization
|
||||
math/ # owning Vector, row-major Matrix, 0-based CSR SparseMatrix
|
||||
model/ # concrete V0 semantic records and immutable Domain
|
||||
results/ # recovery records, full residual, ResultsWriter boundary
|
||||
solvers/
|
||||
linear/ # MKL PARDISO backend, iterative backend boundary
|
||||
nonlinear/ # Newton control, residual/tangent norms, increments
|
||||
analysis/ # static, modal, dynamic, nonlinear procedure drivers
|
||||
results/ # recovery, field/history output, diagnostics
|
||||
validation/ # comparison metrics and tolerance helpers
|
||||
linear/ # LinearSolver interface and MKL PARDISO adapter
|
||||
tests/
|
||||
unit/
|
||||
integration/
|
||||
reference/
|
||||
unit/ # local contracts and failure paths
|
||||
integration/ # analysis orchestration and CLI contracts
|
||||
reference/ # HDF5-to-Abaqus projection and comparison
|
||||
reference/
|
||||
<model-id>/
|
||||
model.inp
|
||||
metadata.json
|
||||
<model-id>_displacements.csv
|
||||
<model-id>_reactions.csv
|
||||
<model-id>_internalforces.csv
|
||||
<model-id>_stresses.csv
|
||||
<model-id>/ # approved read-only Abaqus input/CSV bundle
|
||||
.agents/
|
||||
skills/ # Harness and review skills
|
||||
.codex/
|
||||
hooks/ # Codex hook scripts
|
||||
skills/ # FESA solver and Harness instructions
|
||||
hooks.json # PreToolUse/Stop hook registration
|
||||
agents/ # FESA workflow custom agents
|
||||
skills/ # FESA solver workflow skills
|
||||
docs/ # Product, architecture, ADR, workflow artifacts
|
||||
scripts/
|
||||
execute.py # Phase step executor
|
||||
validate_workspace.py # Default validation entry point
|
||||
test_*.py # Harness self-tests
|
||||
hooks/ # PreToolUse/Stop hook implementations
|
||||
msvc_harness/ # MSVC project discovery and validation adapters
|
||||
phases/ # Optional generated phase plans
|
||||
```
|
||||
|
||||
`materials/`, nonlinear/dynamic analysis, MPC/penalty policies, general element factories,
|
||||
history output과 production validation module은 장기 확장 경계이지 현재 구현된 module이
|
||||
아니다. 새 디렉토리와 추상 계층은 승인된 기능이 실제로 필요로 할 때 추가한다.
|
||||
|
||||
## Harness Execution Layer
|
||||
`scripts/execute.py`:
|
||||
- creates or checks out `codex/<phase-name>`
|
||||
- refuses to run on a dirty worktree
|
||||
- requires per-step `allowed_paths`
|
||||
- stages only explicit allowed paths and runner housekeeping files
|
||||
- runs Python Harness self-tests and workspace validation before every runner-created commit
|
||||
|
||||
Harness는 solver core와 분리된 세 계층의 개발 운영 인프라다.
|
||||
|
||||
- 계획 계층: `.agents/skills/harness`가 사용자 승인 전 Step 초안을 만들고, 승인 후 `phases/` 파일을 생성한다.
|
||||
- 실행 계층: `scripts/execute.py`가 `feat-<phase-name>` 브랜치에서 Step마다 독립 Codex 세션을 실행하고 상태와 커밋을 관리한다.
|
||||
- 검증 계층: `.codex/hooks.json`이 `scripts/hooks/pre_tool_use.py`와 `scripts/hooks/stop_validation.py`를 연결한다. Stop 검증은 `scripts/msvc_harness/`를 통해 MSVC build와 test를 실행한다.
|
||||
|
||||
Runner는 `git add -A`를 사용하므로 clean worktree 또는 별도 Git worktree가 실행 전제다. 전체 동작 계약은 `docs/HARNESS_WORKFLOW.md`, 설치와 `.harness/config.json` 설정은 `docs/HARNESS.md`를 source of truth로 삼는다.
|
||||
|
||||
## CMake target과 dependency graph
|
||||
|
||||
Root CMake project는 C++17, extension off, CMake 3.25 이상을 요구하고
|
||||
`cmake/FesaDependencies.cmake`, `src/fesa`, `tests`를 차례로 구성한다.
|
||||
|
||||
```text
|
||||
MKL CONFIG package ─> Fesa::MKL ─┐
|
||||
TBB CONFIG package ─> Fesa::TBB ─┼─> fesa_solver (STATIC) ─> fesa_cli
|
||||
HDF5 CONFIG package ─> Fesa::HDF5 ─┘ │
|
||||
├─> fesa_unit_tests
|
||||
approved local GoogleTest source ─> GTest targets ├─> fesa_integration_tests
|
||||
└─> fesa_reference_tests
|
||||
```
|
||||
|
||||
- `FESA_GTEST_SOURCE_DIR`는 네트워크 fetch 대신 승인된 local GoogleTest source checkout을 가리키는 필수 cache path다.
|
||||
- MKL, TBB, HDF5는 CONFIG package로 탐지한다. Package search가 설치를 찾지 못하면 `MKL_DIR`, `TBB_DIR`, `HDF5_DIR`를 configure 때 지정한다.
|
||||
- Package별 imported target 이름은 `Fesa::MKL`, `Fesa::TBB`, `Fesa::HDF5`로 정규화한다. Product module은 vendor target 이름을 직접 선택하지 않는다.
|
||||
- HDF5 package가 shared와 static C target을 모두 제공하면 approved Windows environment에서는 shared target을 우선한다. Static archive의 숨은 compiler-runtime 요구가 link interface 밖으로 새는 것을 피하기 위한 결정이다.
|
||||
- `fesa_solver`는 외부 dependency를 `PRIVATE`으로 link하고 `/W4 /WX`를 사용한다. 따라서 public header는 MKL/TBB/HDF5/Win32 type을 포함하지 않아야 한다.
|
||||
- Test executable은 unit, integration, reference 경계를 분리하며 `fesa_tests` target은 세 executable을 build하는 aggregate target이다. Reference target에만 source/build root compile definition을 제공한다.
|
||||
|
||||
### Windows runtime closure
|
||||
|
||||
Configure 성공은 executable이 GoogleTest discovery 또는 CLI 실행 시 필요한 DLL을 찾는다는
|
||||
뜻이 아니다. `fesa_cli`와 세 test executable의 POST_BUILD 단계는 TBB, MKL thread/core/default
|
||||
dispatch, OpenMP, `libmmd.dll`, HDF5를 포함한 imported-target runtime DLL을 executable 옆에
|
||||
복사한다. 새 dynamic backend를 도입할 때는 link 성공뿐 아니라 clean environment에서의
|
||||
post-build discovery/실행까지 runtime closure로 다뤄야 한다. 개인 설치 absolute path를
|
||||
CMake source에 기록하지 말고 config package와 imported target metadata를 확장한다.
|
||||
|
||||
## 모듈 경계
|
||||
- `core`는 외부 라이브러리에 의존하지 않는다.
|
||||
- `io/abaqus`는 syntax와 semantic mapping만 담당하고 해석 알고리즘을 알지 않는다.
|
||||
- `model`은 Abaqus keyword 문자열이 아니라 solver semantic model을 가진다.
|
||||
- `fem`은 DOF, interpolation, quadrature, local/global mapping을 제공하되 특정 analysis procedure에 종속되지 않는다.
|
||||
- `elements`와 `materials`는 local residual/tangent/stress recovery 계약을 제공한다.
|
||||
- `assembly`는 sparse pattern 생성과 local contribution 조립을 담당한다.
|
||||
- `constraints`는 essential BC, MPC, penalty/elimination 정책을 분리한다.
|
||||
- `solvers`는 MKL/TBB 세부 구현을 감추는 backend boundary를 가진다.
|
||||
- `fem`의 `DofManager`는 DOF, equation ordering, scatter와 sparse pattern을 소유한다.
|
||||
- `elements`는 local/global stiffness, transformation, optional load kernel과 recovery를 제공한다. V0 material/section은 concrete Domain record다.
|
||||
- `assembly`는 element-local contribution과 full nodal load를 stable full-DOF space에 조립한다.
|
||||
- `constraints`는 V0 essential BC elimination과 full/reduced vector 변환을 담당한다. MPC와 penalty는 현재 범위가 아니다.
|
||||
- `solvers`는 `LinearSolver` 뒤에 MKL PARDISO 세부 구현을 감춘다. TBB는 `assembly/ParallelFor`, HDF5는 `results/ResultsWriter` 경계 뒤에 각각 격리된다.
|
||||
- `analysis`는 step/history data를 받아 procedure를 실행하고 solver backend와 result writer를 조율한다.
|
||||
- `results`는 HDF5 schema를 통해 nodal, element, integration-point, diagnostic output을 분리한다.
|
||||
- `results`는 full residual과 beam rows를 복구하고 backend-neutral writer contract를 제공한다. HDF5 schema 구현은 `io/hdf5`가 담당한다.
|
||||
- test helper는 production parser/solver 내부 상태를 우회하지 않는다.
|
||||
|
||||
## V0 입력 경계
|
||||
|
||||
V0 parser는 keyword와 parameter를 case-insensitive하게 해석하되 source label의 원문을
|
||||
보존한다. 지원하는 model/procedure 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`
|
||||
|
||||
Part 내부 label은 `SourceEntityId { instance_name, source_label }`로 보존하고 Domain은
|
||||
별도 stable internal index를 부여한다. 같은 part의 여러 identity instance는 허용하지만
|
||||
translation/rotation data와 nested assembly는 구조화된 unsupported diagnostic으로
|
||||
거부한다. 입력 파일당 하나의 static step만 허용하고 두 번째 step은 오류다.
|
||||
|
||||
`*PREPRINT`, `*RESTART`, `*TRANSVERSE SHEAR STIFFNESS`, `*OUTPUT, FIELD`,
|
||||
`*OUTPUT, HISTORY`, `*NODE OUTPUT`, `*ELEMENT OUTPUT`, `*CONTACT OUTPUT` 및 그에 속한
|
||||
미지원 output variable data는 warning 후 no-op 처리한다. 이 allowlist 밖의 미지원
|
||||
model-affecting keyword는 오류다. FESA output은 Abaqus output request에 좌우되지 않는다.
|
||||
|
||||
## V0 beam과 section 계약
|
||||
|
||||
`EulerBeam3D`는 2절점과 절점당 `[UX, UY, UZ, URX, URY, URZ]` 6 DOF를 사용하며 축,
|
||||
두 방향 Euler–Bernoulli 굽힘과 Saint-Venant 비틀림을 제공한다. Beam tangent를 local
|
||||
`x`, Abaqus first section axis `n1`을 local `y`, `t x n1`을 local `z`로 둔다.
|
||||
`*BEAM GENERAL SECTION`의 `A, I11, I12, I22, J`는 `Iy=I11`, `Iz=I22`로 매핑하고
|
||||
V0는 `I12=0`만 허용한다. `E`, `G`, `A`, `Iy`, `Iz`, `J`는 양수여야 하며 zero-length
|
||||
element와 tangent에 평행한 guide vector를 scale-aware tolerance로 거부한다.
|
||||
|
||||
요소 API는 stiffness, transformation, load와 recovery 책임을 분리한다.
|
||||
|
||||
```cpp
|
||||
Matrix localStiffness() const;
|
||||
Matrix globalStiffness() const;
|
||||
Vector localEquivalentLoad(const ConstantLocalLineLoad& load) const;
|
||||
BeamRecovery recover(const Vector& globalElementDisplacement) const;
|
||||
```
|
||||
|
||||
`localEquivalentLoad`는 formulation의 constant local line-load kernel을 unit test하기
|
||||
위한 계약이다. V0 parser는 `*DLOAD`나 distributed-load Domain object를 생성하지 않으므로
|
||||
CLI pipeline에서는 이 kernel을 호출하지 않는다. Stiffness와 recovery는 formulation의
|
||||
2점 Gauss rule과 부호 규약을 따른다.
|
||||
|
||||
## 핵심 객체 모델
|
||||
|
||||
```text
|
||||
Domain
|
||||
├── Node
|
||||
├── Element
|
||||
├── Material
|
||||
├── Property
|
||||
├── NodeSet
|
||||
├── ElementSet
|
||||
├── BoundaryCondition
|
||||
├── Load
|
||||
└── StepDefinition
|
||||
├── owns nodes, B33 elements, materials, beam sections, sets
|
||||
├── owns boundary conditions, nodal loads, one static step
|
||||
└── owns source path/identity and mapping warnings
|
||||
|
||||
AnalysisModel
|
||||
├── active elements
|
||||
├── active loads
|
||||
├── active boundary conditions
|
||||
├── active properties/materials
|
||||
└── equation system view
|
||||
├── non-owning view into Domain
|
||||
├── stable active element/BC/load indices
|
||||
└── reachable material/section indices
|
||||
|
||||
DofManager
|
||||
├── owns node x [UX,UY,UZ,URX,URY,URZ] full-DOF numbering
|
||||
├── owns stable free/constrained order and prescribed values
|
||||
├── owns element scatter maps
|
||||
└── owns full-space CSR structural pattern
|
||||
|
||||
AnalysisState
|
||||
├── displacement U
|
||||
├── velocity V
|
||||
├── acceleration A
|
||||
├── temperature T
|
||||
├── external force Fext
|
||||
├── internal force Fint
|
||||
├── residual R
|
||||
├── current time / increment / iteration
|
||||
└── element state / integration point state
|
||||
|
||||
DofManager
|
||||
├── node dof definitions
|
||||
├── constrained/free dof mapping
|
||||
├── equation numbering
|
||||
├── sparse matrix pattern ownership
|
||||
└── full/reduced vector reconstruction
|
||||
├── residual R and full-index reaction
|
||||
├── StepFrameIdentity
|
||||
└── endpoint, Gauss and S11 recovery rows
|
||||
|
||||
Analysis
|
||||
├── LinearStaticAnalysis
|
||||
├── NonlinearStaticAnalysis
|
||||
├── DynamicAnalysis
|
||||
├── FrequencyAnalysis
|
||||
└── HeatTransferAnalysis
|
||||
└── LinearStaticAnalysis
|
||||
|
||||
Element
|
||||
├── Element1D
|
||||
│ ├── Truss
|
||||
│ └── Beam
|
||||
├── Element2D
|
||||
│ ├── MITC3
|
||||
│ └── MITC4
|
||||
└── Element3D
|
||||
├── Hexahedral
|
||||
├── Tetrahedral
|
||||
├── Wedge
|
||||
└── Pyramid
|
||||
|
||||
BoundaryCondition
|
||||
├── Fix
|
||||
├── RBE2
|
||||
└── RBE3
|
||||
|
||||
Load
|
||||
├── NodalLoad
|
||||
├── PressureLoad
|
||||
└── BodyForce
|
||||
|
||||
Results
|
||||
├── ResultStep
|
||||
├── ResultFrame
|
||||
├── FieldOutput
|
||||
└── HistoryOutput
|
||||
Vector
|
||||
Matrix
|
||||
SparseMatrix
|
||||
```
|
||||
|
||||
Nonlinear/static, dynamic, frequency, heat-transfer procedure와 general element/material/load
|
||||
base hierarchy는 이 구조 위의 가능한 확장 방향일 뿐 현재 public API가 아니다. 사용 사례가
|
||||
승인되기 전에 V0 concrete record를 speculative hierarchy로 감싸지 않는다.
|
||||
|
||||
## 상태 관리
|
||||
- `Domain`은 입력 파일에서 만들어진 전체 모델 정의를 소유한다. 파싱 이후에는 가능한 한 불변으로 취급한다.
|
||||
- `AnalysisModel`은 현재 step에서 활성화되는 해석 객체들의 실행 view이다. `Domain`을 복사하지 않고 참조 또는 id 기반 view로 구성한다.
|
||||
- `LinearStaticAnalysis`가 `Domain`을 소유하고, 그 뒤에 `AnalysisModel`, `DofManager`, `AnalysisState`, stiffness/RHS를 순서대로 만든다. 재사용 시에는 역순으로 해제하여 이전 Domain을 가리키는 view를 남기지 않는다.
|
||||
- `AnalysisModel`은 현재 step에서 활성화되는 해석 객체들의 실행 view이다. `Domain`을 복사하지 않으므로 Domain이 반드시 더 오래 살아야 한다.
|
||||
- `DofManager`는 자유도와 방정식 번호를 전담한다. `Node` 또는 `Element` 내부에 equation id를 분산 저장하지 않는다.
|
||||
- `AnalysisState`는 해석 중 변하는 물리량과 반복 상태를 소유한다. Phase 1에서는 displacement 중심으로 최소 구현하되, 기하비선형과 thermal-stress coupling을 위해 element/internal state 확장 지점을 유지한다.
|
||||
- 결과는 `ResultStep` -> `ResultFrame` -> `FieldOutput`/`HistoryOutput` 구조로 관리한다.
|
||||
- `AnalysisState`는 V0 frame에 필요한 다섯 full-DOF vector와 recovery rows만 소유한다. Velocity, acceleration, temperature, iteration history, nonlinear element state는 해당 procedure가 승인될 때 별도 계약으로 추가한다.
|
||||
- Result recovery는 모든 candidate vector/row를 검증한 뒤 state에 반영한다. 실패한 recovery가 앞선 유효 state를 부분적으로 덮어쓰지 않아야 한다.
|
||||
|
||||
## 데이터 흐름
|
||||
```text
|
||||
Abaqus input file
|
||||
-> InputParser
|
||||
-> Domain 생성
|
||||
-> StepDefinition 루프
|
||||
-> AnalysisModel 생성
|
||||
-> DofManager로 자유도/방정식 번호 생성
|
||||
-> sparse pattern 생성
|
||||
-> Analysis 실행
|
||||
-> Assembler로 전역 행렬/벡터 조립
|
||||
-> BoundaryCondition 적용
|
||||
-> LinearSolver 또는 nonlinear/time integration loop
|
||||
-> AnalysisState 갱신
|
||||
-> ResultsWriter로 step/frame/history 저장
|
||||
-> 다음 step 진행
|
||||
-> syntax parse and semantic mapping
|
||||
-> immutable Domain 생성
|
||||
-> 단일 step AnalysisModel view 생성
|
||||
-> DofManager DOF/scatter map/sparse pattern 생성
|
||||
-> element stiffness 계산과 deterministic COO-to-CSR 조립
|
||||
-> free/constrained partition 생성
|
||||
-> LinearSolver::factorize(Kff)
|
||||
-> full nodal load vector 조립
|
||||
-> effective RHS = Ff - Kfc * dc
|
||||
-> LinearSolver::solve(rhs, df) substitution
|
||||
-> full displacement 복구
|
||||
-> full residual/reaction = K*d - F 및 element result 복구
|
||||
-> ResultsWriter로 results.h5 atomic finalization
|
||||
```
|
||||
|
||||
강성행렬 factorization은 하중벡터 조립보다 먼저 수행한다. 반력은 element end action의
|
||||
별도 합이 아니라 조립된 전체 residual에서 구한다. Constrained component는 physical
|
||||
reaction이고 free component는 equilibrium residual evidence로 full-index vector에 남긴다.
|
||||
|
||||
## 해석 실행 흐름
|
||||
`Analysis::run()`은 Template Method로 다음 큰 흐름을 고정한다. 해석 종류별 class는 필요한 단계만 재정의한다.
|
||||
`Analysis::run()`은 Template Method로 다음 여덟 hook의 순서와 fail-fast 경계를 고정한다.
|
||||
|
||||
```text
|
||||
initialize
|
||||
buildAnalysisModel
|
||||
buildDofMap
|
||||
buildSparsePattern
|
||||
assemble
|
||||
applyBoundaryConditions
|
||||
solve
|
||||
updateState
|
||||
writeResults
|
||||
```
|
||||
| 순서 | Hook | 주요 작업과 생성되는 소유 객체 | 순서/실패 불변식 |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | `initialize(request)` | `.inp` syntax read, semantic map, owned immutable `Domain`, sorted warnings | 이전 run의 dependent object를 역순으로 제거하고 parse/map 실패를 input category로 반환한다. |
|
||||
| 2 | `buildAnalysisModel()` | non-owning `AnalysisModel` view | Domain을 복사하지 않으며 Domain lifetime 안에서만 사용한다. |
|
||||
| 3 | `buildDofMapAndSparsePattern()` | `DofManager`, zero-initialized `AnalysisState` | Stable full/free/constrained numbering과 structural pattern을 한 소유자에게 둔다. |
|
||||
| 4 | `assembleAndPartitionStiffness()` | full CSR K와 `Kff/Kfc/Kcf/Kcc` | Element-local buffer를 deterministic하게 reduce하고 structural zero와 stable order를 보존한다. |
|
||||
| 5 | `factorize()` | retained `Kff` factorization | 모든 load assembly보다 먼저 호출한다. Valid fully constrained model의 `0 x 0 Kff`는 trivial success다. |
|
||||
| 6 | `assembleLoadsAndEffectiveRhs()` | full F와 `Ff-Kfc*dc` | Semantic load source order와 finite sum을 보존하며 solver를 호출하지 않는다. |
|
||||
| 7 | `substituteAndReconstruct()` | free solution과 full displacement | Factorization을 재수행하지 않고 substitution한 뒤 prescribed value를 stable order로 복구한다. |
|
||||
| 8 | `recoverAndWriteResults()` | full residual/reaction, beam rows, final HDF5 | Recovery candidate를 원자적으로 commit하고 writer 성공 뒤에만 최종 output을 교체한다. |
|
||||
|
||||
비선형 정적해석은 이 흐름을 Newton-Raphson 반복 루프 안에서 사용하고, 동적해석은 time step/frame 루프 안에서 사용한다.
|
||||
비선형 정적 및 동적 해석은 V0 범위가 아니며 별도 ADR과 formulation을 승인한 뒤 이
|
||||
lifecycle과 state/equation 계약을 확장한다. 기존 hook 사이에 조용히 반복·증분·시간 적분
|
||||
동작을 삽입하지 않는다.
|
||||
|
||||
## 설계 패턴
|
||||
- Strategy Pattern: `Analysis`, `LinearSolver`, `TimeIntegrator`, `ConvergenceCriteria`를 교체 가능한 전략으로 둔다.
|
||||
- Strategy/Adapter Pattern: 현재 교체 가능한 public 경계는 `LinearSolver`, `ParallelFor`, `ResultsWriter`다. Vendor API는 concrete adapter implementation 안에만 둔다.
|
||||
- Template Method Pattern: `Analysis::run()`은 공통 실행 흐름을 고정하고 세부 단계는 procedure별로 재정의한다.
|
||||
- Factory + Registry Pattern: Abaqus keyword와 내부 객체 생성을 분리한다. 예: `*Element, type=S4` -> `MITC4ElementFactory`.
|
||||
- Adapter Pattern: MKL, TBB, HDF5 API는 solver core에 직접 노출하지 않는다.
|
||||
- Runtime Polymorphism: 요소, 재료, 하중, 경계조건은 base interface를 통해 다룬다. 대규모 모델 성능 최적화가 필요하면 assembly 내부에서 타입별 batch 처리 또는 kernel 분리를 추가한다.
|
||||
- Syntax/Semantic separation: `AbaqusInputReader`는 syntax record를 만들고 `AbaqusDomainMapper`가 승인된 keyword 의미를 concrete Domain record로 변환한다.
|
||||
- Runtime Polymorphism: V0에서는 backend 경계에만 사용한다. 요소/재료/하중 base hierarchy와 factory/registry는 두 번째 실제 구현이 필요해질 때 trade-off를 다시 결정한다.
|
||||
- RAII: MKL handle, HDF5 file/dataset, temporary solver workspace의 수명과 오류 처리를 wrapper에 묶는다.
|
||||
|
||||
## Sparse Matrix Policy
|
||||
- assembly는 초기에는 COO triplet 수집 후 CSR finalize를 기준으로 한다.
|
||||
- `SparseMatrix`는 solver core가 사용하는 추상 contract이고 MKL PARDISO backend는 CSR input contract만 받는다.
|
||||
- matrix symmetry, definiteness, singularity diagnostic을 구조화된 diagnostic으로 남긴다.
|
||||
- deterministic assembly를 위해 TBB element loop는 thread-local contribution buffer 또는 two-pass sparse assembly를 사용한다.
|
||||
- Assembly는 element마다 index-addressed contribution buffer를 만들고, join 뒤 COO tuple을 stable order로 정렬해 한 thread에서 순서대로 합산한 후 CSR로 finalize한다.
|
||||
- `SparseMatrix`는 0-based CSR 데이터를 소유하는 별도 타입이며 dense `Matrix`를
|
||||
상속하지 않는다. MKL PARDISO backend는 adapter 경계에서 필요한 descriptor와 indexing을
|
||||
변환한다.
|
||||
- CSR row offset, sorted-unique column, dimensions, finite values를 construction boundary에서 검증하며 structural zero를 삭제하지 않는다.
|
||||
- Parallel worker는 global sparse matrix나 shared reduction accumulator를 직접 갱신하지 않는다. Worker별 failure slot과 contribution만 쓰고, deterministic reduction은 join 뒤에 수행한다.
|
||||
- Matrix symmetry와 factorization/substitution failure는 solver adapter가 구조화된 solver diagnostic으로 번역한다. 승인되지 않은 regularization이나 fallback으로 singularity를 숨기지 않는다.
|
||||
|
||||
## Dense Math Policy
|
||||
|
||||
- `Vector`는 contiguous `double` 데이터와 크기를 소유하고 copy, dot, Euclidean norm,
|
||||
scale, axpy를 MKL CBLAS adapter로 수행한다.
|
||||
- `Matrix`는 row-major contiguous `double` 데이터와 dimensions를 소유하고
|
||||
matrix-vector 및 matrix-matrix 연산에 `CBLAS_ROW_MAJOR`를 사용한다.
|
||||
- 두 타입은 copy/move semantics와 bounds-checked access를 제공한다.
|
||||
- MKL header와 MKL-specific type은 adapter implementation 밖으로 노출하지 않는다.
|
||||
|
||||
## Parallel Policy
|
||||
- 첫 번째 oneTBB 적용 지점은 element-local matrix/residual 계산이다.
|
||||
- 전역 sparse write는 thread-local buffer 또는 deterministic reduction으로 제한한다.
|
||||
- `ParallelFor`는 `[0,count)` index-addressed 독립 작업만 노출하며 `SerialParallelFor`와 `TbbParallelFor`가 같은 observable contract를 가진다.
|
||||
- 첫 oneTBB 적용 지점은 element-local stiffness 계산이다. 각 callback은 자기 index의 output slot만 쓴다.
|
||||
- 전역 sparse write와 부동소수 reduction은 parallel callback 밖의 deterministic 단계로 제한한다.
|
||||
- MKL 내부 thread와 TBB element loop가 oversubscription을 만들지 않도록 thread count와 task arena 정책을 명시한다.
|
||||
|
||||
## HDF5 Result Schema
|
||||
@@ -216,10 +288,12 @@ writeResults
|
||||
/metadata
|
||||
/model/nodes
|
||||
/model/elements
|
||||
/steps/<step-name>/frames/<frame-id>/nodal/displacement
|
||||
/steps/<step-name>/frames/<frame-id>/nodal/reaction
|
||||
/steps/<step-name>/frames/<frame-id>/element/stress
|
||||
/steps/<step-name>/frames/<frame-id>/element/strain
|
||||
/steps/<step-name>/frames/0/nodal/displacement
|
||||
/steps/<step-name>/frames/0/nodal/reaction
|
||||
/steps/<step-name>/frames/0/element/end_force_local
|
||||
/steps/<step-name>/frames/0/element/section_resultant
|
||||
/steps/<step-name>/frames/0/element/generalized_strain
|
||||
/steps/<step-name>/frames/0/element/stress_s11
|
||||
/diagnostics
|
||||
```
|
||||
|
||||
@@ -231,41 +305,54 @@ Schema requirements:
|
||||
- Abaqus reference results는 `reference/<model-id>/` 아래 CSV 파일이다.
|
||||
- Verification은 documented IDs, components, units, coordinate system, step/frame identity, tolerance 기준으로 FESA HDF5 rows와 Abaqus reference CSV rows를 비교한다.
|
||||
- FESA HDF5에서 추출한 deterministic CSV view는 optional debugging/review artifact이며 공식 solver output 또는 reference artifact가 아니다.
|
||||
- Writer는 final과 같은 directory의 임시 HDF5에 전체 schema를 쓴 뒤 flush, checked close,
|
||||
read-only reopen/self-check를 수행한다. Existing final은 `ReplaceFileW`, 새 final은
|
||||
`MoveFileExW(..., MOVEFILE_WRITE_THROUGH)`로 완료하며 실패 시 temporary artifact를
|
||||
정리하고 불완전한 파일을 정상 `results.h5`로 노출하지 않는다.
|
||||
|
||||
## Test Architecture
|
||||
- unit: parser, DOF map, shape functions, material law, sparse assembly, HDF5 schema
|
||||
- integration: small `.inp` to HDF5 end-to-end
|
||||
- reference: FESA `results.h5` rows and Abaqus reference CSV rows comparison
|
||||
- physics: equilibrium, sign, symmetry, rigid body mode, stress sanity
|
||||
- harness: hooks, phase executor, workspace validation
|
||||
## V0 결과 복구와 reference normalization
|
||||
|
||||
## Hook 흐름
|
||||
```text
|
||||
apply_patch/Edit/Write
|
||||
-> .codex/hooks/tdd-guard.py
|
||||
-> C++ production changes require related tests
|
||||
- Nodal displacement와 reaction은 global `[UX, UY, UZ, URX, URY, URZ]` 순서다.
|
||||
- Equilibrium end action은 local `[FX,FY,FZ,MX,MY,MZ]`, endpoint section resultant는
|
||||
`[N,T,My,Mz]`, generalized strain/resultant는 두 Gauss point에 기록한다.
|
||||
- General beam section stress는 section point의 axial `S11`만 복구한다. Section point가
|
||||
없으면 centroid `(0,0)`을 `source=fesa-default`로 기록한다.
|
||||
- 승인된 `reference/cantilever beam/cantilever beam elemental forces.csv`는 node station
|
||||
기준 `SF1/SM1/SM2/SM3`을 제공한다. FESA endpoint를 동일한 section-cut 부호로
|
||||
정규화하고 interior node의 두 endpoint가 tolerance 안에서 일치하는지 먼저 확인한 뒤
|
||||
`SF1 -> N`, `SM1 -> My`, `SM2 -> Mz`, `SM3 -> T`로 비교한다.
|
||||
- Reference tolerance는 같은 model, step/frame, quantity, component의 Abaqus rows에서
|
||||
`reference_scale = max(abs(reference_value))`를 구하고 각 row에
|
||||
`absolute_floor + 1e-6 * reference_scale`을 적용한다. SI displacement/rotation floor는
|
||||
`1e-9`, force/moment floor는 `1e-3`이다.
|
||||
- Beam stress는 HDF5 schema와 unit/analytical test로 검증하지만 Abaqus reference
|
||||
comparison은 N/A다.
|
||||
|
||||
git commit command
|
||||
-> .codex/hooks/pre_commit_checks.py
|
||||
-> Python Harness self-tests
|
||||
-> scripts/validate_workspace.py
|
||||
## CLI와 diagnostics
|
||||
|
||||
```powershell
|
||||
fesa.exe <model.inp> --output <results.h5>
|
||||
```
|
||||
|
||||
## Validation 흐름
|
||||
```text
|
||||
HARNESS_VALIDATION_COMMANDS set
|
||||
-> run exact commands
|
||||
`--output`을 생략하면 현재 작업 디렉터리의 `results.h5`를 사용한다. Exit code는
|
||||
`0=success`, `2=usage`, `3=input syntax/semantic mapping`, `4=model validation`,
|
||||
`5=factorization/substitution`, `6=HDF5 output`으로 고정한다. Diagnostic은 `severity`,
|
||||
`code`, `file`, `line`, `keyword`, `entity_identity`, `message`를 가지며 stderr에
|
||||
deterministic한 순서로 출력한다.
|
||||
|
||||
CMakePresets.json has msvc-debug configure preset
|
||||
-> cmake --preset msvc-debug
|
||||
-> cmake --build preset binary dir --config Debug
|
||||
-> ctest --test-dir preset binary dir -C Debug
|
||||
## 기능 확장 플레이북
|
||||
|
||||
CMakeLists.txt exists
|
||||
-> cmake -S . -B build/msvc-debug -G "Visual Studio 17 2022" -A x64
|
||||
-> cmake --build build/msvc-debug --config Debug
|
||||
-> ctest --test-dir build/msvc-debug --output-on-failure -C Debug
|
||||
다음 표는 코드 위치만이 아니라 함께 바뀌어야 하는 계약 경계를 나타낸다. 한 열만
|
||||
구현하고 다른 열을 생략하면 internal utility 또는 실험 kernel일 수는 있어도 제품 기능은
|
||||
아니다.
|
||||
|
||||
No CMake project
|
||||
-> print guidance and exit successfully
|
||||
```
|
||||
| 기능 유형 | 시작 전에 고정할 것 | 주요 구현 경계 | 함께 검증할 것 | 피해야 할 shortcut |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 새 element/material | DOF, interpolation, constitutive law, integration, local axes/sign, invalid geometry/property | Domain record와 mapper, element kernel, DofManager scatter/pattern, SparseAssembler, ResultRecovery | rigid modes/rank/energy, patch·analytical test, rotated coordinates, reference/physics | 기존 TYPE을 비슷한 kernel에 alias, source ID와 internal index 혼용, 검증 전 범용 hierarchy 추가 |
|
||||
| 새 load/constraint | Abaqus target grammar, application order, units, follower 여부, prescribed-value 의미 | Syntax/mapper, Domain target, full-space LoadAssembler 또는 constraint partition, diagnostics | set/direct target ambiguity, multi-instance identity, nonfinite sum, `Ff-Kfc*dc`, reaction | Element load kernel 존재를 parser 지원으로 간주, penalty를 elimination에 몰래 혼합 |
|
||||
| 새 analysis procedure | governing equation, state variables, increment/time lifecycle, tangent/residual, convergence와 output frame | 별도 Analysis implementation, procedure-specific state/equation owner, solver interface extension | orchestration order, failure atomicity, restart/frame identity, numerical benchmark | V0 hook 사이에 조건문으로 반복/시간 적분 삽입, 사용하지 않는 future state 선할당 |
|
||||
| 새 numerical backend | matrix/index contract, lifecycle, reusable state, failure taxonomy, thread/runtime policy | 기존 `LinearSolver` 또는 `ParallelFor` interface의 concrete adapter, CMake normalized target | empty/dimension/extreme-scale input, repeated call, failed-output preservation, clean runtime discovery | Vendor type을 public header에 노출, silent fallback/regularization, absolute install path 고정 |
|
||||
| 새 output/reference quantity | 물리 정의, location, sign, units, coordinates, stable row identity, mandatory 여부, tolerance | Result record/recovery, AnalysisState, ResultsWriter/HDF5 schema, comparator projection | schema dtype/shape, ordering, nonfinite rejection, identity inventory, reference N/A 대체 evidence | 서로 다른 result identity 혼합, station mismatch 평균, output request로 mandatory result 제거 |
|
||||
|
||||
모든 확장은 PRD의 제품 완료 정의와 요구조건→정식화→I/O→구현→reference→physics gate를
|
||||
따른다. 기존 feature contract에 없는 범위를 편의상 “Abaqus compatible”이라고 넓히지 않는다.
|
||||
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
# Harness 운영 가이드
|
||||
|
||||
## Requirements
|
||||
|
||||
Windows, Python 3.10 이상, Codex CLI가 필요하다. CMake 프로젝트에는 Visual Studio의
|
||||
Desktop development with C++ 워크로드와 MSBuild, CMake/CTest를 설치한다.
|
||||
|
||||
## 프로젝트 자동 감지
|
||||
|
||||
프로젝트 형식은 다음 순서로 결정한다: `.harness/config.json`의 명시적 type, 루트의
|
||||
CMake metadata, 하나의 `.sln`, 하나의 `.vcxproj` 순서다. C/C++가 아닌 저장소는
|
||||
건너뛰며, C/C++ 파일은 있지만 CMake/solution metadata가 없는 orphan-C++ 저장소는
|
||||
오류로 처리한다.
|
||||
|
||||
설정 파일은 선택 사항이다. 기본 자동 감지와 `.harness/build` 경로를 그대로 사용할
|
||||
때는 만들지 않아도 된다. 프로젝트별 override가 필요하면 다음처럼 예시를 복사한다.
|
||||
|
||||
```powershell
|
||||
Copy-Item .harness/config.example.json .harness/config.json
|
||||
```
|
||||
|
||||
계획을 승인해 phase 파일을 만든 뒤 Executor를 실행한다.
|
||||
|
||||
```powershell
|
||||
python scripts/execute.py <phase-name>
|
||||
python scripts/execute.py <phase-name> --push
|
||||
```
|
||||
|
||||
## Harness Python 검증
|
||||
|
||||
이 저장소의 테스트와 최종 acceptance 검증은 pytest를 시스템 Python에 설치하지 않고
|
||||
다음 명령으로 실행한다.
|
||||
|
||||
```powershell
|
||||
uv run --with pytest python -m pytest -v -rs
|
||||
```
|
||||
|
||||
## CMake preset 설정
|
||||
|
||||
`projectType`을 `cmake`로 지정하거나 자동 감지를 사용한다. `cmake.sourceDir`,
|
||||
`binaryDir`, `configurePreset`, `buildPreset`, `testPreset`은 preset을 사용할 때 함께
|
||||
지정해야 한다. 빌드 산출물은 저장소의 `.harness/build/`처럼 격리된 경로에 둔다.
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"projectType": "cmake",
|
||||
"cmake": {
|
||||
"sourceDir": ".",
|
||||
"binaryDir": "out/build/windows-debug",
|
||||
"configurePreset": "windows-debug",
|
||||
"buildPreset": "windows-debug",
|
||||
"testPreset": "windows-debug"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```powershell
|
||||
cmake --preset windows-debug
|
||||
cmake --build --preset windows-debug
|
||||
ctest --preset windows-debug --output-on-failure
|
||||
```
|
||||
|
||||
Preset을 쓰지 않는 경우에는 같은 격리된 build directory를 명시한다.
|
||||
|
||||
```powershell
|
||||
cmake -S . -B .harness/build -A x64
|
||||
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
|
||||
```
|
||||
|
||||
## 직접 MSBuild 설정
|
||||
|
||||
`projectType`을 `msbuild`로 설정하면 `msbuild.solution`, `configuration`, `platform`을
|
||||
지정한다. 직접 MSBuild 프로젝트에서는 `msbuild.testCommand`가 필수이며, 테스트 실행
|
||||
파일과 인수를 JSON 배열로 적는다.
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"projectType": "msbuild",
|
||||
"msbuild": {
|
||||
"solution": "MyProject.sln",
|
||||
"configuration": "Debug",
|
||||
"platform": "x64",
|
||||
"testCommand": ["build/tests/Debug/MyProjectTests.exe"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```powershell
|
||||
MSBuild.exe MyProject.sln /m /p:Configuration=Debug /p:Platform=x64
|
||||
.\build\tests\Debug\MyProjectTests.exe
|
||||
```
|
||||
|
||||
## TDD 확장
|
||||
|
||||
`tdd.testRoots`와 `tdd.testPatterns`로 테스트 위치와 이름을 확장한다. 패턴마다
|
||||
`{stem}`이 필요하다. `main`, 테스트, 외부 의존성, 생성 파일, build directory 같은
|
||||
기본 제외 항목은 Harness가 관리하며, `tdd.exclude`의 사용자 제외 항목은 이를
|
||||
대체하지 않고 추가한다.
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"tdd": {
|
||||
"testRoots": ["tests", "integration-tests"],
|
||||
"testPatterns": ["{stem}_test.cpp", "test_{stem}.cpp"],
|
||||
"exclude": ["legacy/generated/**"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 실패 복구
|
||||
|
||||
- Visual Studio C++ workload가 없으면 Installer에서 Desktop development with C++를 설치한 뒤 다시 실행한다.
|
||||
- solution 또는 project가 여러 개라서 모호하면 `projectType`과 `msbuild.solution`을 명시한다.
|
||||
- MSVC가 아닌 컴파일러가 감지되면 MSVC Developer Command Prompt에서 실행하거나 toolchain을 MSVC로 전환한다.
|
||||
- CTest가 0개 테스트를 보고하면 `enable_testing()`과 테스트 등록을 확인한다.
|
||||
- 직접 MSBuild 구성에 test command가 없으면 `msbuild.testCommand` 배열을 추가한다.
|
||||
- timeout 또는 명령 실패 시 Stop 응답의 stage, 안전한 argv 배열, 작업 디렉터리,
|
||||
종료 코드와 출력 tail을 확인하고 해당 명령을 단독으로 다시 실행한다. Harness는
|
||||
별도의 로그 파일을 만들지 않는다.
|
||||
@@ -0,0 +1,607 @@
|
||||
# Harness Framework 동작 과정
|
||||
|
||||
이 문서는 자연어 요구사항을 받은 뒤 Harness Framework가 계획을 만들고, 독립된
|
||||
Codex 세션에서 Step을 실행하고, MSVC로 C++ 프로젝트를 검증하는 전체 과정을
|
||||
설명한다. 설치 및 설정 예시는 [Harness 운영 가이드](HARNESS.md)를 참고한다.
|
||||
|
||||
## 1. 핵심 구조
|
||||
|
||||
Harness Framework는 다음 세 계층으로 구성된다.
|
||||
|
||||
1. **계획 계층**: 요구사항을 분석하고 사용자가 승인할 실행 가능한 Step으로 변환한다.
|
||||
2. **실행 계층**: Step Executor가 Step마다 독립 Codex 세션을 실행하고 상태와 Git
|
||||
커밋을 관리한다.
|
||||
3. **검증 계층**: PreToolUse 훅이 편집 전 정책을 검사하고, Stop 훅이 종료 전 MSVC
|
||||
빌드와 테스트를 실행한다.
|
||||
|
||||
전체 흐름은 다음과 같다.
|
||||
|
||||
```text
|
||||
사용자 요구사항
|
||||
↓
|
||||
프로젝트 탐색 및 요구사항 논의
|
||||
↓
|
||||
Step 초안 작성
|
||||
↓
|
||||
사용자 승인
|
||||
↓
|
||||
phases/index.json, task index, stepN.md 생성
|
||||
↓
|
||||
Step Executor 시작
|
||||
↓
|
||||
각 Step을 독립 Codex 세션에서 실행
|
||||
├─ 도구 호출 전: PreToolUse 정책 검사
|
||||
└─ 응답 종료 전: Stop MSVC 빌드·테스트
|
||||
↓
|
||||
성공: 커밋 후 다음 Step
|
||||
실패: 수정 또는 최대 3회 재시도
|
||||
차단: 사용자 개입을 기다리며 중단
|
||||
```
|
||||
|
||||
자연어 요구사항만으로 Executor가 자동 시작되지는 않는다. 계획을 사용자가 승인하고
|
||||
phase 파일을 생성한 다음 `scripts/execute.py`를 실행해야 구현 루프가 시작된다.
|
||||
|
||||
## 2. 요구사항 탐색과 구체화
|
||||
|
||||
예를 들어 사용자가 다음 요구사항을 전달했다고 가정한다.
|
||||
|
||||
> CMake 기반 C++20 라이브러리에 `divide()` 함수를 추가하고, 0으로 나누면 예외를
|
||||
> 발생시키며 GoogleTest 테스트를 작성한다.
|
||||
|
||||
계획을 작성하기 전에 다음 자료를 확인한다.
|
||||
|
||||
- `AGENTS.md`
|
||||
- `docs/PRD.md`
|
||||
- `docs/ARCHITECTURE.md`
|
||||
- `docs/ADR.md`
|
||||
- 관련 제품 코드와 테스트
|
||||
- `.harness/config.json`
|
||||
|
||||
이 탐색을 통해 다음 조건을 구체화한다.
|
||||
|
||||
- 사용하는 MSVC toolset과 C++ 표준
|
||||
- CMake 프로젝트인지 Visual Studio solution/project인지
|
||||
- 테스트 프레임워크와 테스트 실행 방법
|
||||
- public header와 implementation의 의존성 방향
|
||||
- 수정할 모듈과 범위 밖 항목
|
||||
- 실행 가능한 Acceptance Criteria 명령
|
||||
|
||||
요구사항에 결정되지 않은 부분이 있으면 구현 전에 사용자와 논의한다. 위 예에서는
|
||||
예외 타입, 정수 또는 부동소수점 연산 여부, public API와 ABI 변경 허용 여부가 이에
|
||||
해당한다.
|
||||
|
||||
## 3. 요구사항을 Step으로 분해
|
||||
|
||||
사용자가 구현 계획 작성을 요청하면 요구사항을 작은 Step으로 나눈다. Step 설계
|
||||
규칙은 [Harness Workflow](../.agents/skills/harness/SKILL.md)에 정의되어 있다.
|
||||
|
||||
각 Step은 다음 조건을 만족해야 한다.
|
||||
|
||||
- 하나의 모듈 또는 명확한 한 가지 책임만 다룬다.
|
||||
- 다른 대화 내용을 참조하지 않아도 실행할 수 있도록 자기완결적으로 작성한다.
|
||||
- 먼저 읽을 문서와 이전 Step의 관련 파일을 명시한다.
|
||||
- 클래스와 함수 시그니처 수준으로 작업 범위를 설명한다.
|
||||
- 실제 실행 가능한 빌드·테스트 명령을 Acceptance Criteria로 사용한다.
|
||||
- 성공, 오류, 사용자 개입 필요 상태의 판정 기준을 적는다.
|
||||
- 범위 밖 기능과 기존 테스트 회귀를 명시적으로 금지한다.
|
||||
|
||||
예시 Step은 다음과 같은 내용을 포함할 수 있다.
|
||||
|
||||
```text
|
||||
Step 0: division-api
|
||||
|
||||
읽어야 할 파일
|
||||
- AGENTS.md
|
||||
- include/calculator.hpp
|
||||
- src/calculator.cpp
|
||||
- tests/calculator_test.cpp
|
||||
|
||||
작업
|
||||
- divide(double lhs, double rhs)의 실패 테스트를 먼저 추가한다.
|
||||
- rhs가 0이면 std::invalid_argument가 발생하도록 최소 구현한다.
|
||||
|
||||
Acceptance Criteria
|
||||
- CMake/MSBuild 빌드가 성공한다.
|
||||
- 전체 테스트가 성공한다.
|
||||
- 새로운 컴파일러 경고가 없다.
|
||||
```
|
||||
|
||||
### TDD와 Step 경계
|
||||
|
||||
프로젝트 규칙은 실패하는 테스트를 먼저 요구하지만 Stop 훅은 Codex가 Step을 종료할
|
||||
때 전체 테스트 성공을 요구한다. 따라서 다음처럼 실패 상태를 Step 사이에 남겨둘 수
|
||||
없다.
|
||||
|
||||
```text
|
||||
Step 0: 실패하는 테스트만 추가하고 종료
|
||||
Step 1: 제품 코드를 구현해 테스트 통과
|
||||
```
|
||||
|
||||
실제 red-green 순서는 하나의 Codex 실행 안에서 완료되어야 한다.
|
||||
|
||||
```text
|
||||
테스트 작성
|
||||
→ 테스트 실패 확인
|
||||
→ 최소 제품 코드 구현
|
||||
→ 테스트 성공 확인
|
||||
→ Step 종료
|
||||
```
|
||||
|
||||
즉, 테스트가 구현보다 먼저 작성되는 순서는 지키되 각 Step은 최종적으로 green
|
||||
상태여야 한다.
|
||||
|
||||
## 4. 사용자 승인 후 생성되는 파일
|
||||
|
||||
Step 초안을 사용자가 승인한 뒤에만 다음 파일을 생성한다.
|
||||
|
||||
```text
|
||||
phases/
|
||||
├── index.json
|
||||
└── add-division/
|
||||
├── index.json
|
||||
├── step0.md
|
||||
├── step1.md
|
||||
└── ...
|
||||
```
|
||||
|
||||
### 4.1 Top-level index
|
||||
|
||||
`phases/index.json`은 여러 task의 상태를 관리한다.
|
||||
|
||||
```json
|
||||
{
|
||||
"phases": [
|
||||
{
|
||||
"dir": "add-division",
|
||||
"status": "pending"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 Task index
|
||||
|
||||
`phases/add-division/index.json`은 task 내부 Step의 상태를 관리한다.
|
||||
|
||||
```json
|
||||
{
|
||||
"project": "Calculator",
|
||||
"phase": "add-division",
|
||||
"steps": [
|
||||
{
|
||||
"step": 0,
|
||||
"name": "division-api",
|
||||
"status": "pending"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
상태별 기록은 다음과 같이 나뉜다.
|
||||
|
||||
| 상태 | Codex가 기록 | Executor가 기록 |
|
||||
|---|---|---|
|
||||
| `completed` | `summary` | `completed_at` |
|
||||
| `error` | `error_message` | `failed_at` |
|
||||
| `blocked` | `blocked_reason` | `blocked_at` |
|
||||
|
||||
Executor는 task의 `created_at`과 Step의 `started_at`도 기록한다. `summary`는 다음
|
||||
독립 Codex 세션이 이전 Step의 핵심 산출물과 결정을 이해할 수 있도록 한 줄로
|
||||
작성한다.
|
||||
|
||||
### 4.3 Step 파일
|
||||
|
||||
각 `stepN.md`에는 다음 내용이 들어간다.
|
||||
|
||||
- 읽어야 할 파일
|
||||
- 작업 범위와 인터페이스
|
||||
- 핵심 동작 및 불변 조건
|
||||
- Acceptance Criteria 명령
|
||||
- 아키텍처·ADR·CRITICAL 규칙 확인 절차
|
||||
- 성공, 오류, 차단 상태 기록 방법
|
||||
- 범위 밖 변경 금지사항
|
||||
|
||||
Step은 독립 Codex 실행의 전체 작업 지시서이므로 이전 대화만 참조하는 표현을 넣지
|
||||
않는다.
|
||||
|
||||
## 5. Step Executor 시작
|
||||
|
||||
계획 파일을 생성한 뒤 다음 명령으로 실행한다.
|
||||
|
||||
```powershell
|
||||
python scripts/execute.py add-division
|
||||
```
|
||||
|
||||
완료된 브랜치를 원격 저장소에 자동 push하려면 `--push`를 추가한다.
|
||||
|
||||
```powershell
|
||||
python scripts/execute.py add-division --push
|
||||
```
|
||||
|
||||
[Step Executor](../scripts/execute.py)는 시작할 때 다음 작업을 수행한다.
|
||||
|
||||
1. phase 디렉터리와 task index가 존재하는지 검사한다.
|
||||
2. 이전 실행에서 `error` 또는 `blocked`로 끝난 Step이 있는지 검사한다.
|
||||
3. `feat-{phase-name}` 브랜치를 생성하거나 checkout한다.
|
||||
4. `AGENTS.md`와 `docs/*.md`를 guardrail로 읽는다.
|
||||
5. task의 `created_at`이 없으면 기록한다.
|
||||
6. 첫 번째 `pending` Step부터 순차 실행한다.
|
||||
|
||||
`AGENTS.md`와 모든 `docs/*.md` 내용은 각 Codex 프롬프트에 직접 삽입된다. 따라서
|
||||
이 문서들은 참고 자료가 아니라 실제 실행 입력이다. 서로 충돌하거나 placeholder가
|
||||
남아 있으면 Codex도 그 모순을 입력으로 받는다.
|
||||
|
||||
## 6. Step마다 독립 Codex 세션 실행
|
||||
|
||||
Executor는 각 Step을 다음 형태의 독립 프로세스로 실행한다.
|
||||
|
||||
```text
|
||||
codex exec
|
||||
--json
|
||||
--sandbox workspace-write
|
||||
--dangerously-bypass-hook-trust
|
||||
--cd <repository-root>
|
||||
-
|
||||
```
|
||||
|
||||
Codex에 전달하는 프롬프트는 다음 내용의 조합이다.
|
||||
|
||||
```text
|
||||
AGENTS.md와 docs 문서
|
||||
+ 이전에 완료된 Step의 summary
|
||||
+ 이전 시도의 오류(재시도인 경우)
|
||||
+ Executor 공통 작업 규칙
|
||||
+ 현재 stepN.md
|
||||
```
|
||||
|
||||
이전 Step의 전체 대화나 Codex 세션은 전달하지 않는다. task index에 기록한
|
||||
`summary`만 다음 Step에 누적한다.
|
||||
|
||||
Codex 실행 결과의 exit code, stdout, stderr는 다음 파일에 저장한다.
|
||||
|
||||
```text
|
||||
phases/{task-name}/step{N}-output.json
|
||||
```
|
||||
|
||||
## 7. 도구 호출 전 PreToolUse 검사
|
||||
|
||||
[`.codex/hooks.json`](../.codex/hooks.json)은 shell 및 파일 편집 도구에
|
||||
[PreToolUse 훅](../scripts/hooks/pre_tool_use.py)을 등록한다. Codex가 실제 명령이나
|
||||
편집을 수행하기 전에 이 훅이 요청을 검사한다.
|
||||
|
||||
### 7.1 위험 명령 차단
|
||||
|
||||
다음 유형의 명령은 요구사항과 관계없이 차단한다.
|
||||
|
||||
- `git reset --hard`
|
||||
- `git push --force` 또는 `--force-with-lease`
|
||||
- `rm -rf`
|
||||
- `Remove-Item -Recurse -Force`
|
||||
- `rmdir /s /q`
|
||||
- `DROP TABLE`
|
||||
|
||||
위험 패턴이 발견되면 훅은 차단 이유를 stderr로 출력하고 종료 코드 2를 반환한다.
|
||||
그러면 해당 도구 호출은 실행되지 않는다.
|
||||
|
||||
### 7.2 C++ TDD 검사
|
||||
|
||||
`apply_patch`, `Edit`, `MultiEdit`, `Write`로 다음 C/C++ 확장자의 파일을 편집하려
|
||||
하면 [TDD 정책](../scripts/msvc_harness/tdd_policy.py)을 검사한다.
|
||||
|
||||
```text
|
||||
.c .cc .cpp .cxx .h .hpp .hxx
|
||||
```
|
||||
|
||||
일반 제품 코드를 수정하려면 대응되는 테스트 파일이 먼저 존재해야 한다. 예를 들어
|
||||
`src/calculator.cpp`의 기본 대응 테스트 이름은 다음과 같다.
|
||||
|
||||
```text
|
||||
calculator_test.cpp
|
||||
calculator_tests.cpp
|
||||
test_calculator.cpp
|
||||
calculator.test.cpp
|
||||
```
|
||||
|
||||
테스트는 다음 위치에서 검색한다.
|
||||
|
||||
- `.harness/config.json`의 `tdd.testRoots`
|
||||
- 제품 파일과 같은 디렉터리 아래 `tests/`
|
||||
- 제품 파일과 같은 디렉터리 아래 `test/`
|
||||
|
||||
다음 파일과 디렉터리는 대응 테스트 존재 검사가 면제된다.
|
||||
|
||||
- 테스트 파일 자체
|
||||
- `main.cpp`
|
||||
- `.harness/build/**`, `build/**`, `out/**`
|
||||
- `cmake-build-*/**`
|
||||
- `third_party/**`, `external/**`, `vendor/**`
|
||||
- `generated/**`
|
||||
- `tdd.exclude`에 추가한 경로
|
||||
|
||||
`tdd.exclude`는 기본 제외 항목을 대체하지 않고 추가한다.
|
||||
|
||||
### 7.3 TDD 검사가 보장하는 범위
|
||||
|
||||
현재 TDD 훅이 직접 보장하는 것은 대응되는 이름의 테스트 파일이 존재한다는
|
||||
사실이다. 다음 항목까지 증명하지는 않는다.
|
||||
|
||||
- 테스트가 이번 요구사항을 실제로 검증하는가
|
||||
- 구현 전에 테스트가 실제로 실패했는가
|
||||
- 테스트의 assertion과 경계 조건이 충분한가
|
||||
- 기존 테스트 파일을 이번 변경과 함께 수정했는가
|
||||
|
||||
또한 shell 명령의 리다이렉션 등으로 C++ 파일을 쓰는 경우 shell 위험 패턴 검사는
|
||||
적용되지만 경로 기반 TDD 검사는 적용되지 않는다. 따라서 이 훅은 완전한 TDD
|
||||
증명기가 아니라 테스트 우선 편집을 유도하는 guardrail이다.
|
||||
|
||||
## 8. Codex 종료 전 Stop 검증
|
||||
|
||||
Codex가 Step 작업을 끝내고 응답을 종료하려 하면
|
||||
[Stop 훅](../scripts/hooks/stop_validation.py)이 실행된다. Stop 훅은 변경 파일만이
|
||||
아니라 발견된 C/C++ 프로젝트 전체를 빌드하고 테스트한다.
|
||||
|
||||
### 8.1 저장소 루트와 재진입 방지
|
||||
|
||||
Stop 훅은 `git rev-parse --show-toplevel`로 프로젝트 루트를 결정한다. Git 저장소를
|
||||
찾을 수 없으면 현재 디렉터리를 사용한다.
|
||||
|
||||
빌드나 테스트의 자식 프로세스에는 `CODEX_STOP_VALIDATION_ACTIVE=1`을 전달한다.
|
||||
같은 훅이 자식 프로세스에서 다시 진입하면 즉시 성공 처리하여 검증 재귀를 막는다.
|
||||
|
||||
### 8.2 설정 로드
|
||||
|
||||
[설정 로더](../scripts/msvc_harness/config.py)는 `.harness/config.json`을 읽는다.
|
||||
파일이 없으면 다음 기본값을 사용한다.
|
||||
|
||||
- `version`: 1
|
||||
- `projectType`: `auto`
|
||||
- CMake source: 저장소 루트
|
||||
- preset 미사용 시 binary directory: `.harness/build`
|
||||
- configuration: `Debug`
|
||||
- platform: `x64`
|
||||
- 테스트 루트: `tests`, `test`
|
||||
- 기본 테스트 이름 패턴 네 개
|
||||
|
||||
설정은 다음 조건을 엄격하게 검사한다.
|
||||
|
||||
- 알 수 없는 필드를 거부한다.
|
||||
- `version`은 숫자 1만 허용한다.
|
||||
- `projectType`은 `auto`, `cmake`, `msbuild`만 허용한다.
|
||||
- 저장소 상대 경로만 허용한다.
|
||||
- 저장소 밖으로 해석되는 경로를 거부한다.
|
||||
- CMake preset을 사용하면 `configurePreset`, `buildPreset`, `testPreset`,
|
||||
`binaryDir`를 모두 요구한다.
|
||||
- 모든 `tdd.testPatterns`에 `{stem}`을 요구한다.
|
||||
|
||||
### 8.3 프로젝트 자동 감지
|
||||
|
||||
[프로젝트 탐색기](../scripts/msvc_harness/discovery.py)는 다음 순서로 프로젝트를
|
||||
선택한다.
|
||||
|
||||
1. `projectType: cmake` 또는 `projectType: msbuild` 명시 설정
|
||||
2. 루트의 `CMakePresets.json`
|
||||
3. 루트의 `CMakeUserPresets.json`
|
||||
4. 루트의 `CMakeLists.txt`
|
||||
5. 루트의 단일 `.sln`
|
||||
6. 루트의 단일 `.vcxproj`
|
||||
|
||||
자동 감지 결과는 다음처럼 처리한다.
|
||||
|
||||
| 저장소 상태 | 결과 |
|
||||
|---|---|
|
||||
| CMake metadata가 있음 | CMake 프로젝트 선택 |
|
||||
| 하나의 `.sln` 또는 `.vcxproj`가 있음 | MSBuild 프로젝트 선택 |
|
||||
| 여러 solution/project가 있음 | 설정으로 하나를 지정하라는 오류 |
|
||||
| C/C++ 파일과 build metadata가 모두 없음 | 검증할 프로젝트가 없으므로 통과 |
|
||||
| C/C++ 파일은 있지만 build metadata가 없음 | orphan C++ 프로젝트 오류 |
|
||||
|
||||
### 8.4 MSVC 도구 탐색
|
||||
|
||||
[도구 탐색기](../scripts/msvc_harness/toolchain.py)는 `vswhere.exe`로 다음을
|
||||
확인한다.
|
||||
|
||||
- Visual Studio 설치 경로
|
||||
- Desktop development with C++ workload
|
||||
- `MSBuild.exe`
|
||||
|
||||
CMake 프로젝트에서는 다음 우선순위로 CMake와 CTest를 선택한다.
|
||||
|
||||
1. PATH에서 발견한 독립 `cmake.exe`와 `ctest.exe`
|
||||
2. Visual Studio에 번들된 CMake와 CTest
|
||||
|
||||
따라서 새로 설치한 CMake의 `bin` 디렉터리가 PATH에 반영되어 있으면 독립 CMake를
|
||||
우선 사용한다.
|
||||
|
||||
## 9. 빌드 시스템별 검증 계획
|
||||
|
||||
### 9.1 CMake preset 미사용
|
||||
|
||||
[CMake adapter](../scripts/msvc_harness/adapters/cmake.py)는 다음 검증 계획을 만든다.
|
||||
|
||||
```powershell
|
||||
cmake -S <source> -B .harness/build -A x64
|
||||
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
|
||||
```
|
||||
|
||||
명령 성공 외에 다음 결과도 검사한다.
|
||||
|
||||
- 생성된 CMake compiler metadata의 `CMAKE_CXX_COMPILER_ID`가 `MSVC`인가
|
||||
- CTest JSON에 한 개 이상의 테스트가 있는가
|
||||
|
||||
따라서 빌드가 성공해도 MinGW 등 다른 컴파일러를 사용했거나 CTest가 테스트를 한
|
||||
개도 발견하지 못하면 실패한다.
|
||||
|
||||
### 9.2 CMake preset 사용
|
||||
|
||||
`.harness/config.json`에 preset을 완전히 지정하면 다음 형태로 실행한다.
|
||||
|
||||
```powershell
|
||||
cmake --preset <configurePreset>
|
||||
cmake --build --preset <buildPreset>
|
||||
ctest --preset <testPreset> --show-only=json-v1
|
||||
ctest --preset <testPreset> --output-on-failure
|
||||
```
|
||||
|
||||
이 경우 모든 명령은 `cmake.sourceDir`에서 실행하고 compiler metadata 검사는 설정한
|
||||
`binaryDir`에서 수행한다.
|
||||
|
||||
### 9.3 직접 MSBuild
|
||||
|
||||
[MSBuild adapter](../scripts/msvc_harness/adapters/msbuild.py)는 다음 순서로 실행한다.
|
||||
|
||||
```powershell
|
||||
MSBuild.exe <solution-or-vcxproj> /m /nologo `
|
||||
/p:Configuration=<configuration> `
|
||||
/p:Platform=<platform>
|
||||
|
||||
<msbuild.testCommand>
|
||||
```
|
||||
|
||||
직접 MSBuild 프로젝트는 표준 테스트 탐색 명령이 없으므로
|
||||
`.harness/config.json`의 `msbuild.testCommand`가 반드시 필요하다. 이 값이 없으면
|
||||
Stop 검증이 실패한다.
|
||||
|
||||
## 10. 명령 실행 안전성과 제한시간
|
||||
|
||||
[검증 실행기](../scripts/msvc_harness/process.py)는 다음 안전 규칙을 적용한다.
|
||||
|
||||
- 명령을 shell 문자열이 아닌 argv 배열로 실행한다.
|
||||
- `shell=False`를 사용한다.
|
||||
- 각 명령의 working directory가 저장소 내부인지 검사한다.
|
||||
- 명령별 제한시간과 Stop 전체 제한시간 중 더 짧은 값을 적용한다.
|
||||
- 종료 코드가 0이 아니면 즉시 해당 stage를 실패 처리한다.
|
||||
|
||||
Stop 훅의 전체 제한시간은 저장소 탐색, toolchain 탐색, configure, build, test discovery,
|
||||
test를 모두 포함해 1,800초다. `.codex/hooks.json`의 Stop command timeout도 1,800초다.
|
||||
|
||||
실패 메시지에는 다음 진단 정보를 포함한다.
|
||||
|
||||
- 실패 stage
|
||||
- 안전하게 표현한 argv 배열
|
||||
- working directory
|
||||
- 종료 코드
|
||||
- stdout과 stderr의 마지막 8,000자
|
||||
|
||||
Harness는 별도 빌드 로그 파일을 생성하지 않는다.
|
||||
|
||||
## 11. 성공, 실패, 차단 처리
|
||||
|
||||
### 11.1 Stop 검증 성공
|
||||
|
||||
빌드와 테스트가 모두 성공하면 Stop 훅은 출력 없이 종료한다. Codex가 정상 종료하면
|
||||
Executor가 task index를 다시 읽는다.
|
||||
|
||||
Codex가 Step을 다음처럼 기록한 경우:
|
||||
|
||||
```json
|
||||
{
|
||||
"step": 0,
|
||||
"name": "division-api",
|
||||
"status": "completed",
|
||||
"summary": "divide API와 0 나누기 테스트를 추가함"
|
||||
}
|
||||
```
|
||||
|
||||
Executor는 `completed_at`을 기록하고 변경사항을 커밋한 뒤 다음 `pending` Step을
|
||||
실행한다.
|
||||
|
||||
### 11.2 Stop 검증 실패
|
||||
|
||||
Stop 훅은 Codex hook protocol에 따라 다음 형태의 응답을 출력한다.
|
||||
|
||||
```json
|
||||
{
|
||||
"continue": false,
|
||||
"stopReason": "build failed ...",
|
||||
"systemMessage": "build failed ..."
|
||||
}
|
||||
```
|
||||
|
||||
Codex 프로세스에 대한 훅 자체의 종료 코드는 0이지만 `continue: false`가 Codex의
|
||||
응답 종료를 막는다. Codex는 같은 세션에서 오류를 확인하고 수정을 계속한다.
|
||||
|
||||
### 11.3 Executor 재시도
|
||||
|
||||
Codex 프로세스가 끝났는데 Step 상태가 `completed` 또는 `blocked`가 아니면 Executor가
|
||||
새 Codex 세션으로 재시도한다.
|
||||
|
||||
```text
|
||||
첫 번째 시도 실패
|
||||
→ 오류를 다음 프롬프트에 삽입
|
||||
→ 두 번째 독립 Codex 실행
|
||||
→ 다시 실패하면 세 번째 독립 Codex 실행
|
||||
→ 세 번째도 실패하면 error 기록 후 종료
|
||||
```
|
||||
|
||||
즉, 실패 복구에는 두 층이 있다.
|
||||
|
||||
1. Stop 훅이 같은 Codex 세션에서 수정하도록 요구한다.
|
||||
2. 세션 자체가 성공하지 못하면 Executor가 새 세션으로 최대 3회 재시도한다.
|
||||
|
||||
### 11.4 사용자 개입 필요
|
||||
|
||||
인증, API 키, 수동 설치처럼 Codex가 자동으로 해결할 수 없는 문제가 있으면 Step을
|
||||
`blocked`로 기록한다. Executor는 `blocked_at`과 top-level 상태를 갱신하고 종료 코드
|
||||
2로 중단한다.
|
||||
|
||||
재개하려면 원인을 해결하고 해당 Step을 `pending`으로 되돌린 뒤
|
||||
`blocked_reason`을 제거하고 다시 실행한다. `error`도 같은 방식으로 `pending`으로
|
||||
되돌리고 `error_message`를 제거한 뒤 재실행한다.
|
||||
|
||||
## 12. Git 커밋과 phase 완료
|
||||
|
||||
Step이 성공하면 제품 변경과 Harness metadata를 분리해 다음 형식으로 커밋한다.
|
||||
|
||||
```text
|
||||
feat(add-division): step 0 — division-api
|
||||
chore(add-division): step 0 output
|
||||
```
|
||||
|
||||
두 번째 커밋의 `output`은 task index의 Step 상태와 summary 같은 Harness metadata를
|
||||
뜻한다. 원시 Codex 실행 기록인 `stepN-output.json`은 `.gitignore` 대상이며 커밋에
|
||||
포함되지 않는다.
|
||||
|
||||
모든 Step이 완료되면 Executor는 다음 작업을 수행한다.
|
||||
|
||||
- task의 `completed_at` 기록
|
||||
- `phases/index.json`의 task 상태를 `completed`로 변경
|
||||
- 최종 metadata 커밋
|
||||
- `--push` 사용 시 `origin/feat-{phase-name}`으로 push
|
||||
|
||||
커밋 과정은 `git add -A`를 사용한다. 실행 전에 작업 트리에 관련 없는 사용자
|
||||
변경사항이 남아 있으면 그 변경도 Step 커밋에 포함될 수 있다. 따라서 깨끗한
|
||||
worktree 또는 별도 Git worktree에서 실행하는 것이 안전하다.
|
||||
|
||||
## 13. 요구사항 종류별 동작
|
||||
|
||||
| 받은 요구사항 또는 변경 | PreToolUse 동작 | Stop 동작 |
|
||||
|---|---|---|
|
||||
| 새 C++ 제품 파일 추가 | 대응 테스트가 먼저 없으면 차단 | 전체 빌드·테스트 |
|
||||
| 기존 C++ 구현 또는 header 수정 | 대응 테스트 파일 존재 여부 검사 | 전체 빌드·테스트 |
|
||||
| 테스트 파일 추가 | TDD 차단 없이 허용 | 모든 테스트가 성공해야 종료 |
|
||||
| `main.cpp` 수정 | TDD 대응 테스트 검사 면제 | 전체 빌드·테스트 |
|
||||
| 문서, JSON, Python 수정 | C++ TDD 검사 없음 | C++ 프로젝트가 있으면 전체 검증 |
|
||||
| 위험한 Git 또는 삭제 명령 | 즉시 차단 | 도달하지 않음 |
|
||||
| C++ 파일은 있지만 build metadata 없음 | 편집은 허용될 수 있음 | orphan 프로젝트 오류 |
|
||||
| 직접 MSBuild인데 `testCommand` 없음 | 편집은 허용될 수 있음 | 설정 오류로 종료 차단 |
|
||||
| C/C++가 전혀 없는 저장소 | 관련 편집 검사 없음 | 검증할 프로젝트가 없어 통과 |
|
||||
|
||||
## 14. 적용 전 준비사항
|
||||
|
||||
이 저장소는 대상 C++ 프로젝트에 맞게 채워 사용하는 템플릿이다. 실행 전 다음을
|
||||
확인한다.
|
||||
|
||||
1. `AGENTS.md`의 프로젝트명, toolset, C++ 표준, 테스트 프레임워크, CRITICAL 규칙을
|
||||
실제 값으로 교체한다.
|
||||
2. `docs/PRD.md`, `docs/ARCHITECTURE.md`, `docs/ADR.md`의 placeholder와 예시를 실제
|
||||
프로젝트 정보로 교체한다.
|
||||
3. 기본 자동 감지로 충분하지 않을 때만 `.harness/config.example.json`을 참고해
|
||||
`.harness/config.json`을 만든다.
|
||||
4. CMake 또는 MSBuild metadata와 테스트 실행 방법을 확인한다.
|
||||
5. `phases/`가 없다면 요구사항 논의와 계획 승인을 거쳐 task 파일을 먼저 만든다.
|
||||
6. Executor 실행 전에 Git working tree가 깨끗한지 확인한다.
|
||||
|
||||
특히 `AGENTS.md`와 `docs/*.md`는 각 Codex 실행에 그대로 주입된다. C++ 프로젝트에서
|
||||
TypeScript 예시나 미완성 placeholder가 남아 있으면 실제 작업 지시와 충돌할 수 있다.
|
||||
+84
-34
@@ -15,41 +15,73 @@ FESA는 Abaqus `.inp` keyword subset을 입력으로 받아 유한요소법 기
|
||||
1. Abaqus `.inp` keyword subset parser와 내부 `Domain` semantic model 생성
|
||||
2. `AnalysisModel`, `DofManager`, `AnalysisState` 기반의 step별 equation system 구성
|
||||
3. 선형 정적 해석을 시작점으로 하는 `Analysis` procedure 계층
|
||||
4. 요소, 재료, 경계조건, 하중의 runtime-polymorphic base interface
|
||||
4. Stable source identity를 보존하는 concrete V0 node, B33 element, material, section, boundary, load record
|
||||
5. sparse matrix pattern 생성, 전역 행렬/벡터 조립, 제약조건 적용
|
||||
6. `LinearSolver` adapter를 통한 MKL PARDISO backend와 향후 iterative solver 확장
|
||||
7. HDF5 기반 `ResultStep` -> `ResultFrame` -> `FieldOutput`/`HistoryOutput` 저장
|
||||
6. `LinearSolver`, `ParallelFor`, `ResultsWriter` interface를 통한 MKL PARDISO, oneTBB, HDF5 backend 격리
|
||||
7. HDF5 기반 versioned step/frame field-result 저장과 향후 history-output 확장 경계
|
||||
8. FESA HDF5 rows와 `reference/<model-id>/` 아래 Abaqus reference CSV rows의 직접 비교
|
||||
9. CMake/MSVC/x64/Debug, CTest, Harness validation, TDD guard 기반 개발 검증
|
||||
9. CMake/MSVC/x64/Debug, CTest 기반 개발 검증
|
||||
|
||||
Element/material 계층의 일반적인 runtime polymorphism, iterative solver, history output은 장기 확장 방향이다. 현재 제품 계약으로 간주하지 않으며, 실제 사용 사례와 성능·수명 요구가 승인되기 전에 추상 base class를 미리 추가하지 않는다.
|
||||
|
||||
## 사용자 관점 제품 흐름
|
||||
|
||||
1. 사용자는 승인된 Abaqus `.inp` subset으로 모델과 단일 analysis step을 기술한다.
|
||||
2. FESA는 syntax를 읽은 뒤 semantic mapping과 model validation을 수행한다. 지원하지 않는 모델 의미는 구조화된 diagnostic과 안정된 exit code로 거부한다.
|
||||
3. 해석 procedure는 active model view, DOF/equation map과 sparse system을 만들고, essential constraint elimination을 적용해 선형계를 factorize하고 substitution한다.
|
||||
4. FESA는 full displacement를 복구하고 equilibrium residual/reaction과 element 결과를 계산한다.
|
||||
5. 성공 시 output request와 무관한 mandatory 결과, metadata와 diagnostic을 versioned `results.h5`에 기록한다. 실패 시 불완전한 최종 결과 파일을 정상 결과처럼 남기지 않는다.
|
||||
6. 검증 workflow는 HDF5 row를 승인된 Abaqus reference CSV identity에 투영해 tolerance를 판정하고, 별도로 equilibrium과 물리적 타당성을 검토한다.
|
||||
|
||||
Parser keyword, element kernel, solver backend 또는 output dataset 중 하나만 추가된 상태는 end-to-end 제품 기능이 아니다. 같은 기능의 입력 의미부터 외부 결과와 검증까지 연결되어야 한다.
|
||||
|
||||
## V0 범위
|
||||
- 선형 정적 해석 골격
|
||||
- 첫 end-to-end 기능 후보: 1D truss/bar element
|
||||
- 선형 정적 해석 파이프라인 구현
|
||||
- 승인된 첫 end-to-end 기능: 2절점 3D Euler–Bernoulli beam, Abaqus `TYPE=B33`
|
||||
- 입력 파일당 하나의 `*STEP, *STATIC`
|
||||
- 절점당 자유도 `[UX, UY, UZ, URX, URY, URZ]`
|
||||
- 축, 두 방향 굽힘, Saint-Venant 비틀림 및 선형 등방 탄성
|
||||
- 최소 Abaqus keyword subset:
|
||||
- `*HEADING`
|
||||
- `*NODE`
|
||||
- `*ELEMENT`
|
||||
- `*NSET`
|
||||
- `*ELSET`
|
||||
- `*PART`, `*END PART`
|
||||
- `*NODE`, `*ELEMENT, TYPE=B33`
|
||||
- `*NSET`, `*ELSET`, including `GENERATE`
|
||||
- `*MATERIAL`
|
||||
- `*ELASTIC`
|
||||
- section keyword
|
||||
- `*BEAM GENERAL SECTION, SECTION=GENERAL`
|
||||
- `*SECTION POINTS`
|
||||
- `*ASSEMBLY`, `*END ASSEMBLY`
|
||||
- `*INSTANCE`, `*END INSTANCE`
|
||||
- `*BOUNDARY`
|
||||
- `*CLOAD`
|
||||
- `*STEP`
|
||||
- `*STATIC`
|
||||
- output request subset
|
||||
- displacement 중심의 최소 `AnalysisState`
|
||||
- `*STEP`, `*STATIC`, `*END STEP`
|
||||
- `*PREPRINT`, `*RESTART`, `*TRANSVERSE SHEAR STIFFNESS`, `*OUTPUT, FIELD`,
|
||||
`*OUTPUT, HISTORY`, `*NODE OUTPUT`, `*ELEMENT OUTPUT`, `*CONTACT OUTPUT`과 그에 속한
|
||||
미지원 variable data는 warning 후 no-op 처리
|
||||
- 같은 part의 여러 identity instance와 stable source label mapping
|
||||
- nonzero prescribed displacement를 포함한 free/constrained partition
|
||||
- formulation의 constant local line-load equivalent nodal vector kernel. V0 parser와 CLI는
|
||||
`*DLOAD`를 지원하거나 이 kernel을 호출하지 않음
|
||||
- deterministic COO-to-CSR stiffness assembly
|
||||
- MKL PARDISO 기반 sparse direct solver
|
||||
- stiffness factorization과 load-vector substitution 분리
|
||||
- displacements, reactions, equilibrium end actions, section resultants, generalized results,
|
||||
axial `S11` output
|
||||
- HDF5 result schema v0
|
||||
- FESA HDF5 to Abaqus reference CSV comparison 계약
|
||||
- `fesa.exe <model.inp> --output <results.h5>` CLI
|
||||
- 승인된 `reference/cantilever beam/` B33 결과와 displacement, reaction, section resultant
|
||||
comparison; beam stress reference comparison은 N/A
|
||||
|
||||
## V1 범위
|
||||
- 2D plane stress/plane strain element
|
||||
- 3D solid element
|
||||
- MKL PARDISO 기반 sparse direct solve
|
||||
- TBB element-local computation 병렬화
|
||||
- reference model portfolio 확장
|
||||
- nonlinear static, dynamic, frequency, heat transfer 해석을 위한 interface 확장점
|
||||
## 신규 기능의 제품 완료 정의
|
||||
|
||||
새로운 element, load, constraint, material, analysis procedure 또는 output quantity는 다음 조건을 모두 만족할 때 FESA 제품 기능으로 취급한다.
|
||||
|
||||
1. 지원 범위와 제외 범위, 실패 category, units/coordinates/identity, tolerance가 요구조건과 I/O 계약에 명시되어 있다.
|
||||
2. 필요한 FEM 정식화와 recovery/sign convention이 검토되었고, 수치 위험과 검증 문제를 numerical review가 다룬다.
|
||||
3. Syntax와 semantic mapping이 내부 모델에 안정된 source identity로 연결되며 잘못된 입력을 fail-closed로 거부한다. Kernel만 제공하는 기능은 parser/CLI 지원 여부를 별도로 표시한다.
|
||||
4. DOF, sparse pattern, assembly, constraint, solver lifecycle과 mutable state ownership이 기존 아키텍처에 연결되거나 승인된 새 procedure 경계를 가진다.
|
||||
5. Mandatory HDF5 schema와 diagnostic, CLI 실패 의미가 정의되고 failure path가 기존 state 또는 최종 output을 오염시키지 않는다.
|
||||
6. Unit test가 local 수식과 validation을, integration test가 orchestration과 외부 계약을, reference comparison과 physics sanity가 수치·물리 타당성을 각각 증명한다. Reference가 N/A이면 그 이유와 대체 evidence를 명시한다.
|
||||
|
||||
## 기능 요구조건
|
||||
| ID | 요구조건 | Acceptance Criteria | Verification Method |
|
||||
@@ -58,38 +90,56 @@ FESA는 Abaqus `.inp` keyword subset을 입력으로 받아 유한요소법 기
|
||||
| FESA-PRD-002 | FESA는 입력 모델을 `Domain`으로 변환해야 한다. | nodes, elements, materials, properties, sets, loads, boundary conditions, step definitions가 semantic model에 보존된다. | parser integration test |
|
||||
| FESA-PRD-003 | FESA는 현재 step의 실행 view를 `AnalysisModel`로 구성해야 한다. | active elements, loads, boundary conditions, properties/materials가 Domain 복사 없이 참조 또는 id view로 연결된다. | analysis model unit test |
|
||||
| FESA-PRD-004 | FESA는 equation numbering과 constraint/free mapping을 `DofManager`에 집중해야 한다. | Node/Element 내부에 equation id를 분산 저장하지 않는다. | code review, DofManager unit test |
|
||||
| FESA-PRD-005 | FESA는 해석 중 변하는 물리량을 `AnalysisState`에 저장해야 한다. | displacement, force, residual, increment/iteration 상태가 step/frame 출력과 연결된다. | state unit test, integration test |
|
||||
| FESA-PRD-006 | FESA는 solver 결과를 HDF5 authoritative output `results.h5`로 저장해야 한다. | step/frame, field/history, metadata, diagnostics가 schema version과 함께 저장된다. | HDF5 schema test |
|
||||
| FESA-PRD-007 | FESA는 Abaqus reference CSV rows와 비교 가능한 deterministic row mapping을 제공해야 한다. | displacement, reaction, internal force, stress 등 검증 물리량의 row identity와 tolerance source가 명확하다. | reference comparison report |
|
||||
| FESA-PRD-008 | FESA의 production C++ 변경은 테스트를 먼저 작성하고 실패를 확인한 뒤 구현해야 한다. | 관련 C++ test file이 있고 Harness TDD guard를 통과한다. | hook test, CTest |
|
||||
| FESA-PRD-005 | FESA는 해석 중 변하는 물리량을 `AnalysisState`에 저장해야 한다. | V0 displacement, external/internal force, residual, constrained reaction, step/frame identity와 element recovery rows가 출력에 연결되고 velocity, acceleration, temperature, iteration history는 할당하지 않는다. | state unit test, integration test |
|
||||
| FESA-PRD-006 | FESA는 solver 결과를 HDF5 authoritative output `results.h5`로 저장해야 한다. | V0 step/frame field results, metadata, diagnostics가 schema version과 함께 저장된다. | HDF5 schema test |
|
||||
| FESA-PRD-007 | FESA는 Abaqus reference CSV rows와 비교 가능한 deterministic row mapping을 제공해야 한다. | displacement와 reaction은 node identity, B33 section resultant는 정규화된 node station identity로 비교하고 stress reference comparison은 N/A로 기록한다. | reference comparison report |
|
||||
| FESA-PRD-008 | FESA의 production C++ 변경은 테스트를 먼저 작성하고 실패를 확인한 뒤 구현해야 한다. | 관련 C++ test file, RED 실패와 후속 GREEN 성공 증거가 있고 Stop의 전체 MSVC build/test가 통과한다. | implementation report, Hook guardrail, CTest |
|
||||
| FESA-PRD-009 | FESA는 외부 라이브러리 API를 solver core에 직접 노출하지 않아야 한다. | MKL, TBB, HDF5 의존은 adapter module에 제한된다. | architecture review, dependency review |
|
||||
| FESA-PRD-010 | FESA 기능 완료는 reference comparison과 physics sanity 통과를 요구해야 한다. | 수치 tolerance와 물리 검토가 모두 pass이고 known limitation이 기록된다. | verification report, physics evaluation report |
|
||||
| FESA-PRD-011 | V0는 입력 파일당 하나의 linear static step과 Abaqus B33 3D Euler beam만 해석해야 한다. | 단일 B33 model은 해석되고, B31과 두 번째 step은 구조화된 unsupported diagnostic으로 거부된다. | parser/semantic unit test, CLI integration test |
|
||||
| FESA-PRD-012 | V0는 Part/Assembly/Instance wrapper와 source identity를 보존해야 한다. | 여러 identity instance의 node/element/set label이 stable internal ID로 deterministic하게 매핑되고 transform 또는 nested assembly는 거부된다. | semantic mapping unit test |
|
||||
| FESA-PRD-013 | Output-request allowlist는 해석 의미를 변경하지 않아야 한다. | 승인 keyword와 variable data는 warning 후 no-op이고, allowlist 밖 model-affecting keyword는 오류이며 기본 결과는 output request와 무관하게 생성된다. | parser diagnostic test, HDF5 integration test |
|
||||
| FESA-PRD-014 | 선형 정적 pipeline은 stiffness factorization과 load substitution을 분리해야 한다. | `Kff` factorization이 load vector assembly보다 먼저 수행되고, `rhs=Ff-Kfc*dc` substitution으로 full displacement를 복구한다. | orchestration test, solver-adapter test |
|
||||
| FESA-PRD-015 | FESA는 V0 결과와 diagnostic을 안정된 외부 계약으로 출력해야 한다. | CLI가 `0=success`, `2=usage`, `3=input`, `4=model`, `5=solver`, `6=HDF5` exit code를 사용하고 diagnostic field가 계약과 일치하며 HDF5가 displacement, reaction, end force, section resultant, generalized strain/resultant, axial `S11`을 포함하고 실패 시 불완전한 최종 파일을 남기지 않는다. | CLI integration test, HDF5 schema/atomicity test |
|
||||
| FESA-PRD-016 | Dense와 sparse math storage 및 backend 경계를 분리해야 한다. | `Vector`는 contiguous, `Matrix`는 row-major contiguous storage와 MKL CBLAS를 사용하고 `SparseMatrix`는 별도 0-based CSR 타입이며 MKL 타입이 public core API에 노출되지 않는다. | math unit test, dependency review |
|
||||
| FESA-PRD-017 | B33 reference comparison은 component-scale 혼합 tolerance를 사용해야 한다. | 모든 matched row가 `abs_error <= absolute_floor + 1e-6 * reference_scale`을 만족하고 missing/extra/nonfinite row는 comparison 전에 실패한다. | reference comparison unit/integration test, verification report |
|
||||
| FESA-PRD-018 | 승인된 B33 reference artifact는 read-only baseline으로 유지해야 한다. | `reference/cantilever beam/` 파일을 rename, rewrite, 보정하지 않고 exact legacy path로 읽으며 B33 element type과 expected headers를 artifact check에서 확인한다. | artifact inventory, Git diff review |
|
||||
| FESA-PRD-019 | B33 beam section과 local axis를 Abaqus 의미에 맞게 매핑해야 한다. | `n1 -> local y`, `t x n1 -> local z`, `Iy=I11`, `Iz=I22`, `I12=0`을 적용하고 nonpositive property, zero-length element, tangent-parallel guide vector를 구조화된 model diagnostic으로 거부한다. | section-mapping unit test, element geometry test |
|
||||
|
||||
## 비기능 요구조건
|
||||
- MSVC x64 Debug 환경에서 configure, build, CTest를 검증한다.
|
||||
- reference test 결과는 deterministic해야 한다.
|
||||
- HDF5 schema는 versioned contract로 관리한다.
|
||||
- tolerance policy는 absolute, relative, norm-based 기준을 구분한다.
|
||||
- B33 reference tolerance는 model, step/frame, quantity, component별 Abaqus scale만 사용한다.
|
||||
- 승인된 SI B33 bundle의 absolute floor는 displacement/rotation `1e-9`, force/moment
|
||||
`1e-3`이며 relative coefficient는 `1e-6`이다.
|
||||
- parser, solver, HDF5 writer는 실패 원인을 구조화된 diagnostic으로 보고한다.
|
||||
- oneMKL, oneTBB, HDF5는 CMake에서 명시 탐지하고 실패 원인을 분류한다.
|
||||
- 대규모 모델 성능 최적화보다 Phase 1 명확성, 테스트 가능성, 검증 traceability를 우선한다.
|
||||
- 대규모 모델 성능 최적화보다 V0의 명확성, 테스트 가능성, 검증 traceability를 우선한다.
|
||||
|
||||
## Acceptance Gates
|
||||
1. Requirements approved: 기능 범위, 제외 범위, 입력, 출력, tolerance, 검증 물리량이 정의되어 있다.
|
||||
2. Research evidence complete: 정식화와 benchmark 근거가 신뢰도와 한계와 함께 정리되어 있다.
|
||||
3. Formulation reviewed: 약형, shape function, B matrix, constitutive contract, 수치적분, output recovery가 검토되어 있다.
|
||||
4. I/O contract approved: Abaqus keyword subset, internal model mapping, HDF5 result contract, reference CSV comparison row contract가 승인되어 있다.
|
||||
5. Tests fail before implementation: 구현 전 실패해야 하는 C++/integration/reference test가 준비되어 있다.
|
||||
5. Tests fail before implementation: C++/integration/reference test를 제품 코드보다 먼저 작성하고 같은 Step 안에서 RED 실패와 후속 GREEN 성공을 확인한다.
|
||||
6. CMake/CTest pass: MSVC/x64/Debug 기준 configure, build, test가 통과한다.
|
||||
7. Reference comparison pass: FESA `results.h5` rows와 Abaqus reference CSV rows가 documented IDs, components, units, coordinate system, step/frame identity, tolerance 기준 안에 있다.
|
||||
8. Physics sanity pass: equilibrium, reaction consistency, displacement direction, symmetry, stress sanity가 검토되어 있다.
|
||||
7. Reference comparison pass: FESA `results.h5`의 displacement, reaction, section resultant rows가 승인된 B33 CSV와 documented identity 및 component-scale 혼합 tolerance 안에 있다. Beam stress comparison은 명시적 N/A다.
|
||||
8. Physics sanity pass: equilibrium, reaction consistency, displacement direction, symmetry, section-force consistency와 normalized residual이 검토되어 있다.
|
||||
9. Release readiness pass: acceptance traceability, known limitations, release notes draft가 준비되어 있다.
|
||||
|
||||
## 제외 사항
|
||||
- Abaqus full parser 호환
|
||||
- Abaqus B31/Timoshenko beam
|
||||
- 다중 analysis step과 step 간 load/BC propagation
|
||||
- instance translation/rotation, nested assembly 및 dependent/independent mesh semantics
|
||||
- `I12 != 0`, taper, offset, release, curved beam, warping
|
||||
- Abaqus `*DLOAD` 입력과 Domain distributed-load object
|
||||
- 기하·재료비선형, dynamics, contact, thermal effects
|
||||
- transverse shear stress와 torsional shear stress recovery
|
||||
- beam stress에 대한 Abaqus reference comparison
|
||||
- Abaqus, Nastran 또는 reference solver 직접 실행 자동화
|
||||
- Agent가 Abaqus reference CSV 파일을 임의 생성 또는 수정하는 작업
|
||||
- GUI 또는 postprocessor
|
||||
- Visual Studio `.sln`/`.vcxproj` 전용 MSBuild workflow
|
||||
- Explicit dynamics, contact, plasticity, shell end-to-end 구현
|
||||
- JavaScript/TypeScript fallback 유지
|
||||
- plasticity와 shell end-to-end 구현
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
- Abaqus나 Nastran을 Agent가 직접 실행하지 않는다. `reference/<model-id>/`에 저장된 `model.inp`, `metadata.json`, Abaqus reference CSV files를 검증 기준으로 사용한다.
|
||||
- 기본 개발 환경은 C++17 이상, MSVC, CMake, CTest이다.
|
||||
- 모든 기능은 tolerance 기준을 명시하고, 기준을 만족할 때만 배포 후보가 된다.
|
||||
- Harness 운영은 `docs/HARNESS_WORKFLOW.md`의 계획, 독립 Step 실행, PreToolUse/Stop 검증 계층을 따른다.
|
||||
|
||||
## 전체 Agent 구성
|
||||
|
||||
@@ -168,15 +169,20 @@ C++ 코드를 구현하는 Agent이다.
|
||||
빌드와 테스트를 실행하는 Agent이다.
|
||||
|
||||
책임:
|
||||
- Harness validation을 실행한다.
|
||||
- `.harness/config.json` 또는 자동 감지 결과에 맞는 MSVC build/test 명령을 실행한다.
|
||||
- MSVC x64 Debug CMake configure/build/CTest 결과를 수집한다.
|
||||
- 실패 로그를 요약하고 Correction Agent에 전달한다.
|
||||
|
||||
기본 검증 명령:
|
||||
기본 CMake 검증 명령:
|
||||
```powershell
|
||||
python scripts/validate_workspace.py
|
||||
cmake -S . -B .harness/build -A x64
|
||||
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
|
||||
```
|
||||
|
||||
Preset 또는 직접 MSBuild 프로젝트는 `.harness/config.json`에 선언된 명령을 따른다.
|
||||
|
||||
검증 대상:
|
||||
- CMake configure
|
||||
- MSVC Debug build
|
||||
@@ -301,7 +307,8 @@ flowchart TD
|
||||
통과 조건:
|
||||
- CMake/MSVC/CTest validation이 통과한다.
|
||||
- 단위 테스트와 통합 테스트가 통과한다.
|
||||
- Harness TDD guard를 만족한다.
|
||||
- 관련 C++ test file이 있고 같은 구현 Step 안에 RED 실패와 후속 GREEN 성공 증거가 있다.
|
||||
- Stop의 전체 MSVC build/test 검증이 통과한다.
|
||||
|
||||
### Gate 5: 레퍼런스 검증
|
||||
통과 조건:
|
||||
@@ -352,11 +359,12 @@ Coordinator Agent는 분류 결과에 따라 Requirement, Formulation, I/O Defin
|
||||
## 초기 적용 우선순위
|
||||
|
||||
1. 선형 정적 해석의 최소 골격
|
||||
2. 1D truss 또는 bar element
|
||||
3. 2D plane stress/plane strain element
|
||||
4. 3D solid element
|
||||
5. material model 확장
|
||||
6. nonlinear 또는 dynamic analysis 확장
|
||||
2. Isoparametric 3D Euler beam element
|
||||
3. 1D truss 또는 bar element
|
||||
4. 2D plane stress/plane strain element
|
||||
5. 3D solid element
|
||||
6. material model 확장
|
||||
7. nonlinear 또는 dynamic analysis 확장
|
||||
|
||||
각 단계는 요구조건, 정식화, 테스트모델, 구현, 레퍼런스 비교, 배포 Gate를 독립적으로 통과해야 한다.
|
||||
|
||||
|
||||
+20
-14
@@ -15,7 +15,8 @@ Agent는 역할과 책임 단위이고, skill은 여러 Agent가 반복적으로
|
||||
- Abaqus, Nastran 또는 reference solver 실행은 skill 범위에 포함하지 않는다.
|
||||
- Abaqus reference CSV 파일 생성/수정은 skill 범위에 포함하지 않는다.
|
||||
- C++ 구현 관련 skill은 C++17 이상, MSVC, CMake, CTest, TDD 원칙을 따른다.
|
||||
- 기본 workspace validation 명령은 `python scripts/validate_workspace.py`이다.
|
||||
- C++ 검증 명령은 `.harness/config.json` 또는 `docs/HARNESS.md`의 자동 감지 기본값을 따른다.
|
||||
- Harness Python 변경은 `uv run --with pytest python -m pytest -v -rs`로 검증한다.
|
||||
|
||||
## Skill 구성
|
||||
|
||||
@@ -34,10 +35,10 @@ Agent는 역할과 책임 단위이고, skill은 여러 Agent가 반복적으로
|
||||
|
||||
## 개발 과정별 사용 예
|
||||
|
||||
예시 기능: `linear-truss-1d`
|
||||
예시 기능: `isoparametric-3d-euler-beam`
|
||||
|
||||
1. Requirement Agent는 `fesa-requirements-baseline`을 사용해 기능 범위, 제외 범위, 입력, 출력, 검증 물리량, tolerance, `Requirement Verification Matrix`를 작성한다.
|
||||
2. Research Agent는 `fesa-research-evidence`를 사용해 truss/bar element 이론, benchmark 후보, source reliability, applicability limits를 정리한다.
|
||||
2. Research Agent는 `fesa-research-evidence`를 사용해 3D Euler beam element 이론, benchmark 후보, source reliability, applicability limits를 정리한다.
|
||||
3. Formulation Agent는 `fesa-formulation-spec`을 사용해 strong form, weak form, shape functions, B matrix, element stiffness, output recovery를 정리한다.
|
||||
4. Numerical Review Agent는 `fesa-numerical-review`를 사용해 rigid body modes, patch test, stiffness symmetry, Jacobian, locking 위험을 검토하고 `pass-for-implementation-planning` 여부를 판단한다.
|
||||
5. I/O Definition Agent는 `fesa-io-contract`를 사용해 지원할 Abaqus `.inp` keyword subset, `results.h5` schema, reference CSV comparison row schema를 정의한다.
|
||||
@@ -98,9 +99,17 @@ Agent는 역할과 책임 단위이고, skill은 여러 Agent가 반복적으로
|
||||
- 기본 검증 명령:
|
||||
|
||||
```powershell
|
||||
python -m unittest discover -s scripts -p "test_*.py"
|
||||
python scripts/validate_workspace.py
|
||||
ctest -C Debug -R <feature-or-label>
|
||||
cmake -S . -B .harness/build -A x64
|
||||
cmake --build .harness/build --config Debug
|
||||
ctest --test-dir .harness/build -C Debug -R <feature-or-label> --output-on-failure
|
||||
ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
```
|
||||
|
||||
Preset 또는 직접 MSBuild 프로젝트는 `.harness/config.json`의 설정을 사용한다. Harness
|
||||
Python, Hook, agent config를 변경한 경우에는 다음 명령도 실행한다.
|
||||
|
||||
```powershell
|
||||
uv run --with pytest python -m pytest -v -rs
|
||||
```
|
||||
|
||||
- 실패는 `configure | compile | link | test | reference-comparison | harness | environment | upstream-contract`로 분류한다.
|
||||
@@ -148,7 +157,8 @@ ctest -C Debug -R <feature-or-label>
|
||||
|
||||
## 검증 기준
|
||||
|
||||
Skill 구성 검증은 `scripts/test_fesa_solver_skills.py`가 담당한다.
|
||||
Skill 구성은 실제 `.codex/skills/` 파일을 source of truth로 삼아 정적 계약과 repository
|
||||
pytest suite로 검증한다.
|
||||
|
||||
검증 항목:
|
||||
|
||||
@@ -163,15 +173,11 @@ Skill 구성 검증은 `scripts/test_fesa_solver_skills.py`가 담당한다.
|
||||
검증 명령:
|
||||
|
||||
```powershell
|
||||
python -m unittest discover -s scripts -p "test_*.py"
|
||||
python scripts/validate_workspace.py
|
||||
uv run --with pytest python -m pytest -v -rs
|
||||
```
|
||||
|
||||
Skill 구조 검증:
|
||||
|
||||
```powershell
|
||||
python C:\Users\user\.codex\skills\.system\skill-creator\scripts\quick_validate.py .codex\skills\<skill-name>
|
||||
```
|
||||
개별 skill schema를 점검할 때는 현재 Codex 설치에 포함된 `skill-creator` validator를
|
||||
사용하되 사용자 홈을 하드코딩한 경로를 프로젝트 계약으로 두지 않는다.
|
||||
|
||||
## v1 범위
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# FESA 초기 문서 완성 계획 노트
|
||||
|
||||
> **Historical / Superseded:** 이 문서는 2026-06-10 시점의 초기 조사와 실행 기록이다.
|
||||
> 현재 제품 범위는 `docs/PRD.md`, Harness 운영 계약은 `docs/HARNESS_WORKFLOW.md`와
|
||||
> `docs/HARNESS.md`를 따른다. 아래의 구형 스킬명, 검증 명령, 기능 우선순위는 현재
|
||||
> 지침으로 사용하지 않는다.
|
||||
|
||||
## 메타데이터
|
||||
- 작성일: 2026-06-10
|
||||
- 목적: `AGENTS.md`, `docs/PRD.md`, `docs/ARCHITECTURE.md`를 유한요소법 기반 구조해석 솔버 개발 프로젝트 문서로 완성하기 위한 조사 내용과 실행 계획 정리
|
||||
@@ -2,16 +2,17 @@
|
||||
|
||||
이 디렉터리는 Build/Test Executor Agent가 작성하거나 제안하는 기능별 build/test 실행 리포트를 보관하는 위치다.
|
||||
|
||||
Build/Test Executor Agent는 Implementation Agent 이후 독립적으로 C++/MSVC/CMake/CTest 검증을 실행하고, 실패를 분류해 다음 agent로 handoff한다. 이 agent는 source code, tests, CMake files, requirements, formulations, I/O contracts, reference artifacts, tolerance policies를 수정하지 않는다. build artifacts와 test outputs는 `build/` 아래 생성될 수 있다.
|
||||
Build/Test Executor Agent는 Implementation Agent 이후 독립적으로 C++/MSVC/CMake/CTest 검증을 실행하고, 실패를 분류해 다음 agent로 handoff한다. 이 agent는 source code, tests, CMake files, requirements, formulations, I/O contracts, reference artifacts, tolerance policies를 수정하지 않는다. 기본 build artifact는 `.harness/build/` 아래 생성된다.
|
||||
|
||||
기본 문서명은 `docs/build-test-reports/<feature-id>-build-test.md` 형식을 사용한다.
|
||||
|
||||
## Build/Test Executor Agent 역할
|
||||
|
||||
수행한다:
|
||||
- `python scripts/validate_workspace.py`를 기본 검증 명령으로 실행한다.
|
||||
- implementation plan/report에 명시된 경우 harness self-test와 feature-specific CTest를 실행한다.
|
||||
- `HARNESS_VALIDATION_COMMANDS`, `CMakePresets.json`의 `msvc-debug`, 기본 CMake/MSVC x64 Debug 경로 중 어떤 검증 경로가 사용되었는지 기록한다.
|
||||
- `.harness/config.json`과 프로젝트 자동 감지 결과를 확인하고 같은 build/test 경로를 독립 실행한다.
|
||||
- implementation plan/report에 명시된 feature-specific CTest를 전체 검증 전에 실행한다.
|
||||
- Harness Python, Hook, agent config 변경이 포함되면 `uv run --with pytest python -m pytest -v -rs`를 실행한다.
|
||||
- CMake preset, 직접 MSBuild, 기본 CMake/MSVC x64 Debug 중 어떤 검증 경로가 사용되었는지 기록한다.
|
||||
- configure, compile, link, test, reference-comparison, harness, environment, upstream-contract 실패를 구분한다.
|
||||
- command, exit code, duration, stdout/stderr tail, failed test name을 요약한다.
|
||||
- 실패 원인에 따라 Implementation Agent, Correction Agent, Reference Verification Agent, Implementation Planning Agent 중 handoff 대상을 제안한다.
|
||||
@@ -28,29 +29,43 @@ Build/Test Executor Agent는 Implementation Agent 이후 독립적으로 C++/MSV
|
||||
|
||||
## 실행 순서
|
||||
|
||||
기본 순서는 implementation plan/report에 따라 다음 중 필요한 항목만 실행한다.
|
||||
기본 순서는 implementation plan/report에 따라 다음 중 필요한 항목을 실행한다.
|
||||
|
||||
```powershell
|
||||
python -m unittest discover -s scripts -p "test_*.py"
|
||||
ctest -C Debug -R <feature-or-label>
|
||||
python scripts/validate_workspace.py
|
||||
cmake -S . -B .harness/build -A x64
|
||||
cmake --build .harness/build --config Debug
|
||||
ctest --test-dir .harness/build -C Debug -R <feature-or-label> --output-on-failure
|
||||
ctest --test-dir .harness/build -C Debug --show-only=json-v1
|
||||
ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
```
|
||||
|
||||
`scripts/validate_workspace.py`의 command discovery 우선순위는 다음과 같다.
|
||||
Harness Python, Hook, agent config 변경이 검증 범위에 포함되면 다음 명령을 먼저 실행한다.
|
||||
|
||||
1. `HARNESS_VALIDATION_COMMANDS`
|
||||
2. `CMakePresets.json`의 `msvc-debug`
|
||||
3. 기본 CMake/MSVC x64 Debug 명령
|
||||
4. `CMakeLists.txt`가 없고 override도 없으면 안내 메시지와 함께 성공 종료
|
||||
```powershell
|
||||
uv run --with pytest python -m pytest -v -rs
|
||||
```
|
||||
|
||||
프로젝트 선택 우선순위는 다음과 같다.
|
||||
|
||||
1. `.harness/config.json`의 명시적 `projectType`
|
||||
2. 루트의 CMake metadata
|
||||
3. 루트의 단일 `.sln`
|
||||
4. 루트의 단일 `.vcxproj`
|
||||
|
||||
기본 CMake/MSVC x64 Debug 명령은 다음과 같다.
|
||||
|
||||
```powershell
|
||||
cmake -S . -B build/msvc-debug -G "Visual Studio 17 2022" -A x64
|
||||
cmake --build build/msvc-debug --config Debug
|
||||
ctest --test-dir build/msvc-debug --output-on-failure -C Debug
|
||||
cmake -S . -B .harness/build -A x64
|
||||
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
|
||||
```
|
||||
|
||||
CMake preset을 사용하면 configure/build/test preset과 `binaryDir`를 모두
|
||||
`.harness/config.json`에 지정한다. 직접 MSBuild는 solution/project와
|
||||
`msbuild.testCommand`를 지정한다. C/C++와 build metadata가 모두 없으면 검증 대상이
|
||||
없으므로 통과하지만, C/C++ 파일만 있고 build metadata가 없으면 오류다.
|
||||
|
||||
## 문서 템플릿
|
||||
|
||||
```markdown
|
||||
@@ -69,17 +84,19 @@ ctest --test-dir build/msvc-debug --output-on-failure -C Debug
|
||||
- generator: Visual Studio 17 2022 | <observed generator>
|
||||
- platform: x64 | <observed platform>
|
||||
- config: Debug | <observed config>
|
||||
- build_dir: build/msvc-debug | <observed build dir>
|
||||
- active_override_env_vars: HARNESS_VALIDATION_COMMANDS | HARNESS_CMAKE_GENERATOR | HARNESS_CMAKE_PLATFORM | HARNESS_CMAKE_CONFIG | HARNESS_BUILD_DIR | none
|
||||
- command_discovery_path: HARNESS_VALIDATION_COMMANDS | CMakePresets.json msvc-debug | default CMake/MSVC x64 Debug | no-CMake informational success
|
||||
- build_dir: .harness/build | <configured/observed build dir>
|
||||
- harness_config: .harness/config.json | absent-defaults
|
||||
- project_selection: configured cmake | configured msbuild | auto CMake | auto MSBuild | no C/C++ project
|
||||
- command_discovery_path: CMake preset | direct MSBuild | default CMake/MSVC x64 Debug | no C/C++ project
|
||||
|
||||
## Command Log Summary
|
||||
|
||||
| order | command | exit_code | duration | stdout_stderr_tail |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1 | python -m unittest discover -s scripts -p "test_*.py" | <code> | <duration> | <tail summary> |
|
||||
| 2 | ctest -C Debug -R <feature-or-label> | <code> | <duration> | <tail summary> |
|
||||
| 3 | python scripts/validate_workspace.py | <code> | <duration> | <tail summary> |
|
||||
| 1 | uv run --with pytest python -m pytest -v -rs (when applicable) | <code or skipped> | <duration> | <tail summary> |
|
||||
| 2 | <config-resolved configure/build commands> | <code> | <duration> | <tail summary> |
|
||||
| 3 | <feature-specific test command when applicable> | <code or skipped> | <duration> | <tail summary> |
|
||||
| 4 | <config-resolved test discovery/full test commands> | <code> | <duration> | <tail summary> |
|
||||
|
||||
## Validation Results
|
||||
|
||||
@@ -137,7 +154,7 @@ ctest --test-dir build/msvc-debug --output-on-failure -C Debug
|
||||
- 모든 실행 명령과 exit code를 기록해야 한다.
|
||||
- 실패 로그는 전체 원문을 복제하지 않고 마지막 핵심 구간과 실패 원인을 요약한다.
|
||||
- configure, compile, link, test, reference-comparison, harness, environment, upstream-contract 실패를 구분한다.
|
||||
- no-CMake 상황은 `scripts/validate_workspace.py` 정책대로 안내 메시지와 성공 종료로 기록한다.
|
||||
- C/C++와 build metadata가 모두 없는 상황만 `no C/C++ project` 성공으로 기록한다. C/C++ 파일이 있는데 build metadata가 없으면 `environment` 또는 `configure` 실패로 기록한다.
|
||||
- 성공 판정은 build/test 통과까지만 의미한다.
|
||||
- reference tolerance, physics validation, release readiness는 판정하지 않는다.
|
||||
- upstream 계약 문제는 Implementation Agent에 임의 수정으로 넘기지 않고 적절한 upstream agent로 handoff한다.
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
# Linear Static 3D Euler Beam Build/Test Report
|
||||
|
||||
## Metadata
|
||||
|
||||
- feature_id: `linear-static-3d-euler-beam`
|
||||
- source_commit: `400db191ce9f766ca6b34e5b609eaa13c54ccfa3`
|
||||
- source_implementation_report: `docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`
|
||||
- source_implementation_plan: `docs/implementation-plans/linear-static-3d-euler-beam.md`
|
||||
- status: `pass-for-reference-verification`
|
||||
- owner_agent: `build-test-executor-agent`
|
||||
- date: `2026-08-09`
|
||||
- evidence_window: `2026-08-09T23:16:20.8670416+09:00` through `2026-08-09T23:20:15.7264584+09:00`
|
||||
|
||||
## Verdict
|
||||
|
||||
Fresh Visual Studio 18 2026/MSVC x64 Debug configuration, a clean full rebuild,
|
||||
the exact Step 25 configure/build commands, nonzero JSON discovery, the feature-label
|
||||
CTest run, and the full CTest run all passed. CTest discovered the expected 83 tests
|
||||
and both executed suites passed 83/83. The clean rebuild emitted no compiler or linker
|
||||
warning line, and generated FESA product projects retain Level 4 plus warnings-as-errors.
|
||||
|
||||
The build/test gate therefore passes for handoff to Step 26 Reference Verification.
|
||||
This verdict does not approve reference tolerance, physics sanity, or release readiness.
|
||||
|
||||
## Execution Environment
|
||||
|
||||
- os: `Microsoft Windows 11 Home 10.0.26200 build 26200; 64-bit`
|
||||
- source_head: `400db191ce9f766ca6b34e5b609eaa13c54ccfa3`
|
||||
- generator: `Visual Studio 18 2026`
|
||||
- Visual Studio: `Community 18.8.2` (`18.8.12023.21`)
|
||||
- MSBuild: `18.8.2+ce25c0108`
|
||||
- compiler: `MSVC 19.51.36252.0`
|
||||
- compiler_architecture: `x64`
|
||||
- Windows SDK: `10.0.26100.0`
|
||||
- language: `C++17`, required, extensions disabled
|
||||
- config: `Debug`
|
||||
- build_dir: `.harness/build`
|
||||
- harness_config: absent; repository auto-CMake defaults plus Step 25 explicit cache values
|
||||
- project_selection: auto CMake from root `CMakeLists.txt`
|
||||
- command_discovery_path: default CMake/MSVC x64 Debug with explicit local dependency paths
|
||||
- CMake / CTest: `4.4.0 / 4.4.0`
|
||||
|
||||
### Dependency Revisions
|
||||
|
||||
| dependency | resolved revision or version | evidence |
|
||||
| --- | --- | --- |
|
||||
| GoogleTest | `04ee1b4f2aefdffb0135d7cf2a2c519fe50dabe4` | clean `C:/git/googletest` checkout HEAD |
|
||||
| Intel oneMKL | `2026.1.0` | `MKLConfigVersion.cmake`; configure reported `MKL_VERSION: 2026.1.0`, dynamic ILP64, Intel threading |
|
||||
| Intel oneTBB | `2023.1.0` | `TBBConfigVersion.cmake` from the configured `2023.1` package |
|
||||
| HDF5 | `2.1.1` | `hdf5-config-version.cmake` from the configured `2.1.1` package |
|
||||
|
||||
## Freshness and Configuration Resolution
|
||||
|
||||
The ignored generated build tree already existed. Fresh evidence was obtained without
|
||||
reusing its cache or products by running CMake `--fresh` with the generator explicitly
|
||||
fixed to Visual Studio 18 2026, then running the generated `clean` target before the
|
||||
full build. The literal no-`--fresh`, no-`-G` configure command from Step 25 was then
|
||||
run against that resolved VS18 cache and followed by the literal build, discovery,
|
||||
feature-label, and full-test commands.
|
||||
|
||||
Post-configure metadata recorded:
|
||||
|
||||
- `CMAKE_GENERATOR=Visual Studio 18 2026`
|
||||
- `CMAKE_GENERATOR_PLATFORM=x64`
|
||||
- `CMAKE_CXX_COMPILER_ID=MSVC`
|
||||
- `CMAKE_CXX_COMPILER_VERSION=19.51.36252.0`
|
||||
- `CMAKE_CXX_COMPILER_ARCHITECTURE_ID=x64`
|
||||
|
||||
## Command Log Summary
|
||||
|
||||
| order | command | start / end | exit code | duration | verdict and stdout/stderr tail |
|
||||
| ---: | --- | --- | ---: | ---: | --- |
|
||||
| 1 | `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"` | `23:16:20.867+09:00` / `23:16:27.706+09:00` | 0 | `6.836 s` | pass; MKL 2026.1.0 and required runtime libraries resolved; `Configuring done`, `Generating done`, build files written to `.harness/build` |
|
||||
| 2 | `cmake --build .harness/build --config Debug --target clean` | `23:16:37.194+09:00` / `23:16:37.914+09:00` | 0 | `0.716 s` | pass; generated VS18 clean target completed |
|
||||
| 3 | `cmake --build .harness/build --config Debug` | `23:16:47.054+09:00` / `23:18:01.769+09:00` | 0 | `74.713 s` | pass; clean compile/link produced `fesa.exe` and all three test executables; warning scan count `0` |
|
||||
| 4 | `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"` | `23:19:10.210+09:00` / `23:19:10.861+09:00` | 0 | `0.649 s` | pass; exact Step 25 command selected Windows SDK 10.0.26100.0, retained VS18/x64, and completed configure/generate |
|
||||
| 5 | `cmake --build .harness/build --config Debug` | `23:19:25.404+09:00` / `23:19:28.969+09:00` | 0 | `3.562 s` | pass; exact Step 25 build confirmed `fesa_solver`, `fesa.exe`, and all test executables; warning scan count `0` |
|
||||
| 6 | `ctest --test-dir .harness/build -C Debug --show-only=json-v1` | `23:19:45.728+09:00` / `23:19:45.798+09:00` | 0 | `0.065 s` | pass; JSON kind `ctestInfo` version 1.0; 83 tests; every test has the feature label |
|
||||
| 7 | `ctest --test-dir .harness/build -C Debug -L linear-static-3d-euler-beam --output-on-failure` | `23:20:00.199+09:00` / `23:20:04.163+09:00` | 0 | `3.961 s` | pass; `100% tests passed out of 83`; real test time `3.92 s` |
|
||||
| 8 | `ctest --test-dir .harness/build -C Debug --output-on-failure` | `23:20:11.899+09:00` / `23:20:15.726+09:00` | 0 | `3.825 s` | pass; `100% tests passed out of 83`; real test time `3.79 s` |
|
||||
|
||||
An initial post-clean discovery/feature/full smoke was also run before the literal
|
||||
configure replay: discovery exit 0 in `0.068 s` with 83 tests, feature-label CTest
|
||||
exit 0 in `4.244 s` with 83/83, and full CTest exit 0 in `4.011 s` with 83/83.
|
||||
Rows 4 through 8 are the final canonical Step 25 acceptance chain.
|
||||
|
||||
## Validation Results
|
||||
|
||||
| validation_stage | result | evidence |
|
||||
| --- | --- | --- |
|
||||
| harness self-test | skipped | No Harness Python, Hook, or agent-config file is part of HEAD `400db19` verification scope. |
|
||||
| fresh configure | pass | Explicit VS18/x64 `--fresh` configure exit 0, followed by clean target exit 0. |
|
||||
| exact configure | pass | Literal Step 25 configure exit 0; generated metadata is MSVC/x64. |
|
||||
| clean full build | pass | Exit 0 after clean; all source and test translation units compiled and linked. |
|
||||
| exact build | pass | Exit 0; product and three test executables confirmed. |
|
||||
| compiler/warning policy | pass | `fesa_solver` and `fesa_cli` generated projects have `Level4` and `TreatWarningAsError=true`; clean and exact build scans found zero warning lines. |
|
||||
| CTest discovery | pass | Exit 0; 83 tests, greater than zero and equal to the expected inventory. |
|
||||
| feature-specific tests | pass | Label `linear-static-3d-euler-beam`: 83/83 passed. |
|
||||
| full CTest | pass | 83/83 passed with zero failed tests. |
|
||||
| reference immutability | pass | Pre/post `git diff --exit-code -- reference/` exit 0, status empty, and four exact SHA-256 values unchanged. |
|
||||
| source worktree before report | pass | `git status --short` empty at HEAD `400db19`. |
|
||||
|
||||
## CTest Inventory
|
||||
|
||||
### Label Inventory
|
||||
|
||||
| label | count |
|
||||
| --- | ---: |
|
||||
| `linear-static-3d-euler-beam` | 83 |
|
||||
| `unit` | 73 |
|
||||
| `integration` | 5 |
|
||||
| `reference` | 5 |
|
||||
|
||||
### Suite Inventory and Step Trace
|
||||
|
||||
| implementation Step | CTest suite or suites | count | cumulative count | Step 7-24 report evidence audit |
|
||||
| ---: | --- | ---: | ---: | --- |
|
||||
| 7 | `BuildInfo` | 2 | 2 | pass |
|
||||
| 8 | `CoreDiagnostics` | 3 | 5 | pass |
|
||||
| 9 | `DenseMath` | 2 | 7 | pass |
|
||||
| 10 | `DomainModel` | 3 | 10 | pass |
|
||||
| 11 | `InpSyntax` | 4 | 14 | pass |
|
||||
| 12 | `InpDomainMapping` | 5 | 19 | pass |
|
||||
| 13 | `AnalysisModel` | 3 | 22 | pass |
|
||||
| 14 | `DofManager` | 4 | 26 | pass |
|
||||
| 15 | `AnalysisState` | 3 | 29 | pass |
|
||||
| 16 | `EulerBeam3D` | 10 | 39 | pass |
|
||||
| 17 | `ParallelFor` | 3 | 42 | pass |
|
||||
| 18 | `SparseAssembly` | 5 | 47 | pass |
|
||||
| 19 | `EssentialConstraints` | 4 | 51 | pass |
|
||||
| 20 | `MklPardisoSolver` | 6 | 57 | pass |
|
||||
| 21 | `LoadAssembly` | 5 | 62 | pass |
|
||||
| 22 | `ResultRecovery` | 6 | 68 | pass |
|
||||
| 23 | `Hdf5ResultsWriter` | 5 | 73 | pass |
|
||||
| 24 | `LinearStaticCli` (5), `ReferenceComparisonContract` (4), `B33ReferenceComparison` (1) | 10 | 83 | pass |
|
||||
|
||||
The JSON inventory contains every exact test name registered by GoogleTest discovery.
|
||||
No duplicate CTest name was observed; the label partition is exactly 73 unit + 5
|
||||
integration + 5 reference = 83.
|
||||
|
||||
## Step 7-24 Implementation Evidence Audit
|
||||
|
||||
The cumulative implementation report was checked block-by-block against the implementation
|
||||
plan and the phase index summaries. All 18 Step blocks are present and each records:
|
||||
|
||||
- its matching `TASK-07` through `TASK-24`, `status: completed`, changed files,
|
||||
requirement IDs, and test IDs;
|
||||
- at least one implementation-owned nonzero RED command with the expected missing API
|
||||
or named behavioral failure;
|
||||
- a zero-exit GREEN build/test for the Step's targeted CTest suite;
|
||||
- zero-exit MSVC x64 configure/build, nonzero JSON discovery, and zero-failure full CTest;
|
||||
- `/W4 /WX` or equivalent generated warning-policy evidence and reference-tree
|
||||
immutability evidence.
|
||||
|
||||
Step 20 and Step 22 additionally retain valid behavioral RED/GREEN correction evidence.
|
||||
Step 23 records its environment link incident separately from the valid missing-API RED,
|
||||
so the environment incident was not counted as TDD evidence. The cumulative counts in the
|
||||
implementation report and the Step 7-24 phase summaries progress exactly to the freshly
|
||||
discovered 83-test inventory above.
|
||||
|
||||
The implementation report's cumulative header still says `in-progress`; the audited
|
||||
step-local evidence contract and phase index nevertheless mark every implementation Step
|
||||
7-24 `completed`. This stale aggregate header is not a missing Step block, missing test,
|
||||
or failed build/test gate and was not modified by the independent executor.
|
||||
|
||||
## `/W4 /WX` and Warning Audit
|
||||
|
||||
- `src/fesa/CMakeLists.txt` applies `/W4 /WX` privately to `fesa_solver` and `fesa_cli`.
|
||||
- Generated `fesa_solver.vcxproj` and `fesa_cli.vcxproj` contain
|
||||
`<WarningLevel>Level4</WarningLevel>` and
|
||||
`<TreatWarningAsError>true</TreatWarningAsError>` for Debug and the other generated
|
||||
configurations.
|
||||
- The clean 74.713-second build recompiled the product and all test translation units;
|
||||
its compiler/linker warning scan found `0` lines.
|
||||
- The exact post-configure build also exited 0 and found `0` warning lines.
|
||||
|
||||
Result: no product warning was emitted, and any MSVC product warning would have failed
|
||||
the build under `/WX`.
|
||||
|
||||
## Reference Read-Only Audit
|
||||
|
||||
The following SHA-256 values were identical before and after all configure/build/test
|
||||
commands, while both reference diff checks exited 0 and both reference status checks
|
||||
were empty:
|
||||
|
||||
| exact approved legacy path | SHA-256 |
|
||||
| --- | --- |
|
||||
| `reference/cantilever beam/cantilever beam.inp` | `E406EA9560321B791DB829E03BD24593B9875E0195D35B86BD931EDA122EF3` |
|
||||
| `reference/cantilever beam/cantilever beam displacements.csv` | `7B3312FBC8848E81D9A0FD4FF2B56BC1954636A2C14B5C1CBB269CB9477D3C31` |
|
||||
| `reference/cantilever beam/cantilever beam reactions.csv` | `BF30CDB0CD50106885DE14D63492737736C587426EBD787DE4F7EE6AA86DAA23` |
|
||||
| `reference/cantilever beam/cantilever beam elemental forces.csv` | `E5E77FEC0FA9482AE018DBF296E74D396335C7C711BD2E9AA2315247A34290BA` |
|
||||
|
||||
## Failure Classification
|
||||
|
||||
- classification: `N/A`
|
||||
- primary_failure: `N/A`
|
||||
- first_failed_command: `N/A`
|
||||
- evidence_tail: All required configure, build, discovery, feature-label, and full-test
|
||||
commands exited 0; no failed test exists.
|
||||
- correction_handoff: `N/A`; no implementation-owned, environment, harness, or
|
||||
upstream-contract failure requires correction.
|
||||
|
||||
## Failed Test Inventory
|
||||
|
||||
None. Feature-label CTest and full CTest both passed 83/83.
|
||||
|
||||
## Handoff Recommendation
|
||||
|
||||
| target_agent | reason | required_input |
|
||||
| --- | --- | --- |
|
||||
| Reference Verification Agent | Step 25 build/test gate is `pass-for-reference-verification`. | This report, HEAD `400db19`, `.harness/build/tests/Debug/fesa_reference_tests.exe`, and the unchanged exact legacy bundle. |
|
||||
|
||||
The build-local Step 24 evidence exists at
|
||||
`.harness/build/reference/cantilever-beam-b33/results.h5` and
|
||||
`.harness/build/reference/cantilever-beam-b33/comparison.json`; the JSON is 128,118 bytes
|
||||
with SHA-256
|
||||
`258347AEA791D981AEA9B2BCAD85DE5344D4859ECA3692DC5E7AA01A848F8E0D`.
|
||||
Step 26 must independently rerun and inspect the approved comparison evidence. Its
|
||||
presence and CTest success here are not a reference-verification verdict.
|
||||
|
||||
## No-Change Assertion
|
||||
|
||||
- source_files_modified: `false`
|
||||
- test_files_modified: `false`
|
||||
- cmake_files_modified: `false`
|
||||
- requirements_or_upstream_contracts_modified: `false`
|
||||
- reference_artifacts_modified: `false`
|
||||
- tolerance_policies_modified: `false`
|
||||
- owned_report_modified: `true`
|
||||
- phase_index_step25_modified: `true`
|
||||
- notes: Before report/index creation the worktree was clean at the audited HEAD. Final
|
||||
scope validation is limited to this report and the Step 25 fields in the phase index.
|
||||
|
||||
## Open Issues
|
||||
|
||||
- None blocking Reference Verification.
|
||||
- The implementation report aggregate `in-progress` header is noted above but does not
|
||||
contradict its 18 completed Step blocks, the phase index, or the fresh build/test result.
|
||||
@@ -53,7 +53,7 @@ INTAKE -> STATE AUDIT -> GATE DECISION -> HANDOFF PACKAGE -> STATUS REPORT
|
||||
- Reference Verification Agent report
|
||||
- Physics Evaluation Agent report
|
||||
- Release Agent report
|
||||
- validation command evidence: `python scripts/validate_workspace.py`
|
||||
- Build/Test report의 `.harness/config.json` 또는 자동 감지 기반 MSVC build/test command evidence
|
||||
|
||||
## 문서 템플릿
|
||||
|
||||
@@ -184,6 +184,6 @@ INTAKE -> STATE AUDIT -> GATE DECISION -> HANDOFF PACKAGE -> STATUS REPORT
|
||||
|
||||
## 검증 기준
|
||||
|
||||
- Coordinator Agent config와 문서 템플릿 검증은 Python unittest로 수행한다.
|
||||
- workspace 검증은 `python scripts/validate_workspace.py`를 사용한다.
|
||||
- 현재 repository에 CMake 프로젝트가 없으면 harness 정책에 따라 no-CMake validation 경로가 성공으로 기록될 수 있다.
|
||||
- Coordinator Agent config와 문서 템플릿에 자동화된 Python 검증이 있으면 `uv run --with pytest python -m pytest -v -rs`로 실행한다.
|
||||
- C++ build/test evidence는 `.harness/config.json` 또는 Harness 자동 감지 기본값에 따른 Build/Test report에서 확인한다.
|
||||
- C/C++ 파일과 build metadata가 모두 없을 때만 `no C/C++ project` 성공을 허용한다. C/C++ 파일만 있고 build metadata가 없으면 통과 evidence로 사용하지 않는다.
|
||||
|
||||
@@ -12,8 +12,8 @@ Correction Agent는 Build/Test Executor Agent, Reference Verification Agent, Phy
|
||||
- 실패 로그와 implementation report를 읽고 failure classification을 먼저 확정한다.
|
||||
- configure, compile, link, test, reference-comparison, harness, environment, upstream-contract 실패를 구분한다.
|
||||
- implementation-owned failure에 한해 source/header/test/CMake를 최소 수정한다.
|
||||
- 수정 후 targeted command를 먼저 실행하고 `python scripts/validate_workspace.py`를 실행한다.
|
||||
- harness, hook, agent config 관련 수정에서는 `python -m unittest discover -s scripts -p "test_*.py"`도 실행한다.
|
||||
- 수정 후 targeted command를 먼저 실행하고 `.harness/config.json` 또는 자동 감지 기본값에 따른 전체 MSVC build/test를 실행한다.
|
||||
- Harness Python, Hook, agent config 관련 수정에서는 `uv run --with pytest python -m pytest -v -rs`도 실행한다.
|
||||
- 반복 실패 또는 upstream 계약 문제를 Coordinator Agent나 관련 upstream agent로 handoff한다.
|
||||
|
||||
수행하지 않는다:
|
||||
@@ -40,11 +40,16 @@ TRIAGE -> MINIMAL FIX -> VERIFY -> REPORT
|
||||
|
||||
```powershell
|
||||
<targeted command that reproduced the failure>
|
||||
python scripts/validate_workspace.py
|
||||
python -m unittest discover -s scripts -p "test_*.py"
|
||||
cmake -S . -B .harness/build -A x64
|
||||
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
|
||||
```
|
||||
|
||||
`python -m unittest discover -s scripts -p "test_*.py"`는 harness, hook, agent config, Python validation behavior가 correction 범위에 포함될 때 실행한다.
|
||||
Preset 또는 직접 MSBuild 프로젝트는 `.harness/config.json`의 설정을 따른다. Harness
|
||||
Python, Hook, agent config, Python validation behavior가 correction 범위에 포함될 때는
|
||||
`uv run --with pytest python -m pytest -v -rs`도 실행한다. Stop 검증은 응답 종료 전에
|
||||
같은 전체 프로젝트 검증을 다시 수행한다.
|
||||
|
||||
## Failure Classification
|
||||
|
||||
@@ -53,7 +58,7 @@ python -m unittest discover -s scripts -p "test_*.py"
|
||||
- `link`: linker, symbol resolution, target dependency 실패
|
||||
- `test`: CTest, unit, integration, parser/I/O, ordinary regression test 실패
|
||||
- `reference-comparison`: 저장된 reference artifact와 deterministic comparison 실패
|
||||
- `harness`: Python harness self-test, TDD guard, hook, validation script 실패
|
||||
- `harness`: Python Harness test, PreToolUse/Stop Hook, config loading, discovery, adapter validation 실패
|
||||
- `environment`: MSVC, CMake, Python, path, permission, generator, local dependency 문제
|
||||
- `upstream-contract`: requirements, formulation, I/O, reference artifact, tolerance, implementation plan 불일치 또는 누락
|
||||
|
||||
@@ -104,8 +109,8 @@ Excluded files:
|
||||
| order | command | exit_code | result | evidence |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1 | <targeted command> | <code> | pass | fail | <summary> |
|
||||
| 2 | python scripts/validate_workspace.py | <code> | pass | fail | <summary> |
|
||||
| 3 | python -m unittest discover -s scripts -p "test_*.py" | <code or skipped> | pass | fail | skipped | <summary> |
|
||||
| 2 | <config-resolved full MSVC build/test commands> | <code> | pass | fail | <summary> |
|
||||
| 3 | uv run --with pytest python -m pytest -v -rs | <code or skipped> | pass | fail | skipped | <summary> |
|
||||
|
||||
## Traceability
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,7 @@ Implementation Planning Agent는 승인된 요구조건, 연구 브리프, 정
|
||||
- CMake/CTest target, `add_test`, label, `ctest -C Debug` 검증 계획을 정의한다.
|
||||
- candidate source/header/test/CMake 파일과 ownership boundary를 제안한다.
|
||||
- requirement, task, test, reference model, acceptance criterion을 Acceptance Traceability Matrix로 연결한다.
|
||||
- `python scripts/validate_workspace.py`를 포함한 validation command를 명시한다.
|
||||
- `.harness/config.json` 또는 자동 감지 기본값에서 해석되는 MSVC build/test 명령과 feature-specific command를 명시한다.
|
||||
|
||||
수행하지 않는다:
|
||||
- C++ 코드를 구현하지 않는다.
|
||||
@@ -80,8 +80,8 @@ Implementation Planning Agent는 승인된 요구조건, 연구 브리프, 정
|
||||
- add_test_needs: <CTest registration needs>
|
||||
- labels: unit | integration | reference | parser | io
|
||||
- msvc_config: Debug
|
||||
- expected_feature_command: ctest -C Debug -R <feature-or-label>
|
||||
- workspace_validation: python scripts/validate_workspace.py
|
||||
- expected_feature_command: ctest --test-dir .harness/build -C Debug -R <feature-or-label> --output-on-failure
|
||||
- full_validation_source: .harness/config.json | Harness auto detection
|
||||
|
||||
## Candidate Files and Ownership
|
||||
|
||||
@@ -107,11 +107,17 @@ Implementation Planning Agent는 승인된 요구조건, 연구 브리프, 정
|
||||
|
||||
## Validation Commands
|
||||
```powershell
|
||||
python -m unittest discover -s scripts -p "test_*.py"
|
||||
python scripts/validate_workspace.py
|
||||
ctest -C Debug -R <feature-or-label>
|
||||
cmake -S . -B .harness/build -A x64
|
||||
cmake --build .harness/build --config Debug
|
||||
ctest --test-dir .harness/build -C Debug -R <feature-or-label> --output-on-failure
|
||||
ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
```
|
||||
|
||||
Preset 또는 직접 MSBuild 프로젝트는 `.harness/config.json`에 해석 가능한 명령을 적는다.
|
||||
Harness Python, Hook, agent config 변경이 계획 범위에 포함되면
|
||||
`uv run --with pytest python -m pytest -v -rs`도 추가한다. Stop 검증은 Step 종료 전 전체
|
||||
MSVC build/test를 다시 확인하며, 구현 보고서의 RED 실패 증거를 대체하지 않는다.
|
||||
|
||||
## Risks and Downstream Handoff
|
||||
|
||||
### Implementation Agent
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,473 @@
|
||||
# Linear Static 3D Euler Beam I/O Definition
|
||||
|
||||
## Metadata
|
||||
|
||||
- feature_id: `linear-static-3d-euler-beam`
|
||||
- source_requirement: `docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- source_formulation: `docs/formulations/3d-isoparametric-euler-beam-formulation.md`
|
||||
- source_numerical_review: `docs/numerical-reviews/linear-static-3d-euler-beam-review.md`
|
||||
- source_research: `docs/research/linear-static-3d-euler-beam-research.md`
|
||||
- approved_design: `docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md`
|
||||
- status: `ready-for-implementation-planning`
|
||||
- owner_agent: `io-definition-agent`
|
||||
- date: `2026-08-09`
|
||||
- authoritative_output: `results.h5`
|
||||
- reference_baseline: `reference/cantilever beam/` at source commit `2b34d0b`
|
||||
|
||||
이 문서는 승인된 V0의 semantic I/O contract만 정의한다. Parser, HDF5 writer,
|
||||
comparison tooling의 C++ API나 구현 구조는 정의하지 않으며 Abaqus full compatibility를
|
||||
주장하지 않는다.
|
||||
|
||||
## Abaqus Input Scope
|
||||
|
||||
- input_format: Abaqus input file (`.inp`)
|
||||
- supported_analysis: 입력 파일당 하나의 linear-static step과 `TYPE=B33` 2절점 3D
|
||||
Euler–Bernoulli beam
|
||||
- ordinary_unit_system: user-consistent; `.inp`만 보고 SI를 추론하지 않음
|
||||
- compatibility_disclaimer: 아래 표의 위치, parameter, data grammar만 지원함
|
||||
|
||||
`supported`는 해당 행의 정확한 subset만 의미한다. `warning no-op`은 syntax를 소비하고
|
||||
구조화된 warning을 기록하지만 Domain, AnalysisModel 또는 mandatory HDF5 output을
|
||||
변경하지 않는다는 뜻이다.
|
||||
|
||||
| keyword | status and allowed location | required parameters and data grammar | purpose and semantic mapping | unsupported behavior |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `*HEADING` | supported; optional top-level first keyword | parameters 없음; 다음 keyword 전까지 0개 이상의 text data line | 원문 heading을 source metadata로 보존 | 중첩 위치 또는 parameter는 input error |
|
||||
| `*PART` / `*END PART` | supported; top-level model block | `NAME=<part-name>` 필수; `*END PART` data 없음 | part-local node, element, set, section 정의 범위 | 닫히지 않음, 중첩 part, duplicate part name은 error |
|
||||
| `*NODE` | supported; part 내부 | parameter 없음; 각 row `node_label, x, y, z` | positive integer source label과 finite global Cartesian 좌표 | 다른 arity, duplicate label, nonfinite 좌표는 error |
|
||||
| `*ELEMENT` | supported; part 내부 | `TYPE=B33` 필수; 각 row `element_label, node_1, node_2` | 2절점 straight Euler beam definition | `TYPE=B31`은 `unsupported-element-formulation`; 다른 type/arity와 dangling connectivity는 error |
|
||||
| `*NSET` | supported; part 또는 assembly 내부 | `NSET=<name>` 필수; optional `GENERATE`; assembly에서는 `INSTANCE=<instance-name>` 필수; explicit row는 하나 이상의 node label, generate row는 `first,last,increment` | part-local 또는 single-instance assembly node set | mixed-instance set, zero/negative increment, duplicate name, dangling member는 error |
|
||||
| `*ELSET` | supported; part 또는 assembly 내부 | `ELSET=<name>` 필수; optional `GENERATE`; assembly에서는 `INSTANCE=<instance-name>` 필수; explicit/generate grammar는 `*NSET`과 동일 | part-local 또는 single-instance assembly element set | mixed-instance set, invalid range, duplicate name, dangling member는 error |
|
||||
| `*MATERIAL` | supported; top-level model data | `NAME=<material-name>` 필수; data 없음 | 뒤따르는 단일 isotropic `*ELASTIC`을 소유 | duplicate name, missing/duplicate elasticity, 다른 material model은 error |
|
||||
| `*ELASTIC` | supported; 현재 material 내부 | parameter 없음; 정확히 한 row `E, nu` | homogeneous isotropic elasticity; `G=E/(2(1+nu))` | extra field/row, nonfinite value 또는 `E<=0`/`G<=0`은 model error |
|
||||
| `*BEAM GENERAL SECTION` | supported; part 내부 | `ELSET=<name>`, `MATERIAL=<name>`, `SECTION=GENERAL` 필수; 첫 row `A,I11,I12,I22,J`, 둘째 row `n1x,n1y,n1z` | section assignment, properties와 first section axis | 다른 `SECTION`, missing/dangling reference, `I12!=0`, invalid property/guide vector는 error |
|
||||
| `*SECTION POINTS` | supported; 바로 앞 general beam section에 종속 | parameter 없음; 하나 이상의 row `x1,x2` | 입력 순서의 stress recovery point; `x1=y`, `x2=z` | 선행 section 없음, 다른 arity, nonfinite 또는 duplicate point는 error |
|
||||
| `*ASSEMBLY` / `*END ASSEMBLY` | supported; 정확히 하나의 top-level assembly block | `NAME=<assembly-name>` 필수; `*END ASSEMBLY` data 없음 | identity instance와 assembly set 범위 | nested/duplicate assembly는 `unsupported-nested-assembly` |
|
||||
| `*INSTANCE` / `*END INSTANCE` | supported; assembly 내부 | `NAME=<instance-name>`, `PART=<part-name>` 필수; 두 keyword 사이 data 없음 | named identity copy; 같은 part의 여러 identity instance 허용 | translation/rotation data는 `unsupported-instance-transform`; duplicate/dangling instance는 error |
|
||||
| `*BOUNDARY` | supported; top-level model data 또는 sole step 내부 | parameter 없음; 각 row `target, first_dof, last_dof[, value]`; omitted value는 `0` | sole step의 prescribed displacement | invalid arity/range, unresolved target, conflicting expanded node/DOF value는 error |
|
||||
| `*CLOAD` | supported; sole step 내부 | parameter 없음; 각 row `target, dof, magnitude` | sole step의 global nodal concentrated load | invalid arity/DOF, nonfinite magnitude 또는 unresolved target은 error |
|
||||
| `*STEP` / `*END STEP` | supported; exactly one top-level history block | optional `NAME`; optional `NLGEOM=NO`; `*END STEP` data 없음 | canonical result identity `(Step-1, frame 0)` | second step은 `unsupported-multiple-step`; `NLGEOM=YES`는 `unsupported-nonlinear-geometry` |
|
||||
| `*STATIC` | supported; sole step 내부, exactly once | parameter 없음; exactly one row `initial_increment, time_period, minimum_increment, maximum_increment` | 승인 legacy row를 읽되 V0는 하나의 linear solve와 frame 0만 생성 | missing/extra/nonfinite/nonpositive field 또는 다른 procedure는 error |
|
||||
| `*PREPRINT` | warning no-op; top-level | 모든 parameter를 보존 후 무시; data 없음 | legacy generator control 수용 | semantic object를 만들지 않음 |
|
||||
| `*RESTART` | warning no-op; sole step | 모든 parameter를 보존 후 무시; data 없음 | legacy restart request 수용 | restart state를 만들지 않음 |
|
||||
| `*TRANSVERSE SHEAR STIFFNESS` | warning no-op; beam section context | keyword와 소속 data line을 보존 후 무시 | B33 legacy deck 수용 | Euler formulation/property를 변경하지 않음 |
|
||||
| `*OUTPUT, FIELD` | warning no-op; sole step | output parameter와 subordinate data를 보존 후 무시 | legacy field request root 수용 | mandatory FESA output을 선택·억제하지 않음 |
|
||||
| `*OUTPUT, HISTORY` | warning no-op; sole step | output parameter와 subordinate data를 보존 후 무시 | legacy history request root 수용 | history result를 생성하지 않음 |
|
||||
| `*NODE OUTPUT` | warning no-op; active output request 내부 | 모든 parameter와 다음 keyword 전 variable data를 무시 | legacy nodal variable request 수용 | requested variables로 HDF5 schema를 변경하지 않음 |
|
||||
| `*ELEMENT OUTPUT` | warning no-op; active output request 내부 | 모든 parameter와 다음 keyword 전 variable data를 무시 | legacy element variable request 수용 | requested variables로 HDF5 schema를 변경하지 않음 |
|
||||
| `*CONTACT OUTPUT` | warning no-op; active output request 내부 | 모든 parameter와 다음 keyword 전 variable data를 무시 | legacy contact variable request 수용 | contact model/result를 만들지 않음 |
|
||||
|
||||
`*DLOAD`, `*INCLUDE` 및 표에 없는 model-affecting keyword는 no-op 대상이 아니며
|
||||
`unsupported-keyword` input error다. 특히 formulation-only constant local line-load
|
||||
kernel은 parser나 Domain의 distributed-load 지원을 뜻하지 않는다.
|
||||
|
||||
### Nesting grammar
|
||||
|
||||
```text
|
||||
input-file
|
||||
:= heading? part+ assembly material+ model-boundary* step EOF
|
||||
|
||||
part
|
||||
:= *PART
|
||||
node-block+ element-block+ (nset | elset)*
|
||||
general-section+ section-points*
|
||||
*END PART
|
||||
|
||||
assembly
|
||||
:= *ASSEMBLY
|
||||
instance+ assembly-set*
|
||||
*END ASSEMBLY
|
||||
|
||||
instance
|
||||
:= *INSTANCE *END INSTANCE
|
||||
|
||||
step
|
||||
:= *STEP *STATIC step-boundary* cload* allowed-no-op* *END STEP
|
||||
```
|
||||
|
||||
Top-level material과 model boundary는 step 전에만 나타난다. Part는 assembly 전에 모두
|
||||
닫혀야 하고 assembly 안에는 instance와 assembly-level set만 허용한다. Instance 안의
|
||||
node/element 재정의, nested assembly, dependent/independent mesh option은 지원하지 않는다.
|
||||
Sole step의 source `NAME` spelling은 metadata에 보존하지만 V0 HDF5와 comparison의
|
||||
canonical identity는 항상 `Step-1`, `frame 0`이다.
|
||||
|
||||
## Syntax Policy
|
||||
|
||||
- keyword line은 첫 non-whitespace character가 `*`이고 `**`가 아니어야 한다.
|
||||
- comment line은 `**`로 시작하며 의미 모델에서는 제외하되 file과 1-based line 위치를
|
||||
유지한다.
|
||||
- keyword, parameter name, enumerated parameter value와 named-reference lookup은 ASCII
|
||||
case-insensitive다. Part, instance, material, set의 원래 spelling과 numeric label lexeme는
|
||||
외부 identity를 위해 그대로 보존한다.
|
||||
- keyword line은 comma-separated `KEY[=VALUE]` fields다. Data line도 comma-separated이며
|
||||
field 양끝 whitespace를 제거한다. Required empty field, trailing empty optional value,
|
||||
잘못된 numeric token은 input error다.
|
||||
- Keyword/data continuation, quoted/multiline name, include file 및 line continuation은 V0에서
|
||||
지원하지 않는다. 한 logical keyword/data row는 한 physical line에 완결되어야 한다.
|
||||
- Node/element labels와 explicit set members는 positive base-10 integer다. Internal index로
|
||||
바꾸어도 raw source label text를 잃지 않는다.
|
||||
- 모든 numeric value는 finite `double`이어야 한다. `NaN`, positive/negative infinity는
|
||||
syntax/semantic validation에서 거부한다.
|
||||
- 각 parsed keyword, parameter, data row와 semantic entity는 `file`, 1-based `line`, raw
|
||||
`keyword`, raw source label을 추적할 수 있어야 한다.
|
||||
- Output-request subordinate variable data는 직전의 allowlisted output keyword부터 다음
|
||||
keyword까지에만 warning no-op이다. 그 밖의 예상되지 않은 data line은 input error다.
|
||||
|
||||
### Duplicate and dangling-reference policy
|
||||
|
||||
- Part, assembly, instance, material, set 이름은 각 semantic scope의 case-insensitive key로
|
||||
unique해야 한다. Node/element numeric source label은 part scope에서 unique해야 한다.
|
||||
- 같은 part의 여러 identity instance는 duplicate가 아니다. 각 copy는 instance name으로
|
||||
구분되는 별도 source identity를 가진다.
|
||||
- Element connectivity, set membership, instance `PART`, section `ELSET`/`MATERIAL`, assembly
|
||||
set `INSTANCE`, boundary/load target은 Domain finalization 전에 모두 resolve되어야 한다.
|
||||
- Duplicate definition은 `duplicate-entity`; unresolved reference는 `unresolved-reference`로
|
||||
진단하고 partial Domain을 해석에 넘기지 않는다.
|
||||
|
||||
## Model Data Mapping
|
||||
|
||||
### Stable source identity and instances
|
||||
|
||||
Part-local node, element, set은 instance expansion 뒤 다음 identity를 갖는다.
|
||||
|
||||
```text
|
||||
SourceEntityId { instance_name, source_label }
|
||||
```
|
||||
|
||||
`instance_name`과 `source_label`은 원래 spelling을 보존한다. Case-insensitive lookup key와
|
||||
표시용 raw text는 별개다. Stable Domain internal index는 input declaration order,
|
||||
instance declaration order, part-local entity declaration order의 결정적 순서로 부여하며
|
||||
thread count나 hash iteration order에 의존하지 않는다. 같은 part의 두 identity instance는
|
||||
source label이 같아도 instance name이 다르므로 서로 merge하지 않는다.
|
||||
|
||||
Assembly-level `*NSET`/`*ELSET`의 `INSTANCE`는 정확히 하나의 identity instance를
|
||||
지정하고 data의 label을 그 instance가 참조하는 part-local source label로 resolve한다.
|
||||
따라서 assembly set member도 `(instance_name, source_label)`로 결정된다. V0는 한 set에
|
||||
여러 instance의 member를 섞는 grammar를 제공하지 않는다.
|
||||
|
||||
### Nodes, elements, sets, material, and section
|
||||
|
||||
- Node는 global Cartesian coordinate `[X,Y,Z]`, stable internal node ID와 source identity를
|
||||
가진다.
|
||||
- B33 element는 ordered connectivity `[node_1,node_2]`, stable internal element ID,
|
||||
source identity, general-section assignment를 가진다. Connectivity order가 local tangent
|
||||
`t=(X2-X1)/L`의 방향을 정한다.
|
||||
- Explicit set은 data order, generated set은 inclusive `first,last,increment` expansion
|
||||
order를 보존한다. Membership은 internal ID에 연결되지만 source identity로 round-trip
|
||||
가능해야 한다.
|
||||
- Material은 정확한 입력 `E,nu`를 보존하고 `G=E/(2(1+nu))`를 유도한다.
|
||||
- General section 첫 row는 정확히 `[A,I11,I12,I22,J]`다. V0는 `I12`의 exact numeric
|
||||
zero만 허용하고 `Iy=I11`, `Iz=I22`로 매핑한다.
|
||||
- Guide vector `a=n1`을 tangent에 직교 투영·정규화하여 local `y`로, `t x n1`을 local
|
||||
`z`로 둔다. `(x,y,z)`는 right-handed다.
|
||||
|
||||
### Model validation
|
||||
|
||||
모든 값은 finite여야 하고 다음 조건을 element calculation 전에 검사한다.
|
||||
|
||||
```text
|
||||
E > 0
|
||||
G = E / (2 * (1 + nu)) > 0
|
||||
A > 0, Iy > 0, Iz > 0, J > 0
|
||||
L > 1e-12 * max(1, norm(X1), norm(X2))
|
||||
norm(a_perp) > 1e-12 * max(1, norm(a))
|
||||
```
|
||||
|
||||
`a_perp = a - dot(a,t)*t`다. 길이 조건 실패는 `invalid-beam-length`, zero guide vector나
|
||||
projection 조건 실패는 `invalid-beam-guide-vector`, nonpositive property는
|
||||
`invalid-beam-property`, `I12!=0`은 `unsupported-coupled-section` model diagnostic이다.
|
||||
Fallback axis, absolute-value 보정 또는 B31 재해석은 허용하지 않는다.
|
||||
|
||||
## History Data Mapping
|
||||
|
||||
V0는 하나의 history object, canonical `Step-1`만 만든다. `*STATIC`의 네 legacy field는
|
||||
각각 `initial_increment`, `time_period`, `minimum_increment`, `maximum_increment`로
|
||||
보존한다. 모두 finite positive여야 하고 `minimum_increment <= maximum_increment`여야
|
||||
한다. 이 값들은 입력 호환성과 provenance를 위한 값이며 V0가 increment loop나 여러
|
||||
frame을 생성하게 하지 않는다. 결과는 항상 `(Step-1, frame 0)`이다.
|
||||
|
||||
`*BOUNDARY`의 target은 node source label 또는 node set이다. Assembly set은 그
|
||||
`INSTANCE`를 포함해 source node identity로 확장한다. `first_dof <= last_dof`이고 두 값은
|
||||
1..6이어야 한다. 생략된 value는 exact zero다. Model-level boundary와 step-level boundary는
|
||||
sole step에 활성화되며 같은 expanded node/DOF에 서로 다른 value가 생기면 input error다.
|
||||
|
||||
`*CLOAD` target resolution은 boundary와 같고 각 row는 해당 target의 모든 node에 global
|
||||
component load를 적용한다. 같은 node/DOF로 resolve되는 여러 load row는 input order로
|
||||
결정적으로 합산한다.
|
||||
|
||||
| DOF | nodal kinematic component | boundary unit dimension | CLOAD component | load unit dimension |
|
||||
| ---: | --- | --- | --- | --- |
|
||||
| 1 | `UX` | length | `FX` | force |
|
||||
| 2 | `UY` | length | `FY` | force |
|
||||
| 3 | `UZ` | length | `FZ` | force |
|
||||
| 4 | `URX` | radian | `MX` | force x length |
|
||||
| 5 | `URY` | radian | `MY` | force x length |
|
||||
| 6 | `URZ` | radian | `MZ` | force x length |
|
||||
|
||||
Abaqus output request는 history activation이나 output selection으로 매핑하지 않는다.
|
||||
Allowlisted request의 존재 여부와 무관하게 mandatory HDF5 dataset은 모두 생성된다.
|
||||
|
||||
## Internal Model Contract
|
||||
|
||||
- Domain은 nodes, B33 elements, sets, material, section, boundary, load와 sole static step의
|
||||
완전한 semantic definition을 소유하고 mapping 이후 effectively immutable하다.
|
||||
- AnalysisModel은 sole step에 활성인 Domain IDs/references만 제공하며 Domain object를
|
||||
복사하지 않는다.
|
||||
- Node/element는 equation ID를 소유하지 않는다. DOF numbering과 constrained/free mapping은
|
||||
이 I/O 계약 밖의 DofManager 책임이다.
|
||||
- Boundary와 load는 expansion 전 target identity와 expansion 후 stable node identity를 모두
|
||||
추적할 수 있어야 한다.
|
||||
- Result identity는 source identity와 stable internal identity를 모두 보유해야 하며
|
||||
parser의 raw keyword string을 solver physics object로 사용하지 않는다.
|
||||
- Endpoint equilibrium action, endpoint section resultant, Gauss generalized result,
|
||||
assembled residual reaction은 서로 다른 quantity/location identity다.
|
||||
|
||||
## Output HDF5 Schema
|
||||
|
||||
Authoritative output은 하나의 HDF5 file `results.h5`, schema version `0`이다. 아래의
|
||||
`<step-name>`은 V0에서 literal `Step-1`이다. 모든 string은 UTF-8, 모든 물리 실수는
|
||||
IEEE-754 float64, stable internal ID는 uint64다.
|
||||
|
||||
### Metadata and model identity
|
||||
|
||||
`/metadata`는 group이며 다음 scalar attributes를 반드시 가진다.
|
||||
|
||||
| attribute | required value or meaning |
|
||||
| --- | --- |
|
||||
| `schema_version` | `0` |
|
||||
| `feature_id` | `linear-static-3d-euler-beam` |
|
||||
| `solver_version` | 실행 solver version string |
|
||||
| `source_input_identity` | normalized input path와 content identity를 추적 가능한 string |
|
||||
| `unit_system_label` | ordinary run은 `user-consistent-unspecified` |
|
||||
| `coordinate_convention` | `global-cartesian; beam-local=(t,n1,t-cross-n1)` |
|
||||
| `element_formulation` | `B33-3D-Euler-Bernoulli` |
|
||||
| `step_name` | `Step-1` |
|
||||
| `frame_index` | integer `0` |
|
||||
|
||||
승인 legacy comparison은 `.inp`에서 SI를 추론하지 않는다. Reference Model Contract와
|
||||
verification report가 model `cantilever-beam-b33`에 외부 `SI` provenance를 적용한다.
|
||||
|
||||
| dataset path | shape and dtype | row identity / fields | required attributes and ordering |
|
||||
| --- | --- | --- | --- |
|
||||
| `/model/nodes` | `[node_count]` compound | `internal_node_id:uint64`, `instance_name:utf8`, `source_label:utf8`, `coordinates:float64[3]` | internal node ID ascending; `coordinate_system=global-cartesian`, `units_label=length` |
|
||||
| `/model/elements` | `[element_count]` compound | `internal_element_id:uint64`, `instance_name:utf8`, `source_label:utf8`, `node_internal_ids:uint64[2]`, `local_axes:float64[3,3]` | internal element ID ascending; axes row order `[x,y,z]`, `formulation=B33-3D-Euler-Bernoulli` |
|
||||
|
||||
### Step/frame result datasets
|
||||
|
||||
| quantity | exact dataset path | shape | row identity and component order | units/coordinates/location |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| displacement | `/steps/<step-name>/frames/0/nodal/displacement` | `[node_count,6]` float64 | `/model/nodes` row; `[UX,UY,UZ,URX,URY,URZ]` | `[length,length,length,radian,radian,radian]`; global; nodal |
|
||||
| reaction | `/steps/<step-name>/frames/0/nodal/reaction` | `[node_count,6]` float64 | `/model/nodes` row; `[RF1,RF2,RF3,RM1,RM2,RM3]` | `[force,force,force,force*length,force*length,force*length]`; global; nodal |
|
||||
| equilibrium end action | `/steps/<step-name>/frames/0/element/end_force_local` | `[element_count,2,6]` float64 | element row, endpoint `[-1,+1]`; `[FX,FY,FZ,MX,MY,MZ]` | `[force x3, force*length x3]`; beam local; endpoint outward action |
|
||||
| endpoint section resultant | `/steps/<step-name>/frames/0/element/section_resultant` | `[element_count,2,4]` float64 | element row, endpoint `[-1,+1]`; `[N,T,My,Mz]` | `[force,force*length,force*length,force*length]`; beam local; positive-local-x section cut |
|
||||
| generalized strain | `/steps/<step-name>/frames/0/element/generalized_strain` | `[element_count,2,4]` float64 | element row, Gauss point `[-1/sqrt(3),+1/sqrt(3)]`; `[epsilon0,kappa_x,kappa_y,kappa_z]` | `[1,1/length,1/length,1/length]`; beam local; integration point |
|
||||
| generalized resultant | `/steps/<step-name>/frames/0/element/generalized_resultant` | `[element_count,2,4]` float64 | element row, same Gauss points; `[N,T,My,Mz]` | `[force,force*length,force*length,force*length]`; beam local; integration point |
|
||||
| axial stress | `/steps/<step-name>/frames/0/element/stress_s11` | `[stress_row_count]` compound | `internal_element_id`, `gauss_point_index`, `section_point_index`, `x1`, `x2`, `source`, `S11` | element/Gauss/section order; `units_label=force/length^2`, beam local section point |
|
||||
| diagnostics | `/diagnostics` | `[diagnostic_count]` compound | `severity`, `code`, `file`, `line`, `keyword`, `entity_identity`, `message` | deterministic diagnostic order; empty dataset is required when count is zero |
|
||||
|
||||
각 numeric result dataset은 `component_names`, `component_unit_dimensions`,
|
||||
`coordinate_system`, `location`, `step_name=Step-1`, `frame_index=0` attributes를 가진다.
|
||||
Endpoint axis order는 `xi=-1` then `xi=+1`, Gauss axis order는 negative then positive다.
|
||||
Stress row는 internal element ID, Gauss index 1..2, input section-point index 순으로 정렬한다.
|
||||
입력 section point가 없으면 `(x1,x2)=(0,0)`, index `0`, `source=fesa-default`인 centroid
|
||||
row 하나를 각 Gauss point에 쓴다. 입력 point는 index 1부터 원래 data order를 따른다.
|
||||
|
||||
Reaction은 모든 node와 여섯 component에 존재하며 free DOF의 residual도 포함한다.
|
||||
Transverse/torsional shear stress dataset이나 averaged nodal stress는 만들지 않는다.
|
||||
`S11`은 mandatory HDF5 output이지만 Abaqus reference comparison은 명시적 N/A다.
|
||||
|
||||
### Atomic finalization
|
||||
|
||||
Writer는 requested final path와 같은 directory에 temporary HDF5를 만들고 모든 mandatory
|
||||
group/dataset/attribute 작성, flush, close, schema self-check가 성공한 뒤에만 final path를
|
||||
원자적으로 교체한다. 실패하면 temporary artifact는 비권위적이며 기존 final file이
|
||||
있다면 그대로 보존한다. 실패한 새 run은 불완전한 `results.h5`를 남기지 않고 exit code
|
||||
`6`과 HDF5 diagnostic을 반환한다.
|
||||
|
||||
## FESA HDF5 to Reference CSV Comparison Schema
|
||||
|
||||
Authoritative 비교는 위 HDF5 rows와 read-only Abaqus CSV rows 사이에서만 수행한다.
|
||||
HDF5에서 추출한 deterministic CSV view는 debugging/review 보조물이며 solver output이나
|
||||
reference artifact가 아니다.
|
||||
|
||||
### Approved legacy artifact precheck
|
||||
|
||||
Comparison 전에 다음 exact files가 존재하고 변경되지 않았음을 확인한다.
|
||||
|
||||
- `reference/cantilever beam/cantilever beam.inp`
|
||||
- `reference/cantilever beam/cantilever beam displacements.csv`
|
||||
- `reference/cantilever beam/cantilever beam reactions.csv`
|
||||
- `reference/cantilever beam/cantilever beam elemental forces.csv`
|
||||
|
||||
Input은 `TYPE=B33`이어야 하고 trim한 CSV header는 아래 mapping 표와 정확히 일치해야
|
||||
한다. 각 projected row key는 unique하고 모든 numeric value는 finite여야 한다. 파일
|
||||
missing/type mismatch는 `needs-reference-artifacts`, header/value/identity mismatch는
|
||||
`schema-mismatch`이며 comparison은 시작하지 않는다. 이 legacy bundle에서
|
||||
`metadata.json`과 `README.md`는 N/A이고 파일을 rename, rewrite, zero-clamp 또는 보정하지
|
||||
않는다.
|
||||
|
||||
### Header and component normalization
|
||||
|
||||
| legacy file/header | canonical quantity/component | FESA HDF5 source |
|
||||
| --- | --- | --- |
|
||||
| `U-U1`, `U-U2`, `U-U3` | displacement `UX`, `UY`, `UZ` | `nodal/displacement` columns 0..2 |
|
||||
| `UR-UR1`, `UR-UR2`, `UR-UR3` | displacement `URX`, `URY`, `URZ` | `nodal/displacement` columns 3..5 |
|
||||
| `RF-RF1`, `RF-RF2`, `RF-RF3` | reaction `RF1`, `RF2`, `RF3` | `nodal/reaction` columns 0..2 |
|
||||
| `RM-RM1`, `RM-RM2`, `RM-RM3` | reaction `RM1`, `RM2`, `RM3` | `nodal/reaction` columns 3..5 |
|
||||
| `SF-SF1` | section resultant `N` | `element/section_resultant` component `N` |
|
||||
| `SM-SM1` | section resultant `My` | `element/section_resultant` component `My` |
|
||||
| `SM-SM2` | section resultant `Mz` | `element/section_resultant` component `Mz` |
|
||||
| `SM-SM3` | section resultant `T` | `element/section_resultant` component `T` |
|
||||
|
||||
General Abaqus beam component meaning and FESA local mapping은 다음과 같다.
|
||||
|
||||
| Abaqus component | equilibrium end-action component | section-resultant component |
|
||||
| --- | --- | --- |
|
||||
| `SF1` | `FX` | `N` |
|
||||
| `SF3` | `FY` | N/A in `[N,T,My,Mz]` |
|
||||
| `SF2` | `FZ` | N/A in `[N,T,My,Mz]` |
|
||||
| `SM3` | `MX` | `T` |
|
||||
| `SM1` | `MY` | `My` |
|
||||
| `SM2` | `MZ` | `Mz` |
|
||||
|
||||
이 general mapping은 component axis의 의미다. Outward equilibrium end action과
|
||||
positive-local-x-face section resultant의 sign identity를 합치지 않는다. 승인 legacy
|
||||
CSV는 `SF1/SM1/SM2/SM3`만 제공하고 section-cut result와 비교하므로 `SF2`/`SF3` row를
|
||||
0으로 만들거나 reference row로 합성하지 않는다. HDF5의 transverse end action은
|
||||
unit/analytical test와 physics sanity 대상이다.
|
||||
|
||||
### Frame, instance, and node-station normalization
|
||||
|
||||
- Legacy `Frame` value `Increment 1: Step Time = 1.000`은 canonical `(Step-1, frame 0)`으로
|
||||
변환한다. 승인 bundle의 다른 increment/time string은 `schema-mismatch`다.
|
||||
- `Part Instance Name`은 HDF5 `/model/nodes` 또는 `/model/elements`의 exact preserved
|
||||
`instance_name`과 case-insensitive lookup 후 raw identity 일치 여부를 확인한다.
|
||||
- `Node Label`은 instance 안의 preserved source node label로 resolve한다. Displacement와
|
||||
reaction key는 `(model_id,Step-1,0,instance_name,source_node_label,quantity,component)`다.
|
||||
- Elemental-force CSV는 element label이 없으므로 HDF5 endpoint section resultants를
|
||||
source node station으로 project한다. Boundary station은 유일한 incident endpoint를 쓴다.
|
||||
- Interior station collapse는 정확히 두 incident B33 endpoints, 동일 section/local-axis
|
||||
orientation, 일관된 chain connectivity, 해당 node의 concentrated force/moment가 없는
|
||||
경우에만 허용한다. 두 positive-face section-cut 값이 아래 승인 component tolerance
|
||||
안에서 먼저 일치해야 한다.
|
||||
- Interior 값이 일치하면 stable internal element ID가 작은 endpoint를 deterministic
|
||||
representative로 선택한다. 두 값을 평균하지 않는다. 불일치는 `tolerance-failure`다.
|
||||
- Reversed connectivity, local-axis discontinuity, section jump, branch 또는 loaded interior
|
||||
station은 element label 없는 legacy schema로 collapse할 수 없다. 이 approved bundle
|
||||
밖에서는 element-aware reference row가 필요하며 legacy projection은 `schema-mismatch`로
|
||||
중단한다.
|
||||
|
||||
Projected canonical comparison row는 다음 fields를 가진다.
|
||||
|
||||
```text
|
||||
model_id, step_name, frame_index, instance_name, source_node_label,
|
||||
quantity, component, value, unit_dimension, coordinate_system, hdf5_dataset_path
|
||||
```
|
||||
|
||||
Stable ordering은 quantity inventory order, instance declaration order, stable source node
|
||||
order, component order다. Approved model ID는 `cantilever-beam-b33`; nodal quantities는
|
||||
global Cartesian, section resultants는 beam local이다.
|
||||
|
||||
### Row-set precheck and tolerance
|
||||
|
||||
먼저 양쪽을 legacy contract가 실제 제공하는 quantity/component projection으로 제한한다.
|
||||
그 projection 안에서는 missing, extra, duplicate, nonfinite, schema-mismatched 또는
|
||||
identity-mismatched row가 하나라도 있으면 tolerance 계산 전에 실패한다. HDF5에만
|
||||
mandatory인 `SF2/SF3` 대응 end action, generalized results와 `S11`은 계약상 비교 대상이
|
||||
아니므로 extra reference row가 아니다.
|
||||
|
||||
Matched rows는 같은 `model_id`, step/frame, quantity, component로 group한다.
|
||||
|
||||
```text
|
||||
reference_scale = max(abs(reference_value_i))
|
||||
row_tolerance = absolute_floor + 1e-6 * reference_scale
|
||||
row_pass = abs(fesa_value_i - reference_value_i) <= row_tolerance
|
||||
```
|
||||
|
||||
즉 exact policy는 `absolute_floor + 1e-6 * reference_scale`이다. `reference_scale`은
|
||||
read-only Abaqus values만 사용하고 FESA 값으로 조정하지 않는다. Scale이 zero면 relative
|
||||
term은 zero다. Reference value나 작은 residue를 zero-clamp하지 않고 모든 row를 판정한다.
|
||||
|
||||
| approved SI component class | absolute floor |
|
||||
| --- | ---: |
|
||||
| displacement and rotation | `1e-9` |
|
||||
| force and moment | `1e-3` |
|
||||
|
||||
Interior endpoint consistency도 해당 CSV quantity/component의 same Abaqus-only scale과
|
||||
floor를 사용한다. Verification report는 모든 row pass/fail과 quantity별 max absolute
|
||||
error, component-scale normalized error, RMS error, norm error, worst row/component를
|
||||
기록한다. 이 reference tolerance는 analytical/formulation tolerance를 대체하지 않는다.
|
||||
|
||||
## CLI and Diagnostics Contract
|
||||
|
||||
```powershell
|
||||
fesa.exe <model.inp> --output <results.h5>
|
||||
```
|
||||
|
||||
`--output`을 생략하면 현재 작업 directory의 `results.h5`가 final path다. Input path는
|
||||
정확히 하나이며 unknown option, missing argument, repeated `--output`은 usage error다.
|
||||
|
||||
| exit code | meaning |
|
||||
| ---: | --- |
|
||||
| `0` | success; authoritative HDF5 finalization complete |
|
||||
| `2` | CLI usage error |
|
||||
| `3` | input syntax or semantic mapping error, including unsupported keyword/formulation/wrapper |
|
||||
| `4` | model validation error, including geometry, section or property invalidity |
|
||||
| `5` | factorization or substitution error |
|
||||
| `6` | HDF5 write, validation or atomic finalization error |
|
||||
|
||||
각 stderr diagnostic record는 exact field order `severity`, `code`, `file`, `line`,
|
||||
`keyword`, `entity_identity`, `message`를 사용한다. Source-backed diagnostics는 normalized
|
||||
file path와 1-based line을 가지며, source가 없는 solver/output error는 빈 source field를
|
||||
명시한다. 출력 순서는 source file declaration order, line, entity stable internal ID,
|
||||
diagnostic code의 tuple로 결정하고 같은 tuple에서는 discovery order를 보존한다. Warning은
|
||||
성공 run에서도 `/diagnostics`에 기록되며 error가 있으면 해당 exit class를 반환한다.
|
||||
|
||||
## Validation Rules
|
||||
|
||||
| validation area | required pass condition | failure class |
|
||||
| --- | --- | --- |
|
||||
| keyword inventory | supported 또는 exact warning no-op allowlist에 속함 | input, exit 3 |
|
||||
| nesting/cardinality | closed part/assembly/instance/step; one assembly and one static step | input, exit 3 |
|
||||
| source identity | duplicate 없음; all references resolve; multi-instance identity unique | input, exit 3 |
|
||||
| B33 semantics | only `TYPE=B33`; two distinct connected nodes | input/model, exit 3 or 4 |
|
||||
| section/material | exact data arity/mapping, `I12=0`, all required positive properties | model, exit 4 |
|
||||
| geometry/local axes | approved length/projection thresholds and right-handed axes | model, exit 4 |
|
||||
| history | DOF 1..6, resolved targets, finite values, sole canonical frame | input, exit 3 |
|
||||
| HDF5 | all exact paths, shapes, attributes, identities and finite result values | output, exit 6 |
|
||||
| legacy artifacts | exact four files, B33, exact headers, unique finite rows | reference precheck |
|
||||
| comparison | exact projected row-set, endpoint eligibility/consistency, approved tolerance | reference verification |
|
||||
|
||||
No parser/HDF5 implementation, reference artifact mutation, Abaqus execution, physics pass 또는
|
||||
release approval을 이 status가 의미하지 않는다.
|
||||
|
||||
## Open Issues and Downstream Handoff
|
||||
|
||||
### Resolved numerical-review handoff
|
||||
|
||||
`NR-O03-STATION-NORMALIZATION`은 approved legacy bundle에 대해 unloaded, consistently
|
||||
oriented two-endpoint interior station만 collapse하고, tolerance check 후 smaller stable
|
||||
element ID를 선택하는 규칙으로 구체화했다. Reversed/branched/loaded/jumped station은
|
||||
element-aware reference가 없는 한 비교하지 않는다.
|
||||
|
||||
### Reference Model Agent
|
||||
|
||||
- Exact legacy inventory, generator `Abaqus/CAE Learning Edition 2024`, source commit
|
||||
`2b34d0b`, external SI provenance와 stress comparison N/A를 계약에 고정한다.
|
||||
- 추가 reference model은 canonical filenames와 metadata를 사용하며 이 legacy file을
|
||||
변경하지 않는다.
|
||||
|
||||
### Implementation Planning Agent
|
||||
|
||||
- Keyword별 positive/negative grammar, source location, duplicates/dangling references,
|
||||
B31/transform/nested/multiple-step/NLGEOM diagnostics를 TDD cases로 만든다.
|
||||
- Exact HDF5 path/shape/component/identity, mandatory-output independence와 atomic failure를
|
||||
검증한다.
|
||||
- C++ API는 이 semantic contract에서 파생하되 여기에 소급해 API 설계를 추가하지 않는다.
|
||||
|
||||
### Reference Verification Agent
|
||||
|
||||
- Artifact precheck 뒤 HDF5-to-legacy projection, node-station eligibility, row-set equality,
|
||||
component-scale comparison 순서를 유지한다.
|
||||
- Missing/extra/nonfinite row를 무시하거나 `SF2/SF3`/stress reference row를 합성하지 않는다.
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
# Linear Static 3D Euler Beam Numerical Review
|
||||
|
||||
## Metadata
|
||||
|
||||
- feature_id: `linear-static-3d-euler-beam`
|
||||
- source_formulation: `docs/formulations/3d-isoparametric-euler-beam-formulation.md`
|
||||
- source_requirements: `docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- source_research: `docs/research/linear-static-3d-euler-beam-research.md`
|
||||
- approved_design: `docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md`
|
||||
- status: `pass-for-implementation-planning`
|
||||
- owner_agent: `numerical-review-agent`
|
||||
- date: `2026-08-09`
|
||||
- scope: formulation correctness and implementation-planning readiness only
|
||||
|
||||
## Review Verdict
|
||||
|
||||
- verdict: `pass-for-implementation-planning`
|
||||
- reason: The DOF/sign convention, natural boundary actions, 4x12 B matrix, 12x12 stiffness, 2-point Gauss rule, transformation, constant line-load vector, constrained partition, and residual reaction are mutually consistent. No confirmed mathematical defect was found.
|
||||
- qualification: This verdict permits implementation planning only; it is not reference-comparison, physics-sanity, release, or full Abaqus-compatibility approval.
|
||||
|
||||
## Critical Findings
|
||||
|
||||
### Confirmed defects
|
||||
|
||||
- None.
|
||||
|
||||
### Independent DOF, curvature, and end-action derivation
|
||||
|
||||
The fixed local nodal order is
|
||||
|
||||
$$
|
||||
[u_1,v_1,w_1,\theta_{x1},\theta_{y1},\theta_{z1},
|
||||
u_2,v_2,w_2,\theta_{x2},\theta_{y2},\theta_{z2}].
|
||||
$$
|
||||
|
||||
For a small right-handed section rotation,
|
||||
$\boldsymbol\theta\times[0,y,z]^T
|
||||
=[z\theta_y-y\theta_z,-z\theta_x,y\theta_x]^T$.
|
||||
The zero-shear constraints are therefore
|
||||
$\theta_z=v'$ and $\theta_y=-w'$. Hence
|
||||
|
||||
$$
|
||||
\varepsilon_{xx}=u'-zw''-yv'
|
||||
=\varepsilon_0+z\kappa_y-y\kappa_z,
|
||||
\quad \kappa_y=-w'',\quad \kappa_z=v''.
|
||||
$$
|
||||
|
||||
Using the reviewed section-force definitions independently gives
|
||||
|
||||
$$
|
||||
M_y=EI_y\kappa_y=-EI_yw'',\qquad
|
||||
M_z=EI_z\kappa_z=EI_zv''.
|
||||
$$
|
||||
|
||||
Twice integrating the bending virtual work, with outward sign $n=-1$ at
|
||||
$x=0$ and $n=+1$ at $x=L$, yields
|
||||
|
||||
$$
|
||||
F_y=-nM_z',\quad M_z^{end}=nM_z,\qquad
|
||||
F_z=nM_y',\quad M_y^{end}=nM_y.
|
||||
$$
|
||||
|
||||
The axial and torsional pairs are $F_x=nN$ and $M_x=nT$. Direct expansion of
|
||||
$K_ld_l$ reproduces these relations at both endpoints when the V0 distributed
|
||||
load is zero. Thus the equilibrium end action is an outward action, while
|
||||
$DBd$ is the positive-local-x section resultant before the outward-normal
|
||||
sign is applied. These outputs must remain distinct.
|
||||
|
||||
### B matrix, stiffness, quadrature, and modes
|
||||
|
||||
- Differentiating the Hermite fields reproduces the documented 4x12 B matrix. The $\kappa_y=-w''$ row has $[-H_1'',H_2'',-H_3'',H_4'']$ in the $[w_1,\theta_{y1},w_2,\theta_{y2}]$ columns; the $\kappa_z=v''$ row has $[H_1'',H_2'',H_3'',H_4'']$ in the $[v_1,\theta_{z1},v_2,\theta_{z2}]$ columns.
|
||||
- Axial/torsional B rows are constant and bending rows are linear in $\xi$, so $B^TDBJ_x$ is degree at most two. The 2-point Gauss rule, exact through degree three, exactly produces the closed-form 12x12 stiffness.
|
||||
- The axial and torsion blocks each have rank one, and each exact bending block has rank two. With positive $EA,GJ,EI_y,EI_z$, the free-element stiffness is symmetric positive semidefinite with rank 6.
|
||||
- The six rigid modes are the three equal nodal translations, equal $\theta_x$, $\theta_{y1}=\theta_{y2}$ with $w_2-w_1=-L\theta_y$, and $\theta_{z1}=\theta_{z2}$ with $v_2-v_1=L\theta_z$. Each gives $Bd=0$.
|
||||
- Since $d^TKd=\int(Bd)^TD(Bd)dx$, energy is strictly positive outside the six-dimensional rigid kernel, but the unconstrained element itself is not positive definite.
|
||||
- A 1-point bending rule reduces the total element rank to 4 and introduces two spurious zero-energy modes. Production must use the approved 2-point rule or the reviewed closed form.
|
||||
|
||||
### Transformation and energy invariance
|
||||
|
||||
Projection/normalization of `n1` gives orthogonal unit $e_x,e_y$, and
|
||||
$e_z=e_x\times e_y$ makes $R=[e_x^T;e_y^T;e_z^T]$ orthogonal and
|
||||
right-handed: $RR^T=I$, $\det R=+1$. With
|
||||
$T=\operatorname{diag}(R,R,R,R)$ in node translation/rotation block order,
|
||||
|
||||
$$
|
||||
d_l=Td_g,\quad K_g=T^TK_lT,\quad f_g=T^Tf_l,
|
||||
\quad d_g^TK_gd_g=d_l^TK_ld_l.
|
||||
$$
|
||||
|
||||
This also confirms virtual-work invariance. Reversing the transform direction
|
||||
would violate the documented component contract.
|
||||
|
||||
### Constant local line-load vector
|
||||
|
||||
Exact integration of $N_q^T[p_x,p_y,p_z,m_x,0,0]^T$ gives equal half-span
|
||||
nodal forces/torques and
|
||||
|
||||
$$
|
||||
M_{y1}=-p_zL^2/12,\quad M_{y2}=+p_zL^2/12,\qquad
|
||||
M_{z1}=+p_yL^2/12,\quad M_{z2}=-p_yL^2/12.
|
||||
$$
|
||||
|
||||
The signs follow from the $-H_2,-H_4$ interpolation for $w$ and
|
||||
$H_2,H_4$ for $v$. The 2-point rule integrates the cubic load integrand
|
||||
exactly. This remains a formulation-only kernel: `*DLOAD` input, a Domain
|
||||
distributed-load object, and CLI distributed loading are out of scope.
|
||||
|
||||
### Independent numerical cross-check
|
||||
|
||||
An independent double-precision evaluation at $L=3.7$ with unequal positive
|
||||
$EA,GJ,EI_y,EI_z$ produced:
|
||||
|
||||
| check | observed result |
|
||||
| --- | ---: |
|
||||
| 2-point Gauss/closed-form normalized error | $3.20\times10^{-16}$ |
|
||||
| symmetry normalized error | $2.00\times10^{-17}$ |
|
||||
| six rigid-mode residual norms | 0 to $2.81\times10^{-15}$ |
|
||||
| numerical rank at relative $10^{-10}$ | rank 6 |
|
||||
| constant line-load normalized error | $3.08\times10^{-16}$ |
|
||||
| 1-point stiffness | rank 4 |
|
||||
| rotated local/global energy difference | 0 |
|
||||
| $\det R$ | $0.9999999999999999$ |
|
||||
|
||||
These calculations corroborate the derivation but do not replace production
|
||||
tests.
|
||||
|
||||
## Numerical Risk Assessment
|
||||
|
||||
Confirmed defects, risks, and open issues are separated.
|
||||
|
||||
| id | risk or limit | assessment and required control |
|
||||
| --- | --- | --- |
|
||||
| NR-R01 | zero/near-zero length | Singular Jacobian and divergent $L^{-3}$ terms; `NR-T05` tests the approved scale-aware boundary before evaluation. |
|
||||
| NR-R02 | zero/tangent-parallel `n1` | Undefined axes and inertia directions; `NR-T05` tests the projection boundary and forbids a silent fallback. |
|
||||
| NR-R03 | under-integration | 1-point integration adds two mechanisms; `NR-T03` must show 2-point rank 6 and negative-control rank 4. |
|
||||
| NR-R04 | mixed translation/rotation scaling | Raw rank is length-unit dependent; `NR-T04` uses length scaling and a well-scaled fixture. |
|
||||
| NR-R05 | incomplete constraints | `Kff` is singular while any rigid mode survives; `NR-T09` covers free, partial, and stable systems. |
|
||||
| NR-R06 | extreme stiffness ratios/units | A mathematically SPD system may be ill-conditioned; `NR-T10` checks residual/analytical error. Automatic scaling or a new threshold is not approved. |
|
||||
| NR-R07 | transform direction | Rotated bending signs/components can be wrong; `NR-T05` checks orthogonality, handedness, work, and energy. |
|
||||
| NR-R08 | end-action/section-cut confusion | Opposite signs can contaminate comparison; `NR-T07` checks both endpoints and distinct result types. |
|
||||
| NR-R09 | sparse duplicate reduction | Thread-dependent summation can break reproducibility; `NR-T11` checks canonical CSR and normalized values. |
|
||||
| NR-R10 | short/deep beam | Euler–Bernoulli may be too stiff; explicit limitation only. No unapproved slenderness diagnostic and no B31 reinterpretation. |
|
||||
| NR-R11 | warping, eccentricity, or `I12!=0` | The diagonal constitutive model is insufficient; explicit rejection/exclusion, never silent approximation. |
|
||||
| NR-R12 | result averaging | Averaging can hide discontinuities; baseline nodal averaging is excluded and `NR-T07` preserves endpoint identity. |
|
||||
|
||||
- shear_locking: N/A because no independent shear strain exists; deep-beam applicability remains limited.
|
||||
- volumetric_locking: N/A.
|
||||
- hourglass: N/A for the approved 2-point rule; the distinct 1-point rank deficiency is NR-R03.
|
||||
- distortion: no curved/distorted mapping exists in this straight affine element; length and axis singularities are NR-R01/NR-R02.
|
||||
- nonlinear convergence: N/A; linear residual and conditioning are NR-T09/NR-T10.
|
||||
- mesh convergence: tip-force/tip-moment polynomial fields are one-element exact; the formulation-only constant transverse load has a quartic exact displacement and requires refinement evidence.
|
||||
|
||||
## Consistency Checks
|
||||
|
||||
| check | result | evidence |
|
||||
| --- | --- | --- |
|
||||
| units | pass | Stiffness blocks and nodal work pairs are dimensionally consistent. |
|
||||
| dimensions | pass | B is 4x12, D is 4x4, and $B^TDBJ_x$ is 12x12. |
|
||||
| signs | pass | Cross-product, curvature, natural-boundary, end-action, and line-load derivations agree. |
|
||||
| dof_ordering | pass | Node blocks preserve `[u,v,w,theta_x,theta_y,theta_z]`. |
|
||||
| coordinate_transforms | pass | R/T are right-handed orthogonal maps with local = transform times global. |
|
||||
| jacobian | pass with validation | $J_x=L/2>0$ for accepted elements. |
|
||||
| constitutive | pass | Positive diagonal $EA,GJ,EI_y,EI_z$ gives nonnegative energy; `I12!=0` is rejected. |
|
||||
| integration | pass | The 2-point locations, unit weights, and $J_x$ integrate stiffness and constant-load kernels exactly. |
|
||||
| symmetry | pass | Variational and numerical checks agree. |
|
||||
| rank 6 and rigid modes | pass | Independent ranks $1+1+2+2=6$ and six rigid vectors span the kernel. |
|
||||
| positive deformation energy | pass | Strictly positive outside the rigid kernel. |
|
||||
| constrained partition | pass | $K_{ff}d_f=F_f-K_{fc}d_c$ includes nonzero $d_c$. |
|
||||
| residual reaction | pass | $R_c=(Kd-F)_c=K_{cf}d_f+K_{cc}d_c-F_c$. |
|
||||
| output locations | pass with downstream contract | Gauss values, section resultants, end actions, and residual reactions remain distinct. |
|
||||
|
||||
## Verification Readiness
|
||||
|
||||
| test id | concrete criterion |
|
||||
| --- | --- |
|
||||
| `NR-T01-DOF-SIGN` | Compare `B*d` with independently differentiated Hermite fields at multiple $\xi$; normalized error $\le10^{-12}$ and explicit $\theta_y=-w'$, $M_y=-EI_yw''$. |
|
||||
| `NR-T02-PATCH` | Check endpoint value/slope, constant axial strain/twist, both constant-curvature patches, and six rigid modes; rigid residual $\le10^{-10}$. |
|
||||
| `NR-T03-GAUSS-CLOSED` | All 12x12 entries and symmetry normalized $\le10^{-12}$; negative 1-point control must be rank 4. |
|
||||
| `NR-T04-RANK-ENERGY` | Use $Q=\operatorname{diag}(1,1,1,L,L,L,1,1,1,L,L,L)$ and $\widehat K=Q^{-T}KQ^{-1}$. For a documented well-scaled fixture require six singular values $\le10^{-10}\sigma_{max}$, six $>10^{-10}\sigma_{max}$, and positive energy for six deformation vectors. |
|
||||
| `NR-T05-TRANSFORM` | For a non-axis-aligned member require normalized orthogonality, handedness, virtual-work, transformed-stiffness, and energy errors $\le10^{-12}$; test geometry thresholds. |
|
||||
| `NR-T06-LINE-LOAD` | Compare all 12 signed closed-form components at normalized $\le10^{-12}$; separately verify `*DLOAD` remains unsupported. |
|
||||
| `NR-T07-END-SIGNS` | Pure axial/torsion/two-plane bending states must match outward natural actions and positive-face resultants at both endpoints, normalized $\le10^{-12}$; no averaging. |
|
||||
| `NR-T08-ANALYTICAL` | Axial, torsion, local-y, and local-z cantilevers at relative $\le10^{-9}$; constant transverse load requires load-vector equality and mesh convergence. |
|
||||
| `NR-T09-PARTITION-SPD` | Nonzero $d_c,F_c$: displacement and free/reaction residual normalized $\le10^{-10}$. Stable `Kff` factorizes; surviving rigid modes fail structurally with no result. |
|
||||
| `NR-T10-CONDITIONING` | Sweep documented valid scales; accepted well-conditioned cases require residual $\le10^{-10}$ and analytical error $\le10^{-9}$; numerically unresolved cases fail explicitly. |
|
||||
| `NR-T11-DETERMINISTIC-ASSEMBLY` | Across repeated thread counts require identical CSR structure/reduction order and values normalized $\le10^{-12}$. |
|
||||
|
||||
### Open issues
|
||||
|
||||
1. `NR-O01-PARDISO-CONTRACT`: official oneMKL evidence is still required for SPD matrix type, phases, zero-based CSR, repeated RHS, conditioning/error reporting, and failure codes before that adapter plan is approved. This is non-blocking for element mathematics and connects to NR-T09/NR-T10.
|
||||
2. `NR-O02-DETERMINISTIC-REDUCTION`: stable COO sort and duplicate-summation rules are project policy and must be made explicit before NR-T11.
|
||||
3. `NR-O03-STATION-NORMALIZATION`: reversed connectivity/local-axis orientation and legitimate jumps at loaded interior nodes need an explicit downstream row-normalization/eligibility rule. The legacy baseline may use its documented stable orientation and unloaded interior stations, but mismatch must never be averaged. NR-T07 covers element signs.
|
||||
|
||||
No open issue requires formulation revision. NR-O01/NR-O02 are implementation-planning
|
||||
handoffs; NR-O03 belongs to I/O and reference-model contracts.
|
||||
|
||||
## Required Revisions
|
||||
|
||||
### Formulation Agent
|
||||
|
||||
- None. No confirmed mathematical defect or missing derivation blocks implementation planning.
|
||||
|
||||
### Research Agent
|
||||
|
||||
- Resolve NR-O01 from official Intel documentation before finalizing the PARDISO adapter plan.
|
||||
|
||||
### Reference Model Agent
|
||||
|
||||
- Make NR-O03 orientation and unloaded-interior assumptions explicit without modifying the approved legacy artifacts.
|
||||
|
||||
## Downstream Handoff
|
||||
|
||||
### Implementation Planning Agent
|
||||
|
||||
- Convert NR-T01 through NR-T11 into TDD `RED -> GREEN -> VERIFY` work without changing approved tolerances.
|
||||
- Preserve stiffness/partition/factorization before load/effective-RHS/substitution.
|
||||
- Treat SPD as a post-constraint property and retain singularity/conditioning diagnostics.
|
||||
- Resolve NR-O01 and NR-O02 before the corresponding implementation steps.
|
||||
|
||||
### I/O Definition Agent
|
||||
|
||||
- Preserve outward endpoint action, positive-face section resultant, Gauss result, and assembled residual reaction as distinct identities.
|
||||
- Define NR-O03 without broadening the approved Abaqus subset.
|
||||
|
||||
### Reference Model Agent
|
||||
|
||||
- Cover axial, torsion, both bending planes, rotated-space transformation, endpoint signs, and nonzero prescribed displacement.
|
||||
- Keep `reference/cantilever beam/` read-only, stress comparison N/A, and `*DLOAD` outside CLI support.
|
||||
@@ -0,0 +1,268 @@
|
||||
# Linear Static 3D Euler Beam Physics Evaluation Report
|
||||
|
||||
## Metadata
|
||||
|
||||
- feature_id: `linear-static-3d-euler-beam`
|
||||
- model_id: `cantilever-beam-b33`
|
||||
- evaluated_head: `d76d052456ec134a98bcd5aa3b3c18a6b0ad6ba4`
|
||||
- source_reference_verification_report: `docs/reference-verifications/linear-static-3d-euler-beam-reference-verification.md`
|
||||
- source_reference_model: `docs/reference-models/linear-static-3d-euler-beam-reference-models.md`
|
||||
- source_requirement: `docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- source_formulation: `docs/formulations/3d-isoparametric-euler-beam-formulation.md`
|
||||
- source_numerical_review: `docs/numerical-reviews/linear-static-3d-euler-beam-review.md`
|
||||
- source_io_definition: `docs/io-definitions/linear-static-3d-euler-beam-io.md`
|
||||
- status: `pass-for-release-agent`
|
||||
- owner_agent: `physics-evaluation-agent`
|
||||
- date: `2026-08-09`
|
||||
|
||||
This verdict means that the documented physical checks pass and the Release Agent may audit
|
||||
release readiness. It does not approve release readiness and does not re-evaluate the Step 26
|
||||
reference tolerance decision.
|
||||
|
||||
## Input Evidence
|
||||
|
||||
The reference-verification prerequisite has status `pass-for-physics-evaluation`. Its checked
|
||||
artifact identity was reproduced before the physics checks and again after the targeted CTest.
|
||||
|
||||
| evidence | exact path or identity | status | notes |
|
||||
| --- | --- | --- | --- |
|
||||
| reference verification | `docs/reference-verifications/linear-static-3d-euler-beam-reference-verification.md` | pass-for-physics-evaluation | Required gate satisfied. |
|
||||
| solver HDF5 | `.harness/build/reference/cantilever-beam-b33/results.h5` | present and readable | 25,336 bytes; post-acceptance-run SHA-256 `13ECCF68262C14BBDE0F63667C0F10896ACD40EFEC56E8C9121C298333FD9B6D`. |
|
||||
| comparison evidence | `.harness/build/reference/cantilever-beam-b33/comparison.json` | present and passing | 128,118 bytes; SHA-256 `258347AEA791D981AEA9B2BCAD85DE5344D4859ECA3692DC5E7AA01A848F8E0D`; `passed=true`, 176 rows, 16 metrics. |
|
||||
| reference input | `reference/cantilever beam/cantilever beam.inp` | exact read-only artifact | SHA-256 `E406EA9560321B791DB829E03BD24593B9875E0195D35B86BD931EDA122EF3`; `TYPE=B33`. |
|
||||
| reference displacement | `reference/cantilever beam/cantilever beam displacements.csv` | exact read-only artifact | SHA-256 `7B3312FBC8848E81D9A0FD4FF2B56BC1954636A2C14B5C1CBB269CB9477D3C31`. |
|
||||
| reference reaction | `reference/cantilever beam/cantilever beam reactions.csv` | exact read-only artifact | SHA-256 `BF30CDB0CD50106885DE14D63492737736C587426EBD787DE4F7EE6AA86DAA23`. |
|
||||
| reference elemental force | `reference/cantilever beam/cantilever beam elemental forces.csv` | exact read-only artifact | SHA-256 `E5E77FEC0FA9482AE018DBF296E74D396335C7C711BD2E9AA2315247A34290BA`. |
|
||||
| solver CSV views | N/A | not used | No derived FESA CSV was generated or used. |
|
||||
| stress reference CSV | N/A by approved contract | not applicable | `S11` is evaluated from HDF5 schema, formulation, and analytical/unit evidence only. |
|
||||
| targeted physics tests | `.harness/build`, MSVC x64 Debug | pass | Exact Step 27 CTest passed 17/17: EulerBeam3D 10, ResultRecovery 6, B33ReferenceComparison 1. |
|
||||
|
||||
Read-only HDF5 inspection confirmed schema `0`, solver `0.1.0`, feature identity, `Step-1` frame
|
||||
`0`, formulation `B33-3D-Euler-Bernoulli`, source content identity
|
||||
`fnv1a64:04543464cc970405`, and coordinate convention
|
||||
`global-cartesian; beam-local=(t,n1,t-cross-n1)`. The file contains 11 nodes at
|
||||
`(x,y,z)=(0..10,0,0)` m and 10 consecutive one-metre elements. Every element has identity local
|
||||
axes, so local `(x,y,z)` equals global `(X,Y,Z)` for this model.
|
||||
|
||||
The documented physical model is a 10 m cantilever with node 1 fixed in all six DOFs and a
|
||||
free-end global/local `FZ=-1.0e6 N` at node 11. The section and material are SI:
|
||||
`E=2.1e11 Pa`, `Iy=I11=0.0833333 m^4`, and the only expected deformation mode is local-`z`
|
||||
translation with bending about local `y`.
|
||||
|
||||
## Physics Checks
|
||||
|
||||
All normalized physics criteria below come from the approved `1e-10` residual/equilibrium,
|
||||
`1e-12` matrix/transform/end-sign, or `1e-9` analytical contracts. They are independent checks of
|
||||
physical meaning, not a second application of the Abaqus row tolerance.
|
||||
|
||||
### 1. global equilibrium
|
||||
|
||||
In global Cartesian coordinates, force equilibrium is
|
||||
|
||||
`r_F = sum(F_applied) + sum(R)`,
|
||||
|
||||
with criterion
|
||||
|
||||
`||r_F|| / max(||sum(F_applied)||, ||sum(R)||) <= 1e-10`.
|
||||
|
||||
The comparison physics evidence records `sum(F_applied)=[0,0,-1000000] N` and
|
||||
`sum(R)=[0,0,999999.9999998808] N`. Therefore
|
||||
`r_F=[0,0,-1.1920928955078125e-7] N`, its norm is
|
||||
`1.1920928955078125e-7 N`, and the normalized value is
|
||||
`1.1920928955078125e-13`. Verdict: **pass**.
|
||||
|
||||
Moment equilibrium about the global origin is
|
||||
|
||||
`r_M = sum(M_applied) + sum(X cross F_applied) + sum(M_reaction) + sum(X cross R_force)`.
|
||||
|
||||
The free-end force gives `[0,1.0e7,0] N*m`; the complete HDF5 reaction field gives
|
||||
`[0,-9999999.999997258,0] N*m`. Thus `r_M=[0,2.7418136596679688e-6,0] N*m`,
|
||||
with normalized norm `2.7418136596679688e-13` against `1.0e7 N*m`. Verdict: **pass**.
|
||||
|
||||
### 2. reaction consistency and true free residual
|
||||
|
||||
The constrained reaction contract is `R_c=(K*d-F)_c`. At fixed node 1 the observed global row is
|
||||
`[RF1,RF2,RF3,RM1,RM2,RM3] = [0,0,1000000.0000008196,0,-10000000.000005051,0]`
|
||||
in `[N,N,N,N*m,N*m,N*m]`. It opposes the applied `-Z` force and balances its positive origin
|
||||
moment. Differences from the physical closed-form reactions are `8.195638656616211e-7 N` and
|
||||
`5.0514936447143555e-6 N*m`, normalized to `8.195638656616211e-13` and
|
||||
`5.0514936447143555e-13`. Verdict: **pass**.
|
||||
|
||||
The reaction dataset intentionally preserves free residuals. The implementation uses
|
||||
|
||||
`rho_f = ||(K*d-F)_f||_2 / max(||K*d||_f, ||F||_f)`
|
||||
|
||||
with no artificial unit floor. The serialized true free residual norm is
|
||||
`9.356339321107032e-7 N-equivalent`; the physical free scale is `1.0e6 N`, so
|
||||
`rho_f=9.356339321107032e-13 <= 1e-10`. The largest observed free force-residual component is
|
||||
`5.9604644775390625e-7 N`, and the largest free moment-residual component is
|
||||
`2.0861625671386719e-7 N*m`. Verdict: **pass**.
|
||||
|
||||
### 3. displacement direction and rotation sign
|
||||
|
||||
For free-end local `Pz=-1.0e6 N`, the documented Euler-Bernoulli solution is
|
||||
|
||||
`w(L)=Pz*L^3/(3*E*Iy)`, `theta_y(L)=-Pz*L^2/(2*E*Iy)`.
|
||||
|
||||
The expected values are `-0.0190476266666697 m` and `+0.00285714400000046 rad`.
|
||||
HDF5 gives tip `UZ=-0.019047626666677083 m` and `URY=+0.0028571440000013902 rad`, with relative
|
||||
errors `3.87e-13` and `3.27e-13`, below the analytical `1e-9` criterion. All non-root `UZ` values
|
||||
are negative and monotonically increase in magnitude toward the loaded tip; all non-root `URY`
|
||||
values are positive, as required by `theta_y=-dw/dx`. Verdict: **pass**.
|
||||
|
||||
### 4. expected zero and uncoupled symmetry
|
||||
|
||||
The fixed-root displacement row is exactly zero in all six components. Across all nodes,
|
||||
`UX`, `UY`, `URX`, and `URZ` are exactly zero. The only nonzero kinematic components are `UZ` and
|
||||
`URY`, and the only physical constrained reactions are `RF3` and `RM2`. In the element recovery,
|
||||
`epsilon0`, `kappa_x`, and `kappa_z`, and the corresponding `N`, `T`, and `Mz`, are exactly zero.
|
||||
This is the documented uncoupled local-`z` bending symmetry, with no axial, torsional, or
|
||||
cross-plane leakage. Verdict: **pass**.
|
||||
|
||||
### 5. element force, adjacent endpoints, and boundary balance
|
||||
|
||||
The HDF5 `end_force_local` rows are outward endpoint actions in
|
||||
`[FX,FY,FZ,MX,MY,MZ]`; `section_resultant` rows are positive-local-`x` section cuts in
|
||||
`[N,T,My,Mz]`. With no distributed load,
|
||||
|
||||
`F_X=n*N`, `M_X=n*T`, `M_Y=n*My`, `M_Z=n*Mz`,
|
||||
`F_Y=-n*dMz/dx`, and `F_Z=n*dMy/dx`, where `n=-1` at `xi=-1` and `n=+1` at `xi=+1`.
|
||||
|
||||
Observed section `My` is positive and decreases linearly from
|
||||
`10000000.000005048 N*m` at the root to `2.4286118949223834e-7 N*m` at the free end. The maximum
|
||||
positive-face `My` mismatch between adjacent unloaded endpoints is
|
||||
`2.73110345005989e-7 N*m`, normalized to `2.73110345005989e-14` against the model moment scale.
|
||||
The comparison ledger independently records `endpoint_consistency_passed=true` without averaging.
|
||||
|
||||
Adjacent outward actions cancel. The maximum interior `FZ_right+FZ_left` magnitude is
|
||||
`5.364418029785156e-7 N` (`5.364418029785156e-13` normalized); the maximum interior
|
||||
`MY_right+MY_left` magnitude is `2.682209014892578e-7 N*m`
|
||||
(`2.682209014892578e-14` normalized). Both satisfy the documented end-sign/residual criteria.
|
||||
|
||||
At the root, the first element action is exactly the constrained reaction evidence:
|
||||
`FZ=+1000000.0000008196 N`, `MY=-10000000.000005051 N*m`. At the free boundary, the last element
|
||||
has `FZ=-999999.9999998808 N` and `MY=-5.9604644775390625e-8 N*m`, balancing the applied end force
|
||||
and the zero applied end moment to normalized residual scale. Verdict: **pass**.
|
||||
|
||||
### 6. local/global mapping and section-force signs
|
||||
|
||||
Every stored local-axis matrix is the identity. Therefore the global `-Z` load is local
|
||||
`Pz=-1.0e6 N`, `UZ=w<0`, `URY=theta_y>0`, and the positive-face section resultant is
|
||||
`My=-Pz*(L-x)>0`. The observed outward signs are `FZ>0, MY<0` at left endpoints and
|
||||
`FZ<0, MY>0` at right endpoints, except for the physically zero free-end moment residue. These
|
||||
values satisfy the documented `theta_y=-w'`, `My=-E*Iy*w''`, outward-normal, and
|
||||
positive-face-section-cut conventions. Verdict: **pass**.
|
||||
|
||||
### 7. stress location, unit, and sign sanity
|
||||
|
||||
The stress contract is
|
||||
|
||||
`S11(xi,y,z)=E*(epsilon0 + z*kappa_y - y*kappa_z)`,
|
||||
|
||||
where `x1=y`, `x2=z`, the coordinate system is beam local, the unit is `force/length^2`, and the
|
||||
location is a section point at each of two Gauss points. The reference input has no section
|
||||
points, so HDF5 correctly contains 20 ordered `fesa-default` centroid rows
|
||||
`(x1,x2)=(0,0)`, one at each Gauss point of ten elements. This model has pure bending with
|
||||
`epsilon0=0`; consequently all 20 observed centroid `S11` values are exactly `0 Pa`.
|
||||
|
||||
Nonzero location/sign evidence comes only from the approved analytical/unit portfolio, not from
|
||||
an Abaqus stress comparison. `EulerBeam3D.RecoversSectionPointAndDefaultCentroidS11` passed with
|
||||
`epsilon0=0.01`, `kappa_y=0.02 1/m`, `kappa_z=-0.03 1/m`, `E=2.1e11 Pa`: the formula gives
|
||||
`1.575e9 Pa` at `(y,z)=(0.25,-0.5)`, `8.4e8 Pa` at `(-0.4,0.3)`, and `2.1e9 Pa` at the default
|
||||
centroid. The test enforces the formula at both Gauss points with normalized `1e-12` evidence.
|
||||
Abaqus beam stress comparison remains explicitly N/A. Verdict: **pass**.
|
||||
|
||||
### 8. nonfinite, rigid-body, abnormal-magnitude, and energy symptoms
|
||||
|
||||
All mandatory numeric HDF5 rows inspected here are finite; `comparison.json` also records no
|
||||
nonfinite row among the 176 compared rows and the 20 stress rows are finite. The fixed root is
|
||||
exactly zero, factorization/solution completed, the normalized free residual is `9.36e-13`, and
|
||||
the displacement field is smooth, so there is no rigid-body-mode symptom.
|
||||
|
||||
For this one-load linear case, the recoverable strain energy is
|
||||
`U=0.5*F^T*d=9523.81333333854 N*m`, which is finite and positive. The ratios
|
||||
`|UZ_tip|/L=0.00190476266666771` and `|URY_tip|=0.00285714400000139 rad` agree with the analytical
|
||||
solution and show no abnormal magnitude relative to the documented small-displacement/rotation
|
||||
model. The targeted rank/energy test also passed the six-rigid-mode, rank-six, and positive
|
||||
deformation-energy checks. Verdict: **pass**.
|
||||
|
||||
### 9. model coverage
|
||||
|
||||
The approved B33 bundle is one identity-axis local-`z` bending cantilever. It directly covers the
|
||||
end-to-end parser/solver/HDF5 path, global equilibrium, reaction sign, `UZ/URY`, `My/FZ`, endpoint
|
||||
continuity, and the centroid stress fallback. It does not by itself cover axial, torsion, local-`y`
|
||||
bending, rotated space, nonzero fiber stress, prescribed displacement, or the formulation-only
|
||||
line-load kernel. The targeted analytical/unit portfolio supplies the documented complementary
|
||||
coverage:
|
||||
|
||||
| coverage | targeted passing evidence | criterion |
|
||||
| --- | --- | --- |
|
||||
| axial, torsion, both bending planes | `EulerBeam3D.AnalyticalAxialTorsionAndTwoPlaneBendingRecover` and `ResultRecovery.MatchesAxialTorsionAndTwoPlaneEndSigns` | analytical relative `1e-9`; signed recovery contract |
|
||||
| rotated local/global mapping | `EulerBeam3D.RotatedTransformPreservesWorkAndEnergy` | transform/work/energy normalized `1e-12` |
|
||||
| constant local line-load kernel | `EulerBeam3D.ConstantLineLoadMatchesAllSignedComponents` | all 12 signed components normalized `1e-12`; `*DLOAD` remains outside CLI scope |
|
||||
| rigid modes, rank, and energy | `EulerBeam3D.HasSixRigidModesRankSixAndPositiveDeformationEnergy` | rigid residual `1e-10`, rank six, positive deformation energy |
|
||||
| prescribed displacement and residual | `ResultRecovery.ComputesResidualReactionForNonzeroPrescription`, `ResultRecovery.EnforcesNormalizedFreeResidual` | partition/reaction and normalized residual `1e-10` |
|
||||
| result identity and continuity | `ResultRecovery.KeepsEndActionSectionAndGaussResultsDistinct`, `ResultRecovery.RequiresInteriorEndpointConsistencyWithoutAveraging` | distinct locations and no-average consistency |
|
||||
| S11 location/sign/default | `EulerBeam3D.RecoversSectionPointAndDefaultCentroidS11`, `ResultRecovery.OrdersStressPointsAndDefaultCentroid` | formula/schema normalized `1e-12` |
|
||||
|
||||
The exact acceptance command passed all 17 selected tests. The single reference model plus this
|
||||
analytical portfolio covers every documented physical expectation without attributing unsupported
|
||||
coverage to the legacy CSV bundle. Verdict: **pass**.
|
||||
|
||||
## Failure Classification
|
||||
|
||||
- classification: `N/A`
|
||||
- primary_failure: `N/A`
|
||||
- evidence: all documented physics checks passed; no equilibrium, reaction, displacement,
|
||||
symmetry, element-force, stress-location, rigid-body, nonfinite, coverage, contract, or
|
||||
environment failure was found
|
||||
- correction_handoff: `N/A`
|
||||
|
||||
## Evaluation Verdict
|
||||
|
||||
- verdict: `pass-for-release-agent`
|
||||
- reason: the exact reference gate and artifact identity are valid; force and origin-moment
|
||||
equilibrium, constrained reaction consistency, true free residual, deformation signs, expected
|
||||
zeros, element force balance, local/global and section-force signs, S11 schema/analytical sanity,
|
||||
finite/energy/mode checks, and complementary model coverage all satisfy their documented criteria
|
||||
- release_approval: `not granted by this report`
|
||||
|
||||
## Handoff Recommendation
|
||||
|
||||
| target_agent | reason | required_input |
|
||||
| --- | --- | --- |
|
||||
| Release Agent | All documented physical checks passed. | This report, the Step 26 reference-verification report, exact build-local HDF5/comparison identities, targeted CTest evidence, and the limitations below. |
|
||||
|
||||
## No-Change Assertion
|
||||
|
||||
- source_files_modified: `false`
|
||||
- test_files_modified: `false`
|
||||
- cmake_files_modified: `false`
|
||||
- requirements_modified: `false`
|
||||
- formulations_modified: `false`
|
||||
- numerical_review_modified: `false`
|
||||
- io_contract_modified: `false`
|
||||
- reference_model_contract_modified: `false`
|
||||
- reference_verification_report_modified: `false`
|
||||
- reference_artifacts_modified: `false`
|
||||
- tolerance_policies_modified: `false`
|
||||
- Abaqus_or_other_reference_solver_executed: `false`
|
||||
- owned_report_created: `true`
|
||||
- phase_index_step27_modified: `true`
|
||||
- notes: HDF5, comparison JSON, and legacy reference artifacts were inspected read-only; the only
|
||||
generated files were the ignored build-local evidence regenerated by the exact approved CTest.
|
||||
|
||||
## Open Issues
|
||||
|
||||
- Non-blocking coverage limitation: the approved Abaqus bundle is one identity-axis local-`z`
|
||||
bending cantilever. Axial, torsion, local-`y`, rotated, prescribed-displacement, line-load, and
|
||||
nonzero stress checks rely on the approved analytical/unit portfolio; no broader Abaqus reference
|
||||
coverage is claimed.
|
||||
- Non-blocking stress limitation: the B33 bundle has no section points, so its physical `S11`
|
||||
evidence is the correct zero centroid result. Nonzero fiber location/sign evidence is analytical;
|
||||
Abaqus beam stress comparison remains N/A.
|
||||
- Non-blocking output limitation: HDF5 has no strain-energy dataset by contract. The positive energy
|
||||
value in this report is calculated from `0.5*F^T*d` and is supported by the rank/energy unit test.
|
||||
- Known formulation limitations remain: Euler-Bernoulli deep-beam applicability, transverse and
|
||||
torsional shear stress, warping, `I12!=0`, B31/Timoshenko behavior, and CLI `*DLOAD` are outside V0.
|
||||
- No open issue blocks Release Agent review.
|
||||
@@ -0,0 +1,420 @@
|
||||
# Linear Static 3D Euler Beam Reference Models
|
||||
|
||||
## Metadata
|
||||
|
||||
- feature_id: `linear-static-3d-euler-beam`
|
||||
- source_requirement: `docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- source_research: `docs/research/linear-static-3d-euler-beam-research.md`
|
||||
- source_formulation: `docs/formulations/3d-isoparametric-euler-beam-formulation.md`
|
||||
- source_numerical_review: `docs/numerical-reviews/linear-static-3d-euler-beam-review.md`
|
||||
- source_io_definition: `docs/io-definitions/linear-static-3d-euler-beam-io.md`
|
||||
- approved_design: `docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md`
|
||||
- status: `ready-for-implementation-planning`
|
||||
- owner_agent: `reference-model-agent`
|
||||
- date: `2026-08-09`
|
||||
- approved_reference_model: `cantilever-beam-b33`
|
||||
- approved_reference_schema: `abaqus-cae-report-csv-v0`
|
||||
- reference_baseline: `reference/cantilever beam/` at source commit `2b34d0b`
|
||||
|
||||
이 문서는 구현 전에 필요한 code verification, analytical solution verification 및
|
||||
approved B33 reference comparison의 모델·artifact 계약을 정의한다. 이 status는 모델과
|
||||
테스트를 구현 계획으로 넘길 준비가 되었다는 뜻일 뿐, FESA 결과 비교, physics sanity,
|
||||
release readiness 또는 Abaqus full compatibility의 pass를 뜻하지 않는다.
|
||||
|
||||
## Reference Strategy
|
||||
|
||||
### Code verification
|
||||
|
||||
요소 수식과 solver infrastructure를 외부 reference 값 없이 직접 검사한다. Hermite
|
||||
보간, `theta_y=-dw/dx`, 4x12 `B`, 12x12 closed-form stiffness, 2-point Gauss, six rigid
|
||||
modes/rank 6, positive deformation energy, local/global transform, constant local line-load
|
||||
kernel, constrained partition, deterministic assembly 및 HDF5 schema가 대상이다. Numerical
|
||||
Review의 `NR-T01`부터 `NR-T11`까지를 구현 전 RED test inventory로 사용한다.
|
||||
|
||||
### Analytical solution verification
|
||||
|
||||
서로 분리된 axial, torsion, local y bending, local z bending cantilever와 rigidly rotated
|
||||
beam을 사용한다. 각 모델은 displacement/rotation, reaction, end action, section
|
||||
resultant, residual 및 해당되는 axial `S11`을 upstream closed form과 비교한다. Nonzero
|
||||
prescribed displacement는 partition 식을, constant local line load는 formulation-only
|
||||
equivalent-vector 식을 검증한다. 이 모델들은 Abaqus CSV를 요구하지 않는 code/solution
|
||||
test fixtures이며 reference artifact bundle로 가장하지 않는다.
|
||||
|
||||
### B33 reference comparison
|
||||
|
||||
논리 모델 `cantilever-beam-b33`의 exact read-only legacy bundle만 사용하여 FESA
|
||||
`results.h5`의 displacement, reaction 및 endpoint section resultant를 Abaqus/CAE report
|
||||
CSV row와 비교한다. Artifact precheck와 exact row-set matching이 먼저 통과해야 하며,
|
||||
수치 비교는 component-scale mixed tolerance를 사용한다. Axial `S11` output은 필수지만
|
||||
Abaqus beam stress comparison은 명시적 N/A다.
|
||||
|
||||
### Excluded validation scope
|
||||
|
||||
실험 자료에 대한 physical validation, Abaqus/Nastran 실행, 새로운 reference 값 생성,
|
||||
deep-beam/Timoshenko validation, warping, `I12!=0`, instance transform, nonlinear/dynamic
|
||||
behavior는 이 portfolio에 포함하지 않는다.
|
||||
|
||||
## Model Inventory
|
||||
|
||||
| model_id | category | purpose | target quantities or tests | required artifacts | status |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `smoke-b33-cli` | smoke | 단일 B33 deck의 parse-to-HDF5와 mandatory output 확인 | CLI, diagnostics, HDF5 paths/identity/atomicity | implementation test fixture; Abaqus CSV N/A | planned |
|
||||
| `cv-b33-shape-stiffness` | code verification | Hermite, `B`, closed-form stiffness, 2-point Gauss와 signed line-load kernel 격리 | `NR-T01`, `NR-T03`, `NR-T06` | in-process test data; reference bundle N/A | planned |
|
||||
| `cv-b33-patch-rigid-assembly` | patch test | constant strain/curvature, six rigid modes, rank/energy와 deterministic assembly 확인 | `NR-T02`, `NR-T04`, `NR-T11` | implementation test mesh; Abaqus CSV N/A | planned |
|
||||
| `an-b33-axial-cantilever` | analytical | axial response와 centroidal axial stress 확인 | `UX`, `RF1`, `N`, `FX`, `S11`, residual | analytical test fixture; Abaqus CSV N/A | planned |
|
||||
| `an-b33-torsion-cantilever` | analytical | Saint-Venant torsion response 확인 | `URX`, `RM1`, `T`, `MX`, residual | analytical test fixture; Abaqus CSV N/A | planned |
|
||||
| `an-b33-local-y-bending` | analytical | local `+y` force와 `Iz=I22` bending 확인 | `UY`, `URZ`, `RF2`, `RM3`, `Mz`, `FY`, residual | analytical test fixture; Abaqus CSV N/A | planned |
|
||||
| `an-b33-local-z-bending` | analytical | local `+z` force와 `Iy=I11`, `theta_y=-w'` 확인 | `UZ`, `URY`, `RF3`, `RM2`, `My`, `FZ`, `S11`, residual | analytical test fixture; Abaqus CSV N/A | planned |
|
||||
| `an-b33-rotated-space` | analytical | non-axis-aligned 3D beam의 transform와 energy invariance 확인 | transformed displacement/reaction/resultant, work, energy, `NR-T05` | analytical test fixture; Abaqus CSV N/A | planned |
|
||||
| `an-b33-prescribed-displacement` | analytical | nonzero `dc` effective RHS, full reconstruction와 reaction 확인 | `df`, `dc`, `K*d-F`, `NR-T09` | analytical algebra fixture; Abaqus CSV N/A | planned |
|
||||
| `an-b33-line-load-kernel` | analytical | formulation-only constant local line-load equivalent vector 확인 | signed 12-component vector, mesh convergence negative/positive control | element unit fixture; `*DLOAD` reference N/A | planned |
|
||||
| `neg-b33-input-contract` | negative/invalid-input | unsupported/malformed input과 model-validation diagnostic 확인 | B31, second step, transform, nested assembly, `I12`, geometry, property, keyword cases | invalid input fixtures; result CSV N/A | planned |
|
||||
| `cantilever-beam-b33` | benchmark and regression | approved Abaqus B33 nodal/section rows와 end-to-end 회귀 비교 | displacement, reaction, section resultant; stress N/A | exact legacy four-file bundle | inventory-ready; comparison not run |
|
||||
|
||||
`planned` analytical/code rows do not have missing reference artifacts: their acceptance source is
|
||||
the reviewed formulation or an exact invariant. Only a model intended for Abaqus reference
|
||||
comparison is subject to the CSV bundle requirement.
|
||||
|
||||
## Model Records
|
||||
|
||||
### Code and patch verification records
|
||||
|
||||
| model_id | analysis and element | material/section | boundary/load | expected target and tolerance | source |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `smoke-b33-cli` | single linear static, two-node `B33` minimum deck | finite positive isotropic `E,nu,A,Iy,Iz,J`, `I12=0` | stable cantilever constraint and one `*CLOAD` | mandatory HDF5 inventory, identity and finite rows; exact schema | requirements and I/O definition |
|
||||
| `cv-b33-shape-stiffness` | free two-node Euler beam element | unequal positive `EA,GJ,EIy,EIz` to expose component swaps | no global BC/load; direct element states and local line load | matrix/Gauss/line-load normalized error `<=1e-12`; signed components exact by contract | formulation sections 8-13; `NR-T01/T03/T06` |
|
||||
| `cv-b33-patch-rigid-assembly` | one/multiple identity-oriented B33 elements | positive, well-scaled properties | rigid translation/rotation and constant strain/curvature fields | rigid residual `<=1e-10`, rank 6, positive deformation energy; identical CSR structure and values normalized `<=1e-12` | numerical review `NR-T02/T04/T11` |
|
||||
|
||||
### Analytical inventory
|
||||
|
||||
All analytical beam records use a straight prismatic B33 member, homogeneous isotropic linear
|
||||
elasticity with positive `E,G,A,Iy,Iz,J`, `I12=0`, small displacement/rotation and a fixed root.
|
||||
Signs follow the approved local `(x,y,z)=(t,n1,t x n1)` convention.
|
||||
|
||||
| model_id | boundary conditions and load | target quantity/test | analytical target | tolerance/status |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `an-b33-axial-cantilever` | root DOFs fixed; free-end local axial force `Px` | tip `UX`, root `RF1`, constant `N`, outward `FX`, centroid `S11`, residual | `u(L)=Px*L/(E*A)` with force equilibrium and `S11=N/A` | relative `1e-9`; residual normalized `1e-10`; planned |
|
||||
| `an-b33-torsion-cantilever` | root fixed; free-end local torque `Mx` | tip `URX`, root `RM1`, constant `T`, outward `MX`, residual | `theta_x(L)=Mx*L/(G*J)` with torque equilibrium | relative `1e-9`; residual normalized `1e-10`; planned |
|
||||
| `an-b33-local-y-bending` | root fixed; free-end force `Py` along local `+y` | tip `UY`, `URZ`, root `RF2/RM3`, endpoint `Mz/FY`, residual | `v(L)=Py*L^3/(3*E*Iz)`, `theta_z(L)=Py*L^2/(2*E*Iz)` | relative `1e-9`; end-sign normalized `1e-12`; planned |
|
||||
| `an-b33-local-z-bending` | root fixed; free-end force `Pz` along local `+z` | tip `UZ`, `URY`, root `RF3/RM2`, endpoint `My/FZ`, section-point `S11`, residual | `w(L)=Pz*L^3/(3*E*Iy)`, `theta_y(L)=-Pz*L^2/(2*E*Iy)` | relative `1e-9`; end-sign normalized `1e-12`; planned |
|
||||
| `an-b33-rotated-space` | rigidly rotate the axial/torsion/two-bending fixtures to a non-axis-aligned direction | `R*R^T`, `det(R)`, transformed displacement/reaction/resultant, work and energy | inverse-rotated physical results equal axis-aligned cases; `det(R)=+1` | normalized `1e-12`; planned |
|
||||
| `an-b33-prescribed-displacement` | stable free/constrained partition with nonzero `dc`, finite `Ff` and `Fc` | effective RHS, `df`, full `d`, constrained reaction and free residual | `rhs=Ff-Kfc*dc`, `Rc=Kcf*df+Kcc*dc-Fc` | normalized `1e-10`; planned |
|
||||
| `an-b33-line-load-kernel` | element-level constant local `[px,py,pz,mx]`; no parser/CLI `*DLOAD` | all 12 equivalent nodal components and signed end moments | formulation section 12.2 closed-form vector | normalized `1e-12`; planned |
|
||||
|
||||
The rotated record covers transformation rather than Abaqus instance transforms. The line-load
|
||||
record covers only the element kernel and must be paired with a negative parser test proving that
|
||||
`*DLOAD` remains unsupported.
|
||||
|
||||
### Invalid-input record
|
||||
|
||||
`neg-b33-input-contract` is a table-driven portfolio. Each case uses the smallest otherwise-valid
|
||||
single-step deck and changes only the named condition.
|
||||
|
||||
| case | expected result |
|
||||
| --- | --- |
|
||||
| `TYPE=B31` | `unsupported-element-formulation`; no Euler element |
|
||||
| second `*STEP` | `unsupported-multiple-step`; no solve/output |
|
||||
| instance translation or rotation data | `unsupported-instance-transform` |
|
||||
| nested assembly/dependent mesh semantic | structured unsupported diagnostic |
|
||||
| `I12!=0` | `unsupported-coupled-section` model failure |
|
||||
| nonpositive `E,G,A,Iy,Iz,J` | `invalid-beam-property` model failure |
|
||||
| zero/near-zero length | `invalid-beam-length` at the approved scale-aware boundary |
|
||||
| zero/tangent-parallel guide vector | `invalid-beam-guide-vector` at the approved projection boundary |
|
||||
| `*DLOAD` or unlisted model-affecting keyword | `unsupported-keyword`; no distributed-load Domain object |
|
||||
| malformed row, duplicate entity or dangling reference | input failure with source-backed deterministic diagnostic |
|
||||
| missing/extra/duplicate/nonfinite/schema- or identity-mismatched reference row | comparison precheck failure before tolerance evaluation |
|
||||
|
||||
### Approved reference record: `cantilever-beam-b33`
|
||||
|
||||
- category: benchmark and regression
|
||||
- purpose: end-to-end B33 displacement, reaction and section-resultant comparison
|
||||
- analysis_type: single linear static
|
||||
- element_type: ten straight two-node `TYPE=B33` elements, source labels 1 through 10
|
||||
- geometry: global x-axis cantilever, total length 10 m, eleven source nodes
|
||||
- material: `E=2.1e11`, `nu=0.3`, SI
|
||||
- section: `A=1`, `I11=0.0833333`, `I12=0`, `I22=0.0833333`, `J=0.140833`; `n1=(0,1,0)`
|
||||
- boundary_conditions: source node 1, DOFs 1 through 6 fixed
|
||||
- load: source node 11, global DOF 3, magnitude `-1e6` N
|
||||
- model_id: `cantilever-beam-b33`
|
||||
- logical_schema: `abaqus-cae-report-csv-v0`
|
||||
- source_commit: `2b34d0b`
|
||||
- generator: `Abaqus/CAE Learning Edition 2024`
|
||||
- units: SI
|
||||
- nodal_coordinate_system: global Cartesian
|
||||
- section_force_coordinate_system: beam local
|
||||
- step_name: `Step-1`
|
||||
- increment: `1`
|
||||
- step_time: `1.0`
|
||||
- artifact_status: all four exact paths present; structural precheck observed; FESA comparison not run
|
||||
- stress: N/A for Abaqus reference comparison; mandatory FESA `S11` remains covered by unit/analytical and HDF5 schema tests
|
||||
|
||||
The input and CSV numeric reference values are not recalculated, repaired, rounded, clamped or
|
||||
otherwise re-derived by this contract.
|
||||
|
||||
## Abaqus Input Requirements
|
||||
|
||||
The approved input is exactly
|
||||
`reference/cantilever beam/cantilever beam.inp`. Read-only inspection confirms that it contains
|
||||
`*ELEMENT, TYPE=B33` and remains within the V0 supported subset plus the documented warning
|
||||
no-op output-request allowlist. Its single identity instance is `PART-1_1-1`; its canonical result
|
||||
identity is `(Step-1, frame 0)` from increment 1, step time 1.0.
|
||||
|
||||
For later reference models:
|
||||
|
||||
- `model.inp` shall use only the feature-approved Abaqus keyword subset.
|
||||
- Model data shall define nodes, B33 connectivity, sets, material, general section and orientation.
|
||||
- History data shall define exactly one `*STEP, *STATIC`, supported boundary conditions and nodal
|
||||
loads.
|
||||
- `TYPE=B31`, instance transform, nested assembly, `I12!=0` and `*DLOAD` are not admissible ways
|
||||
to create a positive V0 reference model.
|
||||
- Abaqus output requests may be present for human generation of required CSVs, but they are
|
||||
warning no-ops for FESA and never select mandatory HDF5 output.
|
||||
|
||||
## Artifact Bundle Contract
|
||||
|
||||
### Approved legacy exception
|
||||
|
||||
The following exact paths are the entire approved read-only bundle:
|
||||
|
||||
```text
|
||||
reference/cantilever beam/cantilever beam.inp
|
||||
reference/cantilever beam/cantilever beam displacements.csv
|
||||
reference/cantilever beam/cantilever beam reactions.csv
|
||||
reference/cantilever beam/cantilever beam elemental forces.csv
|
||||
```
|
||||
|
||||
These files shall not be generated, modified, renamed, corrected or restored by an agent or
|
||||
Harness. Their spaces and existing CAE report headers are legacy aliases, not a naming pattern for
|
||||
new models.
|
||||
|
||||
Only for this approved legacy bundle:
|
||||
|
||||
- `metadata.json`: N/A
|
||||
- `README.md`: N/A
|
||||
- stress CSV: N/A because beam stress reference comparison is outside the approved V0 scope
|
||||
|
||||
The approved design and this contract jointly replace those missing files by recording model ID,
|
||||
provenance, generator, source commit, units, coordinate systems, step/frame identity, logical CSV
|
||||
schema, exact inventory, tolerance policy and the stress N/A reason. Their absence therefore does
|
||||
not change the legacy record to `needs-reference-artifacts`.
|
||||
|
||||
### Future reference bundles
|
||||
|
||||
Every later reference model shall use this structure unless its approved requirement explicitly
|
||||
marks a quantity N/A:
|
||||
|
||||
```text
|
||||
reference/
|
||||
<model-id>/
|
||||
model.inp
|
||||
metadata.json
|
||||
<model-id>_displacements.csv
|
||||
<model-id>_reactions.csv
|
||||
<model-id>_internalforces.csv
|
||||
<model-id>_stresses.csv
|
||||
README.md
|
||||
```
|
||||
|
||||
CSV names are canonical `<model-id>_*.csv` names. `metadata.json` and `README.md` are mandatory.
|
||||
A quantity CSV may be omitted only when the upstream acceptance contract explicitly records N/A
|
||||
and gives its verification replacement. Missing required files keep that model at
|
||||
`needs-reference-artifacts`.
|
||||
|
||||
## Metadata JSON Contract
|
||||
|
||||
`metadata.json` is N/A only for `cantilever-beam-b33`. Every later bundle shall include at least:
|
||||
|
||||
```json
|
||||
{
|
||||
"feature_id": "linear-static-3d-euler-beam",
|
||||
"model_id": "<model-id>",
|
||||
"artifact_status": "needs-reference-artifacts | ready-for-verification",
|
||||
"input_file": "model.inp",
|
||||
"abaqus_version": "<exact generator/version>",
|
||||
"generation_owner": "<person or approved procedure>",
|
||||
"generation_date": "<YYYY-MM-DD>",
|
||||
"source_commit": "<commit>",
|
||||
"units": "<consistent unit system>",
|
||||
"coordinate_system": "<nodal and element result systems>",
|
||||
"analysis_type": "single linear static",
|
||||
"element_types": ["B33"],
|
||||
"step_name": "Step-1",
|
||||
"increment": 1,
|
||||
"step_time": 1.0,
|
||||
"output_requests": ["U", "RF", "SF"],
|
||||
"reference_csv_schema_version": "<approved schema>",
|
||||
"reference_csv_files": ["<canonical filenames>"],
|
||||
"tolerance_policy": "<approved quantity/component policy>",
|
||||
"limitations": ["<known limitations and explicit N/A quantities>"]
|
||||
}
|
||||
```
|
||||
|
||||
No agent may invent unknown provenance fields or mark a bundle ready merely because filenames
|
||||
exist.
|
||||
|
||||
## Abaqus Reference CSV Requirements
|
||||
|
||||
Header comparison trims whitespace around each comma-separated field but does not rename fields.
|
||||
For every file, `Frame` must normalize exactly from
|
||||
`Increment 1: Step Time = 1.000` to `(Step-1, frame 0)`, `Part Instance Name` must resolve to the
|
||||
preserved instance identity, `Node Label` must be a unique source-node station, and all projected
|
||||
numeric values must be finite.
|
||||
|
||||
| exact legacy path | expected trimmed header | unique row key | observed inventory |
|
||||
| --- | --- | --- | --- |
|
||||
| `reference/cantilever beam/cantilever beam displacements.csv` | `Frame, Part Instance Name, Node Label, U-U1, U-U2, U-U3, UR-UR1, UR-UR2, UR-UR3` | `(Frame, Part Instance Name, Node Label)` | 11 rows; header/key/finite/arity checks observed |
|
||||
| `reference/cantilever beam/cantilever beam reactions.csv` | `Frame, Part Instance Name, Node Label, RF-RF1, RF-RF2, RF-RF3, RM-RM1, RM-RM2, RM-RM3` | `(Frame, Part Instance Name, Node Label)` | 11 rows; header/key/finite/arity checks observed |
|
||||
| `reference/cantilever beam/cantilever beam elemental forces.csv` | `Frame, Part Instance Name, Node Label, SF-SF1, SM-SM1, SM-SM2, SM-SM3` | `(Frame, Part Instance Name, Node Label)` | 11 rows; header/key/finite/arity checks observed |
|
||||
|
||||
The wide-row key becomes unique canonical component rows after adding `quantity` and `component`.
|
||||
Missing, extra, duplicate, nonfinite, header/schema or identity mismatch stops comparison as
|
||||
`needs-reference-artifacts` or `schema-mismatch`. No bad or near-zero row may be silently dropped.
|
||||
|
||||
For the elemental-force CSV, source node station is not an element-end identity. A boundary
|
||||
station uses its only incident endpoint. An interior station may collapse exactly two endpoints
|
||||
only when chain connectivity, section and local axes are consistent and the station has no
|
||||
concentrated force/moment. The two positive-local-x section-cut values must first agree within the
|
||||
approved component tolerance. If they agree, choose the endpoint with smaller stable internal
|
||||
element ID; never average. Reversed orientation, branch, section jump, local-axis discontinuity or
|
||||
loaded interior station requires an element-aware future schema and is a `schema-mismatch` under
|
||||
this legacy schema.
|
||||
|
||||
## Coverage Matrix
|
||||
|
||||
The authoritative comparison source is FESA HDF5, not an extracted FESA CSV. Dataset paths use
|
||||
the canonical V0 step identity.
|
||||
|
||||
| verification quantity | requirement ids | model_id | FESA HDF5 dataset | legacy CSV and components | row identity/location | tolerance | verification method | status |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| nodal displacement/rotation | 003, 029-031, 036-042 | `cantilever-beam-b33` | `/steps/Step-1/frames/0/nodal/displacement` | `reference/cantilever beam/cantilever beam displacements.csv`: `U-U1/U-U2/U-U3 -> UX/UY/UZ`, `UR-UR1/UR-UR2/UR-UR3 -> URX/URY/URZ` | preserved instance + source node; global nodal | `1e-9 + 1e-6*reference_scale` per displacement/rotation component | HDF5-to-read-only CSV after artifact/row-set precheck | ready for implementation planning; comparison not run |
|
||||
| nodal reaction force | 007, 027, 029-031, 036-042 | `cantilever-beam-b33` | `/steps/Step-1/frames/0/nodal/reaction` | `reference/cantilever beam/cantilever beam reactions.csv`: `RF-RF1/RF-RF2/RF-RF3 -> RF1/RF2/RF3` | preserved instance + source node; global nodal | `1e-3 + 1e-6*reference_scale` per force component | HDF5-to-read-only CSV plus global equilibrium | ready for implementation planning; comparison not run |
|
||||
| nodal reaction moment | 007, 027, 029-031, 036-042 | `cantilever-beam-b33` | `/steps/Step-1/frames/0/nodal/reaction` | `reference/cantilever beam/cantilever beam reactions.csv`: `RM-RM1/RM-RM2/RM-RM3 -> RM1/RM2/RM3` | preserved instance + source node; global nodal | `1e-3 + 1e-6*reference_scale` per moment component | HDF5-to-read-only CSV plus moment equilibrium | ready for implementation planning; comparison not run |
|
||||
| section axial force | 031, 036-042 | `cantilever-beam-b33` | `/steps/Step-1/frames/0/element/section_resultant` | `reference/cantilever beam/cantilever beam elemental forces.csv`: `SF-SF1 -> N` | positive-local-x endpoint projected to eligible source node station | `1e-3 + 1e-6*reference_scale` for `N` | endpoint consistency, deterministic station selection, HDF5-to-CSV | ready for implementation planning; comparison not run |
|
||||
| section moments/torsion | 031, 036-042 | `cantilever-beam-b33` | `/steps/Step-1/frames/0/element/section_resultant` | `reference/cantilever beam/cantilever beam elemental forces.csv`: `SM-SM1 -> My`, `SM-SM2 -> Mz`, `SM-SM3 -> T` | positive-local-x endpoint projected to eligible source node station; beam local | `1e-3 + 1e-6*reference_scale` separately for `My`, `Mz`, `T` | endpoint consistency, deterministic station selection, HDF5-to-CSV | ready for implementation planning; comparison not run |
|
||||
| equilibrium end action | 031, 035, 043 | analytical models and physics portfolio | `/steps/Step-1/frames/0/element/end_force_local` | Abaqus CSV N/A for direct outward-action comparison | element endpoint `xi=-1,+1`; local outward action `[FX,FY,FZ,MX,MY,MZ]` | analytical normalized `1e-12`; residual `1e-10` | unit/analytical end-sign tests and later physics sanity | planned |
|
||||
| generalized strain/resultant | 029, 031, 035 | code and analytical models | `/steps/Step-1/frames/0/element/generalized_strain` and `/steps/Step-1/frames/0/element/generalized_resultant` | Abaqus CSV N/A | two Gauss points; beam local | matrix/formulation normalized `1e-12`, analytical relative `1e-9` | formulation/unit/HDF5 schema tests | planned |
|
||||
| axial stress | 029, 032, 035 | axial/local-z analytical models | `/steps/Step-1/frames/0/element/stress_s11` | stress CSV N/A; Abaqus beam stress reference comparison N/A | element, Gauss point, input section point or `fesa-default` centroid | analytical relative `1e-9`; exact unit/row schema | unit/analytical recovery and HDF5 schema tests | planned; reference N/A |
|
||||
|
||||
For every matched reference group,
|
||||
`reference_scale=max(abs(Abaqus reference rows))` for the same model, step/frame, quantity and
|
||||
component, and `row_tolerance=absolute_floor+1e-6*reference_scale`. Abaqus values alone set the
|
||||
scale. A zero scale uses only the floor. Every row decision and max absolute, component-scale
|
||||
normalized, RMS, norm and worst-row/component metrics must be reported.
|
||||
|
||||
### Complete must-requirement coverage
|
||||
|
||||
Every approved `must` requirement is connected below to a model/test/quantity or an explicit
|
||||
non-reference governance check. `N/A` means that an Abaqus CSV is not the applicable evidence;
|
||||
it does not waive the requirement.
|
||||
|
||||
| requirement | model/test/quantity or explicit N/A | planned verification |
|
||||
| --- | --- | --- |
|
||||
| `FESA-REQ-LS3DEB-001` | `smoke-b33-cli`; `neg-b33-input-contract` second-step case | positive single-step and structured rejection test |
|
||||
| `FESA-REQ-LS3DEB-002` | all analytical B33 records | model-validation and formulation scope tests; CSV N/A except approved benchmark |
|
||||
| `FESA-REQ-LS3DEB-003` | all code/analytical records; displacement/reaction rows | exact DOF/component-order tests |
|
||||
| `FESA-REQ-LS3DEB-004` | axial, torsion and both bending records | four independent analytical solution tests |
|
||||
| `FESA-REQ-LS3DEB-005` | `smoke-b33-cli`, `cantilever-beam-b33` | B33 semantic mapping and artifact type precheck |
|
||||
| `FESA-REQ-LS3DEB-006` | `neg-b33-input-contract` B31 case | exact `unsupported-element-formulation` test |
|
||||
| `FESA-REQ-LS3DEB-007` | four cantilevers and prescribed-displacement record | DOF 1..6 load/BC and nonzero `dc` tests |
|
||||
| `FESA-REQ-LS3DEB-008` | `an-b33-line-load-kernel`; negative `*DLOAD` case | closed-form vector and unsupported parser tests; reference CSV N/A |
|
||||
| `FESA-REQ-LS3DEB-009` | `smoke-b33-cli`, keyword table tests, approved legacy input | exact positive keyword inventory |
|
||||
| `FESA-REQ-LS3DEB-010` | parser code-verification cases | case/comment/source-label preservation tests; CSV N/A |
|
||||
| `FESA-REQ-LS3DEB-011` | analytical load/BC decks and invalid arity/target cases | target expansion and row grammar tests |
|
||||
| `FESA-REQ-LS3DEB-012` | both bending and rotated-space records | property/axis mapping and transform checks |
|
||||
| `FESA-REQ-LS3DEB-013` | all analytical records; invalid property cases | `G` calculation and positive property tests |
|
||||
| `FESA-REQ-LS3DEB-014` | `neg-b33-input-contract` geometry cases; `NR-T05` | exact scale-aware length/projection boundary tests |
|
||||
| `FESA-REQ-LS3DEB-015` | multi-instance semantic fixture and all HDF5/reference identities | stable source/internal identity tests |
|
||||
| `FESA-REQ-LS3DEB-016` | multi-instance semantic fixture | distinct deterministic identity test; reference CSV N/A |
|
||||
| `FESA-REQ-LS3DEB-017` | invalid instance-transform case | exact diagnostic test |
|
||||
| `FESA-REQ-LS3DEB-018` | invalid nested/dependent cases | structured unsupported tests |
|
||||
| `FESA-REQ-LS3DEB-019` | `cantilever-beam-b33` input and allowlist table cases | warning/no-op and no semantic-effect tests |
|
||||
| `FESA-REQ-LS3DEB-020` | unknown-keyword negative case and `smoke-b33-cli` | error plus mandatory-output independence test |
|
||||
| `FESA-REQ-LS3DEB-021` | Domain/AnalysisModel code-verification fixture | non-copy/non-mutation ownership tests; CSV N/A |
|
||||
| `FESA-REQ-LS3DEB-022` | DOF/scatter/reconstruction code-verification fixture | DofManager ownership and exact mapping tests; CSV N/A |
|
||||
| `FESA-REQ-LS3DEB-023` | `smoke-b33-cli` and HDF5 state fixture | required/excluded state allocation tests; CSV N/A |
|
||||
| `FESA-REQ-LS3DEB-024` | `cv-b33-patch-rigid-assembly`, `NR-T11` | repeated thread-count CSR determinism test; CSV N/A |
|
||||
| `FESA-REQ-LS3DEB-025` | math/adapter dependency fixtures | storage/layout and public dependency review; CSV N/A |
|
||||
| `FESA-REQ-LS3DEB-026` | orchestration event-trace fixture | exact factorize-before-load order test; CSV N/A |
|
||||
| `FESA-REQ-LS3DEB-027` | `an-b33-prescribed-displacement` | effective RHS, reconstruction and residual reaction test |
|
||||
| `FESA-REQ-LS3DEB-028` | `smoke-b33-cli` writer failure/success fixtures | authoritative output and atomicity tests; CSV N/A |
|
||||
| `FESA-REQ-LS3DEB-029` | HDF5 rows in this Coverage Matrix | exact path/shape/component schema test |
|
||||
| `FESA-REQ-LS3DEB-030` | `smoke-b33-cli`; `cantilever-beam-b33` provenance | ordinary unit label and external SI metadata tests |
|
||||
| `FESA-REQ-LS3DEB-031` | all code/analytical models and three legacy CSV quantities | recovery component/location and mandatory-output tests |
|
||||
| `FESA-REQ-LS3DEB-032` | axial/local-z analytical stress; HDF5 `stress_s11` | stress unit/analytical/schema tests; Abaqus stress comparison N/A |
|
||||
| `FESA-REQ-LS3DEB-033` | `smoke-b33-cli`, diagnostic negative cases | CLI exit-code/field/order integration tests; CSV N/A |
|
||||
| `FESA-REQ-LS3DEB-034` | every implementation model/test | per-step RED/GREEN/VERIFY and full MSVC/CTest evidence; model CSV N/A |
|
||||
| `FESA-REQ-LS3DEB-035` | `NR-T01` through `NR-T11` and analytical inventory | exact numerical criteria in model records |
|
||||
| `FESA-REQ-LS3DEB-036` | `cantilever-beam-b33` and comparison-policy unit fixtures | Abaqus-only component scale and exact formula tests |
|
||||
| `FESA-REQ-LS3DEB-037` | same comparison fixtures, including zero-scale groups | exact SI floors and zero-scale tests |
|
||||
| `FESA-REQ-LS3DEB-038` | malformed reference cases in `neg-b33-input-contract` | pre-tolerance fail-fast and no-clamp/no-drop tests |
|
||||
| `FESA-REQ-LS3DEB-039` | verification-report schema fixture | every row decision and aggregate/worst metrics test |
|
||||
| `FESA-REQ-LS3DEB-040` | exact legacy Artifact Bundle Contract | inventory plus `git diff --exit-code -- reference/` process check |
|
||||
| `FESA-REQ-LS3DEB-041` | approved artifact precheck | four files, B33, exact headers, unique keys, finite values |
|
||||
| `FESA-REQ-LS3DEB-042` | three comparison quantities and station normalization | exact component mapping, endpoint consistency and no-average tests |
|
||||
| `FESA-REQ-LS3DEB-043` | gate audit; later physics portfolio | reference execution N/A at this step; enforce build/test -> comparison -> physics -> release order |
|
||||
| `FESA-REQ-LS3DEB-044` | process/Git diff audit and limitations review | no reference execution/mutation and no out-of-scope support claim |
|
||||
|
||||
## Artifact Acceptance Checklist
|
||||
|
||||
Read-only inventory inspection on `2026-08-09` established the following pre-implementation facts:
|
||||
|
||||
- all four exact legacy paths exist;
|
||||
- the input declares `TYPE=B33`;
|
||||
- each CSV trimmed header matches the documented `abaqus-cae-report-csv-v0` inventory;
|
||||
- each CSV has 11 data rows with a unique `(Frame, Part Instance Name, Node Label)` key;
|
||||
- every projected numeric field is finite and every row has the header arity;
|
||||
- generator, source commit, SI units, coordinates, step/increment/time and tolerance provenance are
|
||||
recorded in the approved design and this contract;
|
||||
- legacy `metadata.json`, `README.md` and stress CSV are accepted N/A exceptions;
|
||||
- no reference value was recalculated and no comparison was performed.
|
||||
|
||||
Before an actual comparison, tooling must repeat all artifact checks, verify the exact Frame and
|
||||
instance identities, compare the complete projected row sets, and stop on any failure. The Step AC
|
||||
must also show no working-tree diff under `reference/`. Passing this checklist is not a reference
|
||||
comparison pass.
|
||||
|
||||
## Open Issues and Downstream Handoff
|
||||
|
||||
### Open issues
|
||||
|
||||
- No missing artifact or user decision blocks implementation planning for the approved legacy
|
||||
model.
|
||||
- `NR-O01` (official oneMKL PARDISO contract) and `NR-O02` (deterministic duplicate-reduction
|
||||
algorithm) remain implementation-planning inputs, not reference artifact defects.
|
||||
- Future reversed, branched, loaded-interior or section-jump reference models require an
|
||||
element-aware canonical CSV schema; the legacy node-station schema must not be generalized.
|
||||
|
||||
### Implementation Planning Agent
|
||||
|
||||
Use this order for tests that must fail before their production implementation:
|
||||
|
||||
1. Hermite/DOF/sign and `B` checks.
|
||||
2. Gauss/closed stiffness, rigid modes, rank and energy.
|
||||
3. Rotation/local-axis and signed line-load kernel.
|
||||
4. Axial, torsion, local-y and local-z analytical cantilevers.
|
||||
5. Nonzero prescribed displacement, SPD/residual and deterministic assembly.
|
||||
6. Parser invalid-input portfolio and CLI/HDF5 output contract.
|
||||
7. Legacy artifact precheck, row projection and tolerance/report policy.
|
||||
|
||||
Keep reference comparison after the full MSVC build/test gate and do not require new Abaqus
|
||||
artifacts for code/analytical fixtures.
|
||||
|
||||
### Reference Verification Agent
|
||||
|
||||
Run `ARTIFACT CHECK -> HDF5 ROW PROJECTION -> EXACT ROW-SET CHECK -> ENDPOINT CONSISTENCY ->
|
||||
COMPONENT-SCALE COMPARE -> REPORT`. Use only the exact legacy files and the HDF5 paths/component
|
||||
mappings in the Coverage Matrix. Do not synthesize `SF2/SF3` or stress rows, clamp values, omit
|
||||
rows, average interior endpoints, or change the approved tolerance.
|
||||
|
||||
### Physics Evaluation Agent
|
||||
|
||||
Only after reference comparison passes, check global force/moment equilibrium, reaction sign,
|
||||
displacement direction, bending symmetry, outward end action versus positive-face section
|
||||
resultant consistency, and normalized residual. The approved reference model is one local-z
|
||||
bending cantilever; broader physical coverage comes from the analytical portfolio, not an inflated
|
||||
claim about the single CSV bundle.
|
||||
|
||||
### I/O Definition Agent
|
||||
|
||||
No upstream contract revision is requested. If a future reference model needs an element-aware row
|
||||
identity, define and approve that schema separately without changing the read-only legacy aliases.
|
||||
@@ -0,0 +1,297 @@
|
||||
# Linear Static 3D Euler Beam Reference Verification Report
|
||||
|
||||
## Metadata
|
||||
|
||||
- feature_id: `linear-static-3d-euler-beam`
|
||||
- model_id: `cantilever-beam-b33`
|
||||
- source_head: `451d9077ea70e3087454db3760e677da0095d27f`
|
||||
- source_build_test_report: `docs/build-test-reports/linear-static-3d-euler-beam.md`
|
||||
- source_reference_models: `docs/reference-models/linear-static-3d-euler-beam-reference-models.md`
|
||||
- source_io_definition: `docs/io-definitions/linear-static-3d-euler-beam-io.md`
|
||||
- source_implementation_plan: `docs/implementation-plans/linear-static-3d-euler-beam.md`
|
||||
- source_implementation_report: `docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`
|
||||
- status: `pass-for-physics-evaluation`
|
||||
- owner_agent: `reference-verification-agent`
|
||||
- date: `2026-08-09`
|
||||
- review_fix_date: `2026-08-10`
|
||||
|
||||
The prerequisite build/test report has status
|
||||
`pass-for-reference-verification`. This report applies only the approved Abaqus
|
||||
B33 reference tolerance. It does not approve physics sanity or release readiness.
|
||||
|
||||
## Artifact Inventory
|
||||
|
||||
The approved B33 exception overrides the generic new-bundle inventory. The exact
|
||||
four legacy files with spaces are the complete read-only reference bundle;
|
||||
`metadata.json`, `README.md`, and a stress CSV are contractually N/A and are not
|
||||
missing artifacts.
|
||||
|
||||
| item | exact path | status | direct audit evidence |
|
||||
| --- | --- | --- | --- |
|
||||
| reference directory | `reference/cantilever beam/` | present, exact inventory | Four regular files only; no extra entry. |
|
||||
| reference input | `reference/cantilever beam/cantilever beam.inp` | present, valid | 2,330 bytes; exactly one `*ELEMENT, TYPE=B33` declaration at line 21. |
|
||||
| displacement CSV | `reference/cantilever beam/cantilever beam displacements.csv` | present, valid | Exact 9-column CAE header; 11 unique rows; 66 finite values. |
|
||||
| reaction CSV | `reference/cantilever beam/cantilever beam reactions.csv` | present, valid | Exact 9-column CAE header; 11 unique rows; 66 finite values. |
|
||||
| elemental-force CSV | `reference/cantilever beam/cantilever beam elemental forces.csv` | present, valid | Exact 7-column CAE header; 11 unique rows; 44 finite values. |
|
||||
| legacy metadata | `reference/cantilever beam/metadata.json` | N/A | Approved design, ADR-010, I/O definition, and reference-model contract supply provenance. |
|
||||
| legacy README | `reference/cantilever beam/README.md` | N/A | Approved B33 legacy exception. |
|
||||
| reference stress CSV | N/A | N/A | Abaqus beam-stress comparison is outside the approved V0 scope. |
|
||||
| authoritative solver output | `.harness/build/reference/cantilever-beam-b33/results.h5` | present, valid | 25,336 bytes; generated by the fresh exact CTest; HDF5 schema inspected read-only with HDF5 2.1.1 utilities. |
|
||||
| comparison ledger | `.harness/build/reference/cantilever-beam-b33/comparison.json` | present, valid | 128,118 bytes; 176 row decisions, 16 component metrics, and `passed=true`. |
|
||||
| solver debug CSV view | N/A | N/A | No derived FESA CSV was generated or used. |
|
||||
|
||||
### Reference hashes
|
||||
|
||||
Fresh pre-comparison and post-comparison SHA-256 values were identical:
|
||||
|
||||
| exact approved legacy path | SHA-256 |
|
||||
| --- | --- |
|
||||
| `reference/cantilever beam/cantilever beam.inp` | `E406EA9560321B791DBDB829E03BD24593B9875E0195D35B86BD931EDA122EF3` |
|
||||
| `reference/cantilever beam/cantilever beam displacements.csv` | `7B3312FBC8848E81D9A0FD4FF2B56BC1954636A2C14B5C1CBB269CB9477D3C31` |
|
||||
| `reference/cantilever beam/cantilever beam reactions.csv` | `BF30CDB0CD50106885DE14D63492737736C587426EBD787DE4F7EE6AA86DAA23` |
|
||||
| `reference/cantilever beam/cantilever beam elemental forces.csv` | `E5E77FEC0FA9482AE018DBF296E74D396335C7C711BD2E9AA2315247A34290BA` |
|
||||
|
||||
`git diff --exit-code -- reference/` exited 0 and
|
||||
`git status --short -- reference/` was empty after both comparison runs.
|
||||
|
||||
### Authoritative HDF5 audit
|
||||
|
||||
`h5ls` and `h5dump` opened `results.h5` read-only and established:
|
||||
|
||||
- schema version `0`, solver version `0.1.0`, feature
|
||||
`linear-static-3d-euler-beam`, formulation `B33-3D-Euler-Bernoulli`,
|
||||
`Step-1`, and frame `0`;
|
||||
- metadata unit label `user-consistent-unspecified`, as required for ordinary
|
||||
`.inp` interpretation; the approved reference-model contract supplies the
|
||||
external SI provenance used by this comparison;
|
||||
- coordinate convention
|
||||
`global-cartesian; beam-local=(t,n1,t-cross-n1)`;
|
||||
- source identity
|
||||
`path=C:/Users/baram/orca/workspaces/FESADev/LinearStatic/reference/cantilever beam/cantilever beam.inp;content_identity=fnv1a64:04543464cc970405`;
|
||||
a fresh FNV-1a calculation of the input bytes reproduced
|
||||
`04543464cc970405`;
|
||||
- 11 nodes with stable internal IDs 0 through 10, source labels 1 through 11,
|
||||
instance `PART-1_1-1`, global coordinates `(0..10,0,0)`;
|
||||
- 10 elements with stable IDs 0 through 9, source labels 1 through 10,
|
||||
consecutive connectivity and identity local axes;
|
||||
- displacement and reaction shapes `[11,6]`, section-resultant shape
|
||||
`[10,2,4]`, exact component/unit/coordinate/location attributes, and finite
|
||||
float64 values;
|
||||
- mandatory `stress_s11` compound schema with 20 finite rows (10 elements x 2
|
||||
Gauss points), `S11`, `force/length^2`, beam-local section-point attributes,
|
||||
and the required `fesa-default` centroid identity.
|
||||
|
||||
Only `results.h5` and `comparison.json` exist in the build-local evidence
|
||||
directory.
|
||||
|
||||
## Comparison Contract
|
||||
|
||||
- reference_csv_schema_version: `abaqus-cae-report-csv-v0`
|
||||
- hdf5_schema_version: `0`
|
||||
- model / frame normalization: CSV
|
||||
`Increment 1: Step Time = 1.000` -> `(cantilever-beam-b33, Step-1, frame 0)`
|
||||
- id_matching: exact preserved `instance_name` plus source node label;
|
||||
section-resultant endpoints project to an eligible source-node station
|
||||
- row-set policy: expected canonical keys are all 11 nodes crossed with 6
|
||||
displacement, 6 reaction, and 4 section-resultant components
|
||||
- displacement normalization:
|
||||
`U-U1/U-U2/U-U3/UR-UR1/UR-UR2/UR-UR3` ->
|
||||
`UX/UY/UZ/URX/URY/URZ`
|
||||
- reaction normalization:
|
||||
`RF-RF1/RF-RF2/RF-RF3/RM-RM1/RM-RM2/RM-RM3` ->
|
||||
`RF1/RF2/RF3/RM1/RM2/RM3`
|
||||
- section normalization: `SF-SF1 -> N`, `SM-SM1 -> My`,
|
||||
`SM-SM2 -> Mz`, `SM-SM3 -> T`
|
||||
- coordinates: global Cartesian for nodal quantities; beam local for section
|
||||
resultants
|
||||
- output locations: nodal displacement/reaction and positive-local-x endpoint
|
||||
section cut projected to node station
|
||||
- interior-node policy: both incident endpoints must first pass the approved
|
||||
component tolerance; the smaller stable element ID is selected without
|
||||
averaging
|
||||
- tolerance source: requirements 036-039, ADR-014, approved I/O definition,
|
||||
and reference-model contract
|
||||
- tolerance policy: `absolute_floor + 1e-6 * reference_scale`
|
||||
- reference scale: maximum absolute value from read-only Abaqus rows in the
|
||||
same model, step/frame, quantity, and component only
|
||||
- SI floors: `1e-9` for displacement/rotation and `1e-3` for force/moment;
|
||||
zero scale uses the floor alone
|
||||
- fail-before-tolerance conditions: missing, extra, duplicate, nonfinite,
|
||||
schema-mismatched, or identity-mismatched row
|
||||
- zero-reference policy: no zero clamp, deletion, substitution, or omission
|
||||
|
||||
The complete expected set of 176 canonical keys was reconstructed independently
|
||||
from the contract and matched the 176 unique ledger rows exactly. The 16 expected
|
||||
quantity/component keys matched the 16 unique metrics. Every serialized absolute
|
||||
error, tolerance, pass decision, Abaqus-only reference scale, maximum error,
|
||||
maximum tolerance-normalized error, RMS error, norm error, and worst-row index was
|
||||
recalculated from the row ledger and matched exactly. Missing rows, extra rows,
|
||||
duplicate rows, nonfinite rows, and failed rows were all zero.
|
||||
|
||||
The authoritative TASK-24 `ComparisonReport`, test contract, serialized JSON, and
|
||||
Step 26 acceptance probe all define the verdict as the boolean `passed`. Final
|
||||
review reproduced that the former `$metrics.status` sample failed against the valid
|
||||
artifact, corrected the phase probe to `$metrics.passed -eq $true`, and reran the
|
||||
exact acceptance chain successfully. The generated JSON has `passed=true`.
|
||||
|
||||
## Execution Evidence
|
||||
|
||||
The exact command was run twice after the artifact precheck:
|
||||
|
||||
```powershell
|
||||
ctest --test-dir .harness/build -C Debug -R B33ReferenceComparison -V --output-on-failure
|
||||
```
|
||||
|
||||
Both executions passed the single exact test
|
||||
`B33ReferenceComparison.GeneratesAuthoritativeHdf5AndComparisonEvidence` 1/1.
|
||||
Each run reset only `.harness/build/reference/cantilever-beam-b33/` and regenerated
|
||||
the same two build-local files. The comparison ledger was byte deterministic on
|
||||
both runs:
|
||||
|
||||
- size: `128118` bytes
|
||||
- SHA-256: `258347AEA791D981AEA9B2BCAD85DE5344D4859ECA3692DC5E7AA01A848F8E0D`
|
||||
- verdict: `passed=true`
|
||||
|
||||
`results.h5` remains the authoritative solver output. The JSON is deterministic
|
||||
review evidence derived directly from HDF5 and the read-only Abaqus CSV rows.
|
||||
|
||||
## Quantity Results
|
||||
|
||||
`maximum_relative_error` below is calculated only where the Abaqus reference is
|
||||
nonzero. It is reported for audit completeness, but it is not the acceptance
|
||||
rule: near-zero Abaqus residues make row-relative error ill-conditioned. The
|
||||
approved component-scale normalized error is `absolute_error / row_tolerance`.
|
||||
|
||||
| quantity | FESA HDF5 dataset | reference CSV | compared | missing | extra | nonfinite | max abs error | max relative error | max tolerance-normalized error | RMS error | norm error | worst ID/component by abs error | result |
|
||||
| --- | --- | --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | --- | --- |
|
||||
| displacement | `/steps/Step-1/frames/0/nodal/displacement` | `reference/cantilever beam/cantilever beam displacements.csv` | 66 | 0 | 0 | 0 | `5.333229170789711e-10` | `1.0` | `0.026602795021994977` | `1.1637590907608428e-10` | `9.454423547085314e-10` | node 11 / `UZ` | pass |
|
||||
| reaction | `/steps/Step-1/frames/0/nodal/reaction` | `reference/cantilever beam/cantilever beam reactions.csv` | 66 | 0 | 0 | 0 | `5.0514936447143555e-6` | `8.195638656616211e-13` | `8.187451205410801e-7` | `6.403678373262425e-7` | `5.202372903532068e-6` | node 1 / `RM2` | pass |
|
||||
| section resultant | `/steps/Step-1/frames/0/element/section_resultant` | `reference/cantilever beam/cantilever beam elemental forces.csv` | 44 | 0 | 0 | 0 | `1.5600242861189492e-2` | `1.0000155680249674` | `0.0015598682992890203` | `0.0023518254339534184` | `0.015600245073676508` | node station 11 / `My` | pass |
|
||||
| stress | `/steps/Step-1/frames/0/element/stress_s11` | N/A | N/A | N/A | N/A | 0 in 20 mandatory HDF5 rows | N/A | N/A | N/A | N/A | N/A | N/A | N/A for Abaqus comparison; HDF5 requirement passed |
|
||||
|
||||
The displacement row-relative maximum occurs at node 1 `UZ`, where the stored
|
||||
reference residue is `-1e-30`; the section row-relative maximum occurs at free-end
|
||||
`My`, where the stored reference residue is `-1.56e-2`. Neither row was clamped or
|
||||
omitted. Their approved mixed-tolerance decisions pass.
|
||||
|
||||
### Component metrics
|
||||
|
||||
Each group contains 11 matched rows. `worst_row` is the zero-based index in the
|
||||
deterministic JSON row ledger.
|
||||
|
||||
| quantity | component | reference scale | row tolerance | max abs error | max normalized error | RMS error | norm error | worst row | worst identity | result |
|
||||
| --- | --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | --- | --- |
|
||||
| displacement | `UX` | `0` | `1e-9` | `0` | `0` | `0` | `0` | 0 | node 1 / `UX` | pass |
|
||||
| displacement | `UY` | `0` | `1e-9` | `0` | `0` | `0` | `0` | 1 | node 1 / `UY` | pass |
|
||||
| displacement | `UZ` | `0.0190476272` | `2.00476272e-8` | `5.333229170789711e-10` | `0.026602795021994977` | `2.790953046857666e-10` | `9.256544063926071e-10` | 62 | node 11 / `UZ` | pass |
|
||||
| displacement | `URX` | `0` | `1e-9` | `0` | `0` | `0` | `0` | 3 | node 1 / `URX` | pass |
|
||||
| displacement | `URY` | `0.00285714399` | `3.85714399e-9` | `1.000013943180944e-10` | `0.025926279801157852` | `5.801658540511775e-11` | `1.924192454063848e-10` | 52 | node 9 / `URY` | pass |
|
||||
| displacement | `URZ` | `0` | `1e-9` | `0` | `0` | `0` | `0` | 5 | node 1 / `URZ` | pass |
|
||||
| reaction | `RF1` | `0` | `1e-3` | `0` | `0` | `0` | `0` | 66 | node 1 / `RF1` | pass |
|
||||
| reaction | `RF2` | `0` | `1e-3` | `0` | `0` | `0` | `0` | 67 | node 1 / `RF2` | pass |
|
||||
| reaction | `RF3` | `1e6` | `1.001` | `8.195638656616211e-7` | `8.187451205410801e-7` | `3.6239383393839433e-7` | `1.2019243735120167e-6` | 68 | node 1 / `RF3` | pass |
|
||||
| reaction | `RM1` | `0` | `1e-3` | `0` | `0` | `0` | `0` | 69 | node 1 / `RM1` | pass |
|
||||
| reaction | `RM2` | `1e7` | `10.001` | `5.0514936447143555e-6` | `5.05098854585977e-7` | `1.5261377760919117e-6` | `5.061626381684292e-6` | 70 | node 1 / `RM2` | pass |
|
||||
| reaction | `RM3` | `0` | `1e-3` | `0` | `0` | `0` | `0` | 71 | node 1 / `RM3` | pass |
|
||||
| section resultant | `N` | `0` | `1e-3` | `0` | `0` | `0` | `0` | 132 | node 1 / `N` | pass |
|
||||
| section resultant | `T` | `0` | `1e-3` | `0` | `0` | `0` | `0` | 133 | node 1 / `T` | pass |
|
||||
| section resultant | `My` | `1e7` | `10.001` | `0.015600242861189492` | `0.0015598682992890203` | `0.004703650867906837` | `0.015600245073676508` | 174 | node 11 / `My` | pass |
|
||||
| section resultant | `Mz` | `0` | `1e-3` | `0` | `0` | `0` | `0` | 135 | node 1 / `Mz` | pass |
|
||||
|
||||
The largest normalized comparison error across all 176 rows is
|
||||
`0.026602795021994977` at node 11 `UZ`, below the pass boundary of `1.0`.
|
||||
|
||||
### Row decision ledger
|
||||
|
||||
Every row decision is recorded in the deterministic build-local
|
||||
`comparison.json` identified above. Its stable row order is displacement nodes
|
||||
1-11 x six components, reaction nodes 1-11 x six components, then section node
|
||||
stations 1-11 x `[N,T,My,Mz]`. Independent parsing confirmed:
|
||||
|
||||
- rows: 176
|
||||
- unique canonical row keys: 176
|
||||
- row decisions with `passed=true`: 176
|
||||
- row decisions with `passed=false`: 0
|
||||
- finite FESA/reference/error/tolerance records: 176
|
||||
- missing / extra / duplicate / identity-mismatched rows: 0 / 0 / 0 / 0
|
||||
- metrics: 16 unique expected component groups
|
||||
|
||||
## Stress Reference Status
|
||||
|
||||
- Abaqus stress reference comparison: N/A
|
||||
- reason: the approved V0 reference contract excludes beam-stress CSV
|
||||
comparison and substitutes analytical/unit plus HDF5 schema evidence
|
||||
- mandatory solver stress output: pass
|
||||
- direct evidence: `stress_s11` exists with the exact compound schema, exact
|
||||
unit/coordinate/location attributes, two Gauss rows for each of ten elements,
|
||||
finite `S11`, and deterministic element/Gauss ordering
|
||||
|
||||
No stress reference row was synthesized, and mandatory HDF5 stress was not
|
||||
treated as optional.
|
||||
|
||||
## Physics Evidence Handoff
|
||||
|
||||
The comparator serialized the following evidence for independent Step 27 review:
|
||||
|
||||
| evidence | value |
|
||||
| --- | --- |
|
||||
| free residual norm | `9.356339321107032e-7` |
|
||||
| applied force | `[0, 0, -1000000]` |
|
||||
| reaction force | `[0, 0, 999999.9999998808]` |
|
||||
| applied moment about origin | `[0, 10000000, 0]` |
|
||||
| reaction moment about origin | `[0, -9999999.999997258, 0]` |
|
||||
| endpoint consistency | `passed=true` |
|
||||
|
||||
These values are handed off as evidence only. This Step does not interpret them
|
||||
as a physics-sanity verdict.
|
||||
|
||||
## Failure Classification
|
||||
|
||||
- classification: `N/A`
|
||||
- primary_failure: `N/A`
|
||||
- evidence: artifact precheck passed; exact comparison CTest passed twice;
|
||||
176/176 rows and 16/16 metric groups passed; no schema, identity, unit,
|
||||
coordinate, nonfinite, missing/extra, or tolerance failure was found
|
||||
- correction_handoff: `N/A`
|
||||
|
||||
## Handoff Recommendation
|
||||
|
||||
| target_agent | reason | required input |
|
||||
| --- | --- | --- |
|
||||
| Physics Evaluation Agent | All required reference comparisons passed the exact approved tolerance. | This report, authoritative build-local `results.h5`, deterministic `comparison.json`, and its `physics_evidence`. |
|
||||
|
||||
The handoff status is `pass-for-physics-evaluation` only. Physics sanity remains
|
||||
responsible for global force/moment equilibrium, reaction sign, displacement
|
||||
direction, symmetry, section-force consistency, residual interpretation, and
|
||||
model-coverage adequacy.
|
||||
|
||||
## No-Change Assertion
|
||||
|
||||
- source_files_modified: `false`
|
||||
- test_files_modified: `false`
|
||||
- cmake_files_modified: `false`
|
||||
- requirements_modified: `false`
|
||||
- formulations_modified: `false`
|
||||
- io_contract_modified: `false`
|
||||
- reference_model_contract_modified: `false`
|
||||
- reference_artifacts_modified: `false`
|
||||
- tolerance_policies_modified: `false`
|
||||
- Abaqus_or_other_reference_solver_executed: `false`
|
||||
- owned_report_created: `true`
|
||||
- phase_index_step26_modified: `true`
|
||||
- phase_step26_acceptance_modified_for_review_fix: `true`
|
||||
- phase_index_step26_summary_modified_for_review_fix: `true`
|
||||
- generated_build_local_evidence: `true`, ignored under `.harness/build/`
|
||||
- notes: comparison and HDF5 inspection were read-only with respect to the
|
||||
approved reference bundle; the final review fix changed only acceptance/report/index
|
||||
documentation, and pre/post hashes, Git diff, and Git status agree
|
||||
|
||||
## Open Issues
|
||||
|
||||
- Non-blocking evidence typo: the Step 25 build/test report prints the input
|
||||
SHA-256 without the second `DB` after `...1DB`; the fresh 64-character pre/post
|
||||
value in this report matches the unchanged working-tree file. Reference Git
|
||||
diff/status and the end-to-end reference snapshot check are clean.
|
||||
- Resolved final-review finding: the Step 26 acceptance probe now reads the
|
||||
authoritative boolean `passed`, and its exact command passes on the current artifact.
|
||||
- No issue blocks Physics Evaluation.
|
||||
@@ -43,7 +43,7 @@ GATE AUDIT -> TRACEABILITY CHECK -> RELEASE DOCUMENTATION -> RELEASE VERDICT
|
||||
- Build/Test report status: `pass-for-reference-verification`
|
||||
- Implementation report와 implementation plan의 feature scope 일치
|
||||
- requirements, formulations, numerical reviews, I/O definitions, reference models 문서의 feature scope 일치
|
||||
- validation command evidence: `python scripts/validate_workspace.py`
|
||||
- Build/Test report의 `.harness/config.json` 또는 자동 감지 기반 MSVC build/test command evidence
|
||||
|
||||
## 문서 템플릿
|
||||
|
||||
@@ -99,8 +99,8 @@ GATE AUDIT -> TRACEABILITY CHECK -> RELEASE DOCUMENTATION -> RELEASE VERDICT
|
||||
|
||||
| command_or_report | expected | observed | notes |
|
||||
| --- | --- | --- | --- |
|
||||
| python scripts/validate_workspace.py | pass | <result> | <summary> |
|
||||
| CMake/MSVC/CTest | pass | <result> | <summary> |
|
||||
| Build/Test report의 config-resolved CMake/MSVC/CTest | pass | <result> | <summary> |
|
||||
| Harness Python pytest (when applicable) | pass or N/A | <result> | <summary> |
|
||||
| reference verification | pass-for-physics-evaluation | <status> | <summary> |
|
||||
| physics evaluation | pass-for-release-agent | <status> | <summary> |
|
||||
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
# Linear Static 3D Euler Beam Release Report
|
||||
|
||||
## Metadata
|
||||
|
||||
- feature_id: `linear-static-3d-euler-beam`
|
||||
- approved_design: `docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md` (`status: approved`; approved 2026-08-08, amended 2026-08-09)
|
||||
- source_requirement: `docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- source_research: `docs/research/linear-static-3d-euler-beam-research.md`
|
||||
- source_formulation: `docs/formulations/3d-isoparametric-euler-beam-formulation.md`
|
||||
- source_numerical_review: `docs/numerical-reviews/linear-static-3d-euler-beam-review.md`
|
||||
- source_io_definition: `docs/io-definitions/linear-static-3d-euler-beam-io.md`
|
||||
- source_reference_model: `docs/reference-models/linear-static-3d-euler-beam-reference-models.md`
|
||||
- source_implementation_plan: `docs/implementation-plans/linear-static-3d-euler-beam.md`
|
||||
- source_implementation_report: `docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`
|
||||
- source_build_test_report: `docs/build-test-reports/linear-static-3d-euler-beam.md`
|
||||
- source_reference_verification_report: `docs/reference-verifications/linear-static-3d-euler-beam-reference-verification.md`
|
||||
- source_physics_evaluation_report: `docs/physics-evaluations/linear-static-3d-euler-beam-physics-evaluation.md`
|
||||
- audited_head: `822b06be3d2128d5dfdc5e394078abbb9dcd5a50`
|
||||
- reference_model_id: `cantilever-beam-b33`
|
||||
- reference_schema: `abaqus-cae-report-csv-v0`
|
||||
- reference_baseline: `reference/cantilever beam/` at source commit `2b34d0b`
|
||||
- status: `ready-for-release`
|
||||
- owner_agent: `release-agent`
|
||||
- date: `2026-08-10`
|
||||
- final_review_source_head: `b7a1258ce0f36a85b888e23470cf9d936a7595cd`
|
||||
|
||||
This is an internal feature-readiness verdict. It authorizes no publish, deploy, package, tag,
|
||||
push, external release, or reference-artifact operation.
|
||||
|
||||
## Release Scope
|
||||
|
||||
| item | included | excluded | notes |
|
||||
| --- | --- | --- | --- |
|
||||
| analysis | one small-displacement/small-rotation `*STEP, *STATIC` linear solve | multiple steps; geometric/material nonlinearity; dynamics; contact; thermal | Stiffness/partition and `Kff` factorization precede load assembly, effective RHS, and substitution. |
|
||||
| element | straight, prismatic, two-node 3D Euler-Bernoulli beam mapped only from `TYPE=B33` | `TYPE=B31`, shear-deformable/Timoshenko, curved/tapered/released/offset/warping members | Axial, two-plane bending, and Saint-Venant torsion are included. |
|
||||
| material/section | homogeneous isotropic linear elasticity; positive `E,G,A,Iy,Iz,J`; `I12=0` | `I12!=0`, anisotropy, plasticity, temperature dependence, warping data | Mapping is `n1 -> local y`, `t x n1 -> local z`, `Iy=I11`, `Iz=I22`. |
|
||||
| Abaqus input subset | approved keyword inventory, identity part/assembly/instance wrappers, `*BOUNDARY`, nodal `*CLOAD` | full compatibility, instance transforms, nested assembly, dependent/independent mesh semantics, `*DLOAD` | Approved output-request allowlist is warning no-op and cannot filter FESA output. |
|
||||
| solver/storage | deterministic COO-to-0-based-CSR, oneTBB element-local work, oneMKL PARDISO SPD factorization/substitution | alternate solver claims, automatic regularization, unsupported conditioning policy | Backend types remain behind adapters. |
|
||||
| authoritative output | HDF5 `results.h5`: displacement, reaction, equilibrium end action, section/generalized results, axial `S11`, metadata, diagnostics | official FESA CSV output; transverse/torsional shear stress; warping stress; nodal stress averaging | Beam stress reference comparison is N/A; `S11` remains mandatory and is analytically/schema tested. |
|
||||
| reference comparison | exact read-only legacy B33 four-file bundle; displacement, reaction, section resultant | Abaqus stress CSV; broad B33 compatibility; reference solver execution | 176/176 rows and 16/16 metrics passed the approved mixed tolerance. |
|
||||
|
||||
## Gate Evidence Inventory
|
||||
|
||||
| gate | source | expected status | observed status/evidence | verdict |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| approved design | approved design | `approved` | `approved`; same feature and legacy baseline | pass |
|
||||
| requirements | requirements baseline | `approved` | `approved`; 44 consecutive `must` rows | pass |
|
||||
| research | research brief | `ready-for-formulation` | `ready-for-formulation`; applicability limits retained | pass |
|
||||
| formulation | formulation document | `ready-for-numerical-review` | `ready-for-numerical-review`; exact requirement/design links | pass |
|
||||
| numerical review | numerical review | `pass-for-implementation-planning` | `pass-for-implementation-planning`; no confirmed mathematical defect | pass |
|
||||
| I/O definition | I/O contract | `ready-for-implementation-planning` | `ready-for-implementation-planning` | pass |
|
||||
| reference model | reference-model contract | `ready-for-implementation-planning` | legacy inventory/provenance and analytical portfolio defined | pass |
|
||||
| implementation plan | implementation plan | `ready-for-implementation` | `ready-for-implementation`; TASK-07 through TASK-24 defined | pass |
|
||||
| implementation evidence | implementation report plus phase index | all Step 7-24 blocks completed | 18/18 Step blocks and index entries `completed`; final cumulative suite 83 tests | pass with stale-header note below |
|
||||
| build/test | build/test report | `pass-for-reference-verification` | `pass-for-reference-verification`; fresh MSVC x64 Debug build, warning count 0, 83/83 | pass |
|
||||
| reference verification | reference-verification report | `pass-for-physics-evaluation` | `pass-for-physics-evaluation`; 176/176 rows and 16/16 metrics | pass |
|
||||
| physics evaluation | physics-evaluation report | `pass-for-release-agent` | `pass-for-release-agent`; all documented physics checks and 17/17 targeted tests pass | pass |
|
||||
| phase sequence | phase index | Steps 0-27 `completed` | 28/28 prerequisite entries completed in gate order | pass |
|
||||
|
||||
### Identity and contradiction audit
|
||||
|
||||
- All feature-level reports use `linear-static-3d-euler-beam`, the same approved design path,
|
||||
authoritative HDF5 contract, logical model `cantilever-beam-b33`, legacy schema, and exact
|
||||
`reference/cantilever beam/` baseline from `2b34d0b`.
|
||||
- The formulation metadata uses the narrower element-document identity
|
||||
`3d-isoparametric-euler-beam`. This is not a competing release feature: it names the exact
|
||||
formulation path referenced by the approved feature requirements, design, numerical review,
|
||||
I/O contract, reference-model contract, and implementation plan. Its `source_requirement` and
|
||||
`approved_design` links establish the same release lineage.
|
||||
- The implementation report aggregate metadata still says `status: in-progress`. This is a stale
|
||||
aggregate header, not an unresolved release gate: every TASK-07 through TASK-24 block is
|
||||
`completed`, all corresponding phase-index entries are `completed`, Step 25 independently audited
|
||||
all 18 blocks, and a fresh build/discovery/full CTest passed 83/83. The Step 25 report reaches the
|
||||
same explicit nonblocking conclusion. The upstream implementation report was not modified.
|
||||
- Final review reproduced that the former Step 26 sample acceptance probe rejected a valid
|
||||
`passed=true` artifact because it read a nonexistent string `status`. The phase probe now reads
|
||||
the authoritative boolean `passed`; its exact command was rerun successfully without changing
|
||||
source, tests, tolerance, or reference artifacts.
|
||||
- The Step 25 prose contains a typo in the input SHA-256. Fresh Step 26/27 hashes, Git diff/status,
|
||||
exact row reconstruction, and passing comparison evidence preserve artifact identity.
|
||||
|
||||
## Acceptance Traceability
|
||||
|
||||
Evidence aliases used below are exact upstream identities: `BT25` is the build/test report;
|
||||
`RV26` is the reference-verification report; `PE27` is the physics-evaluation report. Model IDs
|
||||
(`an-*`, `cv-*`, `neg-b33-input-contract`, `cantilever-beam-b33`) and `NR-T01` through `NR-T11`
|
||||
are defined by the approved reference-model and numerical-review documents. Every row has priority
|
||||
`must` in the approved Requirement Verification Matrix.
|
||||
|
||||
| requirement | acceptance criterion | exact test/evidence IDs | reference or analytical evidence | final disposition |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `FESA-REQ-LS3DEB-001` | One static step runs; a second step is rejected structurally. | `T12-MAP-001`, `T12-MAP-004`, `T13-MODEL-003`, `T24-CLI-001` | `smoke-b33-cli`; `neg-b33-input-contract`; `BT25` | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-002` | Accepted models obey the straight/prismatic/two-node, small linear-static scope and exclusions are not claimed. | `T12-MAP-001`, `T12-MAP-004`, `T16-BEAM-006`, `T24-ORCH-002` | `CB-AXIAL-TIP`, `CB-TORSION-TIP`, both bending candidates; `PE27` model coverage | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-003` | DOF and nodal-result order is exactly `[UX,UY,UZ,URX,URY,URZ]`. | `T14-DOF-001`, `T15-STATE-002`, `T23-HDF5-001` | `cantilever-beam-b33`; `RV26` HDF5 audit | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-004` | Axial, torsion, local-y bending, and local-z bending recover approved analytical quantities. | `T16-BEAM-006`, `T22-RECOVERY-004`, `NR-T08-ANALYTICAL` | `an-b33-axial-cantilever`, `an-b33-torsion-cantilever`, `an-b33-local-y-bending`, `an-b33-local-z-bending`; `PE27` | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-005` | Only B33 creates the approved Euler beam semantic object. | `T12-MAP-001`, `T24-B33-001` | `cantilever-beam-b33`; `RV26` confirms `TYPE=B33` | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-006` | B31 returns exact `unsupported-element-formulation` and creates no Euler beam. | `T12-MAP-004` | `CB-B31-NEGATIVE`; `neg-b33-input-contract` | released rejection behavior; B31 unsupported |
|
||||
| `FESA-REQ-LS3DEB-007` | DOFs 1..6 map correctly and nonzero `dc` affects RHS and reaction. | `T14-DOF-002`, `T19-CONSTRAINT-003`, `T21-LOAD-001`, `T21-LOAD-003`, `T22-RECOVERY-001` | `an-b33-prescribed-displacement`; `NR-T09-PARTITION-SPD`; `PE27` | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-008` | Closed-form line-load vector passes while parser/CLI `*DLOAD` and Domain distributed load remain absent. | `T16-BEAM-005`, `T12-MAP-005`, `NR-T06-LINE-LOAD` | `an-b33-line-load-kernel`; `PE27` targeted portfolio | released kernel; `*DLOAD` unsupported |
|
||||
| `FESA-REQ-LS3DEB-009` | Every approved keyword has positive coverage and no unlisted support claim exists. | `T12-MAP-001`, `T12-MAP-004` | `smoke-b33-cli`; exact I/O keyword inventory; legacy input | released approved subset only |
|
||||
| `FESA-REQ-LS3DEB-010` | Case variants/comments behave correctly and raw source identity survives. | `T11-SYN-001`, `T11-SYN-002`, `T10-DOM-001` | legacy input exact-byte identity `fnv1a64:04543464cc970405`; `RV26` | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-011` | Only approved boundary/load arities and DOFs pass; target expansion is deterministic. | `T12-MAP-001`, `T12-MAP-002`, `T12-MAP-004`, `T14-DOF-002`, `T21-LOAD-001` | analytical load/BC fixtures; invalid-target portfolio | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-012` | Section properties and right-handed local-axis mapping match the contract. | `T12-MAP-001`, `T12-MAP-004`, `T16-BEAM-004`, `NR-T05-TRANSFORM` | both bending models; `an-b33-rotated-space`; `PE27` local/global signs | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-013` | Valid `E,nu`/derived `G` and positive section properties pass; malformed/nonpositive data fails. | `T12-MAP-001`, `T12-MAP-004`, `T16-BEAM-007` | analytical inventory; `neg-b33-input-contract` invalid properties | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-014` | Exact scale-aware length/guide thresholds reject boundary failures and valid geometry gives an orthonormal frame. | `T12-MAP-004`, `T16-BEAM-004`, `T16-BEAM-007`, `NR-T05-TRANSFORM` | `neg-b33-input-contract`; rotated-space analytical model | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-015` | Instance/source labels round-trip to stable unique internal IDs. | `T10-DOM-001`, `T10-DOM-002`, `T12-MAP-002`, `T23-HDF5-001` | multi-instance semantic fixture; `RV26` model identity audit | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-016` | Multiple identity instances remain distinct and deterministic. | `T10-DOM-003`, `T12-MAP-002` | multi-instance semantic fixture; reference CSV N/A | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-017` | Instance translation/rotation fails with exact `unsupported-instance-transform`. | `T12-MAP-004` | `neg-b33-input-contract` transform case | released rejection behavior; transforms unsupported |
|
||||
| `FESA-REQ-LS3DEB-018` | Nested/dependent constructs fail structurally and produce no Domain model. | `T12-MAP-004` | `neg-b33-input-contract` nested/dependent cases | released rejection behavior; nested assembly unsupported |
|
||||
| `FESA-REQ-LS3DEB-019` | Exact no-op allowlist emits deterministic warnings without semantic effect. | `T12-MAP-003`, `T23-HDF5-002`, `T23-HDF5-003` | legacy input/output requests; `RV26` mandatory-output audit | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-020` | Unlisted model keywords fail and allowed output requests cannot suppress mandatory HDF5 output. | `T12-MAP-004`, `T23-HDF5-002`, `T24-CLI-003` | `smoke-b33-cli`; `RV26` exact HDF5 inventory | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-021` | Active-step view neither copies nor mutates Domain. | `T10-DOM-002`, `T13-MODEL-002` | architecture/code-verification fixture; reference CSV N/A | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-022` | DofManager exclusively owns mapping/scatter/reconstruction; Node/Element have no equation IDs. | `T14-DOF-001`, `T14-DOF-003`, `T14-DOF-004`, `T19-CONSTRAINT-001` | code/dependency audit; reference CSV N/A | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-023` | Required V0 state is connected to output and excluded state is unallocated. | `T15-STATE-001`, `T15-STATE-002`, `T23-HDF5-001` | `smoke-b33-cli`; `RV26` HDF5 audit | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-024` | Repeated/thread-varied assembly has identical CSR order and values. | `T17-PFOR-002`, `T18-SPARSE-002`, `T18-SPARSE-004`, `T18-SPARSE-005`, `NR-T11-DETERMINISTIC-ASSEMBLY` | `cv-b33-patch-rigid-assembly`; reference CSV N/A | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-025` | Backend types do not leak and dense/sparse storage matches contract. | `T07-BUILD-002`, `T09-DENSE-001`, `T09-DENSE-002`, `T18-SPARSE-001`, `T20-PARDISO-004`; Step 25 dependency scans | adapter/code audit; `BT25` | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-026` | Event trace is stiffness/partition/factorize/load/RHS/solve with separate factorization. | `T20-PARDISO-002`, `T24-ORCH-001` | lifecycle event-trace fixture; `BT25` | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-027` | Effective RHS, full displacement, and residual reaction satisfy partition equations. | `T19-CONSTRAINT-001`, `T19-CONSTRAINT-003`, `T21-LOAD-003`, `T22-RECOVERY-001`, `T22-RECOVERY-002`, `NR-T09-PARTITION-SPD` | `an-b33-prescribed-displacement`; `PE27` residual/reaction checks | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-028` | Success atomically produces final HDF5 and failure leaves no incomplete final file. | `T23-HDF5-004`, `T23-HDF5-005`, `T24-CLI-001` | CLI writer success/failure fixtures; `RV26` authoritative output | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-029` | Every schema-v0 path exists at frame 0 with exact rank/component identity. | `T23-HDF5-001`, `T24-B33-001` | `RV26` read-only HDF5 schema audit | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-030` | Metadata fields, ordinary unit label, and external SI provenance are exact. | `T07-BUILD-001`, `T23-HDF5-001`, `T24-CLI-001`, `T24-B33-001` | `cantilever-beam-b33`; `RV26` metadata/source-identity audit | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-031` | Component order and endpoint/Gauss locations are exact and output-request independent. | `T15-STATE-002`, `T16-BEAM-006`, `T22-RECOVERY-003`, `T23-HDF5-001`, `T23-HDF5-002`, `T24-CLI-003` | all analytical models; `RV26`; `PE27` end/section checks | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-032` | Correct `S11` rows/default centroid exist, no shear stress is emitted, and stress reference is N/A. | `T16-BEAM-008`, `T22-RECOVERY-005`, `T23-HDF5-003`, `T24-B33-001` | axial/local-z analytical stress; `RV26` Stress Reference Status; `PE27` stress sanity | released; Abaqus stress reference N/A |
|
||||
| `FESA-REQ-LS3DEB-033` | Default/explicit output and exact exit-code/ordered-diagnostic contract pass. | `T08-CORE-002`, `T24-CLI-001`, `T24-CLI-002` | CLI negative portfolio; `BT25` | released-in-V0 |
|
||||
| `FESA-REQ-LS3DEB-034` | Every production step has RED, GREEN, focused/full VERIFY, discovery, and no warning. | `T07-*` through `T24-*`; TASK-07 through TASK-24 report blocks | `BT25`: 18/18 blocks audited, fresh warning count 0, 83 discovered, 83/83 pass | satisfied |
|
||||
| `FESA-REQ-LS3DEB-035` | All matrix, mode, residual, transform, partition, and analytical thresholds pass. | `T16-BEAM-001` through `T16-BEAM-010`; `T18-SPARSE-004`; `T19-CONSTRAINT-003`; `T20-PARDISO-001`, `T20-PARDISO-006`; `T22-RECOVERY-002`; `NR-T01` through `NR-T11` | analytical portfolio; `PE27` exact targeted 17/17 | satisfied |
|
||||
| `FESA-REQ-LS3DEB-036` | Abaqus-only component scale and exact mixed formula apply to every row. | `T24-REF-002`, `T24-B33-001` | `RV26`: 176 recalculated row decisions, 16 metrics | satisfied |
|
||||
| `FESA-REQ-LS3DEB-037` | Exact SI floors and zero-scale behavior are applied. | `T24-REF-002`, `T24-B33-001` | `RV26` component table includes zero-scale groups and exact floors | satisfied |
|
||||
| `FESA-REQ-LS3DEB-038` | Invalid row/schema/identity/nonfinite cases fail before tolerance; no clamp/drop occurs. | `T24-REF-001`, `T24-REF-002` | malformed contract fixtures; `RV26` zero missing/extra/duplicate/nonfinite rows | satisfied |
|
||||
| `FESA-REQ-LS3DEB-039` | Every row decision and aggregate/worst metric is present. | `T24-REF-003`, `T24-B33-001` | `RV26`: 176 ledger rows, 16 component metrics, exact recomputation | satisfied |
|
||||
| `FESA-REQ-LS3DEB-040` | Exact legacy filenames exist and reference content is unchanged. | `T11-SYN-004`, `T24-B33-001`; `BT25`/`RV26`/`PE27` reference diff/status checks | exact approved four-file bundle and pre/post hashes | satisfied legacy exception |
|
||||
| `FESA-REQ-LS3DEB-041` | Four-file/B33/header/key/finite precheck passes before comparison with approved failure classes. | `T24-REF-001`, `T24-B33-001` | `RV26` Artifact Inventory: 4 files, 11/11/11 rows, finite/unique | satisfied |
|
||||
| `FESA-REQ-LS3DEB-042` | Exact component/source identity and endpoint-consistency/no-average policy pass. | `T22-RECOVERY-006`, `T24-REF-004`, `T24-B33-001` | `RV26`: displacement 66, reaction 66, section 44; endpoint consistency true | satisfied |
|
||||
| `FESA-REQ-LS3DEB-043` | Build precedes reference, reference precedes physics, and physics covers required checks. | `BT25`, `RV26`, `PE27`; phase Steps 25-27 | `PE27`: force/moment equilibrium, reaction, displacement, symmetry, section/end force, residual and coverage pass | satisfied |
|
||||
| `FESA-REQ-LS3DEB-044` | No reference solver/artifact mutation occurs and release claims no excluded support. | `T12-MAP-004`, `T12-MAP-005`; `BT25`/`RV26`/`PE27` no-change assertions; Step 28 Git audit | exact legacy diff/status clean; this report's Release Scope and Known Limitations | satisfied |
|
||||
|
||||
Audit result: all 44 expected `must` requirements have an acceptance criterion, exact executable
|
||||
or gate evidence, reference/analytical evidence or an explicit applicable N/A, and a final
|
||||
disposition. No must requirement is deferred or blocked.
|
||||
|
||||
## Validation Evidence
|
||||
|
||||
| command or report | expected | observed | result |
|
||||
| --- | --- | --- | --- |
|
||||
| Step 25 fresh MSVC x64 Debug configure/build | exit 0; `/W4 /WX`; no warnings | exit 0; warning scan 0 | pass |
|
||||
| Step 25 CTest discovery/full | nonzero discovery; zero failures | 83 discovered; feature 83/83; full 83/83 | pass |
|
||||
| exact Build/Test gate string | `status: pass-for-reference-verification` | present | pass |
|
||||
| exact Reference Verification gate string and result probe | `status: pass-for-physics-evaluation`; `passed=true` | present; corrected exact acceptance command and comparison test pass | pass |
|
||||
| exact Physics Evaluation gate string | `status: pass-for-release-agent` | present; targeted physics selection 17/17 | pass |
|
||||
| reference comparison | exact rows/metrics; approved tolerance | 176/176 rows, 16/16 metrics, `passed=true`; largest normalized error `0.026602795021994977 < 1` | pass |
|
||||
| physics sanity | equilibrium/sign/symmetry/section/residual/coverage pass | force `1.1921e-13`, moment `2.7418e-13`, free residual `9.3563e-13`; all checks pass | pass |
|
||||
| phase prerequisites | Steps 0-27 completed | all 28 prerequisite entries completed | pass |
|
||||
|
||||
## Release Checklist
|
||||
|
||||
- [x] Approved design, requirements, research, formulation, numerical, I/O, and reference-model evidence is present.
|
||||
- [x] TASK-07 through TASK-24 implementation evidence is complete and independently audited.
|
||||
- [x] Exact three-gate status strings are present and passing.
|
||||
- [x] All 44 `must` requirements are traced to acceptance, exact evidence, reference/analytical coverage, and disposition.
|
||||
- [x] Reference bundle identity and read-only status are preserved.
|
||||
- [x] Known limitations, accepted Minors, evidence limitations, and explicit N/A items are documented.
|
||||
- [x] No Critical, unresolved Important, defect, missing artifact, failed command, or user decision blocks internal readiness.
|
||||
|
||||
## Known Limitations
|
||||
|
||||
| limitation | category | user impact | disposition |
|
||||
| --- | --- | --- | --- |
|
||||
| Abaqus `TYPE=B31` / Timoshenko | element/input | rejected as `unsupported-element-formulation`; no shear-deformable beam behavior | documented, deferred feature |
|
||||
| multiple analysis steps | analysis/input | a second `*STEP` is rejected; no step-to-step propagation | documented, deferred feature |
|
||||
| instance transforms and nested/dependent assembly | model/input | translation/rotation and nested semantics are rejected | documented, deferred feature |
|
||||
| `I12!=0` and section extensions | section/physics | coupled inertia, taper, offsets, releases, curved geometry, and warping are unsupported | documented, deferred feature |
|
||||
| Abaqus `*DLOAD` | load/input | parser/CLI reject it; only the formulation-level constant local line-load kernel exists | documented, deferred feature |
|
||||
| nonlinear/dynamic/contact/thermal | analysis/physics | no geometric/material nonlinearity, dynamics, contact, or thermal response | documented, deferred feature |
|
||||
| shear and warping stress | output/physics | no transverse/torsional shear-stress or warping-stress recovery; no nodal averaging | documented, deferred feature |
|
||||
| beam stress reference | verification | axial `S11` is mandatory and analytically/schema tested, but Abaqus stress reference is N/A | accepted contract N/A |
|
||||
| approved four-file legacy exception | artifacts | spaces and legacy names remain; `metadata.json`, `README.md`, and stress CSV are N/A only for this bundle | read-only accepted exception; not precedent for new bundles |
|
||||
| reference coverage | verification | single identity-axis local-z B33 cantilever does not itself cover axial/torsion/local-y/rotated/prescribed/line-load/nonzero-fiber stress | accepted; complementary analytical/unit portfolio passes |
|
||||
| Euler-Bernoulli applicability | modeling | deep/short beams may be too stiff; no automatic slenderness threshold is approved | documented modeling limit |
|
||||
| energy evidence | output | no HDF5 energy dataset; Step 27 derives positive `0.5*F^T*d` and uses rank/energy tests | accepted evidence limit |
|
||||
| comparator file-type depth (Minor) | test evidence | test-only comparator pins float64 types but relies on writer self-check/full schema tests for exact uint64/compound/string file types | accepted defense-in-depth coverage limit |
|
||||
| multi-source diagnostic order (Minor) | portability/future scope | sorter is sufficient for V0 single-input CLI but is not the future multi-source declaration/internal-ID ordering contract | accepted V0 limit |
|
||||
| HDF5 `libmmd.dll` staging guard (Minor) | environment portability | unconditional guard is correct for approved shared-HDF5 environment; alternate HDF5 targets may need adjustment | accepted external portability limit |
|
||||
| stale implementation aggregate header | documentation | top-level `in-progress` can confuse readers despite completed evidence | documented nonblocking stale header; upstream unchanged |
|
||||
|
||||
## Release Notes Draft
|
||||
|
||||
### Feature Summary
|
||||
|
||||
- Adds the internally release-ready FESA V0 end-to-end single-step linear-static 3D
|
||||
Euler-Bernoulli beam pipeline for Abaqus `TYPE=B33` input.
|
||||
- Supports stable identity instances, deterministic DOF/sparse assembly, separate PARDISO
|
||||
factorization/substitution, nonzero prescribed displacement, residual reactions, and atomic
|
||||
HDF5 `results.h5` output.
|
||||
- Writes mandatory displacement, reaction, equilibrium end action, endpoint section resultant,
|
||||
generalized strain/resultant, and axial `S11` regardless of Abaqus output requests.
|
||||
|
||||
### Verification Scope
|
||||
|
||||
- Fresh Visual Studio 18 2026/MSVC x64 Debug build passed under `/W4 /WX` with zero warnings and
|
||||
all 83 discovered tests passing.
|
||||
- The approved read-only `cantilever-beam-b33` bundle passed all 176 displacement/reaction/section
|
||||
rows and all 16 metric groups under `absolute_floor + 1e-6 * reference_scale`.
|
||||
- Physics evaluation passed force/moment equilibrium, reactions, displacement/rotation signs,
|
||||
zero symmetry, end/section balance, local/global mapping, residual, `S11`, energy/modes, and
|
||||
complementary analytical coverage.
|
||||
|
||||
### Main Limitations
|
||||
|
||||
- No B31, multiple steps, transforms/nested assembly, `I12!=0`, `*DLOAD`, nonlinear, dynamic,
|
||||
contact, thermal, shear-stress, or warping-stress support.
|
||||
- Abaqus beam stress reference comparison is N/A; nonzero `S11` evidence is analytical/unit-based.
|
||||
- The legacy space-containing four-file reference bundle is a read-only exception. New bundles
|
||||
must use canonical names and metadata.
|
||||
- The single Abaqus cantilever is supplemented by analytical/unit models and does not establish
|
||||
full Abaqus B33 compatibility or experimental validation.
|
||||
- Accepted Minor test-depth and alternate-environment portability limits remain as documented in
|
||||
Known Limitations.
|
||||
|
||||
### Artifacts
|
||||
|
||||
- Authoritative solver output for a run: HDF5 `results.h5`.
|
||||
- Approved reference baseline: `reference/cantilever beam/` exact four-file legacy bundle.
|
||||
- Gate evidence: the Build/Test, Reference Verification, and Physics Evaluation reports listed in
|
||||
Metadata; deterministic build-local `comparison.json` is review evidence, not solver output.
|
||||
|
||||
## Release Verdict
|
||||
|
||||
- verdict: `ready-for-release`
|
||||
- status: `ready-for-release`
|
||||
- reason: all required upstream gates are present and passing, Steps 0-27 are completed, all 44
|
||||
must requirements have complete acceptance/test/reference/disposition traceability, reference
|
||||
identity is unchanged, known limitations and accepted risks are documented, and no unresolved
|
||||
blocker exists.
|
||||
- authority_boundary: internal feature readiness only; no publish, deploy, package, tag, push,
|
||||
external release, or reference-artifact change is authorized. Harness-owned phase evidence
|
||||
commits remain part of the internal development workflow, not release publication.
|
||||
|
||||
## Handoff Recommendation
|
||||
|
||||
| target_agent | reason | required input |
|
||||
| --- | --- | --- |
|
||||
| Coordinator Agent | Close the internal feature workflow with `ready-for-release`. | This report, exact three-gate reports, phase index Step 28 completion, and the documented authority boundary. |
|
||||
| Correction Agent | N/A; no implementation-owned blocker exists. | N/A |
|
||||
| Reference Verification Agent | N/A; required comparison passed. | N/A |
|
||||
| Physics Evaluation Agent | N/A; required physics review passed. | N/A |
|
||||
|
||||
No release engineering, packaging, publication, tag, push, or external coordination was performed.
|
||||
Harness/root phase-evidence commits are internal workflow records, not an external release action.
|
||||
|
||||
## No-Change Assertion
|
||||
|
||||
- source_files_modified: `false`
|
||||
- test_files_modified: `false`
|
||||
- cmake_files_modified: `false`
|
||||
- requirements_or_upstream_contracts_modified: `false`
|
||||
- implementation_report_modified: `false`
|
||||
- build_report_modified: `false`
|
||||
- reference_verification_report_modified_for_review_fix: `true`
|
||||
- physics_report_modified: `false`
|
||||
- reference_artifacts_modified: `false`
|
||||
- tolerance_policies_modified: `false`
|
||||
- Abaqus_or_other_reference_solver_executed: `false`
|
||||
- release_agent_publish_deploy_package_tag_push_commit_performed: `false`
|
||||
- harness_or_root_phase_evidence_commits_performed: `true`
|
||||
- owned_release_report_created: `true`
|
||||
- phase_index_step28_modified: `true`
|
||||
- phase_step26_acceptance_modified_for_review_fix: `true`
|
||||
- phase_index_step26_summary_modified_for_review_fix: `true`
|
||||
- notes: The release audit initially created this report and changed only Step 28. Final review
|
||||
then aligned the Step 26 acceptance probe/report/index summary with authoritative `passed=true`;
|
||||
source, tests, tolerance, reference artifacts, and physical evidence remain unchanged.
|
||||
|
||||
## Open Issues
|
||||
|
||||
- Blocking issues: none.
|
||||
- Nonblocking documentation issue: the implementation report aggregate `status: in-progress` is
|
||||
stale; completed Step blocks, phase index, and Step 25 fresh audit are authoritative for release
|
||||
closure. It remains unchanged to preserve upstream audit independence.
|
||||
- Resolved final-review finding: Step 26 now probes authoritative `passed=true`, and the exact
|
||||
acceptance command passes. The remaining Step 25 input-hash prose typo is nonblocking; later
|
||||
exact hashes and Git audits resolve identity without changing artifacts.
|
||||
- Nonblocking accepted Minors: comparator file-type defense-in-depth coverage, future multi-source
|
||||
diagnostic ordering, and alternate-HDF5 `libmmd.dll` staging portability remain as documented.
|
||||
- Deferred behavior is limited to the Known Limitations and is not claimed as supported.
|
||||
@@ -0,0 +1,224 @@
|
||||
# Linear Static 3D Euler Beam Requirements
|
||||
|
||||
## Metadata
|
||||
|
||||
- feature_id: `linear-static-3d-euler-beam`
|
||||
- title: `Linear Static 3D Euler Beam`
|
||||
- status: `approved`
|
||||
- owner_agent: `requirement-agent`
|
||||
- date: `2026-08-09`
|
||||
- approved_design: `docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md`
|
||||
- approval_basis: design `status: approved`, user approval on `2026-08-08`, and amendment on `2026-08-09`
|
||||
- source_formulation: `docs/formulations/3d-isoparametric-euler-beam-formulation.md`
|
||||
- reference_baseline: `reference/cantilever beam/` at source commit `2b34d0b`
|
||||
|
||||
## Purpose
|
||||
|
||||
이 baseline은 승인된 Abaqus `.inp` subset을 입력으로 받아 2절점 3차원
|
||||
Euler–Bernoulli beam의 단일 선형 정적 step을 해석하고, 검증 가능한 변위, 반력,
|
||||
요소 결과와 축응력을 authoritative `results.h5`에 기록하는 FESA V0 기능을 정의한다.
|
||||
이 문서는 승인 설계를 검증 가능한 `shall` 요구조건으로 전사하며 Abaqus full
|
||||
compatibility, 새로운 수학 계약 또는 새로운 구현 정책을 추가하지 않는다.
|
||||
|
||||
## In Scope
|
||||
|
||||
- 입력 파일당 하나의 `*STEP, *STATIC` 선형 정적 해석
|
||||
- small displacement, small rotation, 균질 선형 등방 탄성
|
||||
- 2절점 직선 prismatic 3D Euler–Bernoulli beam과 Abaqus `TYPE=B33`
|
||||
- 절점당 전역 자유도 `[UX, UY, UZ, URX, URY, URZ]`
|
||||
- 축 변형, 두 방향 굽힘, Saint-Venant 비틀림
|
||||
- nodal concentrated load와 zero/nonzero prescribed displacement
|
||||
- formulation 검증용 constant local line-load equivalent nodal vector kernel
|
||||
- identity `*PART/*ASSEMBLY/*INSTANCE` wrapper와 stable source identity
|
||||
- deterministic COO-to-CSR assembly, element-local oneTBB 계산, MKL PARDISO factorization/substitution
|
||||
- HDF5 displacement, reaction, equilibrium end action, section resultant, generalized strain/resultant, axial `S11`
|
||||
- 승인된 `reference/cantilever beam/` legacy B33 bundle의 displacement, reaction, section resultant comparison
|
||||
|
||||
## Out Of Scope
|
||||
|
||||
- Abaqus full compatibility와 Abaqus `TYPE=B31` Timoshenko beam
|
||||
- 다중 analysis step과 step 간 load/BC propagation
|
||||
- instance translation/rotation, nested assembly, dependent/independent mesh semantics
|
||||
- `I12 != 0`, taper, offset, release, curved beam, warping
|
||||
- Abaqus `*DLOAD` 입력과 Domain distributed-load object
|
||||
- 기하·재료비선형, dynamics, contact, thermal effects
|
||||
- transverse shear stress와 torsional shear stress recovery
|
||||
- beam stress에 대한 Abaqus reference comparison
|
||||
- Abaqus, Nastran 또는 다른 reference solver 실행과 reference artifact 생성·수정·복원
|
||||
|
||||
## Analysis Definition
|
||||
|
||||
- analysis_type: single-step linear static
|
||||
- kinematics: small displacement and small rotation
|
||||
- element: two-node straight prismatic 3D Euler–Bernoulli beam, Abaqus `TYPE=B33`
|
||||
- nodal_dofs: global `[UX, UY, UZ, URX, URY, URZ]`
|
||||
- deformation_modes: axial, local-y/local-z bending, Saint-Venant torsion
|
||||
- material_model: homogeneous isotropic linear elasticity from `E` and `nu`
|
||||
- boundary_conditions: DOF 1 through 6, including nonzero prescribed displacement
|
||||
- loads: nodal concentrated load; formulation-only constant local line-load kernel
|
||||
- local_coordinate_system: `t -> local x`, Abaqus first section axis `n1 -> local y`, `t x n1 -> local z`, right-handed
|
||||
- units: input uses a user-consistent unit system; the approved cantilever reference bundle is SI
|
||||
- authoritative_output: HDF5 `results.h5`
|
||||
|
||||
|
||||
## Input Requirements
|
||||
|
||||
- **FESA-REQ-LS3DEB-001** — The FESA solver shall accept exactly one `*STEP` containing `*STATIC` per input file and shall reject a second analysis step with a structured unsupported diagnostic.
|
||||
- **FESA-REQ-LS3DEB-002** — The FESA solver shall analyze only straight, prismatic, two-node 3D Euler–Bernoulli beams under small-displacement, small-rotation, linear-static assumptions.
|
||||
- **FESA-REQ-LS3DEB-003** — The FESA solver shall assign each beam node the six global DOFs `[UX, UY, UZ, URX, URY, URZ]` in that order.
|
||||
- **FESA-REQ-LS3DEB-004** — The FESA solver shall support axial deformation, bending about both local section axes, Saint-Venant torsion, and homogeneous isotropic linear elasticity.
|
||||
- **FESA-REQ-LS3DEB-005** — The FESA solver shall map only `*ELEMENT, TYPE=B33` to the V0 Euler–Bernoulli beam formulation.
|
||||
- **FESA-REQ-LS3DEB-006** — The FESA solver shall reject `*ELEMENT, TYPE=B31` with `unsupported-element-formulation` and shall not reinterpret B31 as B33.
|
||||
- **FESA-REQ-LS3DEB-007** — The FESA solver shall support nodal `*CLOAD` and `*BOUNDARY` data for DOFs 1 through 6, including nonzero prescribed displacement.
|
||||
- **FESA-REQ-LS3DEB-008** — The element verification contract shall include a constant local line-load equivalent nodal vector kernel, while the V0 parser and CLI shall not support `*DLOAD` or create a Domain distributed-load object.
|
||||
- **FESA-REQ-LS3DEB-009** — The parser shall support exactly `*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`, and `*END STEP` as model/procedure keywords.
|
||||
- **FESA-REQ-LS3DEB-010** — The parser shall interpret keyword and parameter names case-insensitively, recognize `**` comment lines, and preserve source label text for external identity.
|
||||
- **FESA-REQ-LS3DEB-011** — The parser shall accept `*BOUNDARY` rows only as `target, first_dof, last_dof[, value]`, default an omitted value to zero, and accept `*CLOAD` rows only as `target, dof, magnitude`; targets shall resolve by source node label or node set, including assembly-level sets with `INSTANCE`.
|
||||
- **FESA-REQ-LS3DEB-012** — The semantic mapping shall read general-section data as `A, I11, I12, I22, J`, require `I12=0`, map `Iy=I11` and `Iz=I22`, and construct local axes as `n1 -> y` and `t x n1 -> z`.
|
||||
- **FESA-REQ-LS3DEB-013** — A general beam section shall reference a material whose isotropic `*ELASTIC` data provides exactly `E, nu`; the solver shall compute `G=E/(2(1+nu))` and require positive `E`, `G`, `A`, `Iy`, `Iz`, and `J`.
|
||||
- **FESA-REQ-LS3DEB-014** — Before element calculation, the solver shall require `L > 1e-12 * max(1, norm(X1), norm(X2))` and `norm(a_perp) > 1e-12 * max(1, norm(a))`; zero/near-zero length, a zero guide vector, and a tangent-parallel guide vector shall produce structured model-validation diagnostics.
|
||||
- **FESA-REQ-LS3DEB-015** — `*PART/*ASSEMBLY/*INSTANCE` mapping shall preserve `SourceEntityId { instance_name, source_label }` for nodes, elements, and sets and shall map it deterministically to a separate stable Domain internal index.
|
||||
- **FESA-REQ-LS3DEB-016** — The semantic model shall allow multiple identity instances of the same part without merging their source identities.
|
||||
- **FESA-REQ-LS3DEB-017** — An instance containing translation or rotation data shall be rejected with `unsupported-instance-transform`.
|
||||
- **FESA-REQ-LS3DEB-018** — Nested assembly and dependent/independent mesh semantics shall be rejected as unsupported rather than silently approximated.
|
||||
- **FESA-REQ-LS3DEB-019** — The parser shall issue structured warnings and no-op the exact allowlist `*PREPRINT`, `*RESTART`, `*TRANSVERSE SHEAR STIFFNESS`, `*OUTPUT, FIELD`, `*OUTPUT, HISTORY`, `*NODE OUTPUT`, `*ELEMENT OUTPUT`, `*CONTACT OUTPUT`, and unsupported variable data belonging to those output requests.
|
||||
- **FESA-REQ-LS3DEB-020** — Unsupported model-affecting keywords outside the no-op allowlist shall be errors, and accepted Abaqus output requests shall not change or suppress FESA's mandatory HDF5 results.
|
||||
|
||||
## Architecture and Execution Requirements
|
||||
|
||||
- **FESA-REQ-LS3DEB-021** — `Domain` shall own the complete parsed model and remain effectively immutable after mapping; `AnalysisModel` shall expose references or IDs for the single active step without copying Domain objects.
|
||||
- **FESA-REQ-LS3DEB-022** — `DofManager` alone shall own node DOF definitions, full/free equation numbering, constrained/free mappings, element scatter maps, sparse patterns, and full/reduced vector reconstruction; Node and Element shall not store equation IDs.
|
||||
- **FESA-REQ-LS3DEB-023** — V0 `AnalysisState` shall own full displacement, external/internal force, residual, constrained reaction, step/frame identity, and element recovery rows and shall not allocate velocity, acceleration, temperature, iteration history, or nonlinear element state.
|
||||
- **FESA-REQ-LS3DEB-024** — Element-local stiffness work shall use the `ParallelFor`/oneTBB boundary, and global assembly shall deterministically reduce element contributions in stable element order from COO triplets into a 0-based CSR matrix.
|
||||
- **FESA-REQ-LS3DEB-025** — MKL, TBB, and HDF5 API/types shall remain behind the `LinearSolver`, `ParallelFor`, dense/sparse math, and `ResultsWriter` adapter boundaries; `Vector` shall use contiguous doubles, `Matrix` row-major contiguous doubles, and `SparseMatrix` a separate 0-based CSR representation.
|
||||
- **FESA-REQ-LS3DEB-026** — The linear-static lifecycle shall assemble and partition stiffness, call `Kff` factorization, and only then assemble the full load vector, form the effective RHS, and perform substitution; factorization and substitution shall remain observably separate.
|
||||
- **FESA-REQ-LS3DEB-027** — For prescribed displacement `dc`, the solver shall form `rhs=Ff-Kfc*dc`, reconstruct the full displacement after substitution, and recover constrained reaction from `K*d-F`, equivalently `Rc=Kcf*df+Kcc*dc-Fc`, rather than a separate end-force sum.
|
||||
|
||||
## Output Requirements
|
||||
|
||||
- **FESA-REQ-LS3DEB-028** — The sole authoritative solver output shall be HDF5 `results.h5`; the writer shall complete a temporary file before replacing the final path and shall leave no incomplete final file after a writer failure.
|
||||
- **FESA-REQ-LS3DEB-029** — HDF5 schema v0 shall contain `/metadata`, `/model/nodes`, `/model/elements`, `/steps/<step-name>/frames/0/nodal/displacement`, `/steps/<step-name>/frames/0/nodal/reaction`, `/steps/<step-name>/frames/0/element/end_force_local`, `/steps/<step-name>/frames/0/element/section_resultant`, `/steps/<step-name>/frames/0/element/generalized_strain`, `/steps/<step-name>/frames/0/element/stress_s11`, and `/diagnostics`.
|
||||
- **FESA-REQ-LS3DEB-030** — HDF5 metadata/model identity shall record schema version, solver version, source input identity, unit-system label, coordinate convention, element formulation, stable internal IDs, and instance/source-label mappings; ordinary input shall use `user-consistent-unspecified`, while the approved cantilever comparison shall apply its external SI contract without inferring SI from `.inp` alone.
|
||||
- **FESA-REQ-LS3DEB-031** — Output shall include every node's global displacement/reaction in `[UX, UY, UZ, URX, URY, URZ]`, local endpoint equilibrium end actions in `[FX,FY,FZ,MX,MY,MZ]`, endpoint section resultants in `[N,T,My,Mz]`, and generalized strain/resultant values at the two Gauss points, independent of Abaqus output requests.
|
||||
- **FESA-REQ-LS3DEB-032** — The solver shall output axial `S11` at both Gauss points and each input section point, or at centroid `(0,0)` with `source=fesa-default` when section points are absent; transverse/torsional shear stress shall not be recovered, and Abaqus beam-stress reference comparison shall remain explicit N/A while analytical/unit and HDF5 schema tests remain mandatory.
|
||||
- **FESA-REQ-LS3DEB-033** — The CLI shall support `fesa.exe <model.inp> --output <results.h5>`, default output to the current directory's `results.h5`, use exit codes `0=success`, `2=usage`, `3=input`, `4=model`, `5=solver`, `6=HDF5`, and emit `severity`, `code`, `file`, `line`, `keyword`, `entity_identity`, and `message` diagnostics to stderr in deterministic order.
|
||||
|
||||
## Verification Requirements
|
||||
|
||||
- **FESA-REQ-LS3DEB-034** — Every production C++ behavior shall be developed in one step as GoogleTest `RED -> GREEN -> VERIFY`, with a related C++ test file, focused CTest evidence, full MSVC x64 Debug build/CTest evidence, at least one discovered test, and no new warning under the FESA target's `/W4 /WX` policy.
|
||||
- **FESA-REQ-LS3DEB-035** — Numerical tests shall satisfy normalized `1e-12` for stiffness symmetry and two-point-Gauss/closed-form agreement, normalized `1e-10` for rigid-mode and linear-system residual, and relative `1e-9` for analytical solutions, while checking six rigid modes, rank 6, positive deformation energy, transformation orthogonality/energy invariance, prescribed-displacement recovery, and axial/torsion/two-plane bending benchmarks.
|
||||
|
||||
## Verification Quantities
|
||||
|
||||
- nodal_displacement: required, global six components, HDF5-to-Abaqus CSV comparison
|
||||
- reaction: required, global six components plus global force/moment equilibrium
|
||||
- equilibrium_end_action: required, local endpoint six components; unit/analytical and physics tests
|
||||
- section_resultant: required, endpoint `[N,T,My,Mz]`, node-station-normalized reference comparison
|
||||
- generalized_strain_and_resultant: required at two Gauss points; formulation and schema tests
|
||||
- stress: axial `S11` required; Abaqus reference comparison N/A
|
||||
- residual: required, free-DOF and normalized global equilibrium checks
|
||||
- energy_and_modes: required for symmetry, rank, rigid modes, and transform invariance
|
||||
|
||||
|
||||
## Tolerance Policy
|
||||
|
||||
- **FESA-REQ-LS3DEB-036** — The approved B33 reference comparison shall group rows by the same model, step/frame, quantity, and component, compute `reference_scale` only from read-only Abaqus values, and apply `absolute_floor + 1e-6 * reference_scale` to every matched row.
|
||||
- **FESA-REQ-LS3DEB-037** — For the approved SI bundle, displacement and rotation shall use `absolute_floor=1e-9`, force and moment shall use `absolute_floor=1e-3`, and a zero component scale shall use the applicable absolute floor alone.
|
||||
- **FESA-REQ-LS3DEB-038** — Reference values shall not be zero-clamped and rows shall not be dropped; missing, extra, duplicate, nonfinite, schema-mismatched, or identity-mismatched rows shall fail before tolerance evaluation.
|
||||
- **FESA-REQ-LS3DEB-039** — The verification report shall record every row decision and maximum absolute error, component-scale normalized error, RMS error, norm error, and worst row/component for each compared quantity.
|
||||
|
||||
## Reference Artifact Requirements
|
||||
|
||||
The approved logical model is `cantilever-beam-b33`, schema is
|
||||
`abaqus-cae-report-csv-v0`, source commit is `2b34d0b`, generator is
|
||||
`Abaqus/CAE Learning Edition 2024`, and the coordinate/output contract is global Cartesian
|
||||
nodal output plus beam-local section-force output at `Step-1`, increment 1, step time 1.0.
|
||||
|
||||
- **FESA-REQ-LS3DEB-040** — The V0 reference baseline shall use the exact read-only files `reference/cantilever beam/cantilever beam.inp`, `reference/cantilever beam/cantilever beam displacements.csv`, `reference/cantilever beam/cantilever beam reactions.csv`, and `reference/cantilever beam/cantilever beam elemental forces.csv` without rename, rewrite, correction, or restoration; `metadata.json` and `README.md` are N/A only for this approved legacy bundle.
|
||||
- **FESA-REQ-LS3DEB-041** — Before comparison, artifact validation shall confirm all four files, `TYPE=B33`, expected CAE report headers, unique row keys, and finite values; failure shall be classified as `needs-reference-artifacts` or `schema-mismatch` and comparison shall not start.
|
||||
- **FESA-REQ-LS3DEB-042** — Reference verification shall compare displacement by source-node identity (`U1/U2/U3/UR1/UR2/UR3`), reaction by source-node identity (`RF1/RF2/RF3/RM1/RM2/RM3`), and node-station-normalized section resultant by `SF1->N`, `SM1->My`, `SM2->Mz`, `SM3->T`; adjacent interior endpoints shall first agree within approved tolerance and shall not be averaged to hide a mismatch.
|
||||
- **FESA-REQ-LS3DEB-043** — Reference comparison shall run only after build/test passes; physics sanity shall run only after reference comparison passes and shall check global force/moment equilibrium, reaction sign, displacement direction, symmetry, element section-force consistency, and normalized residual; release readiness shall require all prior gate evidence and known limitations.
|
||||
- **FESA-REQ-LS3DEB-044** — FESA agents and Harness shall not execute Abaqus, Nastran, or another reference solver and shall not create, modify, rename, or restore reference artifacts; release documentation shall not claim support for any Out Of Scope behavior.
|
||||
|
||||
|
||||
## Requirement Verification Matrix
|
||||
|
||||
| id | statement | category | rationale | source | priority | verification_method | acceptance_criteria | tolerance | downstream_agents | status |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| FESA-REQ-LS3DEB-001 | The FESA solver shall accept exactly one `*STEP` containing `*STATIC` per input file and shall reject a second analysis step with a structured unsupported diagnostic. | analysis | Preserve the approved V0 single-step boundary. | Approved design §§2, 6.1; PRD FESA-PRD-011 | must | Parser/semantic unit test; CLI integration test | One static step runs; a second step fails with a structured unsupported diagnostic. | N/A | io-definition-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-002 | The FESA solver shall analyze only straight, prismatic, two-node 3D Euler–Bernoulli beams under small-displacement, small-rotation, linear-static assumptions. | analysis | Bound the formulation and validation domain. | Approved design §2; formulation §2 | must | Model validation test; formulation review | Accepted models satisfy every listed assumption and excluded procedures are not represented as supported. | N/A | research-agent; formulation-agent; numerical-review-agent | approved |
|
||||
| FESA-REQ-LS3DEB-003 | The FESA solver shall assign each beam node the six global DOFs `[UX, UY, UZ, URX, URY, URZ]` in that order. | analysis | Keep assembly and result components deterministic. | Approved design §§2, 4.3 | must | DofManager unit test; HDF5 schema test | DOF mapping and nodal result columns use the exact approved order. | Exact ordering | formulation-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-004 | The FESA solver shall support axial deformation, bending about both local section axes, Saint-Venant torsion, and homogeneous isotropic linear elasticity. | analysis | Define the complete V0 beam physics. | Approved design §2; formulation §§2, 10 | must | Element unit tests; analytical benchmarks | Axial, torsion, local-y bending, and local-z bending cases recover the approved analytical quantities. | Relative `1e-9` analytical | research-agent; formulation-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-005 | The FESA solver shall map only `*ELEMENT, TYPE=B33` to the V0 Euler–Bernoulli beam formulation. | input | Preserve Abaqus element-family meaning. | Approved design §6.3; PRD FESA-PRD-011 | must | Parser/semantic unit test | B33 creates the approved beam semantic object and reaches model validation. | N/A | io-definition-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-006 | The FESA solver shall reject `*ELEMENT, TYPE=B31` with `unsupported-element-formulation` and shall not reinterpret B31 as B33. | input | B31 includes transverse shear deformation. | Approved design §§2.2, 6.3; ADR-013 | must | Parser diagnostic test | B31 fails with the exact approved diagnostic code and creates no Euler beam. | Exact diagnostic code | io-definition-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-007 | The FESA solver shall support nodal `*CLOAD` and `*BOUNDARY` data for DOFs 1 through 6, including nonzero prescribed displacement. | input | Exercise constrained partition and RHS correction. | Approved design §§2.1, 6.1, 7 | must | Parser test; constraint/load integration test | DOFs 1..6 map correctly and nonzero `dc` contributes to effective RHS and reaction. | Residual normalized `1e-10` | io-definition-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-008 | The element verification contract shall include a constant local line-load equivalent nodal vector kernel, while the V0 parser and CLI shall not support `*DLOAD` or create a Domain distributed-load object. | scope | Verify the formulation without widening CLI input. | Approved design §§2.1, 2.2, 4.5 | must | Element unit test; parser negative test | The closed-form equivalent vector passes and `*DLOAD` is rejected without a Domain distributed-load object. | Normalized `1e-12` kernel comparison | formulation-agent; io-definition-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-009 | The parser shall support exactly `*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`, and `*END STEP` as model/procedure keywords. | input | Avoid a full-compatibility claim. | Approved design §6.1; ADR-003 | must | Keyword inventory review; parser tests | Every listed keyword has positive coverage and no unlisted keyword is documented as supported. | Exact keyword inventory | io-definition-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-010 | The parser shall interpret keyword and parameter names case-insensitively, recognize `**` comment lines, and preserve source label text for external identity. | input | Match approved syntax and identity behavior. | Approved design §6.1 | must | Lexer/parser unit tests | Case variants parse equally, comments are ignored, and original label text survives mapping. | Exact source-label identity | io-definition-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-011 | The parser shall accept `*BOUNDARY` rows only as `target, first_dof, last_dof[, value]`, default an omitted value to zero, and accept `*CLOAD` rows only as `target, dof, magnitude`; targets shall resolve by source node label or node set, including assembly-level sets with `INSTANCE`. | input | Prevent ambiguous semantic mapping. | Approved design §6.1 | must | Parser positive/negative tests | Only approved row arities and DOFs 1..6 pass, and all approved target forms resolve deterministically. | N/A | io-definition-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-012 | The semantic mapping shall read general-section data as `A, I11, I12, I22, J`, require `I12=0`, map `Iy=I11` and `Iz=I22`, and construct local axes as `n1 -> y` and `t x n1 -> z`. | input | Preserve stiffness directions and signs. | Approved design §6.2; PRD FESA-PRD-019 | must | Section-mapping test; rotated-element test | Every property and right-handed local-axis mapping matches the approved contract. | Exact mapping; transform normalized `1e-12` | formulation-agent; io-definition-agent; numerical-review-agent | approved |
|
||||
| FESA-REQ-LS3DEB-013 | A general beam section shall reference a material whose isotropic `*ELASTIC` data provides exactly `E, nu`; the solver shall compute `G=E/(2(1+nu))` and require positive `E`, `G`, `A`, `Iy`, `Iz`, and `J`. | input | Prevent nonphysical or indefinite stiffness. | Approved design §6.2; formulation §10 | must | Semantic/model validation tests | Complete valid data passes; malformed elasticity data or any nonpositive required property fails. | Input-consistent units; normalized `1e-12` for computed `G` | formulation-agent; io-definition-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-014 | Before element calculation, the solver shall require `L > 1e-12 * max(1, norm(X1), norm(X2))` and `norm(a_perp) > 1e-12 * max(1, norm(a))`; zero/near-zero length, a zero guide vector, and a tangent-parallel guide vector shall produce structured model-validation diagnostics. | input | Prevent singular geometry and undefined local axes. | Approved design §6.2; formulation §§3.1, 19 | must | Geometry validation tests | Values at or below either approved threshold fail and valid values produce a right-handed orthonormal frame. | Both thresholds use coefficient `1e-12` | numerical-review-agent; io-definition-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-015 | `*PART/*ASSEMBLY/*INSTANCE` mapping shall preserve `SourceEntityId { instance_name, source_label }` for nodes, elements, and sets and shall map it deterministically to a separate stable Domain internal index. | model | Make row mapping and diagnostics traceable. | Approved design §§4.1, 6.4 | must | Semantic mapping and determinism tests | Instance/source labels round-trip and map to stable unique internal IDs. | Exact identity | io-definition-agent; reference-model-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-016 | The semantic model shall allow multiple identity instances of the same part without merging their source identities. | model | Support approved wrapper reuse without transforms. | Approved design §§2.1, 6.4; ADR-013 | must | Multi-instance semantic integration test | Nodes, elements, and sets for each identity instance remain distinct and deterministic. | Exact identity | io-definition-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-017 | An instance containing translation or rotation data shall be rejected with `unsupported-instance-transform`. | model | V0 has no transform semantics. | Approved design §§2.2, 6.4 | must | Parser/semantic negative tests | Any translation or rotation data fails with the exact approved diagnostic code. | Exact diagnostic code | io-definition-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-018 | Nested assembly and dependent/independent mesh semantics shall be rejected as unsupported rather than silently approximated. | model | Prevent silent topology changes. | Approved design §§2.2, 6.4 | must | Semantic negative tests | Each excluded construct produces a structured unsupported diagnostic and no Domain model. | N/A | io-definition-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-019 | The parser shall issue structured warnings and no-op the exact allowlist `*PREPRINT`, `*RESTART`, `*TRANSVERSE SHEAR STIFFNESS`, `*OUTPUT, FIELD`, `*OUTPUT, HISTORY`, `*NODE OUTPUT`, `*ELEMENT OUTPUT`, `*CONTACT OUTPUT`, and unsupported variable data belonging to those output requests. | input | Accept the legacy input without changing analysis meaning. | Approved design §6.5; PRD FESA-PRD-013 | must | Parser diagnostic test | Every allowlisted keyword/data form yields deterministic warnings, no semantic effect, and no error. | Exact allowlist | io-definition-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-020 | Unsupported model-affecting keywords outside the no-op allowlist shall be errors, and accepted Abaqus output requests shall not change or suppress FESA's mandatory HDF5 results. | input/output | Keep the supported subset explicit. | Approved design §6.5; ADR-003 | must | Parser negative test; HDF5 integration test | An unlisted model keyword fails and mandatory datasets exist with or without allowed output requests. | Exact dataset inventory | io-definition-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-021 | `Domain` shall own the complete parsed model and remain effectively immutable after mapping; `AnalysisModel` shall expose references or IDs for the single active step without copying Domain objects. | architecture | Preserve approved ownership and activation boundaries. | Approved design §§4.1, 4.2; ADR-004 | must | Unit test; architecture review | Active-step view construction neither copies nor mutates Domain objects. | N/A | implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-022 | `DofManager` alone shall own node DOF definitions, full/free equation numbering, constrained/free mappings, element scatter maps, sparse patterns, and full/reduced vector reconstruction; Node and Element shall not store equation IDs. | architecture | Prevent distributed numbering state. | Approved design §4.3; ADR-004 | must | DofManager tests; dependency/code review | All maps reconstruct correctly and no Node or Element stores equation IDs. | Exact mapping | implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-023 | V0 `AnalysisState` shall own full displacement, external/internal force, residual, constrained reaction, step/frame identity, and element recovery rows and shall not allocate velocity, acceleration, temperature, iteration history, or nonlinear element state. | architecture | Keep V0 state minimal and traceable. | Approved design §4.4; PRD FESA-PRD-005 | must | State unit/integration tests | All required state is connected to output and every excluded state remains unallocated. | N/A | io-definition-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-024 | Element-local stiffness work shall use the `ParallelFor`/oneTBB boundary, and global assembly shall deterministically reduce element contributions in stable element order from COO triplets into a 0-based CSR matrix. | architecture | Ensure repeatable sparse assembly and reference rows. | Approved design §§2.1, 7; ADR-008, ADR-009 | must | Repeated assembly tests; CSR structure tests | Repeated and thread-count-varied runs produce identical CSR ordering and numerically identical values. | Stable ordering; normalized numeric `1e-12` | numerical-review-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-025 | MKL, TBB, and HDF5 API/types shall remain behind the `LinearSolver`, `ParallelFor`, dense/sparse math, and `ResultsWriter` adapter boundaries; `Vector` shall use contiguous doubles, `Matrix` row-major contiguous doubles, and `SparseMatrix` a separate 0-based CSR representation. | architecture | Isolate external backends from solver core. | Approved design §5; ADR-006 | must | Dependency review; math/backend unit tests | No public core API exposes backend types and every storage layout matches the approved contract. | N/A | implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-026 | The linear-static lifecycle shall assemble and partition stiffness, call `Kff` factorization, and only then assemble the full load vector, form the effective RHS, and perform substitution; factorization and substitution shall remain observably separate. | execution | Preserve reusable factorization and failure classification. | Approved design §§1, 7; ADR-007 | must | Orchestration test; solver-adapter test | The event trace is stiffness, partition, factorize, load, RHS, solve and no opaque solve hides factorization. | Exact event order | implementation-planning-agent; build-test-executor-agent | approved |
|
||||
| FESA-REQ-LS3DEB-027 | For prescribed displacement `dc`, the solver shall form `rhs=Ff-Kfc*dc`, reconstruct the full displacement after substitution, and recover constrained reaction from `K*d-F`, equivalently `Rc=Kcf*df+Kcc*dc-Fc`, rather than a separate end-force sum. | execution | Correctly handle nonzero constraints and equilibrium. | Approved design §7; formulation §§15, 16.5 | must | Constraint/load integration and residual tests | RHS, full displacement, and constrained reactions match the approved partition equations. | Residual normalized `1e-10` | formulation-agent; numerical-review-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-028 | The sole authoritative solver output shall be HDF5 `results.h5`; the writer shall complete a temporary file before replacing the final path and shall leave no incomplete final file after a writer failure. | output | Prevent ambiguous or partial results. | Approved design §9; ADR-005 | must | HDF5 integration/atomicity tests | Success produces the final file and injected failure leaves no incomplete final `results.h5`. | N/A | io-definition-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-029 | HDF5 schema v0 shall contain `/metadata`, `/model/nodes`, `/model/elements`, `/steps/<step-name>/frames/0/nodal/displacement`, `/steps/<step-name>/frames/0/nodal/reaction`, `/steps/<step-name>/frames/0/element/end_force_local`, `/steps/<step-name>/frames/0/element/section_resultant`, `/steps/<step-name>/frames/0/element/generalized_strain`, `/steps/<step-name>/frames/0/element/stress_s11`, and `/diagnostics`. | output | Give downstream comparison a stable schema root. | Approved design §9 | must | HDF5 schema test | Every named path exists at frame 0 with documented identity and rank/component contracts. | Exact paths | io-definition-agent; reference-verification-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-030 | HDF5 metadata/model identity shall record schema version, solver version, source input identity, unit-system label, coordinate convention, element formulation, stable internal IDs, and instance/source-label mappings; ordinary input shall use `user-consistent-unspecified`, while the approved cantilever comparison shall apply its external SI contract without inferring SI from `.inp` alone. | output | Make results auditable without guessing units or identity. | Approved design §9; ADR-005 | must | Metadata/schema test; reference contract review | Every field is present, ordinary runs use the exact label, and legacy comparison records external SI provenance. | Exact labels and identity | io-definition-agent; reference-model-agent; reference-verification-agent | approved |
|
||||
| FESA-REQ-LS3DEB-031 | Output shall include every node's global displacement/reaction in `[UX, UY, UZ, URX, URY, URZ]`, local endpoint equilibrium end actions in `[FX,FY,FZ,MX,MY,MZ]`, endpoint section resultants in `[N,T,My,Mz]`, and generalized strain/resultant values at the two Gauss points, independent of Abaqus output requests. | output | Separate equilibrium, section, and generalized results. | Approved design §§8, 9 | must | Recovery unit tests; HDF5 schema test | Every component order and endpoint/Gauss location matches the contract in runs with and without output requests. | Analytical `1e-9`; reference policy where applicable | formulation-agent; io-definition-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-032 | The solver shall output axial `S11` at both Gauss points and each input section point, or at centroid `(0,0)` with `source=fesa-default` when section points are absent; transverse/torsional shear stress shall not be recovered, and Abaqus beam-stress reference comparison shall remain explicit N/A while analytical/unit and HDF5 schema tests remain mandatory. | output | Retain useful stress recovery without inventing a reference baseline. | Approved design §§2.2, 8.3, 12 | must | Stress unit/analytical test; HDF5 schema test; report review | Correct stress rows and fallback label exist, no shear stress is emitted, and reference report marks stress N/A. | Analytical relative `1e-9`; Abaqus reference N/A | formulation-agent; io-definition-agent; reference-verification-agent | approved |
|
||||
| FESA-REQ-LS3DEB-033 | The CLI shall support `fesa.exe <model.inp> --output <results.h5>`, default output to the current directory's `results.h5`, use exit codes `0=success`, `2=usage`, `3=input`, `4=model`, `5=solver`, `6=HDF5`, and emit `severity`, `code`, `file`, `line`, `keyword`, `entity_identity`, and `message` diagnostics to stderr in deterministic order. | output | Stabilize automation and failure classification. | Approved design §10 | must | CLI integration and diagnostic ordering tests | Default/explicit output works and every failure class returns its exact code and complete ordered fields. | Exact codes, fields, and order | io-definition-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-034 | Every production C++ behavior shall be developed in one step as GoogleTest `RED -> GREEN -> VERIFY`, with a related C++ test file, focused CTest evidence, full MSVC x64 Debug build/CTest evidence, at least one discovered test, and no new warning under the FESA target's `/W4 /WX` policy. | verification | Enforce project TDD and warning policy. | Approved design §§11.1, 11.4; ADR-012 | must | Implementation report; build/CTest logs | The related test fails first, then focused/full tests pass, discovery finds tests, and FESA emits no warning. | Zero test failures and new warnings | implementation-planning-agent; implementation-agent; build-test-executor-agent | approved |
|
||||
| FESA-REQ-LS3DEB-035 | Numerical tests shall satisfy normalized `1e-12` for stiffness symmetry and two-point-Gauss/closed-form agreement, normalized `1e-10` for rigid-mode and linear-system residual, and relative `1e-9` for analytical solutions, while checking six rigid modes, rank 6, positive deformation energy, transformation orthogonality/energy invariance, prescribed-displacement recovery, and axial/torsion/two-plane bending benchmarks. | verification | Detect sign, integration, rank, and transform defects. | Approved design §§11.2, 11.3; formulation §18 | must | Unit, analytical, and orchestration tests | Every listed invariant and analytical case passes at its stated threshold. | `1e-12` matrix; `1e-10` residual; `1e-9` analytical | formulation-agent; numerical-review-agent; implementation-planning-agent | approved |
|
||||
| FESA-REQ-LS3DEB-036 | The approved B33 reference comparison shall group rows by the same model, step/frame, quantity, and component, compute `reference_scale` only from read-only Abaqus values, and apply `absolute_floor + 1e-6 * reference_scale` to every matched row. | tolerance | Give zero and nonzero rows one deterministic rule. | Approved design §11.3; ADR-014 | must | Comparison unit/integration test; report review | Every group uses the Abaqus-only maximum absolute scale and every matched row uses the exact formula. | Relative coefficient `1e-6` | reference-model-agent; reference-verification-agent | approved |
|
||||
| FESA-REQ-LS3DEB-037 | For the approved SI bundle, displacement and rotation shall use `absolute_floor=1e-9`, force and moment shall use `absolute_floor=1e-3`, and a zero component scale shall use the applicable absolute floor alone. | tolerance | Preserve dimensional meaning near zero. | Approved design §11.3; ADR-014 | must | Comparison tests with zero/near-zero rows | Each quantity uses its exact SI floor and zero-scale groups use no relative contribution. | SI `1e-9` displacement/rotation; `1e-3` force/moment | reference-model-agent; reference-verification-agent | approved |
|
||||
| FESA-REQ-LS3DEB-038 | Reference values shall not be zero-clamped and rows shall not be dropped; missing, extra, duplicate, nonfinite, schema-mismatched, or identity-mismatched rows shall fail before tolerance evaluation. | tolerance | Prevent false passes through omission or clamping. | Approved design §§11.3, 12; ADR-014 | must | Negative comparison tests | Every listed invalid case fails before numeric comparison and zero values remain unchanged. | No ignored invalid rows | reference-verification-agent | approved |
|
||||
| FESA-REQ-LS3DEB-039 | The verification report shall record every row decision and maximum absolute error, component-scale normalized error, RMS error, norm error, and worst row/component for each compared quantity. | tolerance | Make the pass/fail decision auditable. | Approved design §11.3; ADR-014 | must | Verification report schema/review | Per-row decisions and all required aggregate/worst metrics are present for every quantity. | Report completeness | reference-verification-agent; release-agent | approved |
|
||||
| FESA-REQ-LS3DEB-040 | The V0 reference baseline shall use the exact read-only files `reference/cantilever beam/cantilever beam.inp`, `reference/cantilever beam/cantilever beam displacements.csv`, `reference/cantilever beam/cantilever beam reactions.csv`, and `reference/cantilever beam/cantilever beam elemental forces.csv` without rename, rewrite, correction, or restoration; `metadata.json` and `README.md` are N/A only for this approved legacy bundle. | reference | Protect the approved correctness baseline. | Approved design §12; ADR-010, ADR-014 | must | Artifact inventory; Git diff review | Exact filenames exist and no reference file is added, removed, renamed, or content-modified. | Exact path/content identity | reference-model-agent; reference-verification-agent; release-agent | approved |
|
||||
| FESA-REQ-LS3DEB-041 | Before comparison, artifact validation shall confirm all four files, `TYPE=B33`, expected CAE report headers, unique row keys, and finite values; failure shall be classified as `needs-reference-artifacts` or `schema-mismatch` and comparison shall not start. | reference | Detect stale B31 or malformed evidence. | Approved design §§6.3, 12 | must | Artifact-check integration test | All checks pass before comparison and every failure uses an approved classification. | Exact inventory and schema | reference-model-agent; reference-verification-agent | approved |
|
||||
| FESA-REQ-LS3DEB-042 | Reference verification shall compare displacement by source-node identity (`U1/U2/U3/UR1/UR2/UR3`), reaction by source-node identity (`RF1/RF2/RF3/RM1/RM2/RM3`), and node-station-normalized section resultant by `SF1->N`, `SM1->My`, `SM2->Mz`, `SM3->T`; adjacent interior endpoints shall first agree within approved tolerance and shall not be averaged to hide a mismatch. | reference | Compare equivalent quantities despite legacy station rows. | Approved design §§8.2, 12 | must | Reference comparison test/report | All components match by source identity and interior endpoints pass before deterministic representative selection. | Requirements 036 and 037 policy | io-definition-agent; reference-model-agent; reference-verification-agent | approved |
|
||||
| FESA-REQ-LS3DEB-043 | Reference comparison shall run only after build/test passes; physics sanity shall run only after reference comparison passes and shall check global force/moment equilibrium, reaction sign, displacement direction, symmetry, element section-force consistency, and normalized residual; release readiness shall require all prior gate evidence and known limitations. | governance | Keep numerical similarity distinct from physical/release approval. | Approved design §§11, 12, 13 | must | Gate evidence audit | Each downstream report cites the preceding pass and physics evidence covers all six checks before release review. | Relevant upstream tolerances | coordinator-agent; physics-evaluation-agent; release-agent | approved |
|
||||
| FESA-REQ-LS3DEB-044 | FESA agents and Harness shall not execute Abaqus, Nastran, or another reference solver and shall not create, modify, rename, or restore reference artifacts; release documentation shall not claim support for any Out Of Scope behavior. | governance | Prevent baseline contamination and scope inflation. | Approved design §§2.2, 12; ADR-010 | must | Process audit; Git diff; release documentation review | No reference execution or artifact mutation occurs and every exclusion is recorded without a support claim. | N/A | coordinator-agent; reference-model-agent; release-agent | approved |
|
||||
|
||||
## Open Questions
|
||||
|
||||
- 이 approved requirements baseline 안에는 사용자 결정을 기다리는 항목이 없다.
|
||||
- source formulation의 `needs-research` 상태와 그 문서에 남은 evidence/open-issue 항목은 후속 Research, Formulation Alignment, Numerical Review gate에서 이 승인 baseline에 맞춰 해결해야 하며, 이 Step에서 새 정책으로 해소하지 않는다.
|
||||
- 이 baseline의 수치, 단위, schema, keyword, reference 경로를 바꾸려면 요구조건 변경 승인과 downstream traceability 갱신이 필요하다.
|
||||
|
||||
## Downstream Handoff
|
||||
|
||||
### Research Agent
|
||||
|
||||
- B33/Euler–Bernoulli 의미, slender-beam 적용 한계, 두 방향 굽힘·비틀림 benchmark와 source reliability를 조사하되 승인 범위나 tolerance를 바꾸지 않는다.
|
||||
- 확인된 사실과 추론을 분리하고 unresolved evidence gap을 명시한다.
|
||||
|
||||
### Formulation Agent
|
||||
|
||||
- source formulation의 feature/status를 이 baseline과 정렬하고 DOF 순서, local-axis, `theta_y=-dw/dx`, 2점 Gauss, stiffness/recovery 부호를 추적한다.
|
||||
- 요구조건을 충족하는 수학 계약만 정리하고 C++ API나 input/output schema를 설계하지 않는다.
|
||||
|
||||
### I/O Definition Agent
|
||||
|
||||
- 요구조건 009~020과 028~033을 exact parser/model/HDF5 row schema와 diagnostic 계약으로 구체화한다.
|
||||
- 최소 HDF5 path, stable source identity, ordinary-run unit label, legacy SI comparison provenance를 보존한다.
|
||||
|
||||
### Reference Model Agent
|
||||
|
||||
- 요구조건 036~044에 따라 read-only legacy inventory, provenance, row keys, component mapping, artifact precheck, tolerance coverage를 계약화한다.
|
||||
- `reference/cantilever beam/`의 네 파일은 어떤 방식으로도 변경하지 않는다.
|
||||
|
||||
### Implementation Planning Agent
|
||||
|
||||
- 모든 `must` row를 테스트에 추적하고 C++ production 작업마다 같은 Step 안에서 RED/GREEN/VERIFY를 증명하는 계획을 작성한다.
|
||||
- factorization-before-load orchestration, nonzero prescribed displacement, deterministic assembly, atomic HDF5, CLI diagnostics, reference precheck를 독립적으로 검증 가능하게 분해한다.
|
||||
@@ -0,0 +1,165 @@
|
||||
# Linear Static 3D Euler Beam Research Brief
|
||||
|
||||
## Metadata
|
||||
|
||||
- feature_id: `linear-static-3d-euler-beam`
|
||||
- source_requirement: `docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- approved_design: `docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md`
|
||||
- source_formulation: `docs/formulations/3d-isoparametric-euler-beam-formulation.md`
|
||||
- status: `ready-for-formulation`
|
||||
- owner_agent: `research-agent`
|
||||
- date: `2026-08-09`
|
||||
- evidence_route: configured FEM wiki at `C:\git\MultiPhysicsVault`; `wiki/hot.md` -> `wiki/index.md` -> selected wiki pages and their recorded raw-source chunks
|
||||
- source_policy: verified external facts use Tier 1 or Tier 2 sources; approved FESA decisions and mathematical consequences are labeled `Project contract` or `Inference`
|
||||
|
||||
This brief supplies evidence for formulation alignment and later verification planning. It does not approve the existing formulation, define a C++ API, introduce a tolerance, or claim full Abaqus compatibility.
|
||||
|
||||
## Research Questions
|
||||
|
||||
1. What distinguishes Abaqus B31 from B33, and what supports treating only B33 as the Euler–Bernoulli member in FESA V0?
|
||||
2. What evidence supports cubic Hermite bending interpolation, six free-element rigid modes, rank 6, two-point Gauss exactness, local/global transformation, and end-force sign checks for a two-node spatial Euler beam?
|
||||
3. What do Abaqus general beam section data `A, I11, I12, I22, J`, the first section axis `n1`, beam resultants `SF*`/`SM*`, and axial `S11` mean?
|
||||
4. Which axial, torsional, and two-plane bending cantilever cases provide analytical checks, and which quantities or behaviors do they not verify?
|
||||
5. What technical evidence and limitations apply to SPD factorization, PARDISO selection, deterministic sparse assembly, and row-based reference comparison?
|
||||
|
||||
## Source Inventory
|
||||
|
||||
| id | document | provider_or_author | wiki page identity | original source/manual identity | reliability tier | applicable evidence |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| S1 | Abaqus beam element and section documentation | Dassault Systèmes / SIMULIA | [[Abaqus Structural Element Families]]; [[Abaqus Beam and Shell Section Definitions]] | *Abaqus 2016 Analysis User's Guide, Volume IV: Elements*, sections 29.3.3, 29.3.4, 29.3.7, 29.3.8; vault chunks `AbaqusAnalysisUserGuide4_030.md`, `_031.md`, `_033.md`, `_035.md` | Tier 1 | B31/B33 family and interpolation classification, slender-beam limit, section axes/properties, beam output components |
|
||||
| S2 | Beam and frame finite elements | Daryl L. Logan; Thomson | [[Beam and Frame Finite Elements]] | *A First Course in the Finite Element Method*, Fourth Edition, Chapter 4 and Gaussian quadrature material; chunks `AFirstCourseInTheFiniteElementMethod_018.md`, `_020.md`, `_049.md` | Tier 2 | Euler–Bernoulli assumptions, cubic Hermite interpolation, end-force signs, equivalent loads, cantilever checks, Gauss exactness |
|
||||
| S3 | Static equation solution | Klaus-Jürgen Bathe | [[Static Equilibrium Equation Solvers]] | *Finite Element Procedures*, Second Edition (2014), Chapter 8; chunks `FiniteElementProcedures_072.md`, `_074.md`, `_076.md`, `_077.md` | Tier 2 | symmetry/positive-definiteness conditions, LDLT/Cholesky factorization, positive-pivot failure, conditioning limits |
|
||||
| S4 | Isoparametric mapping and quadrature synthesis | FEM wiki, with Bathe, Logan, Abaqus, and local source provenance | [[Isoparametric Finite Elements]] | *Finite Element Procedures*; Logan textbook; *Abaqus Theory Manual*; *Abaqus Analysis User's Guide, Volume IV* | Tier 2 synthesis; Tier 1 where Abaqus-specific | natural coordinates, Jacobian mapping, quadrature choice, under-integration risk |
|
||||
| S5 | FEM program verification workflow | FEM wiki, with textbook and official-manual provenance | [[Finite Element Program Implementation]]; [[Finite Element Modeling and Convergence Checks]] | *Finite Element Procedures*; Logan textbook; Abaqus user guides; production solver manuals | Tier 2 synthesis; Tier 1 for cited official-manual behavior | element-local/global separation, sparse assembly context, constraint/solve/recovery workflow, benchmark and equilibrium checks |
|
||||
| P1 | Approved FESA feature contract | FESA project | N/A | approved requirements and design named in Metadata | Project contract, not external evidence | exact V0 scope, fixed tolerance policy, read-only reference inventory, required output and orchestration |
|
||||
| P2 | Existing candidate formulation | FESA project | cites [[Beam and Frame Finite Elements]], [[Isoparametric Finite Elements]], and S5 pages | `docs/formulations/3d-isoparametric-euler-beam-formulation.md` | Candidate derivation, not an approved source | equations and sign choices that downstream Formulation and Numerical Review agents must check |
|
||||
|
||||
The wiki source records identify S1 as high-confidence manual provenance, S2 as a high-confidence textbook source, and S3 as a current textbook source. P1 and P2 are intentionally not assigned an external reliability tier.
|
||||
|
||||
## Extracted Facts
|
||||
|
||||
### B31, B33, and the supported Euler–Bernoulli meaning
|
||||
|
||||
- **F-01 — Verified, Tier 1 (S1):** Abaqus lists B33 as a two-node cubic three-dimensional beam and includes B33/B33H among its Euler–Bernoulli beam elements. These elements suppress transverse shear deformation and retain cross-sections normal to the beam axis in the no-warping idealization. [[Abaqus Structural Element Families]]
|
||||
- **F-02 — Verified, Tier 1 (S1):** Abaqus lists B31 as a two-node linear three-dimensional Timoshenko beam. B31 allows transverse shear deformation, so interpreting B31 as the same formulation as a classical shear-free B33 changes the element meaning. [[Abaqus Structural Element Families]]
|
||||
- **F-03 — Verified, Tier 1 (S1):** The manual gives a modeling guideline, not a universal acceptance threshold: for a homogeneous member, a typical cross-section dimension below roughly `1/15` of the typical axial distance makes transverse-shear flexibility negligible. [[Abaqus Structural Element Families]]
|
||||
- **F-04 — Project-contract conclusion (P1), supported by F-01/F-02:** Mapping only `TYPE=B33` to the FESA Euler–Bernoulli element and rejecting B31 preserves the documented family distinction. This establishes a supported subset; it does not establish numerical or file-format equivalence with every Abaqus B33 capability.
|
||||
- **F-05 — Applicability distinction, Tier 1 plus P1:** Abaqus documents its cubic beam for a wider small-strain/large-rotation setting, whereas FESA V0 deliberately restricts the model to small displacement and small rotation. The FESA restriction is narrower than the source element family. [[Abaqus Structural Element Families]]
|
||||
|
||||
### Interpolation, modes, integration, transformation, and signs
|
||||
|
||||
- **F-06 — Verified, Tier 2 (S2):** A two-node Euler–Bernoulli bending field has transverse displacement and slope/rotation at each node. A complete cubic field supplies the four interpolation conditions and is `C1` across connected beam elements; the functions are Hermite cubic interpolation functions. [[Beam and Frame Finite Elements]]
|
||||
- **F-07 — Verified, Tier 2 (S2):** Gaussian quadrature with `n` points integrates a polynomial through degree `2n-1` exactly; two points therefore integrate a cubic polynomial exactly. [[Isoparametric Finite Elements]]
|
||||
- **F-08 — Inference from F-07 and P2:** For the straight, constant-property FESA candidate, the bending rows of `B` are linear in the natural coordinate, so each entry of `B^T D B J` is at most quadratic. Two-point Gauss integration should reproduce the closed-form stiffness. This is a testable consequence, not final approval of the current `B` matrix.
|
||||
- **F-09 — Verified principle, Tier 2 (S2/S4):** Spatial frame members transform nodal vectors between local member axes and the global system before assembly. An orthonormal, right-handed rotation preserves vector work; FESA energy-invariance and orthogonality checks are downstream consequences. [[Beam and Frame Finite Elements]]
|
||||
- **F-10 — Inference from P2 and the 12-DOF model:** A free two-node spatial beam should have three translational and three rotational rigid-body modes. With six independent positive deformation modes, its 12-by-12 stiffness should have rank 6. The queried wiki does not state the exact FESA rank claim, so all six null vectors, six positive modes, and scale-aware rank classification require independent Numerical Review and executable tests.
|
||||
- **F-11 — Verified sign risk, Tier 2 (S2):** Textbook beam nodal force and classical section-cut conventions can have opposite signs at an element end; local end forces must be defined as forces exerted on the element or on the adjoining cut, not inferred only from a component name. [[Beam and Frame Finite Elements]]
|
||||
- **F-12 — Project-contract inference (P1/P2):** The approved FESA endpoint normalization and `theta_y=-dw/dx` determine the proposed end-action signs. S1 defines Abaqus output component meanings but does not prove the exact FESA-to-Abaqus endpoint section-cut sign transform. That transform remains an explicit review and reference-test item.
|
||||
|
||||
### Abaqus general beam section and output meanings
|
||||
|
||||
- **F-13 — Verified, Tier 1 (S1):** For `*BEAM GENERAL SECTION, SECTION=GENERAL`, the manual orders the direct geometric data as `A, I11, I12, I22, J` before optional warping-related terms. `A` is area, `I11` and `I22` are moments of inertia for bending about section axes 1 and 2, `I12` is the cross-bending inertia, and `J` is the Saint-Venant torsional constant. [[Abaqus Beam and Shell Section Definitions]]
|
||||
- **F-14 — Verified, Tier 1 (S1):** Abaqus defines a local right-handed `(t,n1,n2)` beam section frame: `t` is positive from the first element node to the second, `n1` is the first beam section axis, and `n2` is the second section axis/beam normal. For a spatial beam, an approximate `n1` can be supplied with the section or an off-axis node. [[Abaqus Beam and Shell Section Definitions]]
|
||||
- **F-15 — Mathematical inference from F-14 and Project contract P1:** In a right-handed frame, `n2=t x n1`; therefore the approved mapping `t -> local x`, `n1 -> local y`, and `t x n1 -> local z` is consistent with the manual axis order. `Iy=I11`, `Iz=I22`, and rejection of `I12!=0` are the approved FESA subset and must not be generalized to all Abaqus general sections.
|
||||
- **F-16 — Verified, Tier 1 (S1):** Abaqus beam output defines `SF1` as axial force, `SM1` as bending moment about local section axis 1, `SM2` as bending moment about local section axis 2, and `SM3` as twisting moment about the beam axis. `SF2` and `SF3` are transverse shear components and are unavailable for B33/B33H. [[Abaqus Structural Element Families]]
|
||||
- **F-17 — Verified, Tier 1 (S1):** `S11` is axial beam stress. Shear components documented for other beam/section cases do not establish that FESA V0 can recover them. [[Abaqus Beam and Shell Section Definitions]]
|
||||
- **F-18 — Project-contract mapping (P1), supported by F-14/F-16:** With section axis 1 mapped to FESA local `y` and axis 2 to local `z`, the approved legacy comparison uses `SF1 -> N`, `SM1 -> My`, `SM2 -> Mz`, and `SM3 -> T`. The transverse `SF2/SF3` rows are outside the approved CSV comparison.
|
||||
|
||||
### Static solution, sparse assembly, and comparison evidence
|
||||
|
||||
- **F-19 — Verified, Tier 2 (S3):** Properly supported linear elastic FE systems commonly produce symmetric positive-definite coefficient matrices. Cholesky requires positive definiteness, and a nonpositive pivot indicates an invalid assumption, insufficient support, indefiniteness, or severe numerical difficulty rather than a result to accept silently. [[Static Equilibrium Equation Solvers]]
|
||||
- **F-20 — Verified, Tier 2 (S3):** Matrix factorization and load-vector reduction/back substitution are distinct stages; retaining a factorization permits additional right-hand sides without repeating decomposition. [[Static Equilibrium Equation Solvers]]
|
||||
- **F-21 — Project-contract inference (P1):** Using an SPD PARDISO mode for constrained `Kff` is consistent with F-19 only after positive section/material data and sufficient constraints remove all rigid modes. The FEM vault contains no Intel oneMKL PARDISO manual page, phase contract, or CSR indexing contract, so those product-specific details are not verified here.
|
||||
- **F-22 — Verified workflow, Tier 2 synthesis (S5):** Reliable FEM software separates element-local calculations, global DOF mapping and assembly, constraint application, equation solution, and result recovery, then checks new elements with analytical or benchmark problems. [[Finite Element Program Implementation]]
|
||||
- **F-23 — Project-contract inference (P1):** Stable element ordering, deterministic triplet sorting, duplicate reduction, and canonical 0-based CSR finalization are FESA reproducibility policies. The queried wiki supports sparse assembly as a stage but does not prescribe this exact deterministic algorithm.
|
||||
- **F-24 — Verified verification principle, Tier 2 synthesis (S5):** Displacement, reaction, equilibrium, compatibility, convergence, coordinate-system meaning, and result location must be checked before trusting output tables. [[Finite Element Modeling and Convergence Checks]]
|
||||
- **F-25 — Project contract (P1):** Exact row identities, the component-scale mixed tolerance, all-row reporting, and fail-fast handling of missing/extra/nonfinite rows come from approved FESA requirements. This brief neither alters nor independently approves those numerical values.
|
||||
## Candidate Benchmarks
|
||||
|
||||
The equations below reproduce the already approved analytical candidates in P1/P2. They are not newly generated reference values. Load and response signs assume the P2 local-axis and rotation convention and must be independently checked before formulation approval.
|
||||
|
||||
| benchmark_id | evidence classification | configuration | target quantities | can verify | cannot verify |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `CB-AXIAL-TIP` | Tier 2 beam/bar principle plus P2 equation | one straight cantilever, tip force `Px` along local `+x` | `u(L)=Px L/(EA)`, fixed-end reaction, constant `N`, axial `S11` at specified section points | axial stiffness, DOF/component direction, reaction equilibrium, centroidal axial stress | bending, torsion, B33 interpolation details, reference row normalization |
|
||||
| `CB-TORSION-TIP` | Tier 2 member principle plus P2 equation | one cantilever, tip torque `Mx` about local `+x` | `theta_x(L)=Mx L/(GJ)`, reaction torque, constant `T` | Saint-Venant torsional stiffness, rotation sign, reaction and section torque | warping, bimoment, torsional shear-stress distribution, open-section fidelity |
|
||||
| `CB-BEND-LOCAL-Y` | Tier 2 Euler beam theory plus P2 equation | one cantilever, tip force `Py` along local `+y` | `v(L)=Py L^3/(3 E Iz)`, `theta_z(L)=Py L^2/(2 E Iz)`, reaction force/moment, linear `Mz` | Hermite bending plane, `Iz=I22`, `theta_z` sign, endpoint equilibrium | shear deformation, deep-beam behavior, transverse stress recovery |
|
||||
| `CB-BEND-LOCAL-Z` | Tier 2 Euler beam theory plus P2 sign convention | one cantilever, tip force `Pz` along local `+z` | `w(L)=Pz L^3/(3 E Iy)`, `theta_y(L)=-Pz L^2/(2 E Iy)`, reaction force/moment, linear `My` | second bending plane, `Iy=I11`, critical `theta_y=-dw/dx` sign | shear deformation, `I12` coupling, transverse stress recovery |
|
||||
| `CB-RIGID-RANK` | Inference F-10 | unconstrained, otherwise valid free element | six explicit rigid vectors, `K r_i`, numerical rank, positive energy of six deformation modes | missing/extra constraints, sign errors that create spurious strain, rank loss from integration | global constraint sufficiency, PARDISO behavior, deep-beam accuracy |
|
||||
| `CB-GAUSS-CLOSED` | Tier 2 Gauss theorem plus inference F-08 | constant `E,G,A,Iy,Iz,J`, straight element | two-point-Gauss stiffness versus independently evaluated closed form | quadrature/Jacobian/`B` consistency and stiffness symmetry | variable property/load integration, curved or tapered members |
|
||||
| `CB-ROTATED-SPACE` | Tier 2 frame transformation plus inference F-09 | rigidly rotate each analytical cantilever to a non-axis-aligned 3D orientation | transformed displacement/reaction/resultant, `R R^T`, determinant, strain energy | local-axis construction, local/global mapping, energy invariance | instance transforms, curved axes, orientation fallback outside P1 |
|
||||
| `CB-B31-NEGATIVE` | Tier 1 S1 plus P1 | otherwise valid input with `TYPE=B31` | `unsupported-element-formulation`; no Euler element | semantic preservation of Abaqus family meaning | numerical B31/Timoshenko behavior |
|
||||
| `CB-LEGACY-B33-ROWS` | Project contract P1 with Tier 1 output semantics | exact read-only `reference/cantilever beam/` B33 bundle | displacement, reaction, node-station section-resultant rows | supported pipeline quantities, identities, component meanings, approved tolerance application | beam stress comparison, `SF2/SF3`, broad Abaqus compatibility, correctness outside this model |
|
||||
|
||||
## Verification Relevance
|
||||
|
||||
- **code_verification:** `CB-RIGID-RANK`, `CB-GAUSS-CLOSED`, Hermite value/slope conditions, stiffness symmetry, and `CB-ROTATED-SPACE` isolate interpolation, differentiation, integration, transform, and sign errors before reference comparison. Evidence basis: F-06 through F-12.
|
||||
- **solution_verification:** The four analytical cantilevers compare exact member quantities against numerical displacement, rotation, reaction, section resultant, residual, and axial stress. Separate load cases prevent one sign or stiffness error from being hidden by a mixed response. Evidence basis: S2 and P2.
|
||||
- **solver_verification:** `Kff` symmetry/positive-definiteness, factorization success, repeated-RHS substitution, normalized residual, and reaction recovery check the linear system path. A PARDISO-specific claim still requires the official oneMKL contract identified in Open Issues. Evidence basis: F-19 through F-21.
|
||||
- **assembly_reproducibility:** Repeating assembly with changed thread counts should produce the same canonical CSR structure and values required by P1. This is a project-policy test, not an externally sourced theorem. Evidence basis: F-22/F-23.
|
||||
- **reference_comparison:** S1 establishes Abaqus `U/RF/RM/SF/SM` component meaning; P1 establishes exact files, row identities, component mapping, and tolerance. Artifact/schema mismatches must fail before numeric comparison. `S11` comparison is explicitly N/A.
|
||||
- **physics_sanity:** Global force/moment balance, reaction sign, displacement direction, two bending-plane symmetry, endpoint section-force consistency, and free-DOF residual remain separate from numerical similarity to the CSV. Evidence basis: F-24 and P1.
|
||||
- **validation:** No experimental or physical-validation dataset was identified. These candidates support code verification, analytical solution verification, and source-solver comparison only; they do not validate Euler–Bernoulli theory for a real deep, warped, curved, nonlinear, or anisotropic member.
|
||||
|
||||
## Applicability Limits
|
||||
|
||||
- **linear_or_nonlinear:** linear static only; no geometric or material nonlinearity.
|
||||
- **deformation:** FESA small displacement and small rotation. Abaqus B33's broader documented rotation capability is not inherited.
|
||||
- **element_type:** straight, prismatic, two-node FESA Euler–Bernoulli element mapped only from `TYPE=B33`; no B31/Timoshenko reinterpretation.
|
||||
- **slenderness:** Euler–Bernoulli neglects transverse shear. The S1 `1/15` statement is a modeling guideline and is not converted here into a FESA warning or rejection threshold.
|
||||
- **section:** `A,I11,I12,I22,J` general beam section data with approved `I12=0`; no centroid/shear-center offset, warping constants, taper, release, or curved member.
|
||||
- **material_model:** homogeneous isotropic linear elasticity with positive approved properties; no plasticity, anisotropy, temperature dependence, or nonlinear section integration.
|
||||
- **loads:** nodal concentrated loads in the CLI. The constant local line-load vector is only a formulation verification kernel; it does not imply `*DLOAD` support.
|
||||
- **integration:** two-point exactness applies to the straight constant-property candidate whose integrand degree is covered by F-08. It is not a general rule for variable properties, curved geometry, discontinuities, or higher-order loads.
|
||||
- **coordinate_system:** right-handed local frame based on tangent and supplied `n1`; no silent fallback for zero or tangent-parallel guide vectors and no instance transform.
|
||||
- **solver:** SPD factorization applies only to valid, sufficiently constrained `Kff`. Unconstrained element matrices are positive semidefinite and singular; indefinite, nonsymmetric, ill-conditioned, or multiplier systems are outside this contract.
|
||||
- **results:** displacement/reaction, equilibrium end action, section resultants, generalized results, and axial `S11` only. Transverse/torsional shear stress and Abaqus stress comparison are outside scope.
|
||||
- **units:** user-consistent units generally; the approved legacy comparison alone carries the external SI contract from P1.
|
||||
- **reference_scope:** the existing B33 cantilever bundle is read-only and verifies only documented quantities and model coverage. It cannot establish broad B33 compatibility.
|
||||
|
||||
## Open Issues
|
||||
|
||||
1. **PARDISO manual gap — non-blocking for formulation:** The configured FEM wiki has no Intel oneMKL PARDISO source page. Exact SPD matrix type, phase sequence, zero-based CSR option, reordering, repeated-RHS lifetime, and error-code handling must be checked against an official Intel manual before implementation planning calls the adapter contract source-backed.
|
||||
2. **Deterministic COO-to-CSR gap — project policy:** S5 supports the assembly stage, but no queried source prescribes FESA's stable element order, triplet sort key, duplicate summation order, or thread-count-independent reduction. The implementation plan must specify and test them without presenting them as textbook facts.
|
||||
3. **Endpoint sign-normalization gap:** S1 defines `SF*`/`SM*` meanings and S2 warns that nodal end-action and section-cut signs differ. The exact FESA endpoint-to-node-station transform must be re-derived in Formulation Alignment, checked independently in Numerical Review, and exercised against unmodified reference rows.
|
||||
4. **Exact Abaqus B33 equivalence is not established:** The manual describes a two-node cubic Euler–Bernoulli family and notes additional internal axial variables for cubic beams. This brief supports the approved physical subset, not internal-algorithm identity or bitwise equivalence.
|
||||
5. **Slenderness policy remains intentionally unset:** The official `1/15` guidance documents applicability but P1 contains no automatic slenderness diagnostic. Adding one requires a requirements amendment.
|
||||
6. **Legacy row-location semantics:** The approved CSV provides node-station force rows rather than complete element-end identity. Step 5 must retain the interior-endpoint consistency check and deterministic representative selection; averaging cannot hide a sign or continuity mismatch.
|
||||
|
||||
None of these issues changes the approved V0 scope or blocks mathematical formulation alignment. Issues 1 and 2 are mandatory implementation-planning handoffs; Issues 3 and 4 are mandatory for formulation and numerical review.
|
||||
## Downstream Handoff
|
||||
|
||||
### Formulation Agent
|
||||
|
||||
- Use F-01 through F-18 to align the formulation identity to B33's shear-free cubic member meaning while retaining the narrower small-rotation FESA scope.
|
||||
- Re-derive both bending-plane signs, especially `theta_y=-dw/dx`, and make equilibrium end action versus section-cut resultant conventions explicit at both endpoints.
|
||||
- Treat six rigid modes/rank 6, two-point exactness, and `n2=t x n1` as reviewable consequences, not as facts made true merely by this brief.
|
||||
- Do not add shear deformation, `I12` coupling, offsets, warping, or new tolerances.
|
||||
|
||||
### Numerical Review Agent
|
||||
|
||||
- Independently check all six rigid vectors, numerical rank scaling, positive deformation energy, stiffness symmetry, and Gauss/closed-form agreement.
|
||||
- Check transformation orthogonality, determinant, virtual-work/energy invariance, and both endpoint signs using a rotated 3D member.
|
||||
- Confirm `SM1/SM2` mapping after `n1 -> y`, `n2 -> z`, and audit equilibrium end action versus section resultant.
|
||||
- Preserve S1 slenderness guidance as an applicability limit unless requirements are amended.
|
||||
|
||||
### I/O Definition Agent
|
||||
|
||||
- Use S1 for exact meanings of `A,I11,I12,I22,J`, `n1`, `S11`, `SF*`, and `SM*`, while documenting only the P1-approved keyword subset.
|
||||
- Keep optional Abaqus warping/offset data and B31 outside semantic mapping rather than silently discarding or approximating them.
|
||||
- Keep result location and coordinate metadata explicit enough to distinguish endpoint actions, section resultants, and Gauss/section-point `S11` rows.
|
||||
|
||||
### Reference Model Agent
|
||||
|
||||
- Cover axial, torsional, local-y bending, local-z bending, and rotated-space checks with target quantities and exclusions from Candidate Benchmarks.
|
||||
- Preserve exact legacy B33 paths and do not generate, repair, rename, or rewrite reference artifacts.
|
||||
- Make stress comparison N/A, `SF2/SF3` noncoverage, and interior endpoint consistency visible in the coverage matrix.
|
||||
|
||||
### Implementation Planning Agent
|
||||
|
||||
- Translate every candidate into a RED/GREEN/VERIFY test without changing P1 tolerances.
|
||||
- Resolve Open Issues 1 and 2 with an official oneMKL contract and explicit deterministic reduction algorithm before planning PARDISO and sparse-assembly implementation.
|
||||
- Keep factorization, load assembly, effective-RHS formation, and substitution observable as separate events.
|
||||
|
||||
### Coordinator Agent
|
||||
|
||||
- Carry the PARDISO source gap and endpoint-sign review forward. Reopen requirements only if a new slenderness diagnostic, broader Abaqus compatibility claim, or changed result/tolerance contract is proposed.
|
||||
@@ -1,5 +1,9 @@
|
||||
# Harden Execute Runner Implementation Plan
|
||||
|
||||
> **Historical / Superseded:** 이 계획의 `codex/` 브랜치, `allowed_paths`, explicit
|
||||
> staging, 구형 workspace validation 계약은 현재 Runner 동작이 아니다. 현재 계약은
|
||||
> `docs/HARNESS_WORKFLOW.md`와 `docs/HARNESS.md`를 따른다.
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Make `scripts/execute.py` safe enough to use by enforcing `codex/` branch names, clean starting state, explicit staging, per-step file allowlists, and validation before every runner-created commit.
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# Reference CSV Comparison Contract Implementation Plan
|
||||
|
||||
> **Historical / Partially Superseded:** Reference CSV/HDF5 제품 계약의 배경 기록으로만
|
||||
> 보존한다. 이 문서의 Python `unittest`, 삭제된 workspace validation script, Harness
|
||||
> 환경 변수 관련 검증 절차는 폐기되었으며 현재 운영 계약은
|
||||
> `docs/HARNESS_WORKFLOW.md`와 `docs/HARNESS.md`를 따른다.
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Re-align FESA reference comparison contracts so FESA solver output remains authoritative HDF5, while Abaqus-derived reference results are CSV files compared directly against the FESA `results.h5` datasets.
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
# Linear Static 3D Euler Beam Harness Phase Construction Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Create the approved 29-step Harness phase that drives the FESA V0 single-step B33 linear-static solver from upstream contracts through release readiness.
|
||||
|
||||
**Architecture:** The phase is a sequence of seven document gates, eighteen TDD implementation steps, and four final verification gates. Each `stepN.md` is self-contained, names its role/skill and owned paths, preserves the approved design as the source of truth, and delegates per-step commits and timestamps to `scripts/execute.py`.
|
||||
|
||||
**Tech Stack:** Markdown and JSON phase descriptors; C++17; MSVC x64 Debug; CMake/CTest; GoogleTest from `C:/git/googletest`; Intel oneMKL/oneTBB; HDF5; Python 3 Harness runner.
|
||||
|
||||
## Global Constraints
|
||||
|
||||
- The approved source of truth is `docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md`; phase steps must not silently broaden or reinterpret it.
|
||||
- The solver scope is one `*STEP, *STATIC` using Abaqus `TYPE=B33`; `TYPE=B31`, multiple steps, instance transforms, nested assemblies, and `*DLOAD` input remain unsupported.
|
||||
- Runtime order keeps `Kff` factorization before load-vector assembly and separates factorization from substitution.
|
||||
- Production C++ changes use `RED -> GREEN -> VERIFY`; every production file has a related GoogleTest file.
|
||||
- Validation uses MSVC x64 Debug and the exact dependency cache variables in the approved design; production CMake must not hardcode the local GoogleTest path.
|
||||
- `reference/cantilever beam/` is read-only and must not be renamed, rewritten, regenerated, or repaired by the phase.
|
||||
- Beam stress is written and tested, but Abaqus stress reference comparison is explicitly N/A.
|
||||
- Harness owns per-step commits and timestamps; a step must update only its phase status and must not invoke `git commit`.
|
||||
- Before `python scripts/execute.py linear-static-3d-euler-beam`, use a clean worktree or a separate worktree because the current executor stages with `git add -A`.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Create Phase Indexes
|
||||
|
||||
**Files:**
|
||||
- Create: `phases/index.json`
|
||||
- Create: `phases/linear-static-3d-euler-beam/index.json`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: approved phase name and 29-step table from the design specification.
|
||||
- Produces: top-level pending phase registration and contiguous step numbers `0..28` with kebab-case names.
|
||||
|
||||
- [ ] **Step 1: Register the phase**
|
||||
|
||||
```json
|
||||
{
|
||||
"phases": [
|
||||
{ "dir": "linear-static-3d-euler-beam", "status": "pending" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Create the task index**
|
||||
|
||||
Use `project: "FESA Structural Solver"`, `phase: "linear-static-3d-euler-beam"`, and the exact step names from specification section 3. Do not add timestamps; the executor owns them.
|
||||
|
||||
- [ ] **Step 3: Validate both JSON files**
|
||||
|
||||
```powershell
|
||||
Get-Content -Raw phases/index.json | ConvertFrom-Json | Out-Null
|
||||
$phase = Get-Content -Raw phases/linear-static-3d-euler-beam/index.json | ConvertFrom-Json
|
||||
if ($phase.steps.Count -ne 29) { throw 'Expected 29 steps' }
|
||||
if (($phase.steps.step -join ',') -ne ((0..28) -join ',')) { throw 'Step numbers are not contiguous' }
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Executor commit checkpoint**
|
||||
|
||||
Do not run `git commit`; `scripts/execute.py` commits phase execution results. The phase-construction changes remain for the user to review and commit.
|
||||
|
||||
### Task 2: Create Upstream Contract Gate Steps
|
||||
|
||||
**Files:**
|
||||
- Create: `phases/linear-static-3d-euler-beam/step0.md` through `step6.md`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: approved design, formulation, root project documents, gate-specific README files, and exact FESA skill contracts.
|
||||
- Produces: requirements, research, formulation alignment, numerical review, I/O, reference-model, and implementation-plan documents.
|
||||
|
||||
- [ ] **Step 1: Define role and skill ownership**
|
||||
|
||||
```text
|
||||
0 requirement-agent / fesa-requirements-baseline
|
||||
1 research-agent / fesa-research-evidence + fem-theory-query
|
||||
2 formulation-agent / fesa-formulation-spec
|
||||
3 numerical-review-agent / fesa-numerical-review
|
||||
4 io-definition-agent / fesa-io-contract
|
||||
5 reference-model-agent / fesa-reference-models
|
||||
6 implementation-planning-agent / fesa-cpp-msvc-tdd
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Make each document gate self-contained**
|
||||
|
||||
Each step names required input paths, the exact output path, mandatory sections/status, immutable decisions, executable PowerShell checks, status-update rules, and prohibited changes. Step 2 aligns the existing formulation without changing its approved mathematical meaning; Step 5 documents the approved legacy bundle exception without modifying `reference/`.
|
||||
|
||||
- [ ] **Step 3: Verify gate file structure**
|
||||
|
||||
```powershell
|
||||
0..6 | ForEach-Object {
|
||||
$path = "phases/linear-static-3d-euler-beam/step$_.md"
|
||||
if (-not (Test-Path $path)) { throw "Missing $path" }
|
||||
foreach ($section in @('## 읽어야 할 파일','## 작업','## Acceptance Criteria','## 검증 절차','## 금지사항')) {
|
||||
if (-not (Select-String -LiteralPath $path -SimpleMatch $section -Quiet)) {
|
||||
throw "$path missing $section"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Executor commit checkpoint**
|
||||
|
||||
Do not commit manually; the executor will commit each completed gate.
|
||||
|
||||
### Task 3: Create C++ TDD Implementation Steps
|
||||
|
||||
**Files:**
|
||||
- Create: `phases/linear-static-3d-euler-beam/step7.md` through `step24.md`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: approved upstream documents produced by Steps 0–6.
|
||||
- Produces: build foundation, core/model/parser/FEM/math/solver/result modules, tests, and `fesa.exe`.
|
||||
|
||||
- [ ] **Step 1: Lock module order and interfaces**
|
||||
|
||||
```cpp
|
||||
Matrix EulerBeam3D::localStiffness() const;
|
||||
Matrix EulerBeam3D::globalStiffness() const;
|
||||
Vector EulerBeam3D::localEquivalentLoad(const ConstantLocalLineLoad&) const;
|
||||
BeamRecovery EulerBeam3D::recover(const Vector& globalElementDisplacement) const;
|
||||
|
||||
class LinearSolver {
|
||||
public:
|
||||
virtual ~LinearSolver() = default;
|
||||
virtual Status factorize(const SparseMatrix& matrix) = 0;
|
||||
virtual Status solve(const Vector& rhs, Vector& solution) const = 0;
|
||||
};
|
||||
```
|
||||
|
||||
The remaining steps define signatures for diagnostics, semantic mapping, active views, DOF numbering, state, deterministic parallel assembly, constraints, load assembly, result recovery, HDF5 writing, and orchestration without exposing MKL/TBB/HDF5 types across adapter boundaries.
|
||||
|
||||
- [ ] **Step 2: Encode test-first execution in every production step**
|
||||
|
||||
Each Step 8–24 contains these independently verifiable actions:
|
||||
|
||||
```text
|
||||
1. Add the named GoogleTest cases before production edits.
|
||||
2. Build and run the targeted CTest regex; record the expected missing-behavior RED failure.
|
||||
3. Add only the production behavior owned by the step.
|
||||
4. Rebuild and run the targeted test to GREEN.
|
||||
5. Run CTest discovery and the full CTest suite for VERIFY.
|
||||
```
|
||||
|
||||
Step 7 creates the build/test foundation and proves at least one discovered test. Step 24 also provides the end-to-end CLI and test-only B33 reference comparison command used read-only by Step 26.
|
||||
|
||||
- [ ] **Step 3: Use the approved dependency configure command**
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Verify all implementation step descriptors**
|
||||
|
||||
```powershell
|
||||
7..24 | ForEach-Object {
|
||||
$path = "phases/linear-static-3d-euler-beam/step$_.md"
|
||||
if (-not (Test-Path $path)) { throw "Missing $path" }
|
||||
foreach ($text in @('MSVC x64 Debug','## Acceptance Criteria','## 금지사항')) {
|
||||
if (-not (Select-String -LiteralPath $path -SimpleMatch $text -Quiet)) {
|
||||
throw "$path missing $text"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Executor commit checkpoint**
|
||||
|
||||
Do not commit manually; the executor creates one feature commit and one metadata commit per completed step.
|
||||
|
||||
### Task 4: Create Final Verification Gate Steps
|
||||
|
||||
**Files:**
|
||||
- Create: `phases/linear-static-3d-euler-beam/step25.md` through `step28.md`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: completed solver, generated HDF5 result, approved read-only reference CSVs, and all upstream reports.
|
||||
- Produces: build/test, reference-verification, physics-evaluation, and release-readiness reports.
|
||||
|
||||
- [ ] **Step 1: Define strict gate transitions**
|
||||
|
||||
```text
|
||||
25 pass-for-reference-verification
|
||||
-> 26 pass-for-physics-evaluation
|
||||
-> 27 pass-for-release-agent
|
||||
-> 28 ready-for-release
|
||||
```
|
||||
|
||||
Each later step must block or emit the appropriate `needs-*` status when its required predecessor is not passing. Step 26 applies the exact component-scale mixed tolerance, Step 27 checks physical equilibrium and signs, and Step 28 audits traceability and limitations without publishing anything.
|
||||
|
||||
- [ ] **Step 2: Enforce read-only boundaries**
|
||||
|
||||
Steps 26–28 must not edit source, tests, CMake, upstream contracts, reference artifacts, or tolerance policy. Step 26 must state stress comparison is N/A while requiring the stress output schema/test evidence.
|
||||
|
||||
- [ ] **Step 3: Verify the final gate descriptors**
|
||||
|
||||
```powershell
|
||||
25..28 | ForEach-Object {
|
||||
$path = "phases/linear-static-3d-euler-beam/step$_.md"
|
||||
if (-not (Test-Path $path)) { throw "Missing $path" }
|
||||
foreach ($text in @('## Acceptance Criteria','reference')) {
|
||||
if (-not (Select-String -LiteralPath $path -SimpleMatch $text -Quiet)) {
|
||||
throw "$path missing $text"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Executor commit checkpoint**
|
||||
|
||||
Do not commit manually; Harness owns execution commits and timestamps.
|
||||
|
||||
### Task 5: Validate the Generated Phase
|
||||
|
||||
**Files:**
|
||||
- Read: `docs/superpowers/plans/2026-08-09-linear-static-3d-euler-beam-harness-phase.md`
|
||||
- Read: `phases/index.json`
|
||||
- Read: `phases/linear-static-3d-euler-beam/index.json`
|
||||
- Read: `phases/linear-static-3d-euler-beam/step0.md` through `step28.md`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: all generated planning artifacts.
|
||||
- Produces: structural and source-contract verification evidence; no solver execution.
|
||||
|
||||
- [ ] **Step 1: Parse and cross-check JSON**
|
||||
|
||||
```powershell
|
||||
$top = Get-Content -Raw phases/index.json | ConvertFrom-Json
|
||||
$task = Get-Content -Raw phases/linear-static-3d-euler-beam/index.json | ConvertFrom-Json
|
||||
if (($top.phases | Where-Object dir -eq 'linear-static-3d-euler-beam').status -ne 'pending') { throw 'Top-level phase registration is invalid' }
|
||||
if ($task.project -ne 'FESA Structural Solver') { throw 'Project name mismatch' }
|
||||
if ($task.phase -ne 'linear-static-3d-euler-beam') { throw 'Phase name mismatch' }
|
||||
if ($task.steps.Count -ne 29) { throw 'Step count mismatch' }
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Check step/file correspondence and required sections**
|
||||
|
||||
```powershell
|
||||
$task.steps | ForEach-Object {
|
||||
$path = "phases/linear-static-3d-euler-beam/step$($_.step).md"
|
||||
if (-not (Test-Path $path)) { throw "Missing $path" }
|
||||
if ($_.status -ne 'pending') { throw "Non-pending step $($_.step)" }
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Scan for placeholders and whitespace errors**
|
||||
|
||||
```powershell
|
||||
$markers = @(('T' + 'BD'), ('T' + 'ODO'), ('FIX' + 'ME'), ('PLACE' + 'HOLDER'),
|
||||
('implement' + ' later'), ('Similar' + ' to Task'))
|
||||
$unfinished = rg -n ($markers -join '|') `
|
||||
docs/superpowers/plans/2026-08-09-linear-static-3d-euler-beam-harness-phase.md `
|
||||
phases/linear-static-3d-euler-beam
|
||||
if ($LASTEXITCODE -eq 0) { throw "Unfinished marker found:`n$unfinished" }
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Expected: no placeholder matches and no whitespace errors. CRLF conversion warnings without whitespace error lines are acceptable.
|
||||
|
||||
- [ ] **Step 4: Confirm reference artifacts are untouched**
|
||||
|
||||
```powershell
|
||||
git diff --name-only -- reference/
|
||||
```
|
||||
|
||||
Expected: no output.
|
||||
|
||||
- [ ] **Step 5: Execution handoff**
|
||||
|
||||
After the phase-construction files and existing documentation edits are reviewed and committed, execute from a clean worktree:
|
||||
|
||||
```powershell
|
||||
python scripts/execute.py linear-static-3d-euler-beam
|
||||
```
|
||||
|
||||
Use `--push` only when remote publication is explicitly desired.
|
||||
@@ -0,0 +1,158 @@
|
||||
# FESA Core Documentation Extension Playbook Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** 미래 AI Agent가 FESA에 기능을 추가할 때 실제 해석 흐름, 소유권, CMake 설정, 수치 불변식과 검증 경계를 바로 찾을 수 있도록 핵심 문서를 보강한다.
|
||||
|
||||
**Architecture:** 같은 사실을 네 문서에 반복하지 않고 문서별 책임을 분리한다. AGENTS는 프로젝트 배경·목적·핵심 개발 원칙, PRD는 사용자 관점의 제품 계약, ARCHITECTURE는 구현 구조·빌드 흐름·확장 지점, ADR은 장기 의사결정을 담당한다.
|
||||
|
||||
**Tech Stack:** Markdown, C++17/MSVC, CMake/CTest, Intel oneAPI MKL/TBB, HDF5, Abaqus `.inp` subset
|
||||
|
||||
## Global Constraints
|
||||
|
||||
- 수정 범위는 `AGENTS.md`, `docs/PRD.md`, `docs/ARCHITECTURE.md`, `docs/ADR.md`와 이 작업의 spec/plan 문서뿐이다.
|
||||
- phase 완료 이력, commit hash, 현재 테스트 총개수는 핵심 문서에 기록하지 않는다.
|
||||
- 승인되지 않은 Abaqus keyword와 해석 기능을 지원하는 것처럼 서술하지 않는다.
|
||||
- project hook과 Harness는 실행하지 않는다.
|
||||
- production, test, CMake, reference artifact는 수정하지 않는다.
|
||||
- direct 검증은 `git diff --check`와 문서·코드·CMake 사이의 정적 대조만 사용한다.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: 프로젝트 배경과 핵심 개발 지침 보강
|
||||
|
||||
**Files:**
|
||||
- Modify: `AGENTS.md`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: root CMake options, normalized dependency targets, `Analysis::run()` lifecycle, public dependency boundaries
|
||||
- Produces: FESA의 목적과 개발 판단 기준, 문서 탐색 순서, 최소 검증 진입점
|
||||
|
||||
- [x] **Step 1: 프로젝트 목적과 문서 역할을 선명하게 한다**
|
||||
|
||||
FESA가 검증 가능한 구조해석 솔버라는 점, full Abaqus clone이 아니라 승인된 feature contract를 누적하는 프로젝트라는 점, PRD/ARCHITECTURE/ADR와 기능별 계약의 역할을 기록한다.
|
||||
|
||||
- [x] **Step 2: 개발 시 훼손하면 안 되는 핵심 원칙을 추가한다**
|
||||
|
||||
물리·수치 계약 우선, stable identity, 명시적 소유권, 결정론성, backend isolation, failure atomicity, 공식 HDF5와 read-only reference 원칙을 상위 수준 지침으로 추가한다. 상세 lifecycle은 ARCHITECTURE로 연결한다.
|
||||
|
||||
- [x] **Step 3: 기능 확장 판단 기준을 추가한다**
|
||||
|
||||
입력 계약, semantic model, kernel/assembly, solve/recovery, HDF5/reference/physics evidence가 함께 변경되어야 함을 명시한다.
|
||||
|
||||
- [x] **Step 4: 최소 검증 진입점의 부정확한 예제를 정리한다**
|
||||
|
||||
`FESA_GTEST_SOURCE_DIR`가 빠진 configure와 실제 target이 아닌 `MyProject.sln` 예제를 제거한다. 상세 package/runtime 설명은 ARCHITECTURE로 연결한다.
|
||||
|
||||
- [x] **Step 5: 최소 build 명칭을 실제 CMake 옵션과 대조한다**
|
||||
|
||||
Run: `rg -n "FESA_GTEST_SOURCE_DIR|MKL_DIR|TBB_DIR|HDF5_DIR|Fesa::MKL|Fesa::TBB|Fesa::HDF5" CMakeLists.txt cmake/FesaDependencies.cmake src/fesa/CMakeLists.txt tests/CMakeLists.txt AGENTS.md`
|
||||
|
||||
Expected: AGENTS의 변수와 target 이름이 실제 CMake 정의와 일치한다.
|
||||
|
||||
### Task 2: 제품 계약과 기능 정의 보강
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/PRD.md`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: 승인된 V0 input/output/diagnostic 범위
|
||||
- Produces: 사용자 관점 end-to-end 흐름과 신규 기능의 완료 정의
|
||||
|
||||
- [x] **Step 1: 제품 흐름을 입력→해석→HDF5→검증으로 명확히 한다**
|
||||
|
||||
Syntax parse, semantic validation, linear solve, recovery, mandatory HDF5, optional reference comparison의 사용자 관찰 가능 결과를 기록한다.
|
||||
|
||||
- [x] **Step 2: 현재 구현과 장기 방향을 구분한다**
|
||||
|
||||
현재 concrete V0 model과 backend polymorphism을 정확히 기술하고, runtime-polymorphic element/material 확장은 미래 방향으로 표시한다.
|
||||
|
||||
- [x] **Step 3: 신규 제품 기능의 Definition of Done을 추가한다**
|
||||
|
||||
입력 노출, semantic mapping, solver lifecycle, result schema, diagnostics, unit/integration/reference/physics evidence가 모두 있어야 제품 기능으로 간주한다고 명시한다.
|
||||
|
||||
### Task 3: 실제 아키텍처와 확장 지점 보강
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/ARCHITECTURE.md`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: `src/fesa`와 `tests`의 실제 target/module graph
|
||||
- Produces: ownership/lifetime, 8-stage lifecycle, CMake/runtime graph, extension playbook
|
||||
|
||||
- [x] **Step 1: directory/target 설명에서 구현과 계획을 구분한다**
|
||||
|
||||
현재 존재하는 static solver library, CLI, unit/integration/reference test target을 명시하고 계획된 디렉터리는 계획이라고 표시한다.
|
||||
|
||||
- [x] **Step 2: 소유권과 8단계 실행 흐름을 표로 추가한다**
|
||||
|
||||
각 단계의 입력, 출력, 소유 객체, 실패 범주와 순서 불변식을 기록한다.
|
||||
|
||||
- [x] **Step 3: CMake dependency와 Windows runtime staging을 설명한다**
|
||||
|
||||
normalized `Fesa::*` targets, shared HDF5 preference, private product linkage, CLI/test executable 옆 runtime DLL staging을 기록한다.
|
||||
|
||||
- [x] **Step 4: 기능 유형별 확장 플레이북을 추가한다**
|
||||
|
||||
element, load/constraint, analysis procedure, backend, output/reference quantity별 변경 지점과 금지되는 shortcut을 기록한다.
|
||||
|
||||
### Task 4: 장기 아키텍처 결정을 추가한다
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/ADR.md`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: 실제 CMake/runtime, deterministic assembly, essential constraints, layered verification behavior
|
||||
- Produces: 향후 구현이 지켜야 할 결정과 trade-off
|
||||
|
||||
- [x] **Step 1: 외부 의존성 정규화와 runtime closure ADR을 추가한다**
|
||||
|
||||
Vendor target 이름을 `Fesa::*`로 정규화하고 public header에는 노출하지 않으며 Windows executable runtime closure를 staging하는 결정을 기록한다.
|
||||
|
||||
- [x] **Step 2: 결정론성과 failure atomicity ADR을 추가한다**
|
||||
|
||||
Stable COO/reduction, state/output candidate-commit, atomic HDF5 finalization이 성능 옵션이 아니라 correctness contract임을 기록한다.
|
||||
|
||||
- [x] **Step 3: 구속 제거와 full residual ADR을 추가한다**
|
||||
|
||||
`Kff`, `Ff-Kfc*dc`, valid 0x0 system, reaction=`Kd-F`의 결정과 penalty/MPC 비범위를 기록한다.
|
||||
|
||||
- [x] **Step 4: 계층형 검증 ADR을 추가한다**
|
||||
|
||||
Kernel 존재와 parser/CLI 노출을 구분하고 unit→integration→reference→physics gate가 각기 다른 오류를 검출한다는 결정을 기록한다.
|
||||
|
||||
### Task 5: 문서 전용 정적 검증
|
||||
|
||||
**Files:**
|
||||
- Verify: `AGENTS.md`
|
||||
- Verify: `docs/PRD.md`
|
||||
- Verify: `docs/ARCHITECTURE.md`
|
||||
- Verify: `docs/ADR.md`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: Tasks 1–4의 문서 변경
|
||||
- Produces: 문서 범위·형식·사실 일치 evidence
|
||||
|
||||
- [x] **Step 1: 변경 범위를 확인한다**
|
||||
|
||||
Run: `git status --short`
|
||||
|
||||
Expected: production, test, CMake, reference 경로 변경이 없다.
|
||||
|
||||
- [x] **Step 2: whitespace 오류를 확인한다**
|
||||
|
||||
Run: `git diff --check`
|
||||
|
||||
Expected: exit 0.
|
||||
|
||||
- [x] **Step 3: stale 예제와 승인되지 않은 범위 암시를 검사한다**
|
||||
|
||||
Run: `rg -n "MyProject|full Abaqus compatibility|B31.*지원|현재 테스트.*[0-9]+" AGENTS.md docs/PRD.md docs/ARCHITECTURE.md docs/ADR.md`
|
||||
|
||||
Expected: stale solution 예제와 지원 범위 확대 문구가 없다. Full compatibility/B31은 거부 또는 비범위 문맥에서만 나타난다.
|
||||
|
||||
- [x] **Step 4: 명령·target·lifecycle 이름을 원본과 대조한다**
|
||||
|
||||
Run: `rg -n "FESA_GTEST_SOURCE_DIR|Fesa::MKL|Fesa::TBB|Fesa::HDF5|assembleAndPartitionStiffness|assembleLoadsAndEffectiveRhs|recoverAndWriteResults" AGENTS.md docs/ARCHITECTURE.md cmake/FesaDependencies.cmake src/fesa/analysis/linear_static_analysis.cpp`
|
||||
|
||||
Expected: 문서의 명칭과 구현/CMake 명칭이 일치한다.
|
||||
@@ -0,0 +1,619 @@
|
||||
# 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`
|
||||
- amended_on: `2026-08-09`
|
||||
- source_formulation: `docs/formulations/3d-isoparametric-euler-beam-formulation.md`
|
||||
- reference_baseline: `reference/cantilever beam/` from source commit `2b34d0b`
|
||||
- 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
|
||||
- formulation의 constant local line-load equivalent nodal vector kernel
|
||||
- nonzero prescribed displacement를 포함한 자유/구속 partition
|
||||
- deterministic COO-to-CSR sparse assembly
|
||||
- MKL PARDISO factorization과 substitution의 분리
|
||||
- oneTBB 기반 element-local 계산
|
||||
- 변위, 반력, equilibrium end action, section resultant, axial `S11` 출력
|
||||
- 승인된 `reference/cantilever beam/` B33 bundle의 변위·반력·section resultant 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` 입력과 Domain load object 생성
|
||||
- 기하·재료비선형, 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` | `docs/formulations/3d-isoparametric-euler-beam-formulation.md` |
|
||||
| 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 ConstantLocalLineLoad& load) 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`을 구분한다. `localEquivalentLoad`는 정식화의 constant local line-load vector를
|
||||
검증하기 위한 element kernel이지만 V0 `.inp` parser는 `*DLOAD`를 생성하지 않으므로
|
||||
CLI 해석에서는 호출되지 않는다.
|
||||
|
||||
### 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으로
|
||||
반환한다. V0는 constrained `Kff`를 real symmetric positive definite matrix로
|
||||
factorize하며, positive-definite factorization 실패를 unconstrained, singular 또는
|
||||
invalid model 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은 `**`로 시작한다.
|
||||
|
||||
`*BOUNDARY`는 `target, first_dof, last_dof[, value]` 형식만 지원하고 DOF 범위는
|
||||
1부터 6까지다. value가 없으면 0으로 해석한다. `*CLOAD`는
|
||||
`target, dof, magnitude` 형식만 지원하고 DOF 범위는 1부터 6까지다. target은 source
|
||||
node label 또는 node set이며 assembly-level set의 `INSTANCE` parameter를 해석한다.
|
||||
|
||||
### 6.2 General beam section mapping
|
||||
|
||||
`*BEAM GENERAL SECTION, SECTION=GENERAL`의 data는
|
||||
`A, I11, I12, I22, J` 순서로 읽는다.
|
||||
|
||||
- `MATERIAL` parameter는 필수이며 해당 `*MATERIAL`의 isotropic `*ELASTIC` data는
|
||||
정확히 `E, nu`를 제공해야 한다.
|
||||
- `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`는 양수여야 한다.
|
||||
- `coordinate_scale = max(1, norm(X1), norm(X2))`에 대해
|
||||
`L > 1e-12 * coordinate_scale`이어야 한다.
|
||||
- guide vector는 0이 아니어야 하며
|
||||
`norm(a_perp) > 1e-12 * max(1, norm(a))`이어야 한다.
|
||||
|
||||
이 축 계약은 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` 오류로 거부한다.
|
||||
`reference/cantilever beam/cantilever beam.inp`는 source commit `2b34d0b`에서
|
||||
`TYPE=B33`으로 생성된 승인 reference input이다. Reference artifact check는 비교 전에
|
||||
이 element type을 다시 확인하며 B31로 되돌아간 입력이나 결과를 허용하지 않는다.
|
||||
|
||||
이 결정은 [[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` |
|
||||
|
||||
승인된 B33 reference의 `cantilever beam elemental forces.csv`는 element label 없이
|
||||
`Frame`, `Part Instance Name`, `Node Label`, `SF1`, `SM1`, `SM2`, `SM3`을 기록한다.
|
||||
따라서 이 파일의 comparison은 다음 규칙을 사용한다.
|
||||
|
||||
- Reference row key는 `(Step-1, frame 0, instance name, source node label, component)`다.
|
||||
단일 step invariant에 따라 CSV의 `Increment 1: Step Time = 1.000`을
|
||||
`(Step-1, frame 0)`으로 정규화한다.
|
||||
- FESA endpoint section resultant를 동일한 section-cut 부호로 변환한 뒤 source node
|
||||
station으로 정규화한다. Interior node의 두 인접 element endpoint 값은 먼저 승인된
|
||||
tolerance 안에서 서로 일치해야 한다. 불일치는 평균으로 숨기지 않고
|
||||
`tolerance-failure`로 보고한다.
|
||||
- Interior endpoint가 일치하면 stable internal element ID가 작은 endpoint를 대표 row로
|
||||
선택한다. Boundary node는 하나의 endpoint를 사용한다.
|
||||
- 이 bundle에서 비교하는 mapping은 `SF1 -> N`, `SM1 -> My`, `SM2 -> Mz`,
|
||||
`SM3 -> T`다. CSV에 없는 `SF2`와 `SF3`는 reference comparison 대상이 아니며,
|
||||
FESA equilibrium end action의 transverse force는 unit/analytical test와 physics sanity로
|
||||
검증한다.
|
||||
|
||||
### 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/<step-name>/frames/0/nodal/displacement
|
||||
/steps/<step-name>/frames/0/nodal/reaction
|
||||
/steps/<step-name>/frames/0/element/end_force_local
|
||||
/steps/<step-name>/frames/0/element/section_resultant
|
||||
/steps/<step-name>/frames/0/element/generalized_strain
|
||||
/steps/<step-name>/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을 함께 저장한다.
|
||||
|
||||
Abaqus `.inp` 자체에는 단위 선언이 없으므로 일반 solver run의 unit-system label은
|
||||
`user-consistent-unspecified`로 기록하고 solver가 입력 파일만 보고 SI를 추론하지
|
||||
않는다. 승인된 cantilever B33 reference에 한해서는 이 설계와 후속 Reference Model
|
||||
Contract가 입력 수치의 단위계를 SI로 선언하고, reference verification이 동일한 입력으로
|
||||
생성된 FESA 결과에 그 외부 단위 계약을 적용한다. 새 reference model은 별도
|
||||
`metadata.json`에 단위계를 선언해야 한다.
|
||||
|
||||
- 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 <model.inp> --output <results.h5>
|
||||
```
|
||||
|
||||
`--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
|
||||
- 승인된 B33 CSV header/Frame 정규화, node-station matching, interior endpoint 일치 검사
|
||||
- zero 및 near-zero reference row를 포함한 component-scale 혼합 허용오차 검사
|
||||
|
||||
### 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 | component-scale relative `1e-6` |
|
||||
| SI displacement and rotation absolute floor | `1e-9` |
|
||||
| SI force and moment absolute floor | `1e-3` |
|
||||
|
||||
Reference row 판정은 zero-reference에서도 의미가 있도록 component-scale 혼합
|
||||
허용오차를 사용한다. 같은 model, step/frame, quantity, component의 Abaqus reference
|
||||
rows에 대해 다음 값을 계산한다.
|
||||
|
||||
```text
|
||||
reference_scale = max(abs(reference_value_i))
|
||||
row_tolerance = absolute_floor + 1e-6 * reference_scale
|
||||
row_pass = abs(fesa_value_i - reference_value_i) <= row_tolerance
|
||||
```
|
||||
|
||||
- Scale은 displacement, rotation, force, moment 및 각 component를 섞지 않는다.
|
||||
- Scale은 read-only Abaqus reference 값만 사용하며 FESA 결과로 조정하지 않는다.
|
||||
- Scale이 0이면 absolute floor만 적용한다.
|
||||
- 모든 row를 개별 판정하며 reference 값을 zero-clamp하거나 row를 제거하지 않는다.
|
||||
- Missing/extra row, nonfinite value, schema 또는 identity mismatch는 tolerance 계산 전에
|
||||
실패한다.
|
||||
- Report는 max absolute error, component-scale normalized error, RMS error, norm error,
|
||||
worst row/component를 기록한다.
|
||||
|
||||
현재 B33 `SM1`의 reference scale은 `1.0e7`이고 moment row tolerance는
|
||||
`1.0e-3 + 1.0e-6 * 1.0e7 = 10.001`이다. 자유단 reference residue `-1.56e-2`와
|
||||
FESA의 이론적 zero 사이 오차 `1.56e-2`는 이 기준을 통과하지만, 예를 들어 `100`의
|
||||
자유단 moment 오차는 실패한다.
|
||||
|
||||
승인된 cantilever bundle은 SI absolute floor를 사용한다. 이후 SI가 아닌 reference를
|
||||
추가하면 quantity별 absolute floor를 해당 단위로 변환하고 변환 근거를 metadata와
|
||||
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/`을 V0의 승인된 Abaqus B33 reference baseline으로 사용한다.
|
||||
논리 model ID는 `cantilever-beam-b33`, reference schema ID는
|
||||
`abaqus-cae-report-csv-v0`이며 source baseline은 commit `2b34d0b`이다. Input header가
|
||||
기록한 generator는 `Abaqus/CAE Learning Edition 2024`다. 모델은 SI 단위계, global
|
||||
Cartesian nodal output, beam local section-force output, `Step-1`, increment 1,
|
||||
step time 1.0 계약으로 해석한다.
|
||||
|
||||
| Purpose | Approved artifact |
|
||||
| --- | --- |
|
||||
| analysis input | `reference/cantilever beam/cantilever beam.inp` |
|
||||
| displacement | `reference/cantilever beam/cantilever beam displacements.csv` |
|
||||
| reaction | `reference/cantilever beam/cantilever beam reactions.csv` |
|
||||
| section resultant | `reference/cantilever beam/cantilever beam elemental forces.csv` |
|
||||
| stress | N/A: beam stress reference comparison은 승인 범위에서 제외 |
|
||||
|
||||
이 기존 bundle의 space-containing filename과 CAE report header는 승인된 legacy alias로
|
||||
그대로 지원하며 reference artifact를 rename하거나 rewrite하지 않는다. `metadata.json`과
|
||||
`README.md`는 이 baseline에 한해서 N/A다. 이 설계와 Step 5의 Reference Model Contract가
|
||||
대신 model ID, provenance, units, coordinate system, schema, file inventory, tolerance와
|
||||
stress N/A 사유를 기록한다. 이후 추가하는 reference model에는 canonical artifact 이름,
|
||||
`metadata.json`, `README.md`를 요구한다.
|
||||
|
||||
Reference verification은 build/test gate 통과 후 승인 input으로 FESA `results.h5`를
|
||||
생성하고 다음을 직접 비교한다.
|
||||
|
||||
- nodal displacement: CSV `U1/U2/U3/UR1/UR2/UR3`과 HDF5 displacement
|
||||
- nodal reaction: CSV `RF1/RF2/RF3/RM1/RM2/RM3`과 HDF5 reaction
|
||||
- section resultant: CSV `SF1/SM1/SM2/SM3`과 node station으로 정규화한 HDF5
|
||||
section resultant
|
||||
- stress: 명시적 N/A
|
||||
|
||||
Artifact check는 네 파일의 존재, B33 element type, expected header, 유일한 row key,
|
||||
finite value를 확인한다. 하나라도 충족하지 않으면 `needs-reference-artifacts` 또는
|
||||
`schema-mismatch`로 분류하고 comparison을 시작하지 않는다. 현재 baseline은
|
||||
`metadata.json` 또는 `README.md` 부재만으로 차단하지 않는다.
|
||||
|
||||
Agent와 Harness는 Abaqus를 실행하거나 reference artifact를 생성·수정하지 않는다.
|
||||
|
||||
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가 승인된 cantilever B33 reference CSV와 component-scale
|
||||
혼합 tolerance 안에서 일치한다.
|
||||
6. Beam stress reference comparison은 명시적 N/A이고 stress output schema/test는
|
||||
통과한다.
|
||||
7. Physics sanity가 pass한다.
|
||||
8. Release report에 지원 subset과 모든 V0 제한사항이 기록된다.
|
||||
@@ -0,0 +1,46 @@
|
||||
# FESA Core Documentation Extension Playbook Design
|
||||
|
||||
## 목적
|
||||
|
||||
`AGENTS.md`, `docs/PRD.md`, `docs/ARCHITECTURE.md`, `docs/ADR.md`를 현재 구현에 맞게 보강한다. 작업 완료 이력이나 일시적인 테스트 개수 대신, 다음 기능을 추가할 AI Agent가 바로 사용할 수 있는 해석 흐름, 소유권, 빌드 설정, 수치 불변식, 확장 경계를 기록한다.
|
||||
|
||||
## 문서별 책임
|
||||
|
||||
- `AGENTS.md`: FESA의 배경과 목적, 전체 프로젝트에서 훼손하면 안 되는 개발 원칙, 문서 탐색 순서와 기능 확장 시의 판단 기준을 제공한다. 상세 구현·빌드 매뉴얼의 대체물이 아니다.
|
||||
- `docs/PRD.md`: 사용자가 관찰하는 제품 흐름, 구현된 V0 지원 경계, 신규 기능이 제품 기능으로 인정되기 위한 조건을 정의한다.
|
||||
- `docs/ARCHITECTURE.md`: 실제 모듈과 target, 객체 소유권, 8단계 해석 수명주기, CMake dependency/runtime graph, 기능 유형별 확장 지점을 설명한다.
|
||||
- `docs/ADR.md`: 정규화된 외부 의존성, 결정론적·failure-atomic 경계, 구속 제거와 full residual, 계층형 검증을 장기 결정으로 남긴다.
|
||||
|
||||
## 기록할 구현 사실
|
||||
|
||||
1. 입력은 syntax parse와 semantic mapping을 거쳐 불변 `Domain`이 되고, `AnalysisModel`은 이를 복사하지 않는 view이다.
|
||||
2. `Analysis::run()`은 initialize, model view, DOF/pattern, stiffness/partition, factorization, load/effective RHS, solve/reconstruct, recovery/write 순서를 고정한다.
|
||||
3. `DofManager`가 full/free/constrained numbering과 0-based CSR pattern을 단독 소유하며, Node/Element에는 equation ID를 저장하지 않는다.
|
||||
4. assembly는 element-local buffer, stable COO order, serial ordered reduction으로 결정론적 CSR을 만든다. global sparse storage를 병렬로 직접 갱신하지 않는다.
|
||||
5. essential constraints는 full K를 `Kff/Kfc/Kcf/Kcc`로 분할하고 `Ff - Kfc*dc`를 푼다. fully constrained 0x0 `Kff`도 유효하다.
|
||||
6. reaction/equilibrium evidence는 full residual `K*d - F`를 사용한다. constrained 성분은 physical reaction이고 free 성분은 equilibrium residual이다.
|
||||
7. 외부 API는 `LinearSolver`, `ParallelFor`, `ResultsWriter`와 math adapter 뒤에 둔다. public header에 MKL/TBB/HDF5/Win32 type을 노출하지 않는다.
|
||||
8. HDF5 writer는 같은 directory의 temporary file, checked close/reopen self-check, atomic finalization을 사용한다.
|
||||
9. element end action, section resultant, generalized result, stress identity와 sign convention을 섞지 않으며 station mismatch를 평균내지 않는다.
|
||||
|
||||
## 빌드 및 검증 설계
|
||||
|
||||
- direct build는 Visual Studio generator, x64, Debug를 명시한다. 상세 target graph와 runtime 설명은 `docs/ARCHITECTURE.md`에 두고, `AGENTS.md`에는 최소 검증 진입점만 둔다.
|
||||
- `FESA_GTEST_SOURCE_DIR`는 필수 local source path이다. `MKL_DIR`, `TBB_DIR`, `HDF5_DIR`는 설치 환경에서 package discovery가 되지 않으면 명시한다.
|
||||
- production은 `Fesa::MKL`, `Fesa::TBB`, `Fesa::HDF5` normalized target만 사용한다.
|
||||
- Windows에서는 CLI와 GoogleTest discovery 전에 MKL/TBB/HDF5 및 transitive oneAPI runtime DLL이 executable 옆에 staging되어야 한다.
|
||||
- 문서 작업 검증은 project hook/Harness를 실행하지 않고 `git diff --check`, 링크·경로·명령·target 이름의 정적 대조로 제한한다.
|
||||
|
||||
## 기능 확장 플레이북
|
||||
|
||||
- 새 element: 요구조건/정식화/I/O mapping을 먼저 고정하고 kernel, model mapping, DOF pattern, assembly, recovery, output, reference/physics evidence를 함께 확장한다.
|
||||
- 새 load/constraint: semantic target identity, stable source order, full-space vector/matrix, partition/effective RHS, diagnostics와 output을 함께 검토한다.
|
||||
- 새 analysis procedure: 기존 V0 lifecycle을 조용히 변경하지 않고 별도 orchestration/state/equation 계약과 gate를 정의한다.
|
||||
- 새 numerical backend: public interface를 유지하고 adapter 내부에만 vendor API, lifecycle, runtime dependency를 격리한다.
|
||||
- 새 output/reference quantity: mandatory HDF5 schema, units/coordinates/identity, recovery sign, comparison projection과 tolerance를 동시에 정의한다.
|
||||
|
||||
## 범위 제한
|
||||
|
||||
- phase 완료 이력, commit hash, 현재 테스트 총개수 같은 일시적 사실을 핵심 문서에 넣지 않는다.
|
||||
- full Abaqus compatibility, B31 지원, transform/nested assembly, distributed-load parser exposure 등 승인되지 않은 범위를 암시하지 않는다.
|
||||
- 문서 보강 외 production, test, CMake, reference artifact를 수정하지 않는다.
|
||||
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/model/domain.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
// Provides the sole active-step view while the referenced Domain retains all
|
||||
// semantic ownership and must outlive this object.
|
||||
class AnalysisModel {
|
||||
public:
|
||||
static Result<AnalysisModel> create(const Domain& domain);
|
||||
|
||||
const Domain& domain() const noexcept;
|
||||
const StaticStepDefinition& step() const noexcept;
|
||||
const std::vector<EntityIndex>& activeElements() const noexcept;
|
||||
const std::vector<EntityIndex>& activeMaterials() const noexcept;
|
||||
const std::vector<EntityIndex>& activeSections() const noexcept;
|
||||
const std::vector<EntityIndex>& activeBoundaryConditions() const noexcept;
|
||||
const std::vector<EntityIndex>& activeLoads() const noexcept;
|
||||
|
||||
private:
|
||||
explicit AnalysisModel(const Domain& domain);
|
||||
|
||||
const Domain* domain_;
|
||||
std::vector<EntityIndex> activeElements_;
|
||||
std::vector<EntityIndex> activeMaterials_;
|
||||
std::vector<EntityIndex> activeSections_;
|
||||
std::vector<EntityIndex> activeBoundaryConditions_;
|
||||
std::vector<EntityIndex> activeLoads_;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/fem/dof_manager.hpp"
|
||||
#include "fesa/math/vector.hpp"
|
||||
#include "fesa/results/result_records.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
// Owns only the mutable quantities required by the V0 linear-static frame.
|
||||
class AnalysisState {
|
||||
public:
|
||||
static AnalysisState create(
|
||||
const DofManager& dofs, StepFrameIdentity identity);
|
||||
|
||||
Vector& displacement() noexcept;
|
||||
const Vector& displacement() const noexcept;
|
||||
Vector& externalForce() noexcept;
|
||||
const Vector& externalForce() const noexcept;
|
||||
Vector& internalForce() noexcept;
|
||||
const Vector& internalForce() const noexcept;
|
||||
Vector& residual() noexcept;
|
||||
const Vector& residual() const noexcept;
|
||||
Vector& reaction() noexcept;
|
||||
const Vector& reaction() const noexcept;
|
||||
const StepFrameIdentity& identity() const noexcept;
|
||||
std::vector<EndpointResultRow>& endpointResults() noexcept;
|
||||
const std::vector<EndpointResultRow>& endpointResults() const noexcept;
|
||||
std::vector<GaussResultRow>& gaussResults() noexcept;
|
||||
const std::vector<GaussResultRow>& gaussResults() const noexcept;
|
||||
std::vector<StressS11Row>& stressResults() noexcept;
|
||||
const std::vector<StressS11Row>& stressResults() const noexcept;
|
||||
|
||||
private:
|
||||
AnalysisState(std::size_t fullDofCount, StepFrameIdentity identity);
|
||||
|
||||
StepFrameIdentity identity_;
|
||||
Vector displacement_;
|
||||
Vector externalForce_;
|
||||
Vector internalForce_;
|
||||
Vector residual_;
|
||||
// Reactions retain full-index space so free residual components remain visible.
|
||||
Vector reaction_;
|
||||
// Recovery appends rows in stable element/location order.
|
||||
std::vector<EndpointResultRow> endpointResults_;
|
||||
std::vector<GaussResultRow> gaussResults_;
|
||||
std::vector<StressS11Row> stressResults_;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/analysis/analysis_model.hpp"
|
||||
#include "fesa/analysis/analysis_state.hpp"
|
||||
#include "fesa/constraints/essential_constraints.hpp"
|
||||
#include "fesa/core/status.hpp"
|
||||
#include "fesa/fem/dof_manager.hpp"
|
||||
#include "fesa/math/sparse_matrix.hpp"
|
||||
#include "fesa/math/vector.hpp"
|
||||
#include "fesa/model/domain.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
class LinearSolver;
|
||||
class ParallelFor;
|
||||
class ResultsWriter;
|
||||
|
||||
struct AnalysisRequest {
|
||||
std::filesystem::path inputPath;
|
||||
std::filesystem::path outputPath;
|
||||
};
|
||||
|
||||
// Fixes the public V0 lifecycle while leaving each analysis procedure to
|
||||
// implement its approved stages.
|
||||
class Analysis {
|
||||
public:
|
||||
virtual ~Analysis() = default;
|
||||
Status run(const AnalysisRequest& request);
|
||||
|
||||
protected:
|
||||
virtual Status initialize(const AnalysisRequest& request) = 0;
|
||||
virtual Status buildAnalysisModel() = 0;
|
||||
virtual Status buildDofMapAndSparsePattern() = 0;
|
||||
virtual Status assembleAndPartitionStiffness() = 0;
|
||||
virtual Status factorize() = 0;
|
||||
virtual Status assembleLoadsAndEffectiveRhs() = 0;
|
||||
virtual Status substituteAndReconstruct() = 0;
|
||||
virtual Status recoverAndWriteResults() = 0;
|
||||
};
|
||||
|
||||
// Orchestrates the single-step B33 procedure through injected backend
|
||||
// boundaries so factorization and substitution remain independently visible.
|
||||
class LinearStaticAnalysis final : public Analysis {
|
||||
public:
|
||||
LinearStaticAnalysis(const ParallelFor& parallelFor,
|
||||
LinearSolver& linearSolver,
|
||||
ResultsWriter& resultsWriter);
|
||||
|
||||
protected:
|
||||
Status initialize(const AnalysisRequest& request) override;
|
||||
Status buildAnalysisModel() override;
|
||||
Status buildDofMapAndSparsePattern() override;
|
||||
Status assembleAndPartitionStiffness() override;
|
||||
Status factorize() override;
|
||||
Status assembleLoadsAndEffectiveRhs() override;
|
||||
Status substituteAndReconstruct() override;
|
||||
Status recoverAndWriteResults() override;
|
||||
|
||||
private:
|
||||
const ParallelFor& parallelFor_;
|
||||
LinearSolver& linearSolver_;
|
||||
ResultsWriter& resultsWriter_;
|
||||
AnalysisRequest request_;
|
||||
std::unique_ptr<Domain> domain_;
|
||||
std::unique_ptr<AnalysisModel> model_;
|
||||
std::unique_ptr<DofManager> dofs_;
|
||||
std::unique_ptr<AnalysisState> state_;
|
||||
std::unique_ptr<SparseMatrix> fullStiffness_;
|
||||
std::unique_ptr<PartitionedStiffness> partitionedStiffness_;
|
||||
std::unique_ptr<Vector> effectiveRhs_;
|
||||
std::vector<Diagnostic> diagnostics_;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
// Owns the argv-independent command-line contract and stable process codes.
|
||||
class FesaApplication {
|
||||
public:
|
||||
int run(const std::vector<std::string>& arguments);
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/analysis/analysis_model.hpp"
|
||||
#include "fesa/fem/dof_manager.hpp"
|
||||
#include "fesa/math/sparse_matrix.hpp"
|
||||
#include "fesa/math/vector.hpp"
|
||||
|
||||
namespace fesa {
|
||||
|
||||
// Assembles only semantic nodal CLOAD records and forms the eliminated free
|
||||
// right-hand side; stiffness factorization remains an analysis responsibility.
|
||||
class LoadAssembler {
|
||||
public:
|
||||
static Result<Vector> assembleFullNodalLoad(
|
||||
const AnalysisModel& model,
|
||||
const DofManager& dofs);
|
||||
static Result<Vector> effectiveFreeRhs(
|
||||
const Vector& fullLoad,
|
||||
const SparseMatrix& kfc,
|
||||
const Vector& prescribedValues,
|
||||
const DofManager& dofs);
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
// Executes independent index-addressed work without exposing the backend.
|
||||
// Callers own output storage and must confine each invocation to its index.
|
||||
class ParallelFor {
|
||||
public:
|
||||
virtual ~ParallelFor() = default;
|
||||
virtual void execute(
|
||||
std::size_t count,
|
||||
const std::function<void(std::size_t)>& body) const = 0;
|
||||
};
|
||||
|
||||
class SerialParallelFor final : public ParallelFor {
|
||||
public:
|
||||
void execute(
|
||||
std::size_t count,
|
||||
const std::function<void(std::size_t)>& body) const override;
|
||||
};
|
||||
|
||||
class TbbParallelFor final : public ParallelFor {
|
||||
public:
|
||||
void execute(
|
||||
std::size_t count,
|
||||
const std::function<void(std::size_t)>& body) const override;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/core/status.hpp"
|
||||
#include "fesa/math/sparse_matrix.hpp"
|
||||
|
||||
namespace fesa {
|
||||
|
||||
class AnalysisModel;
|
||||
class DofManager;
|
||||
class ParallelFor;
|
||||
|
||||
class SparseAssembler {
|
||||
public:
|
||||
static Result<SparseMatrix> assembleStiffness(
|
||||
const AnalysisModel& model,
|
||||
const DofManager& dofs,
|
||||
const ParallelFor& parallelFor);
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
// Returns the stable solver version written to externally visible result metadata.
|
||||
std::string_view solverVersion() noexcept;
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/core/status.hpp"
|
||||
#include "fesa/math/sparse_matrix.hpp"
|
||||
#include "fesa/math/vector.hpp"
|
||||
|
||||
namespace fesa {
|
||||
|
||||
class DofManager;
|
||||
|
||||
struct PartitionedStiffness {
|
||||
SparseMatrix kff;
|
||||
SparseMatrix kfc;
|
||||
SparseMatrix kcf;
|
||||
SparseMatrix kcc;
|
||||
};
|
||||
|
||||
// Applies the DofManager's stable elimination order without owning equation
|
||||
// numbering, load assembly, or a solver policy.
|
||||
class EssentialConstraints {
|
||||
public:
|
||||
static Result<PartitionedStiffness> partition(
|
||||
const SparseMatrix& full,
|
||||
const DofManager& dofs);
|
||||
static Vector gatherFree(const Vector& full, const DofManager& dofs);
|
||||
static Vector gatherConstrained(
|
||||
const Vector& full,
|
||||
const DofManager& dofs);
|
||||
static Vector reconstructFull(
|
||||
const Vector& freeValues,
|
||||
const Vector& constrainedValues,
|
||||
const DofManager& dofs);
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/core/source_identity.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
// Distinguishes recoverable warnings from errors that stop the current operation.
|
||||
enum class Severity {
|
||||
warning,
|
||||
error
|
||||
};
|
||||
|
||||
// Carries a structured, backend-independent diagnostic record.
|
||||
struct Diagnostic {
|
||||
Severity severity;
|
||||
std::string code;
|
||||
SourceLocation location;
|
||||
std::string keyword;
|
||||
std::string entityIdentity;
|
||||
std::string message;
|
||||
};
|
||||
|
||||
// Orders diagnostics by their externally visible source tuple while retaining
|
||||
// discovery order for records with identical keys.
|
||||
void sortDiagnostics(std::vector<Diagnostic>& diagnostics);
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
// Identifies the physical input location that produced a model item or diagnostic.
|
||||
struct SourceLocation {
|
||||
std::filesystem::path file;
|
||||
std::size_t line;
|
||||
};
|
||||
|
||||
// Preserves both semantic and raw-text forms of an input entity identity.
|
||||
struct SourceEntityId {
|
||||
std::string instanceName;
|
||||
std::int64_t sourceLabel;
|
||||
std::string sourceLabelText;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,94 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/core/diagnostic.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
// Maps a failure to the stable command-line exit-code classes defined by V0.
|
||||
enum class FailureCategory {
|
||||
input,
|
||||
model,
|
||||
solver,
|
||||
output
|
||||
};
|
||||
|
||||
// Transports success or structured diagnostics without exposing backend errors.
|
||||
class Status {
|
||||
public:
|
||||
static Status ok();
|
||||
static Status failure(std::vector<Diagnostic> diagnostics);
|
||||
static Status failure(
|
||||
FailureCategory category, std::vector<Diagnostic> diagnostics);
|
||||
|
||||
bool isOk() const noexcept;
|
||||
std::optional<FailureCategory> failureCategory() const noexcept;
|
||||
const std::vector<Diagnostic>& diagnostics() const noexcept;
|
||||
|
||||
private:
|
||||
Status(
|
||||
bool isOk,
|
||||
std::optional<FailureCategory> category,
|
||||
std::vector<Diagnostic> diagnostics);
|
||||
|
||||
bool isOk_;
|
||||
std::optional<FailureCategory> category_;
|
||||
std::vector<Diagnostic> diagnostics_;
|
||||
};
|
||||
|
||||
// Owns exactly one successful value or one failed Status.
|
||||
template<class T>
|
||||
class Result {
|
||||
public:
|
||||
static Result success(T value) {
|
||||
return Result{SuccessTag{}, std::move(value)};
|
||||
}
|
||||
|
||||
static Result failure(Status status) {
|
||||
if (status.isOk()) {
|
||||
throw std::invalid_argument{"A failed Result requires a failed Status."};
|
||||
}
|
||||
return Result{FailureTag{}, std::move(status)};
|
||||
}
|
||||
|
||||
bool hasValue() const noexcept {
|
||||
return value_.has_value();
|
||||
}
|
||||
|
||||
T& value() {
|
||||
if (!value_) {
|
||||
throw std::logic_error{"Result has no value."};
|
||||
}
|
||||
return *value_;
|
||||
}
|
||||
|
||||
const T& value() const {
|
||||
if (!value_) {
|
||||
throw std::logic_error{"Result has no value."};
|
||||
}
|
||||
return *value_;
|
||||
}
|
||||
|
||||
const Status& status() const noexcept {
|
||||
return status_;
|
||||
}
|
||||
|
||||
private:
|
||||
struct SuccessTag {};
|
||||
struct FailureTag {};
|
||||
|
||||
Result(SuccessTag, T value)
|
||||
: value_{std::move(value)}, status_{Status::ok()} {}
|
||||
|
||||
Result(FailureTag, Status status)
|
||||
: value_{std::nullopt}, status_{std::move(status)} {}
|
||||
|
||||
std::optional<T> value_;
|
||||
Status status_;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/core/status.hpp"
|
||||
#include "fesa/math/matrix.hpp"
|
||||
#include "fesa/math/vector.hpp"
|
||||
#include "fesa/model/model_types.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
struct ConstantLocalLineLoad {
|
||||
double px;
|
||||
double py;
|
||||
double pz;
|
||||
double mx;
|
||||
};
|
||||
|
||||
struct BeamStressPoint {
|
||||
int gaussPoint;
|
||||
std::size_t sectionPoint;
|
||||
double x1;
|
||||
double x2;
|
||||
double s11;
|
||||
std::string source;
|
||||
};
|
||||
|
||||
struct BeamRecovery {
|
||||
std::array<std::array<double, 6>, 2> equilibriumEndActions;
|
||||
std::array<std::array<double, 4>, 2> endpointSectionResultants;
|
||||
std::array<std::array<double, 4>, 2> gaussGeneralizedStrains;
|
||||
std::array<std::array<double, 4>, 2> gaussGeneralizedResultants;
|
||||
std::vector<BeamStressPoint> stressPoints;
|
||||
};
|
||||
|
||||
// Implements the approved two-node straight prismatic B33 Euler-Bernoulli
|
||||
// kernel. Equation numbering and element identity remain outside this type.
|
||||
class EulerBeam3D {
|
||||
public:
|
||||
static Result<EulerBeam3D> create(const Node& firstNode,
|
||||
const Node& secondNode,
|
||||
const GeneralBeamSection& section,
|
||||
const LinearElasticMaterial& material);
|
||||
Matrix localStiffness() const;
|
||||
Matrix globalStiffness() const;
|
||||
Vector localEquivalentLoad(const ConstantLocalLineLoad& load) const;
|
||||
BeamRecovery recover(const Vector& globalElementDisplacement) const;
|
||||
|
||||
private:
|
||||
EulerBeam3D(double length,
|
||||
double youngsModulus,
|
||||
double shearModulus,
|
||||
double area,
|
||||
double iy,
|
||||
double iz,
|
||||
double torsionalConstant,
|
||||
std::array<double, 9> rotation,
|
||||
std::vector<std::array<double, 2>> sectionPoints);
|
||||
|
||||
double length_;
|
||||
double youngsModulus_;
|
||||
double shearModulus_;
|
||||
double area_;
|
||||
double iy_;
|
||||
double iz_;
|
||||
double torsionalConstant_;
|
||||
std::array<double, 9> rotation_;
|
||||
std::vector<std::array<double, 2>> sectionPoints_;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/analysis/analysis_model.hpp"
|
||||
#include "fesa/math/vector.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
enum class DofComponent : std::uint8_t {
|
||||
ux,
|
||||
uy,
|
||||
uz,
|
||||
urx,
|
||||
ury,
|
||||
urz
|
||||
};
|
||||
|
||||
struct SparsePattern {
|
||||
std::vector<std::size_t> rowOffsets;
|
||||
std::vector<std::size_t> columnIndices;
|
||||
};
|
||||
|
||||
// Owns every equation-space mapping so semantic model objects remain free of
|
||||
// analysis-specific equation IDs.
|
||||
class DofManager {
|
||||
public:
|
||||
static Result<DofManager> create(const AnalysisModel& model);
|
||||
|
||||
std::size_t fullDofCount() const noexcept;
|
||||
std::size_t freeDofCount() const noexcept;
|
||||
std::size_t constrainedDofCount() const noexcept;
|
||||
std::size_t fullDof(EntityIndex node, DofComponent component) const;
|
||||
std::optional<std::size_t> freeEquation(std::size_t fullDof) const;
|
||||
const std::array<std::size_t, 12>& elementScatter(
|
||||
EntityIndex element) const;
|
||||
const std::vector<std::size_t>& freeDofs() const noexcept;
|
||||
const std::vector<std::size_t>& constrainedDofs() const noexcept;
|
||||
const Vector& prescribedValues() const noexcept;
|
||||
const SparsePattern& sparsePattern() const noexcept;
|
||||
|
||||
private:
|
||||
DofManager(
|
||||
std::size_t fullDofCount,
|
||||
std::vector<std::optional<std::size_t>> freeEquations,
|
||||
std::vector<std::array<std::size_t, 12>> elementScatters,
|
||||
std::vector<std::size_t> freeDofs,
|
||||
std::vector<std::size_t> constrainedDofs,
|
||||
Vector prescribedValues,
|
||||
SparsePattern sparsePattern);
|
||||
|
||||
std::size_t fullDofCount_;
|
||||
std::vector<std::optional<std::size_t>> freeEquations_;
|
||||
std::vector<std::array<std::size_t, 12>> elementScatters_;
|
||||
std::vector<std::size_t> freeDofs_;
|
||||
std::vector<std::size_t> constrainedDofs_;
|
||||
Vector prescribedValues_;
|
||||
SparsePattern sparsePattern_;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/core/status.hpp"
|
||||
#include "fesa/io/abaqus/input_syntax.hpp"
|
||||
#include "fesa/model/domain.hpp"
|
||||
|
||||
namespace fesa {
|
||||
|
||||
// Converts syntax-only blocks into the approved immutable B33 semantic model.
|
||||
class AbaqusDomainMapper {
|
||||
public:
|
||||
Result<Domain> map(const ParsedInput& input) const;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/core/status.hpp"
|
||||
#include "fesa/io/abaqus/input_syntax.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
// Reads only physical keyword/data/comment syntax; semantic policy is applied
|
||||
// later by AbaqusDomainMapper.
|
||||
class AbaqusInputReader {
|
||||
public:
|
||||
Result<ParsedInput> read(const std::filesystem::path& inputPath) const;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/core/source_identity.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
// Names are canonicalized for syntax lookup while values remain source text.
|
||||
struct KeywordParameter {
|
||||
std::string name;
|
||||
std::optional<std::string> value;
|
||||
};
|
||||
|
||||
struct DataLine {
|
||||
std::vector<std::string> fields;
|
||||
SourceLocation location;
|
||||
};
|
||||
|
||||
struct KeywordBlock {
|
||||
std::string canonicalName;
|
||||
std::string originalLine;
|
||||
std::vector<KeywordParameter> parameters;
|
||||
std::vector<DataLine> data;
|
||||
SourceLocation location;
|
||||
};
|
||||
|
||||
struct ParsedInput {
|
||||
std::filesystem::path sourcePath;
|
||||
std::string sourceContentIdentity;
|
||||
std::vector<KeywordBlock> blocks;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/results/results_writer.hpp"
|
||||
|
||||
namespace fesa {
|
||||
|
||||
// Writes schema-v0 output while keeping backend and platform types private.
|
||||
class Hdf5ResultsWriter final : public ResultsWriter {
|
||||
public:
|
||||
Status write(
|
||||
const std::filesystem::path& outputPath,
|
||||
const Domain& domain,
|
||||
const AnalysisState& state,
|
||||
const std::vector<Diagnostic>& diagnostics) override;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/math/vector.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
// Owns row-major contiguous dense storage independently of sparse matrices.
|
||||
class Matrix {
|
||||
public:
|
||||
Matrix(std::size_t rows, std::size_t columns, double value = 0.0);
|
||||
Matrix(const Matrix& other);
|
||||
Matrix(Matrix&& other) noexcept;
|
||||
Matrix& operator=(const Matrix& other);
|
||||
Matrix& operator=(Matrix&& other) noexcept;
|
||||
|
||||
std::size_t rows() const noexcept;
|
||||
std::size_t columns() const noexcept;
|
||||
double& operator()(std::size_t row, std::size_t column);
|
||||
const double& operator()(std::size_t row, std::size_t column) const;
|
||||
Vector multiply(const Vector& rhs) const;
|
||||
Matrix multiply(const Matrix& rhs) const;
|
||||
|
||||
private:
|
||||
std::size_t rows_;
|
||||
std::size_t columns_;
|
||||
std::vector<double> values_;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/core/status.hpp"
|
||||
#include "fesa/math/vector.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
struct SparsePattern;
|
||||
|
||||
struct CooContribution {
|
||||
std::size_t row;
|
||||
std::size_t column;
|
||||
double value;
|
||||
std::size_t elementOrder;
|
||||
std::size_t localOrder;
|
||||
};
|
||||
|
||||
// Owns canonical 0-based CSR data independently of the dense Matrix adapter.
|
||||
class SparseMatrix {
|
||||
public:
|
||||
static Result<SparseMatrix> fromCoo(
|
||||
std::size_t rows,
|
||||
std::size_t columns,
|
||||
std::vector<CooContribution> contributions,
|
||||
const SparsePattern& expectedPattern);
|
||||
|
||||
std::size_t rows() const noexcept;
|
||||
std::size_t columns() const noexcept;
|
||||
const std::vector<std::size_t>& rowOffsets() const noexcept;
|
||||
const std::vector<std::size_t>& columnIndices() const noexcept;
|
||||
const std::vector<double>& values() const noexcept;
|
||||
Vector multiply(const Vector& rhs) const;
|
||||
Status validate() const;
|
||||
|
||||
private:
|
||||
SparseMatrix(
|
||||
std::size_t rows,
|
||||
std::size_t columns,
|
||||
std::vector<std::size_t> rowOffsets,
|
||||
std::vector<std::size_t> columnIndices,
|
||||
std::vector<double> values);
|
||||
|
||||
std::size_t rows_;
|
||||
std::size_t columns_;
|
||||
std::vector<std::size_t> rowOffsets_;
|
||||
std::vector<std::size_t> columnIndices_;
|
||||
std::vector<double> values_;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
// Owns a contiguous dense vector while keeping the MKL backend private.
|
||||
class Vector {
|
||||
public:
|
||||
explicit Vector(std::size_t size, double value = 0.0);
|
||||
Vector(const Vector& other);
|
||||
Vector(Vector&& other) noexcept;
|
||||
Vector& operator=(const Vector& other);
|
||||
Vector& operator=(Vector&& other) noexcept;
|
||||
|
||||
std::size_t size() const noexcept;
|
||||
double* data() noexcept;
|
||||
const double* data() const noexcept;
|
||||
double& operator[](std::size_t index);
|
||||
const double& operator[](std::size_t index) const;
|
||||
double dot(const Vector& rhs) const;
|
||||
double norm() const;
|
||||
void scale(double alpha);
|
||||
void axpy(double alpha, const Vector& x);
|
||||
|
||||
private:
|
||||
std::vector<double> values_;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/core/status.hpp"
|
||||
#include "fesa/model/model_types.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
// Owns the complete semantic definition. Public access remains const so a
|
||||
// vector position can serve as a stable internal index after construction.
|
||||
class Domain {
|
||||
public:
|
||||
static Result<Domain> create(ModelDefinition definition);
|
||||
|
||||
const std::vector<Node>& nodes() const noexcept;
|
||||
const std::vector<EulerBeam3DDefinition>& elements() const noexcept;
|
||||
const std::vector<LinearElasticMaterial>& materials() const noexcept;
|
||||
const std::vector<GeneralBeamSection>& sections() const noexcept;
|
||||
const std::vector<NodeSet>& nodeSets() const noexcept;
|
||||
const std::vector<ElementSet>& elementSets() const noexcept;
|
||||
const std::vector<StaticStepDefinition>& steps() const noexcept;
|
||||
const std::vector<Diagnostic>& warnings() const noexcept;
|
||||
const std::filesystem::path& sourcePath() const noexcept;
|
||||
const std::string& sourceContentIdentity() const noexcept;
|
||||
|
||||
private:
|
||||
explicit Domain(ModelDefinition definition);
|
||||
|
||||
ModelDefinition definition_;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,131 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/core/diagnostic.hpp"
|
||||
#include "fesa/core/source_identity.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
// Stable internal identities are vector positions assigned in declaration order.
|
||||
using EntityIndex = std::uint32_t;
|
||||
|
||||
struct Node {
|
||||
SourceEntityId sourceId;
|
||||
std::array<double, 3> coordinates;
|
||||
SourceLocation location;
|
||||
};
|
||||
|
||||
struct LinearElasticMaterial {
|
||||
std::string name;
|
||||
double youngsModulus;
|
||||
double poissonRatio;
|
||||
SourceLocation location;
|
||||
};
|
||||
|
||||
struct GeneralBeamSection {
|
||||
std::string name;
|
||||
double area;
|
||||
double i11;
|
||||
double i12;
|
||||
double i22;
|
||||
double torsionalConstant;
|
||||
std::array<double, 3> firstAxis;
|
||||
std::vector<std::array<double, 2>> sectionPoints;
|
||||
SourceLocation location;
|
||||
};
|
||||
|
||||
struct EulerBeam3DDefinition {
|
||||
SourceEntityId sourceId;
|
||||
std::array<EntityIndex, 2> nodeIndices;
|
||||
EntityIndex materialIndex;
|
||||
EntityIndex sectionIndex;
|
||||
SourceLocation location;
|
||||
};
|
||||
|
||||
struct BoundaryCondition {
|
||||
std::string target;
|
||||
int firstDof;
|
||||
int lastDof;
|
||||
double value;
|
||||
SourceLocation location;
|
||||
};
|
||||
|
||||
struct NodalLoad {
|
||||
std::string target;
|
||||
int dof;
|
||||
double magnitude;
|
||||
SourceLocation location;
|
||||
};
|
||||
|
||||
struct StaticStepDefinition {
|
||||
std::string name;
|
||||
std::vector<BoundaryCondition> boundaries;
|
||||
std::vector<NodalLoad> loads;
|
||||
double initialIncrement;
|
||||
double timePeriod;
|
||||
double minimumIncrement;
|
||||
double maximumIncrement;
|
||||
SourceLocation location;
|
||||
};
|
||||
|
||||
struct NodeSet {
|
||||
std::string name;
|
||||
std::optional<std::string> instanceName;
|
||||
std::vector<EntityIndex> nodeIndices;
|
||||
SourceLocation location;
|
||||
};
|
||||
|
||||
struct ElementSet {
|
||||
std::string name;
|
||||
std::optional<std::string> instanceName;
|
||||
std::vector<EntityIndex> elementIndices;
|
||||
SourceLocation location;
|
||||
};
|
||||
|
||||
struct PartDefinition {
|
||||
std::string name;
|
||||
std::vector<std::int64_t> nodeSourceLabels;
|
||||
std::vector<std::int64_t> elementSourceLabels;
|
||||
std::vector<std::string> nodeSetNames;
|
||||
std::vector<std::string> elementSetNames;
|
||||
SourceLocation location;
|
||||
};
|
||||
|
||||
struct SourceIndexMapping {
|
||||
std::int64_t sourceLabel;
|
||||
EntityIndex internalIndex;
|
||||
};
|
||||
|
||||
struct InstanceDefinition {
|
||||
std::string name;
|
||||
std::string partName;
|
||||
std::vector<SourceIndexMapping> nodeMappings;
|
||||
std::vector<SourceIndexMapping> elementMappings;
|
||||
SourceLocation location;
|
||||
};
|
||||
|
||||
// This construction-boundary value owns every parsed semantic record before
|
||||
// it is finalized into an immutable Domain.
|
||||
struct ModelDefinition {
|
||||
std::filesystem::path sourcePath;
|
||||
std::string sourceContentIdentity;
|
||||
std::string heading;
|
||||
std::vector<Node> nodes;
|
||||
std::vector<EulerBeam3DDefinition> elements;
|
||||
std::vector<LinearElasticMaterial> materials;
|
||||
std::vector<GeneralBeamSection> sections;
|
||||
std::vector<NodeSet> nodeSets;
|
||||
std::vector<ElementSet> elementSets;
|
||||
std::vector<PartDefinition> parts;
|
||||
std::vector<InstanceDefinition> instances;
|
||||
std::vector<StaticStepDefinition> steps;
|
||||
std::vector<Diagnostic> warnings;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/model/model_types.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
struct StepFrameIdentity {
|
||||
std::string stepName;
|
||||
std::size_t frameIndex;
|
||||
};
|
||||
|
||||
struct EndpointResultRow {
|
||||
EntityIndex element;
|
||||
int endpoint;
|
||||
SourceEntityId node;
|
||||
std::array<double, 6> endAction;
|
||||
std::array<double, 4> sectionResultant;
|
||||
};
|
||||
|
||||
struct GaussResultRow {
|
||||
EntityIndex element;
|
||||
int gaussPoint;
|
||||
std::array<double, 4> generalizedStrain;
|
||||
std::array<double, 4> generalizedResultant;
|
||||
};
|
||||
|
||||
struct StressS11Row {
|
||||
EntityIndex element;
|
||||
int gaussPoint;
|
||||
std::size_t sectionPoint;
|
||||
double x1;
|
||||
double x2;
|
||||
double s11;
|
||||
std::string source;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/analysis/analysis_model.hpp"
|
||||
#include "fesa/analysis/analysis_state.hpp"
|
||||
#include "fesa/core/status.hpp"
|
||||
#include "fesa/fem/dof_manager.hpp"
|
||||
#include "fesa/math/sparse_matrix.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
struct NodeStationResultRow {
|
||||
SourceEntityId node;
|
||||
EntityIndex representativeElement;
|
||||
std::array<double, 4> sectionResultant;
|
||||
};
|
||||
|
||||
// Recovers full-space equilibrium and the V0 beam output rows without
|
||||
// exposing element or sparse-backend details to result consumers.
|
||||
class ResultRecovery {
|
||||
public:
|
||||
static Status recover(const AnalysisModel& model,
|
||||
const DofManager& dofs,
|
||||
const SparseMatrix& fullStiffness,
|
||||
AnalysisState& state);
|
||||
|
||||
static Result<std::vector<NodeStationResultRow>>
|
||||
normalizeSectionResultantsToNodeStations(
|
||||
const AnalysisModel& model,
|
||||
const std::vector<EndpointResultRow>& endpointRows,
|
||||
const std::array<double, 4>& componentTolerances);
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/analysis/analysis_state.hpp"
|
||||
#include "fesa/core/diagnostic.hpp"
|
||||
#include "fesa/core/status.hpp"
|
||||
#include "fesa/model/domain.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
// Keeps the solver core independent of the authoritative result-storage backend.
|
||||
class ResultsWriter {
|
||||
public:
|
||||
virtual ~ResultsWriter() = default;
|
||||
|
||||
virtual Status write(
|
||||
const std::filesystem::path& outputPath,
|
||||
const Domain& domain,
|
||||
const AnalysisState& state,
|
||||
const std::vector<Diagnostic>& diagnostics) = 0;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/core/status.hpp"
|
||||
|
||||
namespace fesa {
|
||||
|
||||
class SparseMatrix;
|
||||
class Vector;
|
||||
|
||||
// Separates reusable matrix factorization from right-hand-side substitution.
|
||||
class LinearSolver {
|
||||
public:
|
||||
virtual ~LinearSolver() = default;
|
||||
virtual Status factorize(const SparseMatrix& matrix) = 0;
|
||||
virtual Status solve(const Vector& rhs, Vector& solution) const = 0;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/solvers/linear/linear_solver.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
// Keeps every oneMKL type and the retained factorization in the private Impl.
|
||||
class MklPardisoSolver final : public LinearSolver {
|
||||
public:
|
||||
MklPardisoSolver();
|
||||
~MklPardisoSolver() override;
|
||||
|
||||
Status factorize(const SparseMatrix& matrix) override;
|
||||
Status solve(const Vector& rhs, Vector& solution) const override;
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> impl_;
|
||||
};
|
||||
|
||||
} // namespace fesa
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"phases": [
|
||||
{
|
||||
"dir": "linear-static-3d-euler-beam",
|
||||
"status": "pending"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
{
|
||||
"project": "FESA Structural Solver",
|
||||
"phase": "linear-static-3d-euler-beam",
|
||||
"steps": [
|
||||
{
|
||||
"step": 0,
|
||||
"name": "requirements-baseline",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T01:35:55+0900",
|
||||
"summary": "docs/requirements/linear-static-3d-euler-beam.md에 44개 연속 shall 요구조건과 검증 행렬을 작성하고 2026-08-09 amendment의 approved B33 baseline을 고정함",
|
||||
"completed_at": "2026-08-09T01:53:04+0900"
|
||||
},
|
||||
{
|
||||
"step": 1,
|
||||
"name": "research-evidence",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T01:54:38+0900",
|
||||
"summary": "FEM wiki 근거로 B31/B33, Hermite·Gauss, general beam section/output, analytical benchmark, SPD·assembly·reference 적용 한계를 정리한 research brief를 작성함",
|
||||
"completed_at": "2026-08-09T02:12:54+0900"
|
||||
},
|
||||
{
|
||||
"step": 2,
|
||||
"name": "formulation-alignment",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T02:14:26+0900",
|
||||
"summary": "기존 3D Euler–Bernoulli strong/weak form과 DOF·부호·2점 Gauss·12×12 강성 의미를 보존하면서 B33 n1/section/geometry 및 recovery/tolerance 계약을 승인 V0 요구조건·연구에 정렬함",
|
||||
"completed_at": "2026-08-09T02:33:50+0900"
|
||||
},
|
||||
{
|
||||
"step": 3,
|
||||
"name": "numerical-review",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T02:33:50+0900",
|
||||
"summary": "DOF·theta_y=-w'·end-action 부호, 4x12 B/12x12 강성·2-point Gauss·rank 6/rigid modes·좌표변환·line-load·partition/SPD를 독립 검토하고 pass-for-implementation-planning 판정과 11개 테스트 권고를 기록함",
|
||||
"completed_at": "2026-08-09T02:52:47+0900"
|
||||
},
|
||||
{
|
||||
"step": 4,
|
||||
"name": "io-contract",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T02:52:47+0900",
|
||||
"summary": "승인된 Abaqus B33 keyword subset, stable source identity, HDF5 schema v0와 legacy CSV normalization/component-scale tolerance 계약을 정의함",
|
||||
"completed_at": "2026-08-09T03:16:25+0900"
|
||||
},
|
||||
{
|
||||
"step": 5,
|
||||
"name": "reference-model-contract",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T03:16:25+0900",
|
||||
"summary": "code·analytical·B33 reference 검증을 분리하고 analytical/invalid model inventory와 read-only legacy 4-file provenance·schema·tolerance coverage를 계약화함",
|
||||
"completed_at": "2026-08-09T03:29:44+0900"
|
||||
},
|
||||
{
|
||||
"step": 6,
|
||||
"name": "implementation-plan",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T03:29:45+0900",
|
||||
"summary": "승인 upstream 계약을 Step 7–24의 exact 파일·시그니처·GoogleTest RED/GREEN/VERIFY·CMake/CTest·44개 요구조건 traceability와 read-only B33 comparison handoff로 매핑한 ready-for-implementation 계획을 작성함",
|
||||
"completed_at": "2026-08-09T03:53:12+0900"
|
||||
},
|
||||
{
|
||||
"step": 7,
|
||||
"name": "cmake-test-foundation",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T03:53:12+0900",
|
||||
"summary": "C++17 MSVC x64 Debug CMake foundation, normalized MKL/TBB/HDF5 targets, GoogleTest BuildInfo 2-test suite와 누적 implementation report를 RED/GREEN/VERIFY로 구축함",
|
||||
"completed_at": "2026-08-09T04:44:04+0900"
|
||||
},
|
||||
{
|
||||
"step": 8,
|
||||
"name": "core-diagnostics",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T10:51:14+0900",
|
||||
"summary": "stable source identity, deterministic diagnostic ordering, categorized Status와 value/error-exclusive Result를 TDD로 구현하고 MSVC x64 Debug 5-test full suite를 검증함",
|
||||
"completed_at": "2026-08-09T10:54:29+0900"
|
||||
},
|
||||
{
|
||||
"step": 9,
|
||||
"name": "dense-math-adapters",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T11:13:43+0900",
|
||||
"summary": "contiguous double Vector와 row-major Matrix의 MKL CBLAS copy/dot/norm/scale/axpy/GEMV/GEMM adapter를 TDD로 구현하고 DenseMath 2/2·MSVC x64 Debug full 7/7·public-header leak 0건을 검증함",
|
||||
"completed_at": "2026-08-09T11:35:31+0900"
|
||||
},
|
||||
{
|
||||
"step": 10,
|
||||
"name": "domain-model",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T11:49:47+0900",
|
||||
"summary": "SourceLocation을 포함한 semantic records와 static timing, part/instance source-index mapping, warnings/source identity를 소유하는 effectively immutable Domain을 TDD로 구현하고 DomainModel 3/3 및 전체 10/10을 검증함",
|
||||
"completed_at": "2026-08-09T12:07:11+0900"
|
||||
},
|
||||
{
|
||||
"step": 11,
|
||||
"name": "inp-syntax-parser",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T15:06:01+0900",
|
||||
"completed_at": "2026-08-09T15:19:17+0900",
|
||||
"summary": "keyword/parameter name만 uppercase canonicalize하고 raw value/data/originalLine, normalized source path, exact-byte fnv1a64 identity와 file/line 위치를 보존하는 syntax-only reader를 TDD로 구현해 InpSyntax 4/4, 전체 14/14 및 legacy 30-block read-only parse를 검증함"
|
||||
},
|
||||
{
|
||||
"step": 12,
|
||||
"name": "inp-domain-mapping",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T15:27:22+0900",
|
||||
"completed_at": "2026-08-09T16:15:17+0900",
|
||||
"summary": "승인 B33 단일 static-step Abaqus subset을 immutable Domain으로 mapping하고 identity instance·stable source/internal ID·set/target expansion·material/section·model/step BC/CLOAD·warning no-op와 exact rejection portfolio를 TDD로 구현해 InpDomainMapping 5/5 및 전체 19/19를 검증함"
|
||||
},
|
||||
{
|
||||
"step": 13,
|
||||
"name": "analysis-model",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T16:36:20+0900",
|
||||
"completed_at": "2026-08-09T16:50:12+0900",
|
||||
"summary": "단일 static step의 Domain을 비소유 참조로 유지하고 active element·BC·load stable index와 reachable material/section의 오름차순 dedup view를 TDD로 구현해 address identity·불변성·missing/multiple-step diagnostic, AnalysisModel 3/3 및 전체 22/22를 검증함"
|
||||
},
|
||||
{
|
||||
"step": 14,
|
||||
"name": "dof-manager",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T16:56:29+0900",
|
||||
"completed_at": "2026-08-09T17:10:22+0900",
|
||||
"summary": "절점당 6-DOF full/free/constrained numbering, validated boundary target expansion과 prescribed dc, 12-DOF scatter 및 sorted-unique full CSR pattern을 DofManager 단독 소유로 TDD 구현해 DofManager 4/4와 전체 26/26을 검증함"
|
||||
},
|
||||
{
|
||||
"step": 15,
|
||||
"name": "analysis-state",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T17:19:21+0900",
|
||||
"completed_at": "2026-08-09T17:31:51+0900",
|
||||
"summary": "fullDofCount 크기의 독립 zero-initialized displacement/external/internal/residual/reaction과 StepFrameIdentity·stable endpoint/Gauss/S11 rows를 TDD 구현하고 velocity·acceleration·temperature·iteration/nonlinear state 미할당, AnalysisState 3/3 및 전체 29/29를 검증함"
|
||||
},
|
||||
{
|
||||
"step": 16,
|
||||
"name": "euler-beam-element",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T17:38:34+0900",
|
||||
"completed_at": "2026-08-09T18:04:40+0900",
|
||||
"summary": "Implemented the exact two-node 3D Euler-Bernoulli beam kernel with reviewed local signs, two-point Gauss stiffness and line loading, strict geometry/property validation, transform, end/Gauss/S11 recovery, and 10/10 targeted plus 39/39 full tests passing."
|
||||
},
|
||||
{
|
||||
"step": 17,
|
||||
"name": "parallel-for-tbb",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T18:41:51+0900",
|
||||
"completed_at": "2026-08-09T18:52:20+0900",
|
||||
"summary": "Backend-free ParallelFor/Serial/Tbb adapter가 caller-owned index-addressed slot에서 zero/one/many exact-once와 stable output을 보장하고 oneTBB cancellation의 body exception을 그대로 전파하며 global thread/oversubscription 설정 없이 targeted 3/3 및 전체 42/42를 검증함"
|
||||
},
|
||||
{
|
||||
"step": 18,
|
||||
"name": "sparse-assembly",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T19:07:39+0900",
|
||||
"completed_at": "2026-08-09T19:27:34+0900",
|
||||
"summary": "ParallelFor index-owned 12x12 element buffers를 stable COO tuple order로 fixed-sum하여 exact sorted-unique 0-based CSR pattern과 structural zero를 보존하고 serial/TBB/repeated byte identity, SparseAssembly 5/5 및 전체 47/47을 검증함"
|
||||
},
|
||||
{
|
||||
"step": 19,
|
||||
"name": "essential-constraints",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T19:37:55+0900",
|
||||
"completed_at": "2026-08-09T19:46:22+0900",
|
||||
"summary": "Stable free/constrained DOF order로 full CSR을 Kff/Kfc/Kcf/Kcc에 exact partition하고 structural zero와 nonzero prescribed displacement full/reduced roundtrip을 보존해 EssentialConstraints 4/4 및 전체 51/51을 검증함"
|
||||
},
|
||||
{
|
||||
"step": 20,
|
||||
"name": "mkl-pardiso-solver",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T19:50:41+0900",
|
||||
"completed_at": "2026-08-09T20:05:06+0900",
|
||||
"summary": "Private PImpl oneMKL PARDISO SPD adapter가 full CSR 검증과 checked upper-triangle 변환 뒤 phase 11/22 factorization을 유지하고 phase 33 repeated RHS substitution 및 phase -1 RAII release를 수행하며, structured 실패·conditioning과 targeted 6/6 및 전체 57/57을 검증함"
|
||||
},
|
||||
{
|
||||
"step": 21,
|
||||
"name": "load-assembly",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T20:22:02+0900",
|
||||
"completed_at": "2026-08-09T20:34:21+0900",
|
||||
"summary": "Semantic node/set CLOAD를 stable full-DOF source order로 합산하고 constrained load를 보존하며 exact Ff-Kfc*dc, nonfinite/dimension/order validation, zero-free/zero-constrained cases를 구현해 LoadAssembly 5/5 및 전체 62/62를 검증함"
|
||||
},
|
||||
{
|
||||
"step": 22,
|
||||
"name": "result-recovery",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T20:42:15+0900",
|
||||
"completed_at": "2026-08-09T21:14:47+0900",
|
||||
"summary": "Full K*d-F residual을 reaction에 보존해 constrained physical reaction과 free residual evidence를 원자적으로 복구하고 stable endpoint/Gauss/S11 rows 및 unloaded consistent two-endpoint station no-average normalization을 구현해 ResultRecovery 6/6 및 전체 68/68을 검증함"
|
||||
},
|
||||
{
|
||||
"step": 23,
|
||||
"name": "hdf5-results-writer",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T21:23:14+0900",
|
||||
"completed_at": "2026-08-09T22:03:33+0900",
|
||||
"summary": "Backend-free ResultsWriter 경계 뒤 schema v0의 exact metadata/model/Step-1 frame-0 결과와 stable identity/diagnostics를 mandatory HDF5로 기록하고 same-directory temp flush/checked-close/read-only self-check 뒤 ReplaceFileW 또는 write-through MoveFileExW로 원자화했으며 shared HDF5/libmmd runtime을 stage해 Hdf5ResultsWriter 5/5 및 전체 73/73을 검증함"
|
||||
},
|
||||
{
|
||||
"step": 24,
|
||||
"name": "linear-static-cli",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T22:13:49+0900",
|
||||
"completed_at": "2026-08-09T22:54:33+0900",
|
||||
"summary": "Exact factorize-before-load single-step lifecycle과 argv0-excluded fesa.exe 0/2/3/4/5/6 CLI를 구현하고 repeated/unknown option token을 usage로 거부하며 read-only legacy B33/HDF5 comparator로 176 rows, 16 metrics, deterministic JSON/physics evidence를 생성해 Step24 10/10 및 전체 83/83을 검증함"
|
||||
},
|
||||
{
|
||||
"step": 25,
|
||||
"name": "build-test-verification",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T23:16:20+0900",
|
||||
"summary": "HEAD 400db19에서 fresh Visual Studio 18 2026/MSVC x64 Debug configure와 clean full build를 warning 0건으로 통과하고 JSON discovery 83개, feature-label 83/83, full CTest 83/83, Step 7-24 RED/GREEN/VERIFY 및 reference read-only audit를 확인해 pass-for-reference-verification으로 인계함",
|
||||
"completed_at": "2026-08-09T23:25:28+0900"
|
||||
},
|
||||
{
|
||||
"step": 26,
|
||||
"name": "reference-verification",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T23:34:22+0900",
|
||||
"completed_at": "2026-08-09T23:43:22+0900",
|
||||
"summary": "Approved legacy B33 4-file artifact precheck와 read-only HDF5 schema/source identity/stress audit를 통과하고 exact B33ReferenceComparison을 두 번 1/1 실행해 deterministic comparison.json의 passed=true, 176/176 rows, 16/16 metrics, displacement/reaction/section 66/66/44 rows 및 reference immutability를 독립 검산했으며 final review에서 exact acceptance probe도 authoritative passed boolean으로 정렬·재검증하여 pass-for-physics-evaluation으로 인계함"
|
||||
},
|
||||
{
|
||||
"step": 27,
|
||||
"name": "physics-sanity",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-09T23:45:30+0900",
|
||||
"summary": "Reference gate와 exact B33 HDF5/JSON/reference identity를 확인하고 force/origin-moment equilibrium, constrained reaction와 normalized free residual, displacement/rotation sign, zero symmetry, endpoint/section balance, local/global 및 S11 sanity, finite/energy/mode와 analytical coverage를 검토해 pass-for-release-agent로 인계함",
|
||||
"completed_at": "2026-08-09T23:59:16+0900"
|
||||
},
|
||||
{
|
||||
"step": 28,
|
||||
"name": "release-readiness",
|
||||
"status": "completed",
|
||||
"started_at": "2026-08-10T00:08:50+0900",
|
||||
"completed_at": "2026-08-10T00:11:51+0900",
|
||||
"summary": "Build/Test·Reference Verification·Physics Evaluation의 exact pass gate와 Steps 0-27 completion을 감사하고 44/44 must 요구조건을 acceptance·exact test/evidence·reference/analytical 근거·final disposition에 연결했으며 stale implementation aggregate header를 nonblocking으로 판정하고 limitations·accepted Minors·release notes를 기록해 internal ready-for-release로 인계함"
|
||||
}
|
||||
],
|
||||
"created_at": "2026-08-09T01:35:55+0900"
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
# Step 0: Requirements Baseline
|
||||
|
||||
## 담당 역할과 필수 스킬
|
||||
|
||||
- 담당 역할: `requirement-agent`
|
||||
- 필수 스킬: `fesa-requirements-baseline`
|
||||
- 작업을 시작하기 전에 위 스킬의 `SKILL.md`를 끝까지 읽고 경계를 준수하라.
|
||||
|
||||
## 읽어야 할 파일
|
||||
|
||||
먼저 아래 파일을 읽고 승인된 범위와 프로젝트 규칙을 파악하라.
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/PRD.md`
|
||||
- `/docs/ARCHITECTURE.md`
|
||||
- `/docs/ADR.md`
|
||||
- `/docs/SOLVER_AGENT_DESIGN.md`
|
||||
- `/docs/requirements/README.md`
|
||||
- `/docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md`
|
||||
- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md`
|
||||
- `/reference/cantilever beam/cantilever beam.inp`
|
||||
|
||||
승인된 설계 문서의 `status: approved`와 2026-08-09 amendment를 이 step의 사용자 승인
|
||||
근거로 사용한다.
|
||||
|
||||
## 작업
|
||||
|
||||
`docs/requirements/linear-static-3d-euler-beam.md`를 생성하라. 문서는 다음 계약을
|
||||
downstream agent가 추측 없이 사용할 수 있는 `shall` 요구조건과 검증 행렬로 바꿔야 한다.
|
||||
|
||||
- Metadata: `feature_id: linear-static-3d-euler-beam`, `status: approved`,
|
||||
`owner_agent: requirement-agent`, 현재 날짜, 승인된 설계 경로를 기록한다.
|
||||
- 목적, In Scope, Out Of Scope, Analysis Definition, Input Requirements, Output
|
||||
Requirements, Verification Quantities, Tolerance Policy, Reference Artifact
|
||||
Requirements, Requirement Verification Matrix, Downstream Handoff를 포함한다.
|
||||
- 한 입력당 단일 `*STEP, *STATIC`, 2절점 3D Euler–Bernoulli, node당 6 DOF,
|
||||
`TYPE=B33`만 지원하고 B31은 오류로 거부하는 요구조건을 분리한다.
|
||||
- `*PART/*ASSEMBLY/*INSTANCE` identity wrapper, stable source identity, 여러 identity
|
||||
instance 허용, transform/nested assembly 거부를 요구조건으로 만든다.
|
||||
- 지원 keyword와 warning no-op allowlist를 정확히 열거하고 allowlist 밖 model-affecting
|
||||
keyword는 오류로 요구한다.
|
||||
- factorization-before-load 순서, nonzero prescribed displacement, deterministic
|
||||
COO-to-CSR, MKL/TBB/HDF5 adapter 경계, CLI exit code, HDF5 schema/output을 요구한다.
|
||||
- B33 legacy reference bundle은 read-only이며 exact filename을 보존하고 stress reference
|
||||
comparison은 N/A지만 `S11` output과 test는 필수임을 명시한다.
|
||||
- reference tolerance는 같은 model/step/frame/quantity/component의 read-only Abaqus
|
||||
scale만 사용해 `absolute_floor + 1e-6 * reference_scale`을 모든 row에 적용한다.
|
||||
SI floor는 displacement/rotation `1e-9`, force/moment `1e-3`이다.
|
||||
- 모든 `must` 요구조건에 acceptance criterion, verification method, tolerance 또는 N/A,
|
||||
downstream agent, status를 매핑한다. 숫자 ID는
|
||||
`FESA-REQ-LS3DEB-001`부터 중복 없이 연속 부여한다.
|
||||
|
||||
설계가 이미 승인했으므로 새 정책 결정을 만들지 말고, 충돌을 발견하면 문서를 승인
|
||||
상태로 꾸미지 말고 phase step을 `blocked`로 기록하라.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
```powershell
|
||||
$path = 'docs/requirements/linear-static-3d-euler-beam.md'
|
||||
if (-not (Test-Path $path)) { throw "Missing $path" }
|
||||
$required = @(
|
||||
'feature_id: `linear-static-3d-euler-beam`',
|
||||
'status: `approved`',
|
||||
'## In Scope',
|
||||
'## Out Of Scope',
|
||||
'## Requirement Verification Matrix',
|
||||
'TYPE=B33',
|
||||
'TYPE=B31',
|
||||
'absolute_floor + 1e-6 * reference_scale',
|
||||
'reference/cantilever beam/'
|
||||
)
|
||||
foreach ($text in $required) {
|
||||
if (-not (Select-String -LiteralPath $path -SimpleMatch $text -Quiet)) {
|
||||
throw "Missing contract text: $text"
|
||||
}
|
||||
}
|
||||
$ids = Select-String -LiteralPath $path -Pattern 'FESA-REQ-LS3DEB-\d{3}' -AllMatches |
|
||||
ForEach-Object { $_.Matches.Value }
|
||||
if (($ids | Sort-Object -Unique).Count -lt 1) { throw 'No requirement ids found' }
|
||||
git diff --check -- $path
|
||||
```
|
||||
|
||||
## 검증 절차
|
||||
|
||||
1. Acceptance Criteria 명령을 실행한다.
|
||||
2. 설계 문서 2절, 6절, 9절, 10절, 11절, 12절의 각 필수 계약이 최소 한 요구조건과
|
||||
verification matrix row에 추적되는지 점검한다.
|
||||
3. 수치값, 단위, 좌표계, artifact path가 설계와 정확히 일치하는지 확인한다.
|
||||
4. `/phases/linear-static-3d-euler-beam/index.json`의 Step 0을 갱신한다.
|
||||
- 성공: `status`를 `completed`로 바꾸고 생성 파일과 승인 baseline을 `summary` 한 줄에 기록한다.
|
||||
- 수정 3회 후 실패: `status: error`와 `error_message`를 기록한다.
|
||||
- 승인 설계와 프로젝트 문서가 충돌해 사용자 결정이 필요하면 `status: blocked`와
|
||||
`blocked_reason`을 기록하고 중단한다.
|
||||
|
||||
## 금지사항
|
||||
|
||||
- C++ API나 파일 구조를 설계하지 마라. 이유: Requirement Agent의 책임 범위를 넘는다.
|
||||
- formulation 수식을 수정하지 마라. 이유: 수학 계약은 후속 gate가 담당한다.
|
||||
- Abaqus 또는 reference solver를 실행하지 마라. 이유: 승인된 read-only artifact만 사용한다.
|
||||
- `/reference/` 파일을 생성·수정·rename하지 마라. 이유: correctness baseline을 오염시킨다.
|
||||
- 직접 commit하지 마라. 이유: Harness executor가 commit과 timestamp를 관리한다.
|
||||
@@ -0,0 +1,80 @@
|
||||
# Step 1: Research Evidence
|
||||
|
||||
## 담당 역할과 필수 스킬
|
||||
|
||||
- 담당 역할: `research-agent`
|
||||
- 필수 스킬: `fesa-research-evidence`, `fem-theory-query`
|
||||
- 두 스킬의 `SKILL.md`를 끝까지 읽고, FEM wiki query를 우선 사용하라.
|
||||
|
||||
## 읽어야 할 파일
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/SOLVER_AGENT_DESIGN.md`
|
||||
- `/docs/research/README.md`
|
||||
- `/docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- `/docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md`
|
||||
- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md`
|
||||
|
||||
Step 0 산출물과 phase index의 완료 summary를 확인한 뒤 작업하라.
|
||||
|
||||
## 작업
|
||||
|
||||
FEM wiki에서 다음 연구 질문을 query하고
|
||||
`docs/research/linear-static-3d-euler-beam-research.md`를 생성하라.
|
||||
|
||||
- Abaqus B31과 B33의 formulation 차이 및 B33을 Euler–Bernoulli 의미로 사용하는 근거
|
||||
- 2절점 spatial Euler beam의 cubic Hermite interpolation, 6 rigid modes, rank 6,
|
||||
two-point Gauss exactness, local/global transformation과 end-force sign
|
||||
- Abaqus general beam section의 `A, I11, I12, I22, J`, first axis `n1`, section
|
||||
resultant `SF*`/`SM*`, axial `S11` 의미
|
||||
- analytical cantilever axial/torsion/two-plane bending benchmark와 검증 가능한 물리량
|
||||
- PARDISO SPD factorization, deterministic sparse assembly, reference comparison에 필요한
|
||||
기술 근거와 적용 한계
|
||||
|
||||
문서는 Metadata(`status: ready-for-formulation`), Research Questions, Source Inventory,
|
||||
Extracted Facts, Candidate Benchmarks, Verification Relevance, Applicability Limits,
|
||||
Open Issues, Downstream Handoff를 포함해야 한다. Source Inventory에는 문서명, 제공 기관,
|
||||
wiki page identity, 원 출처/매뉴얼 identity, reliability tier와 적용 범위를 기록한다.
|
||||
확인된 사실과 설계에서 도출한 inference를 구분한다. 기존 정식화 식을 최종 승인하거나
|
||||
새 tolerance를 만들지 않는다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
```powershell
|
||||
$path = 'docs/research/linear-static-3d-euler-beam-research.md'
|
||||
if (-not (Test-Path $path)) { throw "Missing $path" }
|
||||
$required = @(
|
||||
'status: `ready-for-formulation`',
|
||||
'## Research Questions',
|
||||
'## Source Inventory',
|
||||
'## Extracted Facts',
|
||||
'## Candidate Benchmarks',
|
||||
'## Applicability Limits',
|
||||
'B31',
|
||||
'B33',
|
||||
'Hermite',
|
||||
'general beam section'
|
||||
)
|
||||
foreach ($text in $required) {
|
||||
if (-not (Select-String -LiteralPath $path -SimpleMatch $text -Quiet)) {
|
||||
throw "Missing research evidence: $text"
|
||||
}
|
||||
}
|
||||
git diff --check -- $path
|
||||
```
|
||||
|
||||
## 검증 절차
|
||||
|
||||
1. Acceptance Criteria 명령을 실행한다.
|
||||
2. 주요 claim마다 source tier 또는 inference 표시가 있는지 확인한다.
|
||||
3. benchmark마다 target quantity와 검증할 수 없는 범위를 함께 기록했는지 확인한다.
|
||||
4. Step 1을 `completed`와 한 줄 `summary`로 갱신한다. 반복 실패는 `error`, 실제 source
|
||||
부재나 상충으로 사용자 판단이 필요하면 `blocked`로 기록한다.
|
||||
|
||||
## 금지사항
|
||||
|
||||
- 웹 검색 결과나 LLM 기억만을 source로 쓰지 마라. 이유: 사용자가 FEM wiki manual을 허용했다.
|
||||
- formulation을 최종화하거나 C++ API를 설계하지 마라. 이유: downstream 책임이다.
|
||||
- tolerance나 reference 값을 발명하지 마라. 이유: 승인 설계 값을 그대로 사용해야 한다.
|
||||
- Abaqus 실행 및 `/reference/` 변경을 하지 마라. 이유: artifact는 read-only다.
|
||||
- 직접 commit하지 마라. 이유: Harness executor가 담당한다.
|
||||
@@ -0,0 +1,102 @@
|
||||
# Step 10: Domain Model
|
||||
|
||||
## 담당 역할과 필수 스킬
|
||||
|
||||
- 담당 역할: `implementation-agent`
|
||||
- 필수 스킬: `fesa-cpp-msvc-tdd`
|
||||
- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다.
|
||||
|
||||
## 읽어야 할 파일
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/ARCHITECTURE.md`
|
||||
- `/docs/ADR.md`
|
||||
- `/docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- `/docs/io-definitions/linear-static-3d-euler-beam-io.md`
|
||||
- `/docs/implementation-plans/linear-static-3d-euler-beam.md`
|
||||
- `/include/fesa/core/source_identity.hpp`
|
||||
- `/include/fesa/core/status.hpp`
|
||||
- `/src/fesa/CMakeLists.txt`
|
||||
- `/tests/CMakeLists.txt`
|
||||
|
||||
## 소유 파일
|
||||
|
||||
- Create: `/include/fesa/model/model_types.hpp`
|
||||
- Create: `/include/fesa/model/domain.hpp`
|
||||
- Create: `/src/fesa/model/domain.cpp`
|
||||
- Create: `/tests/unit/model/model_types_test.cpp`
|
||||
- Create: `/tests/unit/model/domain_test.cpp`
|
||||
- Modify: `/src/fesa/CMakeLists.txt`
|
||||
- Modify: `/tests/CMakeLists.txt`
|
||||
|
||||
## 작업
|
||||
|
||||
parser와 analysis가 공유할 immutable semantic model을 위 exact paths에 구현하라.
|
||||
최소 model types는 다음을 포함한다.
|
||||
|
||||
```cpp
|
||||
using EntityIndex = std::uint32_t;
|
||||
struct Node { SourceEntityId sourceId; std::array<double, 3> coordinates; };
|
||||
struct LinearElasticMaterial { std::string name; double youngsModulus; double poissonRatio; };
|
||||
struct GeneralBeamSection {
|
||||
std::string name; double area; double i11; double i12; double i22; double torsionalConstant;
|
||||
std::array<double, 3> firstAxis; std::vector<std::array<double, 2>> sectionPoints;
|
||||
};
|
||||
struct EulerBeam3DDefinition {
|
||||
SourceEntityId sourceId; std::array<EntityIndex, 2> nodeIndices;
|
||||
EntityIndex materialIndex; EntityIndex sectionIndex;
|
||||
};
|
||||
struct BoundaryCondition { std::string target; int firstDof; int lastDof; double value; };
|
||||
struct NodalLoad { std::string target; int dof; double magnitude; };
|
||||
struct StaticStepDefinition { std::string name; std::vector<BoundaryCondition> boundaries;
|
||||
std::vector<NodalLoad> loads; };
|
||||
```
|
||||
|
||||
`PartDefinition`과 `InstanceDefinition`은 source name, referenced part, identity-instance
|
||||
restriction과 source-to-internal mapping을 보존한다. `NodeSet`, `ElementSet`,
|
||||
part/instance/source label mapping을 포함한다. `Domain`은 vectors와
|
||||
stable lookup을 소유하고 construction 완료 후 const access만 제공한다. 필요한 builder는
|
||||
construction 경계에만 두고 Domain을 복사하지 않아도 view를 만들 수 있는 stable index를
|
||||
보장한다. Node/element에는 equation ID를 저장하지 않는다.
|
||||
|
||||
Tests는 source identity equality/order, same-part multiple-instance distinction, stable
|
||||
insertion order/index, deep ownership, const access, one static step storage, equation-ID 부재를
|
||||
검증하고 `DomainModel` regex로 등록한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
RED targeted command 후 최소 구현으로 GREEN을 만든다.
|
||||
|
||||
```powershell
|
||||
cmake --build .harness/build --config Debug --target fesa_tests
|
||||
ctest --test-dir .harness/build -C Debug -R DomainModel --output-on-failure
|
||||
```
|
||||
|
||||
```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 -R DomainModel --output-on-failure
|
||||
ctest --test-dir .harness/build -C Debug --show-only=json-v1
|
||||
ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
```
|
||||
|
||||
## 검증 절차
|
||||
|
||||
1. Domain tests를 먼저 추가하고 compile/test RED를 확인한다.
|
||||
2. 최소 semantic types와 immutable Domain ownership으로 GREEN을 만든다.
|
||||
3. full VERIFY와 public dependency direction을 확인한다.
|
||||
4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의
|
||||
Step 10 section에 실제 RED/GREEN/VERIFY command, exit code,
|
||||
핵심 output과 변경 파일을 기록한다.
|
||||
5. Step 10을 `completed`로 갱신하고 model types/stable identity를 summary에 기록한다.
|
||||
|
||||
## 금지사항
|
||||
|
||||
- Abaqus keyword string을 Domain의 핵심 의미로 저장하지 마라. 이유: syntax/model 경계를 깨뜨린다.
|
||||
- Domain에 equation numbering이나 mutable analysis vector를 넣지 마라. 이유: DofManager/AnalysisState 책임이다.
|
||||
- parser를 이 step에서 구현하지 마라. 이유: Step 11–12 범위다.
|
||||
- 직접 commit하지 마라. 이유: Harness executor가 담당한다.
|
||||
@@ -0,0 +1,102 @@
|
||||
# Step 11: Abaqus INP Syntax Parser
|
||||
|
||||
## 담당 역할과 필수 스킬
|
||||
|
||||
- 담당 역할: `implementation-agent`
|
||||
- 필수 스킬: `fesa-cpp-msvc-tdd`
|
||||
- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다.
|
||||
|
||||
## 읽어야 할 파일
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/ARCHITECTURE.md`
|
||||
- `/docs/ADR.md`
|
||||
- `/docs/io-definitions/linear-static-3d-euler-beam-io.md`
|
||||
- `/docs/implementation-plans/linear-static-3d-euler-beam.md`
|
||||
- `/include/fesa/core/diagnostic.hpp`
|
||||
- `/include/fesa/core/status.hpp`
|
||||
- `/src/fesa/CMakeLists.txt`
|
||||
- `/tests/CMakeLists.txt`
|
||||
- `/reference/cantilever beam/cantilever beam.inp`
|
||||
|
||||
## 소유 파일
|
||||
|
||||
- Create: `/include/fesa/io/abaqus/input_syntax.hpp`
|
||||
- Create: `/include/fesa/io/abaqus/input_reader.hpp`
|
||||
- Create: `/src/fesa/io/abaqus/input_reader.cpp`
|
||||
- Create: `/tests/unit/io/abaqus/input_syntax_test.cpp`
|
||||
- Create: `/tests/unit/io/abaqus/input_reader_test.cpp`
|
||||
- Modify: `/src/fesa/CMakeLists.txt`
|
||||
- Modify: `/tests/CMakeLists.txt`
|
||||
|
||||
## 작업
|
||||
|
||||
keyword/data/comment lexical 및 syntax parsing만 위 exact paths에 구현하라. Semantic
|
||||
Domain mapping은 Step 12에 남긴다. 최소 계약은 다음과 같다.
|
||||
|
||||
```cpp
|
||||
struct KeywordParameter { std::string name; std::optional<std::string> value; };
|
||||
struct DataLine { std::vector<std::string> fields; SourceLocation location; };
|
||||
struct KeywordBlock {
|
||||
std::string canonicalName;
|
||||
std::string originalLine;
|
||||
std::vector<KeywordParameter> parameters;
|
||||
std::vector<DataLine> data;
|
||||
SourceLocation location;
|
||||
};
|
||||
struct ParsedInput { std::vector<KeywordBlock> blocks; };
|
||||
class AbaqusInputReader {
|
||||
public:
|
||||
Result<ParsedInput> read(const std::filesystem::path& inputPath) const;
|
||||
};
|
||||
```
|
||||
|
||||
Keyword와 parameter name은 uppercase canonical form으로 비교하되 parameter value와
|
||||
data label 원문을 보존한다. `**` comment line은 무시하고 blank line, comma-separated
|
||||
field, valueless parameter, line number와 file identity를 처리한다. Keyword/data 구분,
|
||||
malformed keyword, keyword 전 data line, unreadable file은 structured diagnostic으로
|
||||
반환한다. Wrapper 의미, keyword allowlist, numeric conversion은 구현하지 않는다.
|
||||
|
||||
Tests는 mixed case, comments, blank/empty trailing fields, parameters, source locations,
|
||||
malformed syntax, legacy cantilever syntax parse를 포함하고 `InpSyntax` regex로 등록한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
RED targeted command:
|
||||
|
||||
```powershell
|
||||
cmake --build .harness/build --config Debug --target fesa_tests
|
||||
ctest --test-dir .harness/build -C Debug -R InpSyntax --output-on-failure
|
||||
```
|
||||
|
||||
GREEN/VERIFY:
|
||||
|
||||
```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 -R InpSyntax --output-on-failure
|
||||
ctest --test-dir .harness/build -C Debug --show-only=json-v1
|
||||
ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
```
|
||||
|
||||
## 검증 절차
|
||||
|
||||
1. syntax tests를 먼저 추가하고 reader 부재 RED를 확인한다.
|
||||
2. semantic 판단이 없는 최소 reader로 GREEN을 만든다.
|
||||
3. legacy input을 read-only fixture로 읽고 전체 VERIFY를 수행한다.
|
||||
4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의
|
||||
Step 11 section에 실제 RED/GREEN/VERIFY command, exit code,
|
||||
핵심 output과 변경 파일을 기록한다.
|
||||
5. Step 11을 `completed`로 갱신하고 parsed syntax/source-location evidence를 summary에 기록한다.
|
||||
|
||||
## 금지사항
|
||||
|
||||
- B33/B31 또는 supported keyword 정책을 syntax reader에 넣지 마라. 이유: semantic mapper 책임이다.
|
||||
- source label/value case를 canonicalize하지 마라. 이유: stable source identity를 보존해야 한다.
|
||||
- `*INCLUDE` 같은 미승인 기능을 추가하지 마라. 이유: scope 밖이다.
|
||||
- reference input을 수정하지 마라. 이유: read-only fixture다.
|
||||
- 직접 commit하지 마라. 이유: Harness executor가 담당한다.
|
||||
@@ -0,0 +1,117 @@
|
||||
# Step 12: INP to Domain Mapping
|
||||
|
||||
## 담당 역할과 필수 스킬
|
||||
|
||||
- 담당 역할: `implementation-agent`
|
||||
- 필수 스킬: `fesa-cpp-msvc-tdd`
|
||||
- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다.
|
||||
|
||||
## 읽어야 할 파일
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/ARCHITECTURE.md`
|
||||
- `/docs/ADR.md`
|
||||
- `/docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md`
|
||||
- `/docs/io-definitions/linear-static-3d-euler-beam-io.md`
|
||||
- `/docs/implementation-plans/linear-static-3d-euler-beam.md`
|
||||
- `/include/fesa/model/model_types.hpp`
|
||||
- `/include/fesa/model/domain.hpp`
|
||||
- `/src/fesa/model/domain.cpp`
|
||||
- `/tests/unit/model/domain_test.cpp`
|
||||
- `/include/fesa/io/abaqus/input_syntax.hpp`
|
||||
- `/include/fesa/io/abaqus/input_reader.hpp`
|
||||
- `/src/fesa/io/abaqus/input_reader.cpp`
|
||||
- `/tests/unit/io/abaqus/input_reader_test.cpp`
|
||||
- `/reference/cantilever beam/cantilever beam.inp`
|
||||
|
||||
## 소유 파일
|
||||
|
||||
- Create: `/include/fesa/io/abaqus/domain_mapper.hpp`
|
||||
- Create: `/src/fesa/io/abaqus/domain_mapper.cpp`
|
||||
- Create: `/tests/unit/io/abaqus/domain_mapper_test.cpp`
|
||||
- Modify: `/src/fesa/CMakeLists.txt`
|
||||
- Modify: `/tests/CMakeLists.txt`
|
||||
|
||||
## 작업
|
||||
|
||||
ParsedInput을 검증된 immutable Domain으로 바꾸는 semantic mapper를 구현하라.
|
||||
|
||||
```cpp
|
||||
class AbaqusDomainMapper {
|
||||
public:
|
||||
Result<Domain> map(const ParsedInput& input) const;
|
||||
};
|
||||
```
|
||||
|
||||
지원 범위는 승인 I/O contract와 정확히 같아야 한다.
|
||||
|
||||
- `*HEADING`, `*PART`/`*END PART`, `*NODE`, `*ELEMENT, TYPE=B33`,
|
||||
`*NSET`/`*ELSET` 및 `GENERATE`, `*MATERIAL`/`*ELASTIC`,
|
||||
`*BEAM GENERAL SECTION, SECTION=GENERAL`, `*SECTION POINTS`,
|
||||
`*ASSEMBLY`/`*END ASSEMBLY`, `*INSTANCE`/`*END INSTANCE`,
|
||||
`*BOUNDARY`, `*CLOAD`, `*STEP`/`*STATIC`/`*END STEP`를 mapping한다.
|
||||
- 같은 part의 여러 identity instance를 deterministic stable internal IDs로 expand하고
|
||||
`SourceEntityId {instance_name, source_label}`를 보존한다.
|
||||
- assembly set의 `INSTANCE` parameter와 node/set target을 해석한다.
|
||||
- `A,I11,I12,I22,J`, `E,nu`, `G=E/(2*(1+nu))`, `Iy=I11`, `Iz=I22`,
|
||||
`n1 -> local y`를 mapping한다. `E>0`, `-1<nu<0.5`, 계산한 `G>0`과 section
|
||||
properties의 positivity를 검증한다.
|
||||
- `*STEP`의 `NLGEOM`은 absent/`NO`만 accept하고 `YES`는 model diagnostic으로 거부한다.
|
||||
`*STATIC`의 1개 또는 2–4개 time-control data field를 finite positive 값으로 읽되 V0는
|
||||
하나의 final frame 0만 만든다. Step 앞의 model-level `*BOUNDARY`는 sole static step에
|
||||
활성화하고 step 안 `*CLOAD`와 함께 `StaticStepDefinition`에 연결한다.
|
||||
- B31은 `unsupported-element-formulation`, instance translation/rotation data는
|
||||
`unsupported-instance-transform` diagnostic으로 거부한다. Second step, nested assembly,
|
||||
`I12!=0`, invalid DOF, duplicate label, dangling target/reference, nonpositive properties,
|
||||
invalid geometry에도 설계/I/O contract가 정한 structured diagnostic code를 반환한다.
|
||||
- `*PREPRINT`, `*RESTART`, `*TRANSVERSE SHEAR STIFFNESS`, `*OUTPUT, FIELD`,
|
||||
`*OUTPUT, HISTORY`, `*NODE OUTPUT`, `*ELEMENT OUTPUT`, `*CONTACT OUTPUT`와 그
|
||||
output-variable data는 warning으로 보존하고 무시한다. 이 allowlist 밖 unknown keyword는
|
||||
error다. FESA default outputs를 output request로 필터링하지 않는다.
|
||||
|
||||
Tests는 모든 supported keyword의 positive path, mixed case, Generate, multiple identity
|
||||
instances, allowlist warning, unknown keyword, B31 rejection, transform/nested/multi-step,
|
||||
duplicate/dangling/invalid numeric와 approved legacy input mapping을 포함하고
|
||||
`InpDomainMapping` regex로 등록한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
RED targeted command:
|
||||
|
||||
```powershell
|
||||
cmake --build .harness/build --config Debug --target fesa_tests
|
||||
ctest --test-dir .harness/build -C Debug -R InpDomainMapping --output-on-failure
|
||||
```
|
||||
|
||||
GREEN/VERIFY:
|
||||
|
||||
```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 -R InpDomainMapping --output-on-failure
|
||||
ctest --test-dir .harness/build -C Debug --show-only=json-v1
|
||||
ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
```
|
||||
|
||||
## 검증 절차
|
||||
|
||||
1. semantic positive/negative tests를 production mapper보다 먼저 작성하고 RED를 확인한다.
|
||||
2. 승인 subset에 필요한 최소 mapping/validation만 구현해 GREEN을 만든다.
|
||||
3. diagnostic field/order와 Domain non-mutation을 점검하고 전체 VERIFY를 수행한다.
|
||||
4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의
|
||||
Step 12 section에 실제 RED/GREEN/VERIFY command, exit code,
|
||||
핵심 output과 변경 파일을 기록한다.
|
||||
5. Step 12를 `completed`로 갱신하고 supported mapping/negative diagnostics를 summary에 기록한다.
|
||||
|
||||
## 금지사항
|
||||
|
||||
- B31을 Euler element로 alias하지 마라. 이유: 물리 formulation 의미가 다르다.
|
||||
- transform을 무시하거나 fallback local axis를 선택하지 마라. 이유: 입력 의미를 왜곡한다.
|
||||
- `*DLOAD` 또는 multiple-step propagation을 구현하지 마라. 이유: 승인 범위 밖이다.
|
||||
- reference input/CSV를 수정하지 마라. 이유: read-only baseline이다.
|
||||
- 직접 commit하지 마라. 이유: Harness executor가 담당한다.
|
||||
@@ -0,0 +1,97 @@
|
||||
# Step 13: AnalysisModel Active View
|
||||
|
||||
## 담당 역할과 필수 스킬
|
||||
|
||||
- 담당 역할: `implementation-agent`
|
||||
- 필수 스킬: `fesa-cpp-msvc-tdd`
|
||||
|
||||
## 읽어야 할 파일
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/ARCHITECTURE.md`
|
||||
- `/docs/ADR.md`
|
||||
- `/docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- `/docs/implementation-plans/linear-static-3d-euler-beam.md`
|
||||
- `/include/fesa/model/model_types.hpp`
|
||||
- `/include/fesa/model/domain.hpp`
|
||||
- `/src/fesa/model/domain.cpp`
|
||||
- `/include/fesa/io/abaqus/domain_mapper.hpp`
|
||||
- `/src/fesa/io/abaqus/domain_mapper.cpp`
|
||||
- `/tests/unit/io/abaqus/domain_mapper_test.cpp`
|
||||
- `/src/fesa/CMakeLists.txt`
|
||||
- `/tests/CMakeLists.txt`
|
||||
|
||||
## 소유 파일
|
||||
|
||||
- Create: `/include/fesa/analysis/analysis_model.hpp`
|
||||
- Create: `/src/fesa/analysis/analysis_model.cpp`
|
||||
- Create: `/tests/unit/analysis/analysis_model_test.cpp`
|
||||
- Modify: `/src/fesa/CMakeLists.txt`
|
||||
- Modify: `/tests/CMakeLists.txt`
|
||||
|
||||
## 작업
|
||||
|
||||
단일 static step에서 활성 entity를 stable index/reference view로 분류하는
|
||||
`AnalysisModel`만 구현하라.
|
||||
|
||||
```cpp
|
||||
class AnalysisModel {
|
||||
public:
|
||||
static Result<AnalysisModel> create(const Domain& domain);
|
||||
const Domain& domain() const noexcept;
|
||||
const StaticStepDefinition& step() const noexcept;
|
||||
const std::vector<EntityIndex>& activeElements() const noexcept;
|
||||
const std::vector<EntityIndex>& activeMaterials() const noexcept;
|
||||
const std::vector<EntityIndex>& activeSections() const noexcept;
|
||||
const std::vector<EntityIndex>& activeBoundaryConditions() const noexcept;
|
||||
const std::vector<EntityIndex>& activeLoads() const noexcept;
|
||||
};
|
||||
```
|
||||
|
||||
AnalysisModel은 Domain 객체나 semantic entity를 복사·수정하지 않고, 자체 소유가 필요한
|
||||
경우 stable ID 목록만 가진다. Element에서 reachable material/section을 deterministic한
|
||||
internal index 순으로 deduplicate한다. 정확히 하나의 static step만 허용하며 missing 또는
|
||||
multiple step은 structured diagnostic이다.
|
||||
|
||||
Tests는 active classification, stable ordering/deduplication, reference address identity,
|
||||
Domain 불변성, missing/multiple step rejection을 포함하고 `AnalysisModel` regex로 등록한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
RED targeted command:
|
||||
|
||||
```powershell
|
||||
cmake --build .harness/build --config Debug --target fesa_tests
|
||||
ctest --test-dir .harness/build -C Debug -R AnalysisModel --output-on-failure
|
||||
```
|
||||
|
||||
GREEN/VERIFY:
|
||||
|
||||
```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 -R AnalysisModel --output-on-failure
|
||||
ctest --test-dir .harness/build -C Debug --show-only=json-v1
|
||||
ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
```
|
||||
|
||||
## 검증 절차
|
||||
|
||||
1. active-view tests를 먼저 작성하고 missing class/behavior RED를 확인한다.
|
||||
2. stable ID view의 최소 구현으로 GREEN을 만든다.
|
||||
3. Domain address/state 불변성과 전체 MSVC x64 Debug VERIFY를 확인한다.
|
||||
4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의
|
||||
Step 13 section에 실제 RED/GREEN/VERIFY command, exit code,
|
||||
핵심 output과 변경 파일을 기록한다.
|
||||
5. Step 13을 `completed`로 바꾸고 active view/non-copy evidence를 summary에 기록한다.
|
||||
|
||||
## 금지사항
|
||||
|
||||
- Domain entity를 AnalysisModel에 복제하지 마라. 이유: source of truth가 분산된다.
|
||||
- load/BC propagation이나 multi-step activation을 추가하지 마라. 이유: V0는 single step이다.
|
||||
- equation number나 numeric state를 저장하지 마라. 이유: DofManager/AnalysisState 책임이다.
|
||||
- 직접 commit하지 마라. 이유: Harness executor가 담당한다.
|
||||
@@ -0,0 +1,104 @@
|
||||
# Step 14: DofManager
|
||||
|
||||
## 담당 역할과 필수 스킬
|
||||
|
||||
- 담당 역할: `implementation-agent`
|
||||
- 필수 스킬: `fesa-cpp-msvc-tdd`
|
||||
- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다.
|
||||
|
||||
## 읽어야 할 파일
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/ARCHITECTURE.md`
|
||||
- `/docs/ADR.md`
|
||||
- `/docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- `/docs/io-definitions/linear-static-3d-euler-beam-io.md`
|
||||
- `/docs/implementation-plans/linear-static-3d-euler-beam.md`
|
||||
- `/include/fesa/model/domain.hpp`
|
||||
- `/include/fesa/analysis/analysis_model.hpp`
|
||||
- `/src/fesa/analysis/analysis_model.cpp`
|
||||
- `/tests/unit/analysis/analysis_model_test.cpp`
|
||||
- `/src/fesa/CMakeLists.txt`
|
||||
- `/tests/CMakeLists.txt`
|
||||
|
||||
## 소유 파일
|
||||
|
||||
- Create: `/include/fesa/fem/dof_manager.hpp`
|
||||
- Create: `/src/fesa/fem/dof_manager.cpp`
|
||||
- Create: `/tests/unit/fem/dof_manager_test.cpp`
|
||||
- Modify: `/src/fesa/CMakeLists.txt`
|
||||
- Modify: `/tests/CMakeLists.txt`
|
||||
|
||||
## 작업
|
||||
|
||||
node별 여섯 DOF, prescribed constraints, full/free numbering, element scatter map와 sparse
|
||||
pattern을 단독 소유하는 `DofManager`를 구현하라.
|
||||
|
||||
```cpp
|
||||
enum class DofComponent : std::uint8_t { ux, uy, uz, urx, ury, urz };
|
||||
struct SparsePattern { std::vector<std::size_t> rowOffsets;
|
||||
std::vector<std::size_t> columnIndices; };
|
||||
class DofManager {
|
||||
public:
|
||||
static Result<DofManager> create(const AnalysisModel& model);
|
||||
std::size_t fullDofCount() const noexcept;
|
||||
std::size_t freeDofCount() const noexcept;
|
||||
std::size_t constrainedDofCount() const noexcept;
|
||||
std::size_t fullDof(EntityIndex node, DofComponent component) const;
|
||||
std::optional<std::size_t> freeEquation(std::size_t fullDof) const;
|
||||
const std::array<std::size_t, 12>& elementScatter(EntityIndex element) const;
|
||||
const std::vector<std::size_t>& freeDofs() const noexcept;
|
||||
const std::vector<std::size_t>& constrainedDofs() const noexcept;
|
||||
const Vector& prescribedValues() const noexcept;
|
||||
const SparsePattern& sparsePattern() const noexcept;
|
||||
};
|
||||
```
|
||||
|
||||
Node internal index와 fixed component 순서로 full DOF를 부여하고, free/constrained mapping도
|
||||
stable하게 만든다. Boundary target expansion과 overlapping equal prescriptions를 처리하고,
|
||||
서로 다른 prescribed value conflict는 diagnostic으로 거부한다. Sparse pattern은 active
|
||||
element scatter에서 생성하고 각 row column을 sorted unique로 유지한다. Node/Element model
|
||||
objects를 수정하지 않는다. `prescribedValues()`는 `constrainedDofCount()` 크기이며
|
||||
`constrainedDofs()`와 동일 순서의 `dc`를 반환한다.
|
||||
|
||||
Tests는 6-DOF numbering, set expansion, zero/nonzero constraints, overlapping/conflicting BC,
|
||||
free equation mapping, 12-DOF element scatter, CSR pattern sorted uniqueness, full/reduced
|
||||
round-trip를 포함하고 `DofManager` regex로 등록한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
```powershell
|
||||
cmake --build .harness/build --config Debug --target fesa_tests
|
||||
ctest --test-dir .harness/build -C Debug -R DofManager --output-on-failure
|
||||
```
|
||||
|
||||
위 command의 RED를 확인한 뒤 구현하고 다음 GREEN/VERIFY를 실행한다.
|
||||
|
||||
```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 -R DofManager --output-on-failure
|
||||
ctest --test-dir .harness/build -C Debug --show-only=json-v1
|
||||
ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
```
|
||||
|
||||
## 검증 절차
|
||||
|
||||
1. numbering/constraint/pattern tests를 먼저 작성하고 RED를 확인한다.
|
||||
2. deterministic mapping에 필요한 최소 구현으로 GREEN을 만든다.
|
||||
3. model objects에 equation ID가 추가되지 않았는지 review하고 full VERIFY를 수행한다.
|
||||
4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의
|
||||
Step 14 section에 실제 RED/GREEN/VERIFY command, exit code,
|
||||
핵심 output과 변경 파일을 기록한다.
|
||||
5. Step 14를 `completed`로 갱신하고 numbering/pattern evidence를 summary에 기록한다.
|
||||
|
||||
## 금지사항
|
||||
|
||||
- equation ID를 Node나 Element에 저장하지 마라. 이유: DofManager 단독 ownership 계약이다.
|
||||
- penalty method, MPC, RBE를 추가하지 마라. 이유: V0 essential elimination 범위 밖이다.
|
||||
- sparse numeric values를 저장하지 마라. 이유: assembly step 책임이다.
|
||||
- 직접 commit하지 마라. 이유: Harness executor가 담당한다.
|
||||
@@ -0,0 +1,103 @@
|
||||
# Step 15: AnalysisState
|
||||
|
||||
## 담당 역할과 필수 스킬
|
||||
|
||||
- 담당 역할: `implementation-agent`
|
||||
- 필수 스킬: `fesa-cpp-msvc-tdd`
|
||||
- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다.
|
||||
|
||||
## 읽어야 할 파일
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/ARCHITECTURE.md`
|
||||
- `/docs/ADR.md`
|
||||
- `/docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- `/docs/io-definitions/linear-static-3d-euler-beam-io.md`
|
||||
- `/docs/implementation-plans/linear-static-3d-euler-beam.md`
|
||||
- `/include/fesa/math/vector.hpp`
|
||||
- `/include/fesa/analysis/analysis_model.hpp`
|
||||
- `/include/fesa/fem/dof_manager.hpp`
|
||||
- `/src/fesa/fem/dof_manager.cpp`
|
||||
|
||||
## 소유 파일
|
||||
|
||||
- Create: `/include/fesa/results/result_records.hpp`
|
||||
- Create: `/include/fesa/analysis/analysis_state.hpp`
|
||||
- Create: `/src/fesa/analysis/analysis_state.cpp`
|
||||
- Create: `/tests/unit/results/result_records_test.cpp`
|
||||
- Create: `/tests/unit/analysis/analysis_state_test.cpp`
|
||||
- Modify: `/src/fesa/CMakeLists.txt`
|
||||
- Modify: `/tests/CMakeLists.txt`
|
||||
|
||||
## 작업
|
||||
|
||||
V0에서 실제 할당하는 mutable analysis quantities와 output row identity를 소유하는
|
||||
`AnalysisState`를 위 exact paths에 구현하라. 최소 계약은 다음 의미를 가진다.
|
||||
|
||||
```cpp
|
||||
struct StepFrameIdentity { std::string stepName; std::size_t frameIndex; };
|
||||
struct EndpointResultRow { EntityIndex element; int endpoint; SourceEntityId node;
|
||||
std::array<double, 6> endAction;
|
||||
std::array<double, 4> sectionResultant; };
|
||||
struct GaussResultRow { EntityIndex element; int gaussPoint;
|
||||
std::array<double, 4> generalizedStrain;
|
||||
std::array<double, 4> generalizedResultant; };
|
||||
struct StressS11Row { EntityIndex element; int gaussPoint; std::size_t sectionPoint;
|
||||
double x1; double x2; double s11; std::string source; };
|
||||
class AnalysisState {
|
||||
public:
|
||||
static AnalysisState create(const DofManager& dofs, StepFrameIdentity identity);
|
||||
Vector& displacement() noexcept;
|
||||
Vector& externalForce() noexcept;
|
||||
Vector& internalForce() noexcept;
|
||||
Vector& residual() noexcept;
|
||||
Vector& reaction() noexcept;
|
||||
// const overloads and owned element-recovery row accessors
|
||||
};
|
||||
```
|
||||
|
||||
각 full vector 크기는 `fullDofCount()`이고 zero-initialized다. Reaction은 constrained value를
|
||||
동일 full-index space에 두며 free component는 residual sanity에 사용할 수 있어야 한다.
|
||||
Endpoint/Gauss/stress row는 stable element/point order로 저장한다. Velocity, acceleration,
|
||||
temperature, iteration history, nonlinear state storage를 만들지 않는다.
|
||||
|
||||
Tests는 allocation/zero initialization, independent ownership, step/frame identity, row ordering,
|
||||
copy/move policy, forbidden-state API 부재 review를 포함하고 `AnalysisState` regex로 등록한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
```powershell
|
||||
cmake --build .harness/build --config Debug --target fesa_tests
|
||||
ctest --test-dir .harness/build -C Debug -R AnalysisState --output-on-failure
|
||||
```
|
||||
|
||||
RED 후 GREEN/VERIFY:
|
||||
|
||||
```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 -R AnalysisState --output-on-failure
|
||||
ctest --test-dir .harness/build -C Debug --show-only=json-v1
|
||||
ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
```
|
||||
|
||||
## 검증 절차
|
||||
|
||||
1. state ownership tests를 먼저 작성하고 RED를 확인한다.
|
||||
2. V0에서 필요한 field만 최소 구현해 GREEN을 만든다.
|
||||
3. 전체 VERIFY와 output row identity/order를 확인한다.
|
||||
4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의
|
||||
Step 15 section에 실제 RED/GREEN/VERIFY command, exit code,
|
||||
핵심 output과 변경 파일을 기록한다.
|
||||
5. Step 15를 `completed`로 갱신하고 allocated fields/omitted fields를 summary에 기록한다.
|
||||
|
||||
## 금지사항
|
||||
|
||||
- velocity, acceleration, temperature, nonlinear iteration history를 할당하지 마라. 이유: V0 범위 밖이다.
|
||||
- Domain 정의를 state에 복사하지 마라. 이유: model/state ownership을 분리해야 한다.
|
||||
- HDF5 API를 state에 노출하지 마라. 이유: ResultsWriter adapter 책임이다.
|
||||
- 직접 commit하지 마라. 이유: Harness executor가 담당한다.
|
||||
@@ -0,0 +1,113 @@
|
||||
# Step 16: 3D Euler Beam Element
|
||||
|
||||
## 담당 역할과 필수 스킬
|
||||
|
||||
- 담당 역할: `implementation-agent`
|
||||
- 필수 스킬: `fesa-cpp-msvc-tdd`
|
||||
|
||||
## 읽어야 할 파일
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/ARCHITECTURE.md`
|
||||
- `/docs/ADR.md`
|
||||
- `/docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md`
|
||||
- `/docs/numerical-reviews/linear-static-3d-euler-beam-review.md`
|
||||
- `/docs/io-definitions/linear-static-3d-euler-beam-io.md`
|
||||
- `/docs/implementation-plans/linear-static-3d-euler-beam.md`
|
||||
- `/include/fesa/math/vector.hpp`
|
||||
- `/include/fesa/math/matrix.hpp`
|
||||
- `/include/fesa/model/model_types.hpp`
|
||||
- `/include/fesa/results/result_records.hpp`
|
||||
- `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`
|
||||
|
||||
## 소유 파일
|
||||
|
||||
- Create: `/include/fesa/elements/euler_beam_3d.hpp`
|
||||
- Create: `/src/fesa/elements/euler_beam_3d.cpp`
|
||||
- Create: `/tests/unit/elements/euler_beam_3d_test.cpp`
|
||||
- Modify: `/src/fesa/CMakeLists.txt`
|
||||
- Modify: `/tests/CMakeLists.txt`
|
||||
|
||||
## 작업
|
||||
|
||||
승인 formulation을 그대로 구현하는 2-node `EulerBeam3D` kernel을 작성하라.
|
||||
|
||||
```cpp
|
||||
struct ConstantLocalLineLoad { double px; double py; double pz; double mx; };
|
||||
struct BeamStressPoint { int gaussPoint; std::size_t sectionPoint; double x1; double x2;
|
||||
double s11; std::string source; };
|
||||
struct BeamRecovery {
|
||||
std::array<std::array<double, 6>, 2> equilibriumEndActions;
|
||||
std::array<std::array<double, 4>, 2> endpointSectionResultants;
|
||||
std::array<std::array<double, 4>, 2> gaussGeneralizedStrains;
|
||||
std::array<std::array<double, 4>, 2> gaussGeneralizedResultants;
|
||||
std::vector<BeamStressPoint> stressPoints;
|
||||
};
|
||||
class EulerBeam3D {
|
||||
public:
|
||||
static Result<EulerBeam3D> create(/* two nodes, guide, E, G, A, Iy, Iz, J, section points */);
|
||||
Matrix localStiffness() const;
|
||||
Matrix globalStiffness() const;
|
||||
Vector localEquivalentLoad(const ConstantLocalLineLoad& load) const;
|
||||
BeamRecovery recover(const Vector& globalElementDisplacement) const;
|
||||
};
|
||||
```
|
||||
|
||||
- Local DOF order와 부호는 formulation의 12-component order를 그대로 쓴다.
|
||||
- `R` rows는 `(ex,ey,ez)`, `T=diag(R,R,R,R)`, `dl=T*dg`, `Kg=T^T*Kl*T`다.
|
||||
- `Kl`은 두 Gauss point로 `B^T D B`를 적분하고 closed-form과 normalized `1e-12`로
|
||||
검증한다. Production에서 1-point reduced integration을 사용하지 않는다.
|
||||
- `coordinate_scale=max(1,norm(X1),norm(X2))`에 대해
|
||||
`L>1e-12*coordinate_scale`, `norm(a_perp)>1e-12*max(1,norm(a))`를 요구한다.
|
||||
`E,G,A,Iy,Iz,J>0`을 검증하고 fallback axis를 쓰지 않는다.
|
||||
- line-load kernel은 constant `[px,py,pz,mx]` consistent vector만 제공한다. Parser/CLI load
|
||||
object로 연결하지 않는다.
|
||||
- Recovery는 equilibrium end action과 section resultants를 구분하고 two Gauss generalized
|
||||
values 및 section point `S11=E(epsilon0+x2*kappa_y-x1*kappa_z)`를 생성한다. Element
|
||||
identity가 없는 kernel-level `BeamStressPoint`를 Step 22가 `StressS11Row`로 감싼다.
|
||||
Section point가 없으면 `(0,0), source=fesa-default` 하나를 사용한다.
|
||||
|
||||
Tests는 Hermite endpoint/derivative, B matrix, Gauss/closed stiffness, symmetry, six rigid
|
||||
modes/rank 6, positive deformation energy, transform orthogonality/determinant/energy invariance,
|
||||
line-load signs, axial/torsion/y-z bending analytical displacement/recovery, invalid geometry와
|
||||
stress formula를 포함하고 `EulerBeam3D` regex로 등록한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
```powershell
|
||||
cmake --build .harness/build --config Debug --target fesa_tests
|
||||
ctest --test-dir .harness/build -C Debug -R EulerBeam3D --output-on-failure
|
||||
```
|
||||
|
||||
RED 후 GREEN/VERIFY:
|
||||
|
||||
```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 -R EulerBeam3D --output-on-failure
|
||||
ctest --test-dir .harness/build -C Debug --show-only=json-v1
|
||||
ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
```
|
||||
|
||||
## 검증 절차
|
||||
|
||||
1. formulation invariant/analytical tests를 먼저 작성해 RED를 확인한다.
|
||||
2. 가장 작은 kernel 구현으로 GREEN을 만들고 normalized tolerance를 그대로 적용한다.
|
||||
3. 수식/코드 component ordering을 대조하고 전체 MSVC x64 Debug VERIFY를 수행한다.
|
||||
4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의
|
||||
Step 16 section에 실제 RED/GREEN/VERIFY command, exit code,
|
||||
핵심 output과 변경 파일을 기록한다.
|
||||
5. Step 16을 `completed`로 갱신하고 element/recovery test evidence를 summary에 기록한다.
|
||||
|
||||
## 금지사항
|
||||
|
||||
- B31/Timoshenko shear deformation을 섞지 마라. 이유: 승인 formulation이 아니다.
|
||||
- 1-point bending integration이나 fallback orientation을 쓰지 마라. 이유: spurious mode/의미 왜곡 위험이다.
|
||||
- transverse/torsional shear stress를 만들어내지 마라. 이유: section 정보가 부족하고 범위 밖이다.
|
||||
- `*DLOAD` parser/CLI 지원을 추가하지 마라. 이유: kernel test만 승인됐다.
|
||||
- 직접 commit하지 마라. 이유: Harness executor가 담당한다.
|
||||
@@ -0,0 +1,96 @@
|
||||
# Step 17: oneTBB ParallelFor Adapter
|
||||
|
||||
## 담당 역할과 필수 스킬
|
||||
|
||||
- 담당 역할: `implementation-agent`
|
||||
- 필수 스킬: `fesa-cpp-msvc-tdd`
|
||||
- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다.
|
||||
|
||||
## 읽어야 할 파일
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/ARCHITECTURE.md`
|
||||
- `/docs/ADR.md`
|
||||
- `/docs/implementation-plans/linear-static-3d-euler-beam.md`
|
||||
- `/include/fesa/core/status.hpp`
|
||||
- `/include/fesa/elements/euler_beam_3d.hpp`
|
||||
- `/src/fesa/elements/euler_beam_3d.cpp`
|
||||
- `/tests/unit/elements/euler_beam_3d_test.cpp`
|
||||
- `/cmake/FesaDependencies.cmake`
|
||||
- `/src/fesa/CMakeLists.txt`
|
||||
- `/tests/CMakeLists.txt`
|
||||
|
||||
## 소유 파일
|
||||
|
||||
- Create: `/include/fesa/assembly/parallel_for.hpp`
|
||||
- Create: `/src/fesa/assembly/parallel_for.cpp`
|
||||
- Create: `/tests/unit/assembly/parallel_for_test.cpp`
|
||||
- Modify: `/src/fesa/CMakeLists.txt`
|
||||
- Modify: `/tests/CMakeLists.txt`
|
||||
|
||||
## 작업
|
||||
|
||||
solver core에서 oneTBB header/type을 숨기는 element-local loop adapter를 구현하라.
|
||||
|
||||
```cpp
|
||||
class ParallelFor {
|
||||
public:
|
||||
virtual ~ParallelFor() = default;
|
||||
virtual void execute(std::size_t count,
|
||||
const std::function<void(std::size_t)>& body) const = 0;
|
||||
};
|
||||
class SerialParallelFor final : public ParallelFor { /* same contract */ };
|
||||
class TbbParallelFor final : public ParallelFor { /* oneTBB implementation in .cpp */ };
|
||||
```
|
||||
|
||||
각 index는 정확히 한 번 처리하고 `count==0`은 no-op이다. Element-local 결과는 호출자가
|
||||
index-addressed storage에 기록해 scheduling과 무관한 ordering을 갖게 한다. Adapter는
|
||||
전역 sparse matrix write나 reduction을 수행하지 않는다. Oversubscription 정책은
|
||||
implementation comment와 test/implementation report에 남기고, 이 step에서 임의 global
|
||||
thread setting을 바꾸지 않는다.
|
||||
|
||||
Tests는 zero/one/many counts, exact-once, serial/TBB semantic equivalence, stable
|
||||
index-addressed output, exception propagation policy를 검증하고 `ParallelFor` regex로 등록한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
```powershell
|
||||
cmake --build .harness/build --config Debug --target fesa_tests
|
||||
ctest --test-dir .harness/build -C Debug -R ParallelFor --output-on-failure
|
||||
```
|
||||
|
||||
RED 후 GREEN/VERIFY:
|
||||
|
||||
```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 -R ParallelFor --output-on-failure
|
||||
ctest --test-dir .harness/build -C Debug --show-only=json-v1
|
||||
ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
$leaks = rg -n "oneapi/tbb|tbb/" include/fesa
|
||||
if ($LASTEXITCODE -eq 0) { throw "oneTBB API leaked into public headers:`n$leaks" }
|
||||
if ($LASTEXITCODE -ne 1) { throw 'Public-header dependency scan failed' }
|
||||
```
|
||||
|
||||
마지막 scan은 public header에서 no-match여야 한다.
|
||||
|
||||
## 검증 절차
|
||||
|
||||
1. adapter conformance tests를 먼저 작성하고 RED를 확인한다.
|
||||
2. Serial과 oneTBB 최소 구현으로 GREEN을 만든다.
|
||||
3. public boundary scan과 전체 VERIFY를 실행한다.
|
||||
4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의
|
||||
Step 17 section에 실제 RED/GREEN/VERIFY command, exit code,
|
||||
핵심 output과 변경 파일을 기록한다.
|
||||
5. Step 17을 `completed`로 갱신하고 deterministic-use contract를 summary에 기록한다.
|
||||
|
||||
## 금지사항
|
||||
|
||||
- 전역 sparse storage에 병렬 write하지 마라. 이유: ordering/race는 Step 18이 통제한다.
|
||||
- TBB type/header를 public API에 노출하지 마라. 이유: adapter boundary 계약이다.
|
||||
- process-wide thread count를 임의 변경하지 마라. 이유: MKL/TBB policy가 불명확해진다.
|
||||
- 직접 commit하지 마라. 이유: Harness executor가 담당한다.
|
||||
@@ -0,0 +1,109 @@
|
||||
# Step 18: Deterministic Sparse Assembly
|
||||
|
||||
## 담당 역할과 필수 스킬
|
||||
|
||||
- 담당 역할: `implementation-agent`
|
||||
- 필수 스킬: `fesa-cpp-msvc-tdd`
|
||||
- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다.
|
||||
|
||||
## 읽어야 할 파일
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/ARCHITECTURE.md`
|
||||
- `/docs/ADR.md`
|
||||
- `/docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- `/docs/implementation-plans/linear-static-3d-euler-beam.md`
|
||||
- `/include/fesa/math/vector.hpp`
|
||||
- `/include/fesa/math/matrix.hpp`
|
||||
- `/include/fesa/fem/dof_manager.hpp`
|
||||
- `/include/fesa/elements/euler_beam_3d.hpp`
|
||||
- `/include/fesa/assembly/parallel_for.hpp`
|
||||
- `/src/fesa/assembly/parallel_for.cpp`
|
||||
|
||||
## 소유 파일
|
||||
|
||||
- Create: `/include/fesa/math/sparse_matrix.hpp`
|
||||
- Create: `/src/fesa/math/sparse_matrix.cpp`
|
||||
- Create: `/include/fesa/assembly/sparse_assembler.hpp`
|
||||
- Create: `/src/fesa/assembly/sparse_assembler.cpp`
|
||||
- Create: `/tests/unit/math/sparse_matrix_test.cpp`
|
||||
- Create: `/tests/unit/assembly/sparse_assembler_test.cpp`
|
||||
- Modify: `/src/fesa/CMakeLists.txt`
|
||||
- Modify: `/tests/CMakeLists.txt`
|
||||
|
||||
## 작업
|
||||
|
||||
element-local stiffness contributions를 deterministic하게 COO로 수집하고 0-based CSR로
|
||||
finalize하는 별도 sparse module을 구현하라.
|
||||
|
||||
```cpp
|
||||
struct CooContribution {
|
||||
std::size_t row;
|
||||
std::size_t column;
|
||||
double value;
|
||||
std::size_t elementOrder;
|
||||
std::size_t localOrder;
|
||||
};
|
||||
class SparseMatrix {
|
||||
public:
|
||||
static Result<SparseMatrix> fromCoo(std::size_t rows, std::size_t columns,
|
||||
std::vector<CooContribution> contributions,
|
||||
const SparsePattern& expectedPattern);
|
||||
std::size_t rows() const noexcept;
|
||||
std::size_t columns() const noexcept;
|
||||
const std::vector<std::size_t>& rowOffsets() const noexcept;
|
||||
const std::vector<std::size_t>& columnIndices() const noexcept;
|
||||
const std::vector<double>& values() const noexcept;
|
||||
Vector multiply(const Vector& rhs) const;
|
||||
Status validate() const;
|
||||
};
|
||||
```
|
||||
|
||||
`SparseMatrix`는 `Matrix`를 상속하지 않는다. COO는 `(row,column,elementOrder,localOrder)`로
|
||||
stable sort한 후 duplicate를 고정 순서로 합산한다. Zero value 보존/제거 policy는
|
||||
implementation plan과 I/O-independent math contract에 맞춰 하나로 고정하고 test한다.
|
||||
Row offsets/column indices는 0-based, columns sorted unique, sizes/ranges consistent해야 한다.
|
||||
Element stiffness 계산은 ParallelFor로 index-addressed buffer에 넣고 global reduction은
|
||||
element internal index 순서로 수행한다.
|
||||
|
||||
Tests는 known matrix CSR/matrix-vector product, duplicate sum, invalid index/pattern, empty row, symmetry,
|
||||
serial-vs-TBB byte-identical row/column/value vectors, repeated runs를 포함하고
|
||||
`SparseAssembly` regex로 등록한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
```powershell
|
||||
cmake --build .harness/build --config Debug --target fesa_tests
|
||||
ctest --test-dir .harness/build -C Debug -R SparseAssembly --output-on-failure
|
||||
```
|
||||
|
||||
RED 후 GREEN/VERIFY:
|
||||
|
||||
```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 -R SparseAssembly --output-on-failure
|
||||
ctest --test-dir .harness/build -C Debug --show-only=json-v1
|
||||
ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
```
|
||||
|
||||
## 검증 절차
|
||||
|
||||
1. CSR invariant/determinism tests를 먼저 작성하고 RED를 확인한다.
|
||||
2. ordered COO reduction과 CSR ownership의 최소 구현으로 GREEN을 만든다.
|
||||
3. repeated serial/TBB equivalence와 전체 VERIFY를 수행한다.
|
||||
4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의
|
||||
Step 18 section에 실제 RED/GREEN/VERIFY command, exit code,
|
||||
핵심 output과 변경 파일을 기록한다.
|
||||
5. Step 18을 `completed`로 갱신하고 CSR/determinism evidence를 summary에 기록한다.
|
||||
|
||||
## 금지사항
|
||||
|
||||
- `SparseMatrix`를 dense `Matrix`에서 상속하지 마라. 이유: storage/backend 의미가 다르다.
|
||||
- TBB worker가 shared CSR value에 직접 쓰게 하지 마라. 이유: race와 nondeterminism이 생긴다.
|
||||
- PARDISO-specific descriptor/index type을 public sparse API에 넣지 마라. 이유: Step 20 adapter 책임이다.
|
||||
- 직접 commit하지 마라. 이유: Harness executor가 담당한다.
|
||||
@@ -0,0 +1,99 @@
|
||||
# Step 19: Essential Constraints and Matrix Partition
|
||||
|
||||
## 담당 역할과 필수 스킬
|
||||
|
||||
- 담당 역할: `implementation-agent`
|
||||
- 필수 스킬: `fesa-cpp-msvc-tdd`
|
||||
- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다.
|
||||
|
||||
## 읽어야 할 파일
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/ARCHITECTURE.md`
|
||||
- `/docs/ADR.md`
|
||||
- `/docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md`
|
||||
- `/docs/implementation-plans/linear-static-3d-euler-beam.md`
|
||||
- `/include/fesa/math/vector.hpp`
|
||||
- `/include/fesa/math/sparse_matrix.hpp`
|
||||
- `/include/fesa/fem/dof_manager.hpp`
|
||||
- `/include/fesa/assembly/sparse_assembler.hpp`
|
||||
- `/src/fesa/assembly/sparse_assembler.cpp`
|
||||
|
||||
## 소유 파일
|
||||
|
||||
- Create: `/include/fesa/constraints/essential_constraints.hpp`
|
||||
- Create: `/src/fesa/constraints/essential_constraints.cpp`
|
||||
- Create: `/tests/unit/constraints/essential_constraints_test.cpp`
|
||||
- Modify: `/src/fesa/CMakeLists.txt`
|
||||
- Modify: `/tests/CMakeLists.txt`
|
||||
|
||||
## 작업
|
||||
|
||||
조립된 full CSR matrix를 DofManager의 stable free/constrained ordering으로 partition하고
|
||||
full/reduced vector를 mapping하는 essential-constraint module을 구현하라.
|
||||
|
||||
```cpp
|
||||
struct PartitionedStiffness {
|
||||
SparseMatrix kff;
|
||||
SparseMatrix kfc;
|
||||
SparseMatrix kcf;
|
||||
SparseMatrix kcc;
|
||||
};
|
||||
class EssentialConstraints {
|
||||
public:
|
||||
static Result<PartitionedStiffness> partition(const SparseMatrix& full,
|
||||
const DofManager& dofs);
|
||||
static Vector gatherFree(const Vector& full, const DofManager& dofs);
|
||||
static Vector gatherConstrained(const Vector& full, const DofManager& dofs);
|
||||
static Vector reconstructFull(const Vector& freeValues,
|
||||
const Vector& constrainedValues,
|
||||
const DofManager& dofs);
|
||||
};
|
||||
```
|
||||
|
||||
Partition은 numeric value와 row/column order를 보존하고 0-based CSR invariants를 다시
|
||||
검증한다. `dc`는 DofManager prescribed values에서 가져오며 zero로 가정하지 않는다.
|
||||
이 step은 load vector나 RHS를 조립하지 않고 matrix/vector mapping만 소유한다.
|
||||
|
||||
Tests는 hand-computed block extraction, no/all/mixed constraints, nonzero prescribed values,
|
||||
full-free-constrained round trip, invalid dimensions/order를 검증하고
|
||||
`EssentialConstraints` regex로 등록한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
```powershell
|
||||
cmake --build .harness/build --config Debug --target fesa_tests
|
||||
ctest --test-dir .harness/build -C Debug -R EssentialConstraints --output-on-failure
|
||||
```
|
||||
|
||||
RED 후 GREEN/VERIFY:
|
||||
|
||||
```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 -R EssentialConstraints --output-on-failure
|
||||
ctest --test-dir .harness/build -C Debug --show-only=json-v1
|
||||
ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
```
|
||||
|
||||
## 검증 절차
|
||||
|
||||
1. partition/mapping tests를 먼저 추가하고 RED를 확인한다.
|
||||
2. elimination에 필요한 최소 block extraction으로 GREEN을 만든다.
|
||||
3. nonzero `dc`와 전체 VERIFY를 확인한다.
|
||||
4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의
|
||||
Step 19 section에 실제 RED/GREEN/VERIFY command, exit code,
|
||||
핵심 output과 변경 파일을 기록한다.
|
||||
5. Step 19를 `completed`로 갱신하고 partition/reconstruction evidence를 summary에 기록한다.
|
||||
|
||||
## 금지사항
|
||||
|
||||
- prescribed displacement를 zero로 덮어쓰지 마라. 이유: 승인된 nonzero BC를 깨뜨린다.
|
||||
- penalty/MPC solver를 추가하지 마라. 이유: V0는 essential partition만 지원한다.
|
||||
- RHS/load assembly를 이 step에 섞지 마라. 이유: factorization-before-load 순서를 검증해야 한다.
|
||||
- 직접 commit하지 마라. 이유: Harness executor가 담당한다.
|
||||
@@ -0,0 +1,83 @@
|
||||
# Step 2: Formulation Alignment
|
||||
|
||||
## 담당 역할과 필수 스킬
|
||||
|
||||
- 담당 역할: `formulation-agent`
|
||||
- 필수 스킬: `fesa-formulation-spec`
|
||||
- 스킬의 `SKILL.md`를 끝까지 읽고 수학 계약과 구현 계약의 경계를 지켜라.
|
||||
|
||||
## 읽어야 할 파일
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/SOLVER_AGENT_DESIGN.md`
|
||||
- `/docs/formulations/README.md`
|
||||
- `/docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- `/docs/research/linear-static-3d-euler-beam-research.md`
|
||||
- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md`
|
||||
- `/docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md`
|
||||
|
||||
Step 0–1 산출물과 완료 summary를 확인하라.
|
||||
|
||||
## 작업
|
||||
|
||||
기존 `docs/formulations/3d-isoparametric-euler-beam-formulation.md`를 승인된 V0 요구조건과
|
||||
연구 근거에 맞춰 정렬하라. 기존 정식화의 정확한 수학적 의미를 유지해야 하며, 이
|
||||
step은 새 요소를 다시 설계하는 작업이 아니다.
|
||||
|
||||
- Metadata의 source requirement/research 경로와 status를 실제 산출물에 맞게 바꾸고
|
||||
`feature_id: 3d-isoparametric-euler-beam`, `status: ready-for-numerical-review`를 기록한다.
|
||||
- 기존 strong/weak form, DOF 순서, `theta_y=-w'`, B matrix, constitutive matrix,
|
||||
2-point Gauss, 12x12 stiffness, transformation, line-load vector, recovery 식을 유지한다.
|
||||
- 승인된 입력 의미를 수학 계약에 연결한다: `n1 -> local y`, `t x n1 -> local z`,
|
||||
`Iy=I11`, `Iz=I22`, `I12=0`, scale-aware geometry validation.
|
||||
- equilibrium end action, endpoint section resultant, Gauss generalized values, section-point
|
||||
axial `S11`을 구분하고 stress reference comparison은 N/A임을 분명히 한다.
|
||||
- 기존 Open Issues 중 승인 설계에서 해결된 tolerance, orientation, HDF5 distinction,
|
||||
requirement/research 부재 항목을 제거하거나 resolved decision으로 바꾼다.
|
||||
- Euler–Bernoulli slenderness 적용 범위는 limitation으로 유지하되 승인되지 않은 임의
|
||||
warning/error threshold를 추가하지 않는다.
|
||||
|
||||
수식 결함을 발견해 정확한 의미를 보존하면서 정렬할 수 없으면 문서를 조용히 수정하지
|
||||
말고 Step 2를 `blocked`로 기록한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
```powershell
|
||||
$path = 'docs/formulations/3d-isoparametric-euler-beam-formulation.md'
|
||||
$required = @(
|
||||
'status: `ready-for-numerical-review`',
|
||||
'docs/requirements/linear-static-3d-euler-beam.md',
|
||||
'docs/research/linear-static-3d-euler-beam-research.md',
|
||||
'theta_y=-',
|
||||
'2점 Gauss',
|
||||
'equilibrium end action',
|
||||
'section resultant',
|
||||
'S11',
|
||||
'n1'
|
||||
)
|
||||
foreach ($text in $required) {
|
||||
if (-not (Select-String -LiteralPath $path -SimpleMatch $text -Quiet)) {
|
||||
throw "Missing aligned formulation contract: $text"
|
||||
}
|
||||
}
|
||||
if (Select-String -LiteralPath $path -SimpleMatch 'status: `needs-research`' -Quiet) {
|
||||
throw 'Stale formulation status remains'
|
||||
}
|
||||
git diff --check -- $path
|
||||
```
|
||||
|
||||
## 검증 절차
|
||||
|
||||
1. Acceptance Criteria 명령을 실행한다.
|
||||
2. 기존 수식의 DOF/component 순서와 부호가 승인 전 문서 의미와 동일한지 diff로 검토한다.
|
||||
3. requirement/research의 모든 math handoff가 정식화 section 또는 limitation에 연결되는지 확인한다.
|
||||
4. Step 2를 `completed`와 변경 요약으로 갱신한다. 수학 결함이나 upstream 충돌은
|
||||
`blocked`, 반복 편집 실패는 `error`로 기록한다.
|
||||
|
||||
## 금지사항
|
||||
|
||||
- C++ class, header, storage API를 설계하지 마라. 이유: formulation은 수학 계약이다.
|
||||
- 승인된 부호·DOF·적분 규칙을 편의상 바꾸지 마라. 이유: reference 의미가 달라진다.
|
||||
- B31/Timoshenko 또는 `*DLOAD` parser 지원을 추가하지 마라. 이유: V0 범위 밖이다.
|
||||
- Abaqus 실행 및 reference artifact 변경을 하지 마라. 이유: 이 gate는 문서 정렬만 담당한다.
|
||||
- 직접 commit하지 마라. 이유: Harness executor가 담당한다.
|
||||
@@ -0,0 +1,110 @@
|
||||
# Step 20: MKL PARDISO Linear Solver
|
||||
|
||||
## 담당 역할과 필수 스킬
|
||||
|
||||
- 담당 역할: `implementation-agent`
|
||||
- 필수 스킬: `fesa-cpp-msvc-tdd`
|
||||
- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다.
|
||||
|
||||
## 읽어야 할 파일
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/ARCHITECTURE.md`
|
||||
- `/docs/ADR.md`
|
||||
- `/docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- `/docs/implementation-plans/linear-static-3d-euler-beam.md`
|
||||
- `/include/fesa/core/status.hpp`
|
||||
- `/include/fesa/core/diagnostic.hpp`
|
||||
- `/include/fesa/math/vector.hpp`
|
||||
- `/include/fesa/math/sparse_matrix.hpp`
|
||||
- `/src/fesa/math/sparse_matrix.cpp`
|
||||
- `/cmake/FesaDependencies.cmake`
|
||||
|
||||
## 소유 파일
|
||||
|
||||
- Create: `/include/fesa/solvers/linear/linear_solver.hpp`
|
||||
- Create: `/include/fesa/solvers/linear/mkl_pardiso_solver.hpp`
|
||||
- Create: `/src/fesa/solvers/linear/mkl_pardiso_solver.cpp`
|
||||
- Create: `/tests/unit/solvers/linear/linear_solver_test.cpp`
|
||||
- Create: `/tests/unit/solvers/linear/mkl_pardiso_solver_test.cpp`
|
||||
- Modify: `/src/fesa/CMakeLists.txt`
|
||||
- Modify: `/tests/CMakeLists.txt`
|
||||
|
||||
## 작업
|
||||
|
||||
MKL PARDISO를 solver core에서 숨기며 SPD `Kff` factorization과 RHS substitution을 분리하는
|
||||
adapter를 구현하라. Public interface는 승인된 계약과 동일해야 한다.
|
||||
|
||||
```cpp
|
||||
class LinearSolver {
|
||||
public:
|
||||
virtual ~LinearSolver() = default;
|
||||
virtual Status factorize(const SparseMatrix& matrix) = 0;
|
||||
virtual Status solve(const Vector& rhs, Vector& solution) const = 0;
|
||||
};
|
||||
|
||||
class MklPardisoSolver final : public LinearSolver {
|
||||
public:
|
||||
MklPardisoSolver();
|
||||
~MklPardisoSolver() override;
|
||||
Status factorize(const SparseMatrix& matrix) override;
|
||||
Status solve(const Vector& rhs, Vector& solution) const override;
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> impl_;
|
||||
};
|
||||
```
|
||||
|
||||
Adapter는 0-based CSR을 명시적으로 처리하고 real symmetric positive definite matrix
|
||||
descriptor를 사용한다. Factorization state/workspace를 RAII로 소유하고 destructor와
|
||||
re-factorization에서 누수 없이 해제한다. 동일 factorization에 여러 RHS를 substitution할
|
||||
수 있어야 한다. invalid CSR, solve-before-factorize, dimension mismatch, nonfinite RHS,
|
||||
PARDISO singular/positive-definite failure를 deterministic structured diagnostic으로 반환한다.
|
||||
MKL header/type은 `.cpp`/private Impl 밖에 노출하지 않는다.
|
||||
|
||||
Tests는 known SPD solution/residual `1e-10`, repeated RHS, re-factorization, invalid CSR,
|
||||
singular/indefinite matrix, solve-before-factorize, dimension mismatch를 포함하고
|
||||
`MklPardisoSolver` regex로 등록한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
```powershell
|
||||
cmake --build .harness/build --config Debug --target fesa_tests
|
||||
ctest --test-dir .harness/build -C Debug -R MklPardisoSolver --output-on-failure
|
||||
```
|
||||
|
||||
RED 후 GREEN/VERIFY:
|
||||
|
||||
```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 -R MklPardisoSolver --output-on-failure
|
||||
ctest --test-dir .harness/build -C Debug --show-only=json-v1
|
||||
ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
$leaks = rg -n "mkl\.h|MKL_INT|pardiso" include/fesa
|
||||
if ($LASTEXITCODE -eq 0) { throw "PARDISO API leaked into public headers:`n$leaks" }
|
||||
if ($LASTEXITCODE -ne 1) { throw 'Public-header dependency scan failed' }
|
||||
```
|
||||
|
||||
마지막 scan은 public header에서 no-match여야 한다.
|
||||
|
||||
## 검증 절차
|
||||
|
||||
1. adapter tests를 먼저 작성하고 missing solver RED를 확인한다.
|
||||
2. factorize/solve phase를 분리한 최소 PARDISO adapter로 GREEN을 만든다.
|
||||
3. repeated RHS, RAII, residual, public boundary와 전체 VERIFY를 확인한다.
|
||||
4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의
|
||||
Step 20 section에 실제 RED/GREEN/VERIFY command, exit code,
|
||||
핵심 output과 변경 파일을 기록한다.
|
||||
5. Step 20을 `completed`로 갱신하고 factorization/substitution evidence를 summary에 기록한다.
|
||||
|
||||
## 금지사항
|
||||
|
||||
- factorization과 solve를 하나의 opaque method로 합치지 마라. 이유: 승인 runtime order를 깨뜨린다.
|
||||
- MKL type/header를 public interface에 노출하지 마라. 이유: adapter boundary 계약이다.
|
||||
- singularity에 임의 regularization을 적용하지 마라. 이유: invalid model을 숨긴다.
|
||||
- 직접 commit하지 마라. 이유: Harness executor가 담당한다.
|
||||
@@ -0,0 +1,94 @@
|
||||
# Step 21: Nodal Load Assembly and Effective RHS
|
||||
|
||||
## 담당 역할과 필수 스킬
|
||||
|
||||
- 담당 역할: `implementation-agent`
|
||||
- 필수 스킬: `fesa-cpp-msvc-tdd`
|
||||
- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다.
|
||||
|
||||
## 읽어야 할 파일
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/ARCHITECTURE.md`
|
||||
- `/docs/ADR.md`
|
||||
- `/docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md`
|
||||
- `/docs/io-definitions/linear-static-3d-euler-beam-io.md`
|
||||
- `/docs/implementation-plans/linear-static-3d-euler-beam.md`
|
||||
- `/include/fesa/analysis/analysis_model.hpp`
|
||||
- `/include/fesa/fem/dof_manager.hpp`
|
||||
- `/include/fesa/constraints/essential_constraints.hpp`
|
||||
- `/src/fesa/constraints/essential_constraints.cpp`
|
||||
|
||||
## 소유 파일
|
||||
|
||||
- Create: `/include/fesa/assembly/load_assembler.hpp`
|
||||
- Create: `/src/fesa/assembly/load_assembler.cpp`
|
||||
- Create: `/tests/unit/assembly/load_assembler_test.cpp`
|
||||
- Modify: `/src/fesa/CMakeLists.txt`
|
||||
- Modify: `/tests/CMakeLists.txt`
|
||||
|
||||
## 작업
|
||||
|
||||
single-step `*CLOAD`를 full external force vector에 deterministic하게 조립하고 effective
|
||||
free RHS를 만드는 module을 구현하라.
|
||||
|
||||
```cpp
|
||||
class LoadAssembler {
|
||||
public:
|
||||
static Result<Vector> assembleFullNodalLoad(const AnalysisModel& model,
|
||||
const DofManager& dofs);
|
||||
static Result<Vector> effectiveFreeRhs(const Vector& fullLoad,
|
||||
const SparseMatrix& kfc,
|
||||
const Vector& prescribedValues,
|
||||
const DofManager& dofs);
|
||||
};
|
||||
```
|
||||
|
||||
Node label/node set target은 semantic Domain의 expanded stable identity를 사용한다. 같은
|
||||
full DOF의 multiple CLOAD는 source order로 합산하고 output vector ordering은 full DOF
|
||||
ordering과 같다. `rhs=Ff-Kfc*dc`를 정확히 구현하며 `dc`는 constrained ordering으로 gather한다.
|
||||
Nonfinite load와 dimension mismatch는 diagnostic이다. 이 module은 element line load나
|
||||
`*DLOAD` object를 만들지 않는다.
|
||||
|
||||
Tests는 single node/set loads, multiple accumulation, six components, negative magnitude,
|
||||
nonfinite rejection, constrained load partition, nonzero prescribed `Kfc*dc` hand calculation,
|
||||
zero loads를 포함하고 `LoadAssembly` regex로 등록한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
```powershell
|
||||
cmake --build .harness/build --config Debug --target fesa_tests
|
||||
ctest --test-dir .harness/build -C Debug -R LoadAssembly --output-on-failure
|
||||
```
|
||||
|
||||
RED 후 GREEN/VERIFY:
|
||||
|
||||
```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 -R LoadAssembly --output-on-failure
|
||||
ctest --test-dir .harness/build -C Debug --show-only=json-v1
|
||||
ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
```
|
||||
|
||||
## 검증 절차
|
||||
|
||||
1. nodal load/effective RHS tests를 먼저 작성하고 RED를 확인한다.
|
||||
2. nodal-only deterministic assembly와 RHS 최소 구현으로 GREEN을 만든다.
|
||||
3. nonzero prescribed displacement와 전체 VERIFY를 확인한다.
|
||||
4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의
|
||||
Step 21 section에 실제 RED/GREEN/VERIFY command, exit code,
|
||||
핵심 output과 변경 파일을 기록한다.
|
||||
5. Step 21을 `completed`로 갱신하고 load/RHS evidence를 summary에 기록한다.
|
||||
|
||||
## 금지사항
|
||||
|
||||
- factorization을 이 module에서 호출하지 마라. 이유: orchestration order는 Step 24가 소유한다.
|
||||
- `*DLOAD` 또는 Domain distributed-load object를 추가하지 마라. 이유: V0 입력 범위 밖이다.
|
||||
- prescribed displacement contribution을 생략하지 마라. 이유: `rhs=Ff-Kfc*dc` 계약이다.
|
||||
- 직접 commit하지 마라. 이유: Harness executor가 담당한다.
|
||||
@@ -0,0 +1,101 @@
|
||||
# Step 22: Result Recovery
|
||||
|
||||
## 담당 역할과 필수 스킬
|
||||
|
||||
- 담당 역할: `implementation-agent`
|
||||
- 필수 스킬: `fesa-cpp-msvc-tdd`
|
||||
- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다.
|
||||
|
||||
## 읽어야 할 파일
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/ARCHITECTURE.md`
|
||||
- `/docs/ADR.md`
|
||||
- `/docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md`
|
||||
- `/docs/io-definitions/linear-static-3d-euler-beam-io.md`
|
||||
- `/docs/implementation-plans/linear-static-3d-euler-beam.md`
|
||||
- `/include/fesa/analysis/analysis_model.hpp`
|
||||
- `/include/fesa/analysis/analysis_state.hpp`
|
||||
- `/include/fesa/fem/dof_manager.hpp`
|
||||
- `/include/fesa/elements/euler_beam_3d.hpp`
|
||||
- `/include/fesa/math/sparse_matrix.hpp`
|
||||
- `/include/fesa/constraints/essential_constraints.hpp`
|
||||
- `/include/fesa/assembly/load_assembler.hpp`
|
||||
|
||||
## 소유 파일
|
||||
|
||||
- Create: `/include/fesa/results/result_recovery.hpp`
|
||||
- Create: `/src/fesa/results/result_recovery.cpp`
|
||||
- Create: `/tests/unit/results/result_recovery_test.cpp`
|
||||
- Modify: `/src/fesa/CMakeLists.txt`
|
||||
- Modify: `/tests/CMakeLists.txt`
|
||||
|
||||
## 작업
|
||||
|
||||
full displacement로 전체 residual 반력과 element outputs를 복구해 AnalysisState에 채우는
|
||||
module을 구현하라.
|
||||
|
||||
```cpp
|
||||
class ResultRecovery {
|
||||
public:
|
||||
static Status recover(const AnalysisModel& model,
|
||||
const DofManager& dofs,
|
||||
const SparseMatrix& fullStiffness,
|
||||
AnalysisState& state);
|
||||
};
|
||||
```
|
||||
|
||||
- `internalForce=K*d`, `residual=internalForce-externalForce`를 full space에서 계산하고
|
||||
constrained DOF reaction을 residual에서 복구한다. Element end action을 별도 합산해
|
||||
reaction을 만들지 않는다.
|
||||
- Free residual normalized criterion은 `1e-10`이고 nonfinite를 실패시킨다.
|
||||
- Active element internal index 순서로 global 12-DOF vector를 gather하고 `EulerBeam3D::recover`
|
||||
결과를 endpoint/Gauss/stress rows에 안정적으로 저장한다.
|
||||
- Equilibrium end action `[FX,FY,FZ,MX,MY,MZ]`, endpoint section resultant `[N,T,My,Mz]`,
|
||||
Gauss generalized strain/resultant, section-point `S11`을 서로 다른 row/data로 유지한다.
|
||||
- Reference용 node-station normalization helper는 동일 section-cut sign으로 endpoint를
|
||||
변환하고 interior endpoint 불일치를 평균으로 숨기지 않으며, 일치한 경우 작은 stable
|
||||
element ID를 대표 row로 선택한다.
|
||||
|
||||
Tests는 hand matrix reaction, nonzero prescribed displacement, free residual, axial/torsion/
|
||||
y-z bending signs, end action vs section resultant distinction, stress point order/default centroid,
|
||||
interior endpoint match/mismatch와 stable representative를 포함하고 `ResultRecovery` regex로 등록한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
```powershell
|
||||
cmake --build .harness/build --config Debug --target fesa_tests
|
||||
ctest --test-dir .harness/build -C Debug -R ResultRecovery --output-on-failure
|
||||
```
|
||||
|
||||
RED 후 GREEN/VERIFY:
|
||||
|
||||
```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 -R ResultRecovery --output-on-failure
|
||||
ctest --test-dir .harness/build -C Debug --show-only=json-v1
|
||||
ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
```
|
||||
|
||||
## 검증 절차
|
||||
|
||||
1. reaction/recovery/sign/normalization tests를 먼저 작성하고 RED를 확인한다.
|
||||
2. residual 기반 최소 recovery 구현으로 GREEN을 만든다.
|
||||
3. formulation component ordering과 full VERIFY를 확인한다.
|
||||
4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의
|
||||
Step 22 section에 실제 RED/GREEN/VERIFY command, exit code,
|
||||
핵심 output과 변경 파일을 기록한다.
|
||||
5. Step 22를 `completed`로 갱신하고 recovered quantities/residual evidence를 summary에 기록한다.
|
||||
|
||||
## 금지사항
|
||||
|
||||
- reaction을 element endpoint 합산 경로로 계산하지 마라. 이유: nodal load와 nonzero BC를 놓친다.
|
||||
- interior endpoint mismatch를 average로 숨기지 마라. 이유: tolerance failure evidence다.
|
||||
- shear stress나 nodal stress averaging을 추가하지 마라. 이유: V0 recovery 범위 밖이다.
|
||||
- 직접 commit하지 마라. 이유: Harness executor가 담당한다.
|
||||
@@ -0,0 +1,127 @@
|
||||
# Step 23: HDF5 Results Writer
|
||||
|
||||
## 담당 역할과 필수 스킬
|
||||
|
||||
- 담당 역할: `implementation-agent`
|
||||
- 필수 스킬: `fesa-cpp-msvc-tdd`
|
||||
- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다.
|
||||
|
||||
## 읽어야 할 파일
|
||||
|
||||
- `/AGENTS.md`
|
||||
- `/docs/ARCHITECTURE.md`
|
||||
- `/docs/ADR.md`
|
||||
- `/docs/requirements/linear-static-3d-euler-beam.md`
|
||||
- `/docs/io-definitions/linear-static-3d-euler-beam-io.md`
|
||||
- `/docs/implementation-plans/linear-static-3d-euler-beam.md`
|
||||
- `/include/fesa/core/diagnostic.hpp`
|
||||
- `/include/fesa/model/domain.hpp`
|
||||
- `/include/fesa/analysis/analysis_state.hpp`
|
||||
- `/include/fesa/results/result_records.hpp`
|
||||
- `/cmake/FesaDependencies.cmake`
|
||||
|
||||
## 소유 파일
|
||||
|
||||
- Create: `/include/fesa/results/results_writer.hpp`
|
||||
- Create: `/include/fesa/io/hdf5/hdf5_results_writer.hpp`
|
||||
- Create: `/src/fesa/io/hdf5/hdf5_results_writer.cpp`
|
||||
- Create: `/tests/unit/results/results_writer_test.cpp`
|
||||
- Create: `/tests/unit/io/hdf5/hdf5_results_writer_test.cpp`
|
||||
- Modify: `/src/fesa/CMakeLists.txt`
|
||||
- Modify: `/tests/CMakeLists.txt`
|
||||
|
||||
## 작업
|
||||
|
||||
HDF5 API를 adapter 안에 숨기고 schema v0를 임시 파일에 완성한 후 final path로 교체하는
|
||||
ResultsWriter를 구현하라.
|
||||
|
||||
```cpp
|
||||
class ResultsWriter {
|
||||
public:
|
||||
virtual ~ResultsWriter() = default;
|
||||
virtual Status write(const std::filesystem::path& outputPath,
|
||||
const Domain& domain,
|
||||
const AnalysisState& state,
|
||||
const std::vector<Diagnostic>& diagnostics) = 0;
|
||||
};
|
||||
class Hdf5ResultsWriter final : public ResultsWriter {
|
||||
public:
|
||||
Status write(const std::filesystem::path& outputPath,
|
||||
const Domain& domain,
|
||||
const AnalysisState& state,
|
||||
const std::vector<Diagnostic>& diagnostics) override;
|
||||
};
|
||||
```
|
||||
|
||||
다음 group/dataset을 exact path와 승인 shape/component order로 기록한다.
|
||||
|
||||
```text
|
||||
/metadata
|
||||
/model/nodes
|
||||
/model/elements
|
||||
/steps/<step-name>/frames/0/nodal/displacement
|
||||
/steps/<step-name>/frames/0/nodal/reaction
|
||||
/steps/<step-name>/frames/0/element/end_force_local
|
||||
/steps/<step-name>/frames/0/element/section_resultant
|
||||
/steps/<step-name>/frames/0/element/generalized_strain
|
||||
/steps/<step-name>/frames/0/element/generalized_resultant
|
||||
/steps/<step-name>/frames/0/element/stress_s11
|
||||
/diagnostics
|
||||
```
|
||||
|
||||
승인 설계의 schema 목록은 minimum contract이며, 별도 `generalized_resultant` dataset은
|
||||
설계가 요구한 Gauss-point generalized resultant를 손실 없이 기록하기 위한 필수 sibling이다.
|
||||
Metadata는 schema/solver version, source input identity, `user-consistent-unspecified` unit
|
||||
label, coordinate convention, `B33 Euler-Bernoulli` formulation을 가진다. Model rows는 stable
|
||||
internal ID와 instance/source label을 함께 쓴다. 모든 field에는 component/output-location
|
||||
identity를 기록한다. HDF5 handle은 RAII로 닫고 failure 시 incomplete final `results.h5`를
|
||||
남기지 않는다. Existing final 교체도 Windows에서 실패 중간 상태를 만들지 않는 adapter
|
||||
내 정책과 test를 제공한다. HDF5/Windows API type은 public header에 노출하지 않는다.
|
||||
|
||||
Tests는 complete schema/shape/metadata/identity/component, diagnostics warning, no section
|
||||
points centroid, failed path/no partial final, successful replacement을 포함하고
|
||||
`Hdf5ResultsWriter` regex로 등록한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
```powershell
|
||||
cmake --build .harness/build --config Debug --target fesa_tests
|
||||
ctest --test-dir .harness/build -C Debug -R Hdf5ResultsWriter --output-on-failure
|
||||
```
|
||||
|
||||
RED 후 GREEN/VERIFY:
|
||||
|
||||
```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 -R Hdf5ResultsWriter --output-on-failure
|
||||
ctest --test-dir .harness/build -C Debug --show-only=json-v1
|
||||
ctest --test-dir .harness/build -C Debug --output-on-failure
|
||||
$leaks = rg -n "H5[A-Z_a-z0-9]*|hid_t" include/fesa
|
||||
if ($LASTEXITCODE -eq 0) { throw "HDF5 API leaked into public headers:`n$leaks" }
|
||||
if ($LASTEXITCODE -ne 1) { throw 'Public-header dependency scan failed' }
|
||||
```
|
||||
|
||||
마지막 scan은 public header에서 no-match여야 한다.
|
||||
|
||||
## 검증 절차
|
||||
|
||||
1. schema/atomicity tests를 먼저 작성하고 writer 부재 RED를 확인한다.
|
||||
2. exact schema와 RAII/temporary finalization의 최소 구현으로 GREEN을 만든다.
|
||||
3. HDF5 inspection, failure cleanup, public boundary와 전체 VERIFY를 확인한다.
|
||||
4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의
|
||||
Step 23 section에 실제 RED/GREEN/VERIFY command, exit code,
|
||||
핵심 output과 변경 파일을 기록한다.
|
||||
5. Step 23을 `completed`로 갱신하고 schema/atomicity evidence를 summary에 기록한다.
|
||||
|
||||
## 금지사항
|
||||
|
||||
- CSV를 공식 solver output으로 추가하지 마라. 이유: authoritative output은 HDF5 하나다.
|
||||
- Abaqus output request로 dataset을 생략하지 마라. 이유: FESA default output은 항상 생성된다.
|
||||
- HDF5 type/header를 public API에 노출하지 마라. 이유: adapter boundary 계약이다.
|
||||
- 실패 후 incomplete final file을 남기지 마라. 이유: output integrity 계약이다.
|
||||
- 직접 commit하지 마라. 이유: Harness executor가 담당한다.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user