docs: organize project guidance and module contracts

This commit is contained in:
KOKO\Mimi
2026-09-29 00:34:57 +09:00
parent 73db138566
commit a3502c9b97
50 changed files with 1748 additions and 414 deletions
+102 -231
View File
@@ -1,260 +1,131 @@
# FESA 구조해석 솔버 아키텍처
# FESA 시스템 구조
## 목적과 적용 범위
## 구성과 의존성
FESA는 유한요소법 기반 구조해석 솔버를 단계적으로 구축한다. 이 문서는
[PRD](PRD.md)의 제품 목표를 공통 책임, 의존성, 데이터와 수명 경계로 연결한다.
특정 요소·재료·하중의 정식화, 해석 알고리즘, 코드 목록 또는 구현 완료 현황은 다루지 않는다.
구체적인 API, 수식, 실행 순서와 결과 schema는 `docs/<feature-id>/`의 승인된
정식화·I/O·구현 계약에서 정의한다. 아래의 책임 모델은 아직 없는 클래스, 공통 base,
state field 또는 디렉토리를 미리 만들라는 지시가 아니다. 기존 구현의 승인된 의미를
일반적인 설명에 맞추어 변경하지 않는다.
설계 결정과 변경 근거는 [ADR](ADR.md), 코드 규약은 [CODINGSTYLE](CODINGSTYLE.md)을
따른다. 현재 프로젝트의 기술 선택은 [AGENTS.md](../AGENTS.md)와 실행 가능한
build/configuration에서 확인한다.
## 아키텍처 원칙
- 물리·수치 의미는 외부 파일 형식과 vendor API보다 독립적인 계약으로 유지한다.
- 모델 정의, 현재 실행 view, equation 구성, mutable state와 결과의 소유권을 구분한다.
- Local physics 계산과 global topology, assembly, constraint, solve 책임을 분리한다.
- Identity, units, coordinates, ordering과 failure 의미를 경계마다 명시한다.
- Candidate를 완성·검증한 뒤 계약된 state나 authoritative output에 반영한다.
- 병렬화와 최적화에서도 결정적인 ordering과 failure preservation을 유지한다.
- 실제 승인된 사용 사례에 필요한 최소 확장만 도입한다.
## Solver runtime과 개발 운영 영역
FESA는 로컬 모델 파일을 읽어 해석하고 HDF5 결과를 저장하는 C++ 솔버다. 현재 공개
실행 경로는 하나의 CLI이며, 내부 정적 library와 테스트 target이 같은 core를 사용한다.
개발용 Python 실행기는 솔버 runtime의 의존성이 아니다.
```text
Solver runtime
입력 adapter → semantic model → analysis procedure → recovery/results → 출력 adapter
│
├─ DOF / equation / sparse pattern
├─ element / material / load contribution
├─ assembly / constraint policy
└─ numerical backend
개발 운영 영역
사용자 요구 → 메인 assistant → 필요한 전문 작업·구현 → 검증·결과 확인
│
└─ 명시적 Harness / 코드·테스트·문서 변경
fesa_cli
└─ app: 경로·출력 쓰기 소유권·실행 조합
├─ io/abaqus: 입력 읽기 → syntax → semantic mapping
│ └─ model: Domain·source identity·재료/단면/step 정의
└─ analysis: 준비된 모델 → procedure별 실행 → 완료 candidate
├─ AnalysisModel: Domain의 non-owning view
├─ fem / constraints: DOF·equation·partition
├─ elements / materials / properties / loads: local 계산
├─ assembly: 결정적인 global 누적
├─ math / solvers: storage·PARDISO·FEAST
└─ results: 물리 결과 복구·state 반영
└─ io/hdf5: candidate 파일 → self-check·close → 최종 교체
```
첫 흐름은 해석 데이터의 전달을, 두 번째는 개발 작업과 검증의 흐름을 나타낸다.
Agent, skill과 Harness는 solver runtime API나 물리 모델의 일부가 아니다.
개발 운영 영역은 저장소의 변경과 검증을 통제하며 solver가 실행 중 이를 호출하지 않는다.
Consumer는 backend-neutral contract를 통해 값을 주고받는다. MKL·TBB·HDF5·Win32
header와 handle은 private implementation에 머문다. 새 물리나 backend를 추가할 때
core가 외부 adapter를 참조하는 방향으로 의존성을 뒤집지 않는다.
## 공통 책임과 의존성
## 모듈 경계
아래 명칭은 책임 경계이며 반드시 각각 하나의 클래스나 독립 library를 뜻하지 않는다.
실제 타입과 파일 배치는 승인된 Feature와 현재 코드 구조에서 결정한다.
| 경계 | 소유하는 책임 | 소유하지 않는 책임 |
| 영역 | 소유하는 책임 | 경계 밖의 책임 |
| --- | --- | --- |
| Core identity/diagnostic | Source identity, 공통 상태와 진단의 의미 | 파일 문법, 물리 정식화, vendor resource |
| Input adapter | 외부 syntax와 지원 semantics의 검증·mapping | 해석 알고리즘과 acceptance 변경 |
| Model definition | Topology, 재료·property·하중·제약·step 정의와 stable identity | Equation 번호, 해석 중 mutable solution |
| Active model view | 현재 procedure/step에 필요한 모델의 non-owning 참조 | 원본 모델 복사나 수명 소유 |
| Element/material | 승인된 local ordering의 물리 응답과 recovery 계약 | Global equation numbering, 직접 sparse write, 파일 저장 |
| Load definition/evaluation | Target·magnitude·configuration 의미와 ordered contribution | Global vector의 공유 누적 |
| DOF/equation | 활성 DOF, full/free/constrained mapping, numbering, scatter와 sparse pattern | 요소 정식화, 수치 factorization |
| Assembly | Local contribution을 지정된 global structure에 결정적으로 누적 | Physics 재해석, equation 번호의 분산 생성 |
| Constraint policy | 승인된 제약의 equation 적용과 해 복구 의미 | Input syntax나 별도 물리 모델의 임의 도입 |
| Analysis procedure | 필요한 state·해법·반복/종료·commit·recovery lifecycle | Vendor handle이나 concrete storage API의 공개 |
| Numerical backend | 행렬·벡터 연산, 해법 resource와 backend failure translation | Source label의 물리 의미, 입력 모델 해석 |
| Results/recovery | 계산 결과의 물리량·위치·identity와 state 반영 | 저장 파일 layout이나 reference 데이터 보정 |
| Output adapter | 승인 schema로의 serialization, self-check와 finalization | 물리량 정의와 acceptance 판정 변경 |
| `include/fesa` | 공개 선언, 값·실패·수명 계약 | Vendor handle, 실행별 equation 저장 |
| `app` | CLI 경로, output lease, 객체 조합과 외부 종료 | 요소 정식화, 수렴 기준 결정 |
| `core` | Source identity, ASCII 처리, Status·Diagnostic | 입력 procedure 허용 범위 |
| `io/abaqus` | 문법·scope·semantic mapping, Domain 생성 | 해법, 결과 복구 |
| `model` | 전체 정의, target 해석, 초기 shell geometry | Mutable solution, global equation 번호 |
| `properties` | 재료 연결과 beam/shell 단면 정의 | 물성 평가식, state 수명 |
| `materials` | 구성 관계와 필요한 물성 capability | Element topology, analysis state |
| `elements` | Local 행렬·힘·관성·회복에 필요한 응답 | Global CSR 갱신, 파일 접근 |
| `loads` | 하중 의미·configuration·local contribution | Global 공유 누적, 입력 target 이름 해석 |
| `fem` | DOF, scatter, full/free/constrained mapping, pattern | 선형계 factorization |
| `constraints` | 지정값 적용, partition·대입 정책 | 물리 결과 재해석 |
| `assembly` | Sparse·하중·압력 contribution의 ordered reduction | Equation 번호 발급, 수렴 판정 |
| `analysis` | Procedure별 초기화·증분·반복·종료·state lifecycle | Concrete 저장 형식, vendor resource 공개 |
| `math` | Vector·Matrix·SparseMatrix, private BLAS adapter | 모델 의미, source target lookup |
| `solvers/linear` | PARDISO factorization·solve, resource와 실패 변환 | 경계조건 변경, 모델 수정 |
| `solvers/eigen` | FEAST 실행과 수치 제어의 backend 경계 | Source EIGENSOLVER의 재해석, 외부 비교 판정 |
| `results` | Location·부호·좌표가 명확한 복구와 candidate commit | HDF5 layout, reference 보정 |
| `io/hdf5` | Schema serialization·readback·최종 파일 교체 | 물리량 정의, acceptance 완화 |
의존성은 consumer가 명시된 contract를 사용하는 방향으로 둔다. Input/output과 vendor
adapter가 core 계약에 의존하며, public core가 concrete adapter나 vendor/OS 타입에
의존하지 않는다. Interface와 implementation의 의존성 방향을 역전하지 않는다.
같은 module의 public 선언은 `include/fesa/<module>`, implementation은
`src/fesa/<module>`에 나뉜다. 이 물리적 분리가 interface와 implementation의 소유권을
둘로 나누지는 않는다. Parser가 concrete numerical storage를 생성·조작하는 대신
semantic 정의와 검증된 생성 경계로 연결한다.
Numerical consumer가 요소 종류별 concrete storage를 직접 분기하지 않도록 승인된
evaluation/contribution contract를 사용한다. Definition과 runtime object의 호환성은
지정된 생성 경계에서 검사한다. 이를 위해 speculative registry, 공유 소유권 또는
사용하지 않는 polymorphic capability를 추가하지 않는다.
## 대표 실행 흐름
## 데이터 계약
1. App이 단일 입력 경로에서 lexical sibling 결과·로그 경로를 만들고 output lease를
획득한다. Lease를 얻기 전에 공개 파일을 truncate하지 않는다.
2. 입력을 한 번 읽고 source 위치·raw 표기와 함께 syntax를 해석한다. Mapper가 target,
element/section/material 및 procedure 조합을 검증해 Domain을 만든다.
3. 준비 단계가 static, nonlinear static, frequency 또는 HHT executor로 분기한다.
Domain을 복사해 별도 모델을 만들지 않는다.
4. 선택된 procedure가 active view, equation과 workspace를 구성하고 local 계산,
ordered assembly, constraint, solve 및 필요한 반복을 수행한다.
5. 해와 recovery를 검증해 procedure 전용 state에 반영한다. 비선형·동적 trial은
이전 committed state/history와 독립적이며 실패한 trial은 공개하지 않는다.
6. 완료 outcome을 얻은 뒤 로그 close를 확인하고 해당 writer를 호출한다. Writer는
임시 파일에 기록·검사·close를 마친 뒤 최종 HDF5를 교체한다.
### Identity
State commit과 파일 교체는 별개의 실패 경계다. 일부 frame을 내부에서 accept했더라도
전체 해석이 실패했다면 미완성 이력을 새로운 정상 결과 파일로 공개하지 않는다.
반면 실행 로그는 실패를 설명하기 위해 남을 수 있어 최종 결과와 보존 범위가 다르다.
다음 개념을 같은 정수나 row 위치라는 이유로 서로 대체하지 않는다.
## 해석 모델과 수명
- Source identity: 외부 입력에서 의미가 있는 label과 instance/scope
- Internal identity/index: 검증된 모델 내부의 안정된 식별 또는 위치
- DOF identity: Entity의 물리 자유도와 component
- Equation index: 특정 procedure의 equation ordering
- Result identity: Entity, quantity, location, component, step/frame과 coordinate 의미
Domain이 모델 정의를 소유한다. AnalysisModel, DOF 구성에 사용되는 참조와 실행 객체가
Domain보다 오래 살아서는 안 된다. DofManager는 topology에서 물리 DOF와 equation
순서를 구성하며 node/element 내부에 equation 번호를 배포하지 않는다.
Renumbering, filtering, 병렬 scheduling과 serialization 뒤에도 필요한 대응 관계를
보존한다. Reference matching은 row 순서가 아니라 계약된 source identity와 component를
사용한다. 특정 typed wrapper나 result-key 클래스를 이 문서만으로 새로 만들지 않는다.
현재 procedure마다 static, nonlinear, eigen, dynamic state를 구별한다. 공통된다는
이유로 사용하지 않는 가속도·plastic state·thermal field를 일괄 추가하지 않는다.
새 procedure는 필요한 lifecycle을 정의한 뒤 준비 단계에서 연결한다. 기존 static
반복문에 조건문으로 물리를 누적하지 않는다.
### Units, coordinates와 result meaning
Source identity, internal entity index, DOF component, equation index와 결과 위치는
서로 다른 경계의 식별자다. Assembly와 serialization 사이에서 row 순서를 바꾸더라도
source와 결과의 대응은 명시적으로 유지한다.
입력 값의 단위계를 임의로 추론하거나 결과에 맞춰 변환하지 않는다. 필요한 dimension,
좌표계, component 순서, 변환과 부호는 정식화 및 I/O 계약으로 고정한다.
서로 다른 위치나 정의의 recovery quantity를 같은 결과로 취급하지 않는다.
Averaging, extrapolation 또는 station 변환은 별도 승인된 의미가 있을 때만 수행한다.
## 계산과 병렬화
### 모델, view와 state의 수명
Element/local load 계산은 index-owned buffer에 기록한다. TBB 작업을 join한 뒤
stable COO ordering과 고정된 reduction으로 sparse matrix와 global vector를 만든다.
Global storage를 여러 worker가 직접 수정하지 않으므로 thread scheduling이 합산 순서를
정하지 않는다. 진단 선택과 결과 row의 순서도 같은 원칙으로 관리한다.
- `Domain`은 전체 모델 정의를 소유하며 검증 이후 가능한 한 불변으로 취급한다.
- `AnalysisModel`은 Domain을 복사하지 않는 non-owning 실행 view다. Domain은 모든
view와 그에 의존하는 계산보다 오래 살아야 한다.
- `DofManager`는 DOF/equation mapping과 sparse pattern을 전담한다. Node나 Element에
equation 번호를 분산 저장하지 않는다.
- Analysis owner는 해당 procedure가 실제로 사용하는 mutable state와 workspace만 소유한다.
재사용·재시도·해제 시 dependent object를 남기지 않는다.
- Trial/committed 구분이 필요한 procedure는 update 실패와 commit 시점을 별도 계약으로
정의한다. 모든 procedure나 material에 이 state를 일괄 추가하지 않는다.
- Recovery와 output은 유효한 candidate를 검증한 뒤 반영한다. 기존 state와 최종 파일의
보존 범위는 성공 경로뿐 아니라 실패 경로에서도 검증한다.
## 해석 실행 흐름
공통적으로 외부 입력의 의미를 검증하고 실행 모델을 구성한 뒤, 선택된 procedure가
equation과 state를 관리하여 결과를 복구·저장한다. 이것은 책임 수준의 설명이며 모든
procedure에 동일한 반복문이나 고정된 단계 목록을 강제하는 Template Method가 아니다.
각 procedure 계약은 다음을 명시한다.
1. 입력 준비와 procedure 선택의 경계, 원본 모델의 owner와 lifetime
2. 필요한 DOF, state, equation, workspace와 초기화 조건
3. Contribution, constraint, factorization/solve와 update의 순서
4. 해당하는 경우 increment, iteration, convergence와 종료 조건
5. 성공 candidate의 commit, recovery와 결과 frame의 의미
6. 실패 category, rollback·재사용 조건과 final output의 보존 범위
정적·동적, 선형·비선형, eigen 또는 contact 계열은 실제 요구와 승인된 계약으로
정의한다. 이 구분을 명시하는 것은 해당 기능이 이미 지원된다는 뜻이 아니다.
기존 절차에 조건문으로 새 physics를 끼워 넣거나, 간결한 공통 그림을 근거로 승인된
연산 순서·reaction·residual·commit 의미를 바꾸지 않는다.
현재 개별 procedure의 구체적인 실행 계약은 해당 Feature의 formulation·I/O·구현 문서를
확인한다. 기존 프로젝트 문서의 실행 순서와 객체 배치는
[개정 전 아키텍처](archive/pre-generalization/ARCHITECTURE.md)에 이력으로 보존한다.
## Local 계산, assembly와 constraint
Local kernel은 승인된 geometry, material/property, DOF/state와 요청된 계산 범위를 받아
local ordering이 명시된 contribution 또는 recovery 값을 만든다. Global numbering,
공유 matrix 갱신, 파일 lookup, 전체 convergence 판정이나 최종 저장을 수행하지 않는다.
DOF owner가 지정한 pattern과 scatter를 assembly가 사용한다. Contribution 생성과
누적 순서를 명시하고 병렬 worker는 소유한 buffer에만 기록한다. Join 이후 reduction과
diagnostic 선택은 결정적으로 수행한다. Hash iteration이나 실행 scheduling을
authoritative ordering으로 사용하지 않는다.
Constraint 방식, full/reduced space, prescribed value, residual과 reaction의 정의는
선택된 procedure의 수학 계약에 포함한다. 서로 다른 enforcement 방식의 결과 의미를
같다고 가정하지 않는다. 특수 차원·빈 시스템·singularity의 처리는 계약에 따라 검증하며
임의의 regularization, zero clamp 또는 fallback으로 실패를 숨기지 않는다.
## Numerical backend와 실행 환경
Math storage, index convention, matrix capability, resource lifetime과 오류 변환은
backend-neutral 계약으로 노출한다. Vendor header, handle과 OS 타입은 private adapter에
격리한다. Dense와 sparse의 의미가 다르면 하나의 storage hierarchy로 억지로 합치지 않는다.
Build dependency는 프로젝트가 소유한 target 경계에서 정규화하고, 새로운 dynamic
dependency는 link뿐 아니라 실제 실행에 필요한 runtime closure까지 확인한다.
개인 설치 절대 경로를 소스 계약으로 고정하지 않는다. Thread와 workspace 정책은
실제 workload와 재현성 evidence에 근거하여 관리한다.
현재 target graph와 dependency 선택은 [CMakeLists.txt](../CMakeLists.txt),
[dependency 설정](../cmake/FesaDependencies.cmake),
[solver target](../src/fesa/CMakeLists.txt), [test target](../tests/CMakeLists.txt)과
[CMakePresets.json](../CMakePresets.json)을 확인한다. 이 참조는 다른 toolchain이나
backend를 자동 승인하지 않으며 FESA의 현재 검증 baseline은 프로젝트 지침을 따른다.
MKL은 private dense 연산과 PARDISO·FEAST backend에서 사용한다. Linear solver와
tangent solver의 matrix 성질을 구별하고, eigen finite-space reduction은 해석 모델의
책임으로 유지한다. Backend 선택이 물성·경계조건·질량을 바꾸는 fallback이 되지 않는다.
## 입력, 결과와 진단
Input adapter는 지원되는 외부 syntax, scope, default와 model/history 의미를
검증된 semantic model로 mapping한다. 의미상 무해하다고 계약된 항목만 warning/no-op으로
처리할 수 있으며 나머지 미지원 semantics는 fail-closed로 진단한다.
입력 adapter는 syntax뿐 아니라 procedure별 허용 의미까지 검사한다. Source 이름·
label·raw spelling은 보존하고 내부 정렬과 결과 schema의 고정 storage 이름을 분리한다.
무시 가능한 출력 요청은 허용된 조합에만 적용한다.
Results/recovery가 물리량의 의미를, output adapter가 저장 layout을 소유한다.
Authoritative output과 diagnostic log, debug view, reference artifact를 구분한다.
공식 형식, 파일명, schema version, mandatory dataset과 backward compatibility는
현재 프로젝트·Feature I/O 계약을 따른다. 일반화 때문에 기존의 필수 결과를 optional로
바꾸거나 다른 파일 형식으로 대체하지 않는다.
Recovery는 물리량의 위치·좌표·단위·부호를 결정하고 writer는 이를 저장한다.
Final output은 입력의 lexical sibling인 `<stem>_results.h5`다. Log와 debug CSV는
다른 역할이며 공식 HDF5를 대신하지 않는다. HDF5 self-check와 solver의 물리 검증은
서로 다른 책임이다.
Output은 계약된 임시 candidate에 기록하고 검증·close를 완료한 뒤 최종 결과로 반영한다.
실패 frame이나 불완전한 파일을 정상 결과처럼 공개하지 않는다. 내부 state의 commit과
외부 파일의 finalization은 서로 다른 경계이므로 각각의 failure contract를 정의한다.
Expected failure는 Status/Result로 이동하며 source location과 entity를 포함한
Diagnostic으로 변환한다. App이 공개 오류 출력과 종료값을 결정한다. Vendor 코드가
public exit code나 사용자 입력의 의미를 직접 결정하지 않는다.
Diagnostic은 실패 단계, 안정된 code와 메시지, 가능한 source location/entity를 제공한다.
정확한 category, field와 CLI exit code는 I/O 계약을 따른다. Backend 오류를 그대로
누출하거나 내부 failure classification을 새 public exit code로 임의 승격하지 않는다.
## 빌드와 개발 실행 영역
## 검증과 reference 경계
CMake는 `fesa_solver` static library, `fesa_cli` 실행 파일과 C++ 테스트를 구성한다.
Project-owned dependency target이 MKL·TBB·HDF5의 package target 차이를 감싼다.
GoogleTest는 승인된 로컬 source checkout을 사용한다. Windows 실행 target 옆에
필요한 MKL·OpenMP·TBB·HDF5 및 관련 runtime을 준비하며 link 성공만으로 실행 환경이
완성되었다고 판단하지 않는다.
검증 coverage와 비교량의 논리적 정의는 Numerical Review, 물리량의 저장·외부 대응은
I/O, 실행 evidence는 구현 담당자, 독립 물리 판단은 Physics Evaluation의 전문 책임이다.
메인은 작업에 필요한 전문 판단만 배정하며 고정 stage 순회를 요구하지 않는다. 수식·요소·
재료·적분·상태 갱신 변경에는 독립 수치 검토와 해당 analytical/invariant 검증을 수행한다.
각 담당자는 상위 계약을 결과에 맞춰 수정하지 않는다.
Python 실행 경로는 `execute.py → config/discovery/toolchain → adapter → process`다.
Adapter는 CMake/CTest 또는 MSBuild 명령 계획을 만들고 process는 argv·cwd·timeout과
결과 검사를 수행한다. FESA 제품의 검증 baseline은 CMake/MSVC x64 Debug/CTest다.
Python 실행기 회귀는 별도 suite이며 CTest가 이를 자동 실행하지 않는다.
- Source identity, location과 component 일치 여부를 수치 tolerance보다 먼저 확인한다.
- Missing, extra, duplicate와 nonfinite required value를 숨기지 않는다.
- 외부 reference 판정은 [TOLERANCE](TOLERANCE.md)의 공통 정책을 적용한다. 물리 평형,
정식화와 수렴의 검증 기준은 각자의 계약을 따른다.
- Reference artifact의 naming이나 보조 metadata를 맞추기 위해 파일을 변경하지 않는다.
- 공개 입력 의미나 관찰 가능한 결과 비교를 외부 solver의 내부 동작 동등성으로 해석하지 않는다.
구현 존재, 특정 revision의 검증 통과와 현재 release readiness는 별도로 확인한다.
Architecture 문서의 그림이나 모듈명이 기능의 완료 증거를 대신하지 않는다.
## 개발 운영 인프라
현행 운영은 [ADR-028](ADR.md#adr-028), 역할·인계는
[SOLVER_AGENT_DESIGN](SOLVER_AGENT_DESIGN.md), skill 적용은
[SOLVER_SKILL_DESIGN](SOLVER_SKILL_DESIGN.md)을 따른다. 실행 동작은
[Harness skill](../.agents/skills/harness/SKILL.md)과 현재 source·config에 대조한다.
| Owner | 책임 |
| --- | --- |
| 메인 assistant | 범위·작업 분해, 필요한 전문 작업 배정, 직접 계획·구현·수정, Feature context와 완료 evidence 확인 |
| Specialist | 할당된 전문 판단·파일과 간결한 결과; 상위 계약 문제를 owner와 메인에 전달 |
| 구현 담당자 | 메인 또는 implementation-agent로서 코드·테스트·관련 검증과 필요한 reference evidence 작성 |
| Harness runner | 명시 호출 시 config·project·toolchain 선택, adapter 계획 실행과 결과 반환 |
| Backend adapter/process | CMake/CTest 또는 MSBuild 명령 구성, argv/cwd·timeout·실패·결과 검사 |
구성된 solver build/test와 Harness 구현의 Python 회귀 검증은 별도 범위다.
현재 CMake adapter와 CTest 등록은 Harness Python suite를 실행하지 않는다.
Harness 동작 변경의 Python 검사는 구현 담당자가 변경 영향에 맞게 별도로 수행하며,
Runner 성공을 미실행한 Python 검사나 reference 비교의 통과로 확장하지 않는다.
Runner는 내부 LLM, phase 상태기계, 자동 Git·retry, 파일명 TDD gate나 대화 종료 hook을
사용하지 않는다. 과거 phase/coordination 기록은 이력으로 보존한다. 일반 실패는 현재
구현 owner가 수정하며 새 근거나 변경 없이 같은 명령·agent 호출을 반복하지 않는다.
Project config·preset·command는 검토해야 할 실행 입력이다. Repository 경로 검사,
`shell=False`와 timeout이 실행 파일의 side effect를 모두 격리하는 sandbox는 아니다.
사용자 변경을 보존하고 실제 도구 권한과 외부 solver·원격·파괴 작업의 명시적 승인을 따른다.
승인된 일반 작업에 반복 승인을 추가하지 않으며 계획 요청만으로 실행을 시작하지 않는다.
변경 중에는 관련 검사를, 솔버 기능 완료 시에는 구성된 전체 build/test와 계약상 필수
reference 비교를 한 번 수행한다. 요청이나 넓은 영향으로 전체 검증이 필요한 경우에도
실행하고 이후 변경·실패가 없으면 반복하지 않는다. 문서 작업은 정적 검토로 확인한다.
명령·exit code·판정값과 미실행 항목을 필요한 보고서에 기록하며 Harness 성공만으로
물리·수치 correctness나 외부 release readiness를 선언하지 않는다.
## 문서와 아키텍처의 변경
프로젝트 공통 원칙의 변경은 공통 ADR로, 구현 항목별 선택은 해당 Feature ADR로
기록한다. Feature PRD는 범위·작은 요구사항·acceptance와 현재 checklist의 원본이다.
복잡한 requirements·formulation·I/O는 필요한 경우에만 전문 문서로 분리하고 PRD에서
참조하여 원본을 중복하지 않는다. 메인이 관리하는 핵심 문서 3개와 선택적 상세 산출물은
[FEATURE_DOCUMENTATION](FEATURE_DOCUMENTATION.md)의 소유권과 링크 규칙을 따른다.
Public dependency, identity, 수명, result meaning이나 lifecycle 변경은 영향받는
계약과 evidence를 함께 검토한다. 상위 계약 변경으로 영향받는 evidence는 stale 처리하며,
문서 정리만으로 기존 기능의 재검증이나 release 승인을 완료한 것으로 표시하지 않는다.
개정 전 구현 설명은 [보존본](archive/pre-generalization/ARCHITECTURE.md)에 남긴다.
해당 설명을 Feature 문서로 이관할 때 원래 범위와 승인 revision을 확인한다.
현재 문서는 과거 구현 상세를 삭제하여 계약을 없애거나 미래 API를 선결정하지 않는다.
개발 작업을 조정하는 메인과 전문 agent는 파일·검증 evidence를 다루지만 솔버가 이들을
호출하지 않는다. 실행기는 내부 LLM·phase 상태기계·자동 Git·자동 retry·대화 종료 hook을
소유하지 않는다. 과거 운영 기록은 실행 가능한 현재 pipeline으로 해석하지 않는다.
+93
View File
@@ -0,0 +1,93 @@
# FESA 해석의 의미와 제품 범위
## 목적과 사용자
FESA의 현재 목적은 개인 연구를 위한 유한요소 솔버 개발이다. 사용자는 요소·해법을
구현하는 개발자이면서 결과를 검증하는 해석자다. 외부 사용자 배포는 장기 목표이며,
배포 계획이 현재 지원 범위나 정확성 보장을 확대하지는 않는다.
제품 가치는 승인된 모델에서 물리적으로 설명 가능하고 재현 가능한 결과를 얻는 데 있다.
외부 입력을 읽었다는 사실이나 요소 행렬 하나를 계산했다는 사실만으로 기능을 완성했다고
판정하지 않는다. 입력 의미, 방정식, 해법, 결과와 독립 검증이 연결되어야 한다.
## 모델과 물리량
- Source label은 instance와 함께 입력의 대상을 식별한다. 내부 배열 위치나 equation
번호가 같다는 이유로 다른 instance의 같은 label을 합치지 않는다.
- 입력 단위는 사용자가 일관되게 선택한다. 좌표나 물성의 크기로 SI 단위를 추정하거나
자동 변환하지 않는다. 힘·길이·시간을 기본으로 쓰면 질량은 `force*time^2/length`다.
- 절점 변위, 회전, 단면력, 응력은 위치와 좌표계를 포함한 물리량이다. 요소 끝 작용력과
양의 local-x 단면력, 적분점 응력과 절점 평균 응력은 서로 대체할 수 없다.
- 유효한 재료·단면·연결 관계가 유일하게 결정되어야 해석한다. 누락된 재료를 다른
영역의 평균값으로 채우거나 잘못된 요소를 조용히 제거하지 않는다.
- 미지원 의미는 명확한 실패다. 출력만 제어하는 무해한 요청의 무시도 해당 해석 절차에서
허용한 조합에 한정한다. 한 절차의 예외를 다른 절차로 확대하지 않는다.
## 외부 솔버와의 관계
Abaqus `.inp`의 승인된 일부 문법을 입력으로 사용한다. `S4`와 `S4R`라는 source 표기를
보존하지만 FESA의 MITC4 정식화에 연결한다. Abaqus의 요소 내부 적분, 안정화, 상태 또는
결과 생성 알고리즘이 같다는 뜻이 아니다. 공개 결과의 수치적 일치는 허용되지만 내부
동등성을 증명하지 않는다.
기존 reference는 같은 `.inp` 모델로 생성한 외부 결과다. 비교 대상에는 CSV 외에
고유치 TXT도 있으며, 실제 필요한 원본 경로를 사용한다. Naming 규칙이나 추가 metadata를
맞추기 위해 기준 데이터를 변경하지 않는다.
## 정적 해석
선형 정적 해석에서 free/constrained 분할은 다음 관계를 보존한다.
\[
K_{ff}d_f=F_f-K_{fc}d_c,\qquad r=Kd-F.
\]
지정 변위는 해 복구 뒤에도 정확히 유지된다. `r`의 constrained 성분은 반력,
free 성분은 평형 잔차다. 모든 자유도가 지정된 유효한 모델은 빈 free 방정식을
갖는 해석이지 singular 모델이 아니다. 반력을 외력의 부호 반전만으로 계산하지 않는다.
비선형 정적 해석은 증가분마다 trial과 accepted 상태를 구분한다. 회전벡터에 대한
일반화 모멘트와 공간상의 물리 모멘트를 같은 성분으로 취급하지 않는다. 수렴한 변위만
있고 recovery나 상태 검증이 실패했다면 해당 증가분을 정상 결과로 공개하지 않는다.
물리 변형에너지와 수치 drilling 안정화 에너지는 구별한다. 안정화가 선형계를 풀 수 있게
했다는 사실을 물리 강성·에너지의 정확성 증거로 사용하지 않는다.
## 고유치와 동해석
현재 MITC4 고유치 해석은 원형상·무응력 선형 섭동의 고유쌍을 구한다. Consistent
질량에서 유도한 lumped 질량으로 해석·정규화·검증을 일관되게 수행한다. Source의
`EIGENSOLVER=LANCZOS`는 실제 FEAST 계산과 구별한다. 질량 영공간에 임의 질량을 더해
유한 모드로 바꾸지 않는다.
HHT 동해석은 consistent kinetic mass를 사용한다. 고유치 해석의 lumped 선택을 그대로
가져오지 않는다. 물리적 endpoint 가속도, 회전벡터의 시간 미분, 공간 각가속도,
알고리즘 보조 가속도를 구별한다. 어느 하나의 reference 일치로 다른 양의 시간수렴을
통과했다고 판정하지 않는다. 현재 shell 시간수렴에는 미해결 문제가 있다.
## 열해석의 합의된 향후 범위
가까운 목표는 shell의 단일 step uncoupled transient heat transfer다. 두께가 균질한
단면에 온도점 5개를 두고 면내 및 두께 방향 열전달을 다룬다. 상수 등방 전도도·밀도·비열,
영역별 재료·두께, 고정 시간 증분과 시간에 따라 일정한 입력이 합의된 범위다.
초기 온도는 절점마다 지정하되 그 절점의 두께 온도점에는 같은 값을 준다. 지정 온도와
절점 열률은 아랫면·윗면에 적용하고, edge 열입력은 두께에 걸쳐 균일하게 적용한다.
온도·heat flux·반력 열률의 저장을 요구한다. 5개 온도점에서 source DOF 11은 아랫면,
13은 중앙면, 15는 윗면이다.
Q4 면내 보간과 두 구간의 이차 두께 보간, consistent 열용량, Backward Euler와 flux
복구 위치는 아직 제안이다. Geometry 근사, 초기 경계 jump, edge 문법·단위와 영속 결과
schema를 확정한 뒤 구현한다. 장기 목표인 양방향 열-구조 연성은 현재 열해석의 완료
조건에 포함하지 않는다.
## 수용과 실패
결과가 finite이고 방정식이 풀렸다는 것만으로 correctness를 인정하지 않는다. 해당
물리에 필요한 평형·반력·에너지·영모드·수렴·대칭성과 독립 비교를 확인한다. 외부
reference 오차 기준은 내부 잔차나 시간수렴 기준을 대신하지 않는다.
기준 데이터의 row 누락·추가·중복, 좌표·위치 불일치, nonfinite는 수치 오차 판정 이전의
실패다. 불일치를 평균하거나 임의의 `max(1, scale)` 및 zero clamp로 숨기지 않는다.
실패한 trial과 미완성 출력은 정상 결과가 아니며, 계약된 범위에서 기존 유효 상태와
최종 결과 파일을 보존한다.
+174
View File
@@ -0,0 +1,174 @@
# 실행·입력·결과의 외부 계약
## 호출과 파일 수명
```text
fesa.exe <model.inp>
```
인자는 비어 있지 않은 입력 경로 하나다. 상대 경로는 호출 시 작업 디렉터리 기준으로
lexical normalization한다. 확장자 `.inp`는 대소문자를 구별하지 않는다. 옵션 형태 인자와
`--output`은 지원하지 않는다. Symlink·junction·short name을 resolve해 결과 위치를 바꾸지 않는다.
| 산출물 | 경로와 의미 |
| --- | --- |
| 공식 결과 | 입력의 lexical sibling `<stem>_results.h5` |
| 실행 로그 | 같은 위치의 `<stem>_log.txt`; 실패 진단을 포함할 수 있음 |
| 쓰기 lease | 결과 경로에 `.fesa.lock`을 붙인 임시 소유권 파일; 정상 handle 종료 시 삭제 |
같은 output pair를 다른 실행이 점유하면 `output-busy`로 실패한다. Lease 생성 실패도
같은 output failure로 분류되므로 충돌 외에 OS 권한·디렉터리 상태도 확인해야 한다.
최종 HDF5는 완료 candidate의 기록·self-check·close 후 교체한다. 실패 시 이전 최종
HDF5를 보존하는 계약과 로그가 갱신될 수 있는 계약을 구별한다. 기존 파일의 존재가
새 실행 성공을 의미하지 않는다.
| CLI exit | 의미 |
| ---: | --- |
| 0 | 선택된 해석과 최종 결과 저장 성공 |
| 2 | 잘못된 인자·입력 확장자 등 usage 오류 |
| 3 | 파일 읽기·문법·미지원 입력 오류 |
| 4 | 모델 의미·구성·유효성 오류 |
| 5 | 해법 실패 |
| 6 | Output lease·로그·HDF5 저장 실패 |
진단은 stderr에 결정적인 순서로 출력된다. 한 줄은 탭으로 구분된
`severity=... code=... file=... line=... keyword=... entity_identity=... message=...`
필드를 갖고 빈 source 필드도 유지한다. Backend 원래 오류 번호를 새 CLI exit로 그대로
반환하지 않는다. 경고가 있는 성공도 가능하며 성공 HDF5의 진단은 warning이다.
## 공통 입력 규칙
현재 입력은 하나의 physical `.inp` 파일이다. LF·CRLF, 빈 줄, `**` comment와
keyword parameter continuation을 처리한다. Physical line은 종결자 제외 256 ASCII
bytes 이내이며 printable ASCII와 tab을 사용한다. Keyword·parameter·enum·이름 lookup은
ASCII case-insensitive이고 원문 표기와 줄 번호는 보존한다. 같은 값의 중복 parameter도
실패다. Comma의 빈 field를 없애거나 data continuation으로 연결하지 않는다.
모델은 part의 node·element·set·section, identity instance를 둔 assembly, named material,
모델 경계조건과 하나의 해석 step으로 구성한다. Instance transform, `*INCLUDE`, 일반
contact·MPC·비탄성·혼합 beam/shell model은 현재 공개 subset이 아니다.
| 입력 | 소비자가 지켜야 할 의미 |
| --- | --- |
| `*NODE` | Part 안의 `label,x,y,z`; label은 양의 정수, 좌표는 finite |
| `*ELEMENT, TYPE=B33|S4|S4R, ELSET=...` | B33은 2개, shell은 서로 다른 4개 node label; source type과 내부 정식화 구별 |
| `*NSET`·`*ELSET` | 허용 scope의 label 나열 또는 `GENERATE`; assembly set은 명시 instance에 결속 |
| `*INSTANCE, NAME=..., PART=...` | 기존 part의 identity instance; transform data 미지원 |
| `*ELASTIC` | 상수 등방 `E,nu`; `E>0`, `-1<nu<0.5`, finite |
| `*SHELL SECTION, ELSET=..., MATERIAL=...` | 양의 finite thickness와 optional 양의 integration-point 정수; centered homogeneous section |
| `*BEAM GENERAL SECTION, ELSET=..., MATERIAL=..., SECTION=GENERAL` | 첫 row `A,I11,I12,I22,J`, 둘째 row `n1x,n1y,n1z`; 현재 `I12=0`만 허용, 탄성은 연결 material에서 읽음 |
| `*SECTION POINTS` | 바로 앞 beam section의 `x1,x2` row 목록; 입력 순서의 stress recovery 위치, duplicate/nonfinite 거부 |
| `*BOUNDARY` | `target,first,last[,value]`, DOF 1~6; 생략 value는 0. Procedure별 추가 제한 적용 |
| `*CLOAD` | `target,dof,magnitude`; 같은 resolved node/DOF는 source 순서로 합산. Procedure별 허용 DOF 적용 |
중복 label, 해소되지 않은 target, 모호한 set, 잘못된 section/material 조합과 nonfinite
값은 실패다. 이름이 같더라도 instance가 다르면 다른 entity다. 빈 optional field와
생략 field는 각 구문에서 허용한 경우에만 같으며 임의 default를 채우지 않는다.
한 procedure에서 허용하는 keyword가 다른 procedure에서도 허용된다는 뜻은 아니다.
## Procedure와 하중
| 절차 | 입력·출력 및 제한 |
| --- | --- |
| 선형 정적 | 단일 `*STATIC`, 작은 변위, B33 또는 MITC4 shell. 지정 변위와 global nodal force/moment. Canonical 결과 frame 0 하나 |
| 비선형 정적 | MITC4 shell, `NLGEOM=YES`, full Newton. Static control data에 따른 accepted increment 이력, 유한회전과 해당 하중 의미 |
| 선형 frequency | MITC4 shell, 원형상 무응력, `NLGEOM=NO`, homogeneous BC, 활성 material의 양의 density. 요청 mode N개와 내부 검증 결과 |
| HHT dynamic | MITC4 shell, `NLGEOM=YES`, `*DYNAMIC, DIRECT`, 양의 density, 고정 h/T. 초기 frame 포함 전체 이력. 현재 시간수렴 미해결로 기능 검증 완료 상태는 아님 |
| 열전달 | 계획 단계. DS4·열 입력·온도/flux dataset을 현재 공개 지원으로 소비하면 안 됨 |
정적 `*STATIC`은 parameter 없이 `initial_increment,time_period,minimum_increment,maximum_increment`
한 row를 받으며 값은 finite positive여야 한다. Source increment 값이 물리 시간을 의미하는 것은 아니다. Linear와
nonlinear 절차의 결과 frame 의미를 구별한다. HHT의 시간 값을 static load factor로
읽지 않는다.
정적 shell 압력은 assembly-level `*SURFACE, TYPE=ELEMENT, NAME=...`에
`instance.element,SPOS|SNEG` 또는 instance-bound assembly ELSET과 side로 facet를
선언하고, step의 parameter 없는 `*DSLOAD`에 `surface,P,value`로 적용한다.
Part surface·다른 surface type·추가 parameter·`*DLOAD`·분포 함수는 지원하지 않는다.
양의 P는 선택한 surface normal의 반대 방향이며 음의 P는 방향을 반전한다. 선형 정적은
reference configuration, 비선형 정적은 current-configuration follower pressure와
그 external tangent를 사용한다. Global CLOAD와 같은 하중으로 치환하거나 이 압력
subset을 dynamic이나 미래 thermal에 암묵적으로 확장하지 않는다.
Frequency 입력은 `*FREQUENCY`의 요청 정수 N 뒤 최대 6개의 빈 field를 허용한다.
명시적인 범위·shift 등 나머지 숫자는 허용하지 않는다. EIGENSOLVER는 LANCZOS만 허용해
FEAST로 mapping하고 warning을 남긴다. NORMALIZATION은 MASS, SIM은 flag/YES,
ACOUSTIC COUPLING은 acoustic-free 모델의 ON만 허용한다. BC는 exact 0이며 하중을
modal response로 계산하지 않는다. Density는 `rho` 또는 `rho,`의 상수 양수 한 row다.
HHT는 `h,T` 또는 `h,T,` 한 row를 받는다. 양의 정수 N에 대해 `double(N)*h == T`,
`N<=INC`를 만족해야 하며 마지막 증분을 줄이거나 시간 tolerance로 맞추지 않는다.
STEP의 INC 기본값은 100이다. 계수는 `alpha=-0.05,beta=0.275625,gamma=0.55`,
질량은 consistent-kinetic이다. BC는 전체 시간에 exact 0, CLOAD는 DOF 1~3의 일정한
global force만 지원한다. 초기 q/v는 0이고 전체 STEP 하중이 `0+`부터 적용된다.
비영 초기조건, damping, amplitude, follower/distributed load와 공개 계수 변경은 현재 미지원이다.
출력 요청의 no-op 허용은 procedure마다 다르다. 특히 HHT는 data 없는 PREPRINT의 네
NO flag, RESTART WRITE/FREQUENCY=0, OUTPUT FIELD 또는 HISTORY/VARIABLE=PRESELECT/
FREQUENCY=1 조합만 허용하며 OUTPUT의 FREQUENCY 생략은 1이다. Child NODE/ELEMENT
OUTPUT은 HHT에서 미지원이다. No-op이 필수 FESA 결과의 선택·삭제·추가 권한을 주지 않는다.
## HDF5 소비 규칙
Reader는 metadata의 feature identity와 version, 해당 형식에 정의된 procedure discriminator를
함께 확인한다. `schema_version`만 보고 static 결과로 가정하지 않는다. 기존 선형 static에는
`analysis_procedure` attribute가 없으므로 이를 새로 필수화하지 않는다. 알려지지 않은
형식이나 필수 dataset 누락은 명시적 오류이며 모르는 optional additive field만 무시할 수 있다.
| 결과 | 식별·주요 경로 |
| --- | --- |
| 선형 정적 | schema 0, `feature_id=linear-static-3d-euler-beam` 또는 `linear-static-mitc4-shell`, `/steps/Step-1/frames/0/` 결과; `analysis_procedure` 없음 |
| 비선형 정적 | schema 1, `feature_id=nonlinear-static-newton-raphson`, `analysis_procedure=nonlinear-static-full-newton`, `/steps/Step-1/accepted_frames`와 `/steps/Step-1/frames/<n>/` |
| Frequency | schema 0에 `feature_id=mitc4-shell-feast-eigen2`, `analysis_procedure=linear-frequency`, `eigen_schema_version=1` 추가 |
| HHT | `feature_id=hht-implicit-dynamics`, `analysis_procedure=hht-implicit-dynamics`, schema 1, 전체 accepted frame과 `/steps/Step-1/frames/<n>/` |
`Step-1`은 storage slot이다. Frequency는 `/steps/Step-1`의 `source_step_name`, HHT는
`/metadata`의 `source_step_name`에서 원래 이름을 읽는다. 기존 선형·비선형 static은
canonical `step_name=Step-1`만 저장하므로 원래 source 이름이 HDF5에 별도로 있다고
가정하지 않는다. Float64와 fixed-width integer는 little-endian,
문자열은 UTF-8다. Compound는 field name/type/extent로 읽고 C++ struct padding에 의존하지 않는다.
Source 입력 identity는 실제 읽은 byte의 identity를 포함한다.
`/model/nodes`와 `/model/elements`의 source instance/label과 internal ID를 사용해
결과 row를 연결한다. Internal row 번호를 원본 label로 취급하지 않는다. Nodal
displacement와 constraint mask의 6성분 순서는 `[UX,UY,UZ,URX,URY,URZ]`다. Reaction,
가속도 등 다른 dataset에는 각각의 component 이름이 있으므로 이 이름을 재사용하지 않고
단위·좌표·location·component attribute를 함께 읽는다. `/model/nodal_constraint_mask`의
free=0/constrained=1이 반력 해석의 기준이다.
Static nodal `displacement`는 `[node_count,6]`이다. Linear nodal `reaction`의 constrained
성분은 반력, free 성분은 잔차 evidence다. Shell 결과의 기본 location 축은 면내 4점,
응력의 section 축은 bottom/middle/top 3점이다. Section resultant의 8성분은
`[N11,N22,N12,M11,M22,M12,Q13,Q23]`, 응력의 3성분은 `[S11,S22,S12]`다.
두 값의 단위와 위치를 서로 바꾸지 않는다. Beam 결과는 element endpoint와 단면 위치를
유지하며 node 평균 결과로 읽지 않는다.
Frequency의 `/steps/Step-1/eigen/modes`는 N개 `mode_id,eigenvalue,classification,cluster_id`
record이며 mode_id는 1부터다. `frequencies`는 raw eigenvalue가 비음수인 mode의
ID subset, `vectors`는 `[N,node_count,6]`의 mass-normalized mandatory projection이다.
이 벡터는 응답 변위가 아니다. 작은 음수 고유치를 abs/zero clamp하지 않으며 frequency
존재 여부를 eigenvalue와 구별한다. Static reaction·stress를 modal 결과에 요구하지 않는다.
HHT frame은 0부터 N까지이고 `time=double(n)*h`다. `is_initial`은 n=0에만 참이다.
Nodal `acceleration`과 `algorithmic_acceleration`, `angular_acceleration`,
`generalized_reaction`과 공간 `reaction`은 구별된 dataset이다. Accepted frame과 source
identity로 접근하고 failed trial이나 time 기반 nearest-neighbor matching을 사용하지 않는다.
## 외부 비교
Comparison은 필요한 instance·entity·location·component·step/frame을 일대일 대응한다.
Missing·extra·duplicate·nonfinite는 tolerance 전에 실패한다. 같은 case/step/frame/
quantity/단위/좌표/판정 영향의 값만 한 family에 넣는다.
Reference 값만으로 `S=max(abs(r_i))`, `B=0.01*S`를 정한다. `abs(r_i)<=B`이면
`abs(f_i-r_i)<=B`, 나머지는 상대오차 `<=0.05`를 요구한다. Family 전체의
`sqrt(mean((f_i-r_i)^2))/S<=0.01`도 만족해야 한다. S=0이면 모든 FESA 값도 exact 0이어야
하며 nonzero 오류는 `zero-reference-scale-nonzero-error`로 보고한다. 임의 floor는 없다.
MITC4 eigen 첫 구현의 named policy `mitc4-eigen-first-implementation`에 한해 mode별
singleton Value family의 상대오차와 RMS를 모두 5%로 판정한다. 다른 family의 RMS 1%나
내부 eigen 검증 기준을 바꾸지 않는다. MITC4 U는 blocking, UR는 warning-only이며 warning도
결정적 순서로 남긴다. 사전검사 실패는 warning-only family에서도 전체 실패다.
CSV view는 비교 보조 산출물이다. FESA 공식 output으로 대체하거나 reference 값을
보정하는 중간 형식으로 사용하지 않는다.
+72
View File
@@ -0,0 +1,72 @@
# 수치 구현과 검증에서 주의할 점
## 실행 성공과 기능 완료의 차이
HHT 원본 모델의 변위 비교는 통과 기록이 있지만 실제 shell의 두 시간수렴 사례는
미해결이다. 따라서 외부 변위가 맞는다는 이유로 가속도 복구·시간수렴·physics 완료를
추론하면 안 된다. 변경 후에는 동일한 dt refinement에서 변위·속도·물리 가속도의 차수를
각각 확인해야 하며 auxiliary acceleration의 결과를 물리 가속도로 대신하지 않는다.
과거 I/O 문서의 `implementation-pending` 같은 문구는 그 문서가 작성된 시점의 상태일 수
있다. 현재 코드는 dynamic/eigen state와 writer를 포함한다. 코드 존재, 작성 당시 계획,
후속 실행 보고서를 구분하고 날짜가 오래된 머리말 하나로 전체 기능 상태를 결정하지 않는다.
## 단면력과 회전
Shell 굽힘 모멘트 복구에는 두께의 세제곱 계수 `M=t^3 C kappa/12`가 들어간다.
막력과 같은 두께 계수로 처리하면 displacement가 맞아도 section resultant가 틀릴 수 있다.
복구식을 바꿀 때 두께를 독립적으로 바꾸는 사례와 HDF5 readback을 함께 대조한다.
비선형 shell의 rotation-vector generalized moment는 spatial moment와 다르다. Chart에
대한 일의 짝을 유지해야 하므로 성분 이름만 바꿔 공개 reaction으로 내보내지 않는다.
자세 변화가 큰 사례와 원점 이동 시 moment balance를 확인한다.
Beam section resultant는 요소 endpoint identity로 대응한다. 같은 절점에 모인 여러
endpoint 값을 node 평균으로 줄이면 end action 부호 또는 station 불일치를 숨긴다.
Instance·element·endpoint node·component를 함께 비교해야 한다.
## 질량·영공간과 source 옵션
고유치의 derived lumped mass와 HHT의 consistent kinetic mass는 승인 목적이 다르다.
두 절차가 같은 shell을 쓴다는 이유로 질량 구현을 한 가지로 치환하지 않는다. 질량
영공간이 있으면 analytic null과 free 공간의 교집합을 확인하고 임의 drilling inertia를
더하지 않는다. 부분 회전 구속을 full clamp로 바꾸는 것도 같은 모델이 아니다.
Source `S4R`나 shell section의 integration-point 필드는 FESA의 적분법 선택 스위치가
아니다. Source 보존·허용 문법과 실제 numerical integration을 별도로 검증한다.
## 열해석 계획에서 혼동하기 쉬운 위치
온도점 5개의 DOF 11은 아랫면이며 중앙면은 DOF 13이다. 열해석 제안의 54개 직접
적분점과 24개 flux trace는 서로 다른 목적의 위치다. 두 구간 이차 보간의 중앙면에서는
두께 미분의 양쪽 trace가 다를 수 있어 평균하지 않는다. 이 수치 방법은 아직 채택 대기다.
열전달 반력에는 열용량에 의한 저장률이 포함된다. 전도 flux만으로 반력 열률을 정의하면
transient 에너지 수지가 달라진다. 첫 증분에서 지정 온도가 변하는 경우에는 이전 constrained
온도의 용량 결합 항도 필요하므로 초기값을 조용히 projection하지 않는다.
열 reference의 NT11에는 음수가 있다. 모든 음수를 roundoff라고 가정하거나 clamp하지
않고 원본 identity와 승인된 비교 기준으로 다룬다. 현재 CSV의 한 시점 온도만으로 flux,
반력, 다른 두께 온도점 또는 전체 시간수렴을 검증했다고 주장하지 않는다.
## 실행 환경과 결과 파일
Preset 파일이 존재해도 Python 실행기가 자동 선택하지 않는다. 개인 설정에서
`configurePreset`, `buildPreset`, `testPreset`, `binaryDir`를 함께 맞춰야 다른 build tree의
테스트를 읽는 실수를 피할 수 있다. CTest discovery 결과가 비거나 다른 compiler가
선택되면 실행 실패로 다룬다.
MSVC link 성공 뒤 실행 시 DLL을 못 찾는다면 dependency runtime staging을 확인한다.
개발자 PATH에 우연히 있던 DLL로 성공한 것을 배포 환경 검증으로 보고하지 않는다.
Python suite는 CTest와 별개이므로 runner의 성공에 포함시켜 보고하지 않는다.
CLI 결과 경로는 입력의 lexical parent다. Symlink나 junction을 canonical 경로로
치환하면 사용자가 지정한 output 위치 의미가 바뀐다. Output lease와 atomic replace의
검증에서는 기존 final HDF5뿐 아니라 로그·임시 파일의 서로 다른 실패 수명을 확인한다.
## 과거 개발 절차와 검사
일부 Python 검사는 삭제된 coordinator·planning·correction profile과 고정 단계 표를
기대한다. 현재 agent inventory 및 인자 없는 실행기와 맞지 않는 정적 근거가 있다.
이전 검사를 만족시키기 위해 폐기된 profile·phase·hook을 복원하지 않는다. 현행 절차를
확인한 뒤 별도 테스트 변경 작업으로 정리하고 실제 실행 결과를 기록한다.
+117
View File
@@ -0,0 +1,117 @@
# 개발 환경과 실행 방법
## 최초 준비
Windows에서 Visual Studio의 Desktop development with C++ 워크로드, CMake 3.25 이상,
Ninja, Intel oneAPI MKL·TBB, HDF5 C package와 승인된 GoogleTest 로컬 checkout을 준비한다.
Runner는 Python 3.10 이상, `tomllib`을 사용하는 Python 검사에는 3.11 이상이 필요하다.
자동 dependency download나 특정 개인 설치 경로를 전제하지 않는다.
저장소 루트를 작업 디렉터리로 하는 **MSVC x64 Developer PowerShell**을 연다.
일반 PowerShell에서 아래 configure를 먼저 실행하면 compiler와 runtime 환경이 빠질 수 있다.
설치 경로가 환경변수에 없다면 아래 질문에 실제 로컬 경로를 입력한다.
```powershell
$env:FESA_GTEST_SOURCE_DIR = Read-Host 'GoogleTest source checkout 경로'
$env:MKL_DIR = Read-Host 'MKLConfig.cmake가 있는 디렉터리'
$env:TBB_DIR = Read-Host 'TBBConfig.cmake가 있는 디렉터리'
$env:HDF5_DIR = Read-Host 'hdf5-config.cmake 또는 HDF5Config.cmake가 있는 디렉터리'
Get-Command cl, cmake, ctest, ninja, python
Test-Path -LiteralPath (Join-Path $env:FESA_GTEST_SOURCE_DIR 'CMakeLists.txt')
```
`FESA_GTEST_SOURCE_DIR`는 source root, 나머지 세 변수는 CMake package config directory다.
네 값은 현재 프로세스·개인 설정에 두며 저장소의 절대 경로로 고정하지 않는다.
`Test-Path`가 false이거나 명령이 없으면 먼저 준비 환경을 수정한다.
## C++ 구성·빌드·검사
다음 순서로 실행한다. Configure 전에 dependency 경로와 x64 compiler가 준비되어야 하며,
build 전에 configure가 성공해야 한다. 각 명령이 실패하면 다음 단계로 진행하지 않는다.
```powershell
cmake --preset windows-msvc-ninja-debug
cmake --build --preset windows-msvc-ninja-debug
ctest --preset windows-msvc-ninja-debug --show-only=json-v1
ctest --preset windows-msvc-ninja-debug --output-on-failure
```
Build tree는 `.harness/build-ninja-msvc-debug`다. CTest discovery는 실제 등록된 검사를
확인하며 0개 검사는 검증 성공이 아니다. 관련 검사만 실행할 때는 같은 preset에 `-R`로
실제 CTest 이름을 지정한다. 솔버 기능 완료 시 전체 검사와 필수 수치/reference 비교를
수행하고, 문서만 수정할 때는 실행하지 않는다.
## 설정된 실행기로 검증
개인 `.harness/config.json`이 이미 있으면 보존하고 실제 선택된 backend를 확인한다.
동일 preset을 사용하려면 다음 설정을 사용한다. 기존 설정을 무조건 덮어쓰지 않는다.
```json
{
"version": 1,
"projectType": "cmake",
"cmake": {
"sourceDir": ".",
"binaryDir": ".harness/build-ninja-msvc-debug",
"configurePreset": "windows-msvc-ninja-debug",
"buildPreset": "windows-msvc-ninja-debug",
"testPreset": "windows-msvc-ninja-debug"
}
}
```
```powershell
python scripts/execute.py
```
실행기는 명령을 한 번 구성·실행하고 compiler metadata와 CTest discovery를 확인한다.
전체 deadline은 CLI 시작부터 1,800초이며 각 명령 제한과 남은 시간 중 짧은 값을 적용한다.
Phase 인자·`--push`·`--approve-danger-full-access`를 받지 않는다. 자동 Git·retry·외부
solver 실행이나 필요한 추가 reference 비교의 추론은 하지 않는다.
성공은 exit 0, config/toolchain/backend/timeout 실패는 exit 1이다. 잘못된 CLI 인자나
자동 감지에서 project metadata가 없는 경우는 exit 2다. 원래 backend exit와 runner exit를
구분해 기록하고 출력 tail에 포함된 stage·argv·cwd에서 실패 경계를 찾는다.
## Python 검사와 비교 도구
Runner 또는 Python 비교기를 변경하면 관련 Python 검사를 별도로 실행한다.
전체 Python 검사 명령은 다음과 같으며 CTest 실행에 포함되지 않는다.
```powershell
uv run --with pytest python -B -m pytest -v -rs
```
HHT 비교 도구에는 Python 3.11 이상과 `numpy`·`h5py`가 필요하다. 현재 도구는 지정된
`shellNL-dyn-meshfine`의 729개 절점 중 선택한 9개 절점, 101 frames의 U/UR 비교용이다.
다음 명령은 **이미 생성된** HDF5와 원본 변위 CSV를 비교하며 솔버나 Abaqus를 실행하지 않는다.
다른 모델의 범용 비교기로 사용하지 않는다. Report의 상위 디렉터리는 도구가 생성한다.
```powershell
$inputPath = Read-Host '비교할 원본 .inp 경로'
$referencePath = Read-Host '원본 변위 CSV 경로'
$resultPath = Read-Host 'FESA HDF5 경로'
$reportPath = Read-Host '비교 보고서 JSON 경로'
uv run --with numpy --with h5py python scripts/verification/compare_hht_dynamic.py --input $inputPath --reference $referencePath --results $resultPath --report $reportPath
```
Reference 원본을 생성·복원하거나 다른 곳으로 옮기는 명령은 검증 절차에 포함하지 않는다.
원본이 없으면 필요한 경로와 미실행 이유를 보고한다. 외부 solver와 라이선스 사용은
별도 명시된 권한 아래 수행한다.
## 모델 실행과 배포 상태
성공한 Debug build 뒤 생성된 CLI를 실행한다. 모델 경로는 실제 승인된 입력을 지정한다.
```powershell
$modelPath = Read-Host '해석할 .inp 경로'
& ./.harness/build-ninja-msvc-debug/src/fesa/fesa.exe $modelPath
```
입력 옆에 `<stem>_results.h5`와 `<stem>_log.txt`를 생성하므로 해당 디렉터리에 쓸 수
있어야 한다. 실행 실패 때 이전 HDF5가 남아 있을 수 있으므로 파일 존재만으로 이번 실행의
성공을 판단하지 않는다. Exit와 진단, 실제 저장된 source identity를 함께 확인한다.
현재 별도의 데이터베이스 초기화·계정 생성·서비스 배포 명령은 없다. 외부 사용자 배포의
형식, 설치 방식, dependency 재배포 조건과 지원 범위는 아직 정하지 않았다. 로컬 실행
성공을 설치·배포 검증으로 간주하지 않는다.
+49
View File
@@ -0,0 +1,49 @@
# 실행 권한과 데이터 취급
## 현재 사용 환경
FESA는 개인 연구용으로 로컬 입력 파일을 읽고 로컬 결과를 저장하는 솔버다. 사용자에게
별도의 데이터 분류·보안 정책은 없다. 고객 기밀이 없다고 단정하거나 모델의 외부 전송이
허용되었다고 해석하지 않는다. 외부 배포는 계획이며, 공개 서비스 인증·계정·권한 관리가
현재 구현된 것으로 설명하지 않는다.
현재 CLI에는 별도 로그인·토큰·비밀번호 수명주기가 없다. 실행 파일과 입력·결과에
대한 접근 권한은 운영체제의 실행 계정과 파일 권한에 따른다. 잘못된 자격증명·만료·계정
잠금에 대한 솔버 응답은 적용 대상이 아니다. 이후 서버나 계정 기능이 추가되면 새 정책과
실패 경로를 정의해야 하며 로컬 실행 권한을 그대로 서버 권한 모델로 사용하지 않는다.
## 보호 대상과 허용 범위
| 주체 | 동작 | 조건과 경계 |
| --- | --- | --- |
| 로컬 해석 사용자 | 입력을 읽고 결과·로그 생성 | 실행 계정이 경로에 접근할 수 있어야 한다. OS 접근 거부를 우회하지 않는다. |
| 솔버 프로세스 | 같은 입력의 결과·로그 쓰기 | Output write lease 획득 후 수행한다. Lease 충돌 시 새 쓰기를 시작하지 않는다. |
| 개발 담당자 | 요청한 소스·문서·테스트 수정 | 요청 범위의 일반 작업은 진행하고 관련 없는 사용자 변경은 보존한다. |
| 개발 담당자 | Reference 생성·변경·복원 | 해당 작업이 명시적으로 요청되어야 한다. 구현의 실패를 없애기 위한 데이터 보정은 허용하지 않는다. |
| 개발 담당자 | 외부 solver·라이선스·자격증명·비용 사용 | 기존 승인 범위가 없으면 사용자 결정이 필요하다. 파일의 존재가 실행 허가를 뜻하지 않는다. |
| 개발 담당자 | Commit·push·tag·publish·release | 각각 요청된 범위에 한정한다. 검증 실행기가 이 권한을 부여하지 않는다. |
## 입력과 실행의 신뢰 경계
`.inp`는 모델 데이터다. 지원하지 않는 keyword를 외부 명령이나 파일 포함으로 실행하지
않는다. 문법·참조·물성 검사는 해석 의미를 보호하지만, 악의적인 입력에 대한 자원 제한이나
프로세스 격리가 입증되었다는 뜻은 아니다. 외부에서 받은 임의 모델을 안전하게 실행하는
서비스라는 보장은 현재 없다.
빌드 설정, CMake preset, 실행할 프로그램과 스크립트는 코드 실행 권한을 가진 입력이다.
작업 디렉터리 검사·`shell=False`·timeout은 실행 파일의 모든 부작용을 차단하지 못한다.
신뢰하지 않는 설정을 단순 데이터로 보고 자동 실행하지 않는다.
Output lease는 동시 쓰기 충돌 방지 장치다. 파일 ACL이나 사용자 인증을 대신하지 않는다.
결과 경로의 lexical 의미와 OS가 해석하는 symlink·junction의 실제 위치도 구별한다.
## 기록과 배포 시 남은 결정
솔버 진단에는 source 파일 경로, 줄 번호, keyword, entity identity와 오류 설명이 들어갈
수 있다. 모델·결과·진단을 외부 공유할 때 경로와 모델 정보가 포함될 수 있음을 확인한다.
현재 별도의 암호화·자동 마스킹·보존기간·사용자 접근 감사 정책은 정해져 있지 않다.
수치 실행 로그를 보안 감사 로그로 간주하지 않는다.
개인 dependency 경로와 자격증명을 공용 문서나 버전 관리에 넣지 않는다. 향후 외부 배포
전에 배포 방식, dependency 재배포 권리, 입력 신뢰 범위와 데이터 취급 방침을 결정해야 한다.
이는 현재 기능 완료의 새 조건이나 배포 승인 기록이 아니다.
+133
View File
@@ -0,0 +1,133 @@
# FESA 개발 규칙
## 계약과 변경 범위
요구조건, 정식화, 부호, 단위, 좌표계, source identity와 수치 기준을 구현 전에 고정한다.
구현 편의나 실패한 결과를 이유로 승인된 의미를 조용히 변경하지 않는다. Physics·지원
범위·공개 호환성·acceptance·영속 schema 변경과 해결되지 않은 필수 reference 충돌은
사용자 결정 사항이다. 이미 승인된 일반 수정과 인계에는 반복 승인 절차를 추가하지 않는다.
요청 범위에 필요한 최소 변경만 한다. 미래 기능을 위한 state·base class·registry를
선할당하지 않는다. 다른 작업자의 변경을 되돌리거나 주변 코드를 함께 정리하지 않는다.
계획 요청만으로 solver 구현이나 외부 실행을 시작하지 않는다.
## 의존성과 소유권
- Public core는 concrete I/O adapter나 MKL·TBB·HDF5·Win32 타입에 의존하지 않는다.
Backend 교체는 interface 경계 뒤에서 처리하고 vendor 오류는 공개 실패 형식으로 변환한다.
- Domain은 전체 모델 정의를 소유하고 파싱 이후 가능한 한 불변이다. AnalysisModel은
복사본이 아닌 non-owning view이며 Domain이 view보다 오래 살아야 한다.
- DofManager가 자유도 정의·free/constrained mapping·equation 번호·sparse pattern을
전담한다. Node와 Element에 equation 번호를 저장하지 않는다.
- Element/material은 local response, assembly는 global reduction, procedure는 해법과
상태 수명, recovery는 물리량, writer는 serialization을 소유한다. 책임을 역전하지 않는다.
- Procedure가 실제 사용하는 mutable state만 할당한다. Trial을 검증한 뒤 commit하고
실패한 candidate가 기존 state나 최종 HDF5를 부분적으로 오염시키지 않게 한다.
## 수치 코드
Element-local contribution을 stable ordering으로 생성하고 고정된 순서로 합산한다.
병렬 worker는 자기 index의 buffer만 갱신하며 global CSR이나 결과 row를 공유 누적하지
않는다. Hash 순서나 thread scheduling이 sparse structure·결과·진단 순서를 결정하면 안 된다.
선형 정적 해석은 full K를 stable free/constrained 순서로 분할하고 `Kff` factorization을
load assembly보다 먼저 수행한다. 유효한 all-constrained의 빈 free system을 singular로
바꾸지 않는다. 반력과 free 평형은 같은 full residual에서 복구한다.
서로 다른 결과 위치·단위·부호·source identity를 평균으로 합치지 않는다. 식이나
reduction 순서를 바꾸는 최적화도 수치 변경이다. 임의 absolute floor, zero clamp,
missing-row 무시, 실패 시 다른 물성·질량·solver로의 silent fallback을 추가하지 않는다.
## C++ 규약
현재 검증 기준은 C++17 이상, Windows MSVC x64 Debug, CMake target과 CTest다.
다른 backend를 지원하는 실행 스크립트가 FESA의 다른 platform 검증을 뜻하지 않는다.
새 compiler warning을 추가하지 않는다. Vendor target에 FESA warning 정책을 강제하지 않는다.
| 대상 | 규칙 |
| --- | --- |
| 파일·namespace | 소문자 snake_case, source `.cpp`, header `.h` |
| 타입·함수·accessor | PascalCase; constructor·destructor·operator는 언어 규칙 |
| 변수·parameter | snake_case |
| Class 멤버 | snake_case 뒤 `_`; struct record는 trailing `_` 없음 |
| 상수·enumerator | `kPascalCase` |
| Header | Self-contained include와 repository 경로 기반 include guard; `#pragma once`로 대체하지 않음 |
| Formatting | Google 기반 `.clang-format`, space 2개, 통상 80자, namespace 본문 들여쓰기 없음 |
Include는 대응 header, C, C++ standard, third-party, FESA 순서로 그룹화하고 그룹 내부는
알파벳순이다. Transitive include에 의존하지 않는다. 한 statement에 한 declaration을
두고 변수를 가능한 좁은 범위에서 초기화한다. 의미 없는 type modifier를 장식으로 붙이지 않는다.
RAII와 단독 ownership의 `unique_ptr`를 우선한다. 실제 공유 수명이 없는 `shared_ptr`,
미래용 virtual method, static 함수 묶음용 class를 만들지 않는다. Polymorphic base는
public virtual destructor를 갖고, non-owning 수명은 API 계약에 적는다.
Expected failure는 `Status` 또는 `Result<T>`다. Backend exception을 그대로 외부로
노출하지 않는다. 같은 물리·단위·좌표·실패·소유권 의미일 때만 공통화하며, 코드 모양만
비슷한 다른 정식화를 합치지 않는다.
Production의 public/protected 선언과 private/internal 함수에는 필요한 목적·수명·단위·
부호·실패·결정적 순서를 기록한다. Public API Doxygen는 영어를 기본으로 하고 테스트에
형식적인 Doxygen를 요구하지 않는다. 코드 동작의 번역보다 비자명한 이유를 설명한다.
Formatting-only 변경은 동작 변경과 같은 commit에 섞지 않는다.
## 검증 조건
1. 동작·interface 변경은 해당 의미를 확인하는 테스트로 검증한다. 버그는 가능한 경우
실패를 먼저 재현하고 최소 수정한다. Coverage가 충분한 rename이나 문서 작업에는
구현을 반복하는 형식적 테스트를 추가하지 않는다.
2. 수식·요소·재료·적분·상태 갱신 변경에는 독립 numerical review와 해당 analytical/
invariant 검사를 수행한다. 필요한 물리·reference 검증도 유지한다.
3. 개발 중에는 관련 검사를 실행한다. 솔버 기능 완료 시 구성된 전체 build/test와 필수
reference 비교를 한 번 수행한다. 이후 변경·실패·미해결 우려가 없으면 반복하지 않는다.
4. 외부 비교는 row identity·component·finite 검사를 먼저 통과해야 한다. 수치 기준이나
reference 경로·값을 구현 결과에 맞춰 바꾸지 않는다. 기존 비교 기준 변경은 승인·결정
기록·경계값 테스트·영향받는 비교의 재실행을 요구한다.
5. 문서만 수정하면 링크·source 대조·diff 정적 검토를 하고 build/test는 실행하지 않는다.
미실행·실패·과거 revision의 결과를 현재 통과로 표시하지 않는다.
6. Runner, CTest, Python 회귀, 독립 물리 검토의 성공 범위는 각각 다르다. 실행기 exit 0만으로
모든 검증이나 외부 배포 준비가 완료됐다고 보고하지 않는다.
## 작업 배정과 실패 처리
메인이 필요한 전문 작업만 선택한다. 작은 작업은 직접 수행하며 고정 stage 순회,
별도 coordinator, 자동 retry 예산을 도입하지 않는다. 일반 실패는 현재 구현 owner가
수정하고 새 근거·변경 없이 같은 명령이나 agent 호출을 반복하지 않는다.
| 작업 | 담당과 적용 조건 |
| --- | --- |
| 요구사항 | `requirement-agent`: 복잡하거나 상충하는 범위·acceptance |
| 근거 조사 | `research-agent`: 부족한 이론·benchmark·reference 근거 |
| 정식화 | `formulation-agent`: 새 수식·요소·해석 알고리즘 |
| 독립 수치 검토 | `numerical-review-agent`: 정식화·수치 변경·불일치 |
| 입력·결과 | `io-definition-agent`: syntax·진단·schema·비교 mapping |
| 구현 | 메인 또는 `implementation-agent`: 위임 이점이 있는 코드 묶음 |
| 물리 평가 | `physics-evaluation-agent`: 평형·타당성·coverage |
일반 역할은 medium, 정식화·수치·물리 역할은 high 추론 강도를 기본으로 한다. 실제 profile과
사용 가능한 도구를 확인한다. 인계는 작업·관련 경로/절·수정 파일·검증 기준, 반환은 결과·
변경 파일·검사·미해결 항목으로 충분하다. Specialist는 peer에게 재위임하거나 상위 계약을
자기 결과에 맞춰 수정하지 않는다. 독립 검토를 자기 승인으로 대체하지 않는다.
Release-readiness 감사는 별도 명시 요청에만 수행한다. 감사 결과는 release 권한이 아니다.
실행기는 내부 LLM·phase 상태기계·자동 Git·대화 종료 hook을 사용하지 않는다.
## 기능 기록과 Git
지속할 계약이 필요한 기능에는 stable kebab-case ID와 `docs/<feature-id>/`를 정한다.
메인이 `FEATURED_AGENTS.md`, `PRD.md`, `ADR.md`를 관리한다. 기능 PRD 한 곳에서 현재
checklist를 관리하며 복잡한 수식·schema만 별도 전문 문서로 분리한다. `FEATURED_AGENTS.md`는
자동 로드되는 코드 영역의 `AGENTS.md`가 아니다.
기능 문서는 한국어로 작성하고 identifier·field·명령은 원래 표기를 유지한다. 새 요구사항
이름은 기존 `FEM-REQ-<FEATURE>-###` 형식을 유지한다. 기존 ID·승인 근거·전문 계약을
번호 정리 때문에 변경하지 않는다. 의미 변화 없는 편집마다 hash·인계·gate 기록을 만들지 않는다.
기존 프로젝트 PRD·ADR·수치 기준과 기능별 계약은 승인된 상세 의미를 보존한다. 공통
규칙의 재정리는 그 의미를 변경하지 않는다. 일반 기능 작업은 공통 문서를 읽기 전용으로
취급하며 공통 기준 변경은 별도 요청으로 다룬다. 과거 phase·coordination 기록을 재작성하거나
현재 실행 입력으로 복원하지 않는다. 전체 진행 현황은 요약이며 기능 checklist를 복제하지 않는다.
Commit 요청 시 작업 경로만 stage하고 Conventional Commits를 사용한다. Push·tag·publish·
파괴적 작업은 명시 범위에 한정한다. 개인 설정·machine 절대 경로·generated build 결과를
공용 계약으로 commit하지 않는다.
@@ -0,0 +1,24 @@
# 외부 입력 subset과 독립 솔버
- 상태: 기존 승인·인터뷰 합의의 의미 유지
- 결정 주체: 사용자와 기존 승인 계약의 담당자
## 배경
기존 모델을 읽고 외부 결과로 검증해야 하지만, 공개 입력 형식과 외부 솔버의 내부 알고리즘은
같은 계약이 아니다. 파서 호환성을 제품 목표로 삼으면 검증 가능한 물리 의미보다 문법 수용이 앞설 수 있다.
## 결정
승인된 Abaqus keyword subset의 의미만 지원한다. S4/S4R 등 source 표기는 보존하고
FESA 정식화로 연결한다. 외부 solver의 내부 적분·안정화·상태·결과 생성 동등성은 주장하지 않는다.
## 대안과 선택 이유
Full compatibility는 비공개 내부 동작까지 추정해야 하므로 채택하지 않는다.
자체 입력 형식만 쓰는 방식은 기존 .inp와 외부 reference를 직접 활용하는 현재 작업 흐름과 맞지 않는다.
## 영향
입력과 kernel의 연결·차이를 명시해야 한다. Exact 수치 일치는 가능하지만 내부 동등성의
증거가 아니다. Unknown model-affecting 입력은 silent approximation 대신 실패한다.
@@ -0,0 +1,24 @@
# 검증 환경과 private backend
- 상태: 기존 승인·인터뷰 합의의 의미 유지
- 결정 주체: 사용자와 기존 승인 계약의 담당자
## 배경
수치 library의 package target·integer·resource와 Windows runtime이 core로 퍼지면
물리 코드와 설치 환경을 독립적으로 검증하기 어렵다.
## 결정
현재 CMake/MSVC x64 Debug/CTest와 C++17 이상을 검증 기준으로 유지한다. MKL·TBB·
HDF5·Win32는 backend-neutral 경계 뒤에 두고 project-owned dependency target과 runtime staging을 사용한다.
## 대안과 선택 이유
Vendor 타입을 public에 노출하면 adapter 교체가 core와 consumer 변경으로 전파된다.
다른 toolchain의 즉시 지원 선언은 해당 환경의 numerical/runtime evidence 없이 할 수 없다.
## 영향
Dependency 추가마다 build뿐 아니라 실제 runtime closure를 확인한다. 개인 설치 경로를
제품 계약으로 고정하지 않으며 실행기 MSBuild 지원을 FESA의 별도 제품 검증으로 취급하지 않는다.
@@ -0,0 +1,24 @@
# 모델 정의와 equation 소유권
- 상태: 기존 승인·인터뷰 합의의 의미 유지
- 결정 주체: 사용자와 기존 승인 계약의 담당자
## 배경
Source label, 모델 배열과 equation 번호는 서로 다른 수명과 의미를 가진다. 실행별
제약이나 procedure가 바뀌어도 원본 모델과 결과 identity는 보존되어야 한다.
## 결정
Domain이 전체 정의를 소유하고 AnalysisModel은 non-owning view로 둔다.
DofManager가 DOF·partition·equation·sparse pattern을 전담한다. Semantic definition과 numerical object는 검증된 생성 경계로 연결한다.
## 대안과 선택 이유
Node/Element에 equation 번호를 저장하면 여러 실행 상태가 원본 정의에 섞인다.
모델 복사는 별도 수명·동기화 비용을 만들고 source identity가 다른 복사본처럼 취급될 수 있다.
## 영향
Domain 수명을 view보다 길게 유지해야 한다. Parser나 consumer가 모든 concrete storage를
알아야 하는 구조를 피하되 speculative clone·registry·사용하지 않는 capability는 추가하지 않는다.
@@ -0,0 +1,24 @@
# Local contribution과 결정적인 조립
- 상태: 기존 승인·인터뷰 합의의 의미 유지
- 결정 주체: 사용자와 기존 승인 계약의 담당자
## 배경
병렬 계산의 속도를 얻으면서 같은 입력의 sparse 구조·합산·진단·결과 순서를
재현해야 한다. Floating-point 누적 순서는 수치 결과에 영향을 준다.
## 결정
Local contribution은 index-owned buffer에 계산하고 join 뒤 stable COO와 고정된
reduction으로 global matrix/vector에 반영한다. Global pattern은 DOF owner가 정의한다.
## 대안과 선택 이유
Worker의 직접 global CSR 갱신은 race 또는 lock 순서 의존을 만든다.
Hash iteration에 의존한 누적도 stable source ordering을 보장하지 않는다.
## 영향
Contribution buffer와 정렬 비용을 부담한다. Optimization은 같은 순서·물리 의미·실패
선택을 보존해야 하며 더 빠르다는 이유로 결정론을 선택 기능으로 만들 수 없다.
@@ -0,0 +1,24 @@
# Candidate 검증과 공식 HDF5
- 상태: 기존 승인·인터뷰 합의의 의미 유지
- 결정 주체: 사용자와 기존 승인 계약의 담당자
## 배경
반복 중 일부 값 또는 저장 중 일부 dataset만 성공한 결과를 정상 해석으로 읽으면
실패 뒤 기존 유효 결과까지 신뢰할 수 없게 된다.
## 결정
State와 recovery는 완성·검증된 candidate만 반영한다. 공식 결과는 입력 lexical sibling의
HDF5이며 임시 파일의 self-check·close 후 최종 교체한다. Output lease로 동일 output pair의 동시 쓰기를 막는다.
## 대안과 선택 이유
실패 중간 state나 final 파일에 직접 누적하면 rollback 범위를 명확히 하기 어렵다.
CSV를 공식 결과로 두면 계층적 위치·단위·identity 계약을 현재 방식으로 유지할 수 없다.
## 영향
Candidate와 readback 비용을 부담한다. State commit과 file finalize, final HDF5와
진단 로그의 수명은 구분하며 실패 시 로그까지 동일하게 보존된다고 약속하지 않는다.
@@ -0,0 +1,24 @@
# Procedure별 lifecycle과 full residual
- 상태: 기존 승인·인터뷰 합의의 의미 유지
- 결정 주체: 사용자와 기존 승인 계약의 담당자
## 배경
정적·비선형·고유치·동적 해석은 초기화·해법·종료·결과 의미가 다르다.
반력과 free 잔차는 같은 수치 vector에 있어도 다른 물리적 역할을 가진다.
## 결정
각 procedure가 필요한 state와 solver lifecycle을 소유한다. 기존 선형 정적 해석은
elimination의 coupling을 유지하고 full residual Kd-F에서 constrained 반력과 free 평형을 구한다.
## 대안과 선택 이유
Static lifecycle에 계속 분기를 누적하면 다른 procedure의 state·종료 의미가 섞인다.
Constrained 외력만 부호 반전한 반력은 지정 변위와 stiffness coupling을 반영하지 못한다.
## 영향
새 procedure는 입력부터 output까지 연결해야 한다. 빈 free system은 유효한 경우
지원하며 arbitrary penalty·regularization을 failure의 우회로로 사용하지 않는다.
@@ -0,0 +1,24 @@
# 원본 reference와 승인된 비교 정책
- 상태: 기존 승인·인터뷰 합의의 의미 유지
- 결정 주체: 사용자와 기존 승인 계약의 담당자
## 배경
구현에 맞춰 기준 데이터를 고치거나 family마다 scale을 달리 정하면 수치 검증이
구현과 기준의 순환적 자기 정당화가 된다.
## 결정
기존 reference의 경로·값을 보존하고 source identity·component를 먼저 일대일
대응한다. Approved family/scale/near-zero/row/RMS/zero-scale 정책과 판정 영향을 유지한다.
## 대안과 선택 이유
Canonical naming·보조 metadata를 필수로 추가하는 방식은 실제 비교에 필요하지 않은
정리 작업을 gate로 만든다. Missing row 무시·평균·floor·clamp는 다른 모델을 통과시킬 수 있다.
## 영향
필수 원본이 없으면 비교 미실행으로 남긴다. 정책 변경은 사용자 승인과 영향 검증을
요구하며 새 evidence를 생성할 수 있지만 과거 실패 보고와 원본을 소급 수정하지 않는다.
@@ -0,0 +1,24 @@
# 수치·물리·외부 비교의 분리
- 상태: 기존 승인·인터뷰 합의의 의미 유지
- 결정 주체: 사용자와 기존 승인 계약의 담당자
## 배경
유한한 해, 선형계 성공 또는 외부 변위 일치만으로 정식화·회복·에너지·시간 정확성을
모두 확인할 수 없다. HHT의 reference 통과와 temporal 실패도 별개 증거다.
## 결정
동작 검사, analytical/invariant, 필요한 reference와 독립 numerical/physics 판단을
구분한다. 수식·요소·재료·적분·상태 갱신 변경은 독립 검토를 받는다.
## 대안과 선택 이유
모든 기능에 같은 고정 benchmark 목록을 강제하면 의미 없는 검사를 늘린다.
반대로 test count나 runner exit만으로 완료를 판정하면 검증되지 않은 물리를 통과로 오인한다.
## 영향
기능별 필수 evidence와 미실행·실패·제외를 명시해야 한다. Release-readiness 감사는
별도 요청이며 독립 검토·감사 결과가 배포 권한을 부여하지 않는다.
@@ -0,0 +1,24 @@
# 필요한 전문 작업과 명시적 검증 실행
- 상태: 기존 승인·인터뷰 합의의 의미 유지
- 결정 주체: 사용자와 기존 승인 계약의 담당자
## 배경
고정 stage·반복 인계·자동 Git·종료 hook 중심 운영은 실질적인 공학 판단보다
형식적인 상태 유지와 중복 실행을 늘렸다.
## 결정
메인이 범위를 파악해 필요한 전문 작업만 배정한다. 실행기는 config·toolchain·
backend 명령을 명시 호출 시 한 번 실행한다. 일반 실패는 현재 owner가 수정한다.
## 대안과 선택 이유
전용 coordinator·planning/correction profile·고정 상태기계·retry 예산을 유지하는
방식은 폐기한다. 검증 script에 commit/push 권한을 묶는 방식도 채택하지 않는다.
## 영향
메인이 작업 범위와 evidence를 확인해야 한다. 반복 승인 없이 승인된 일반 작업을
이어가되 원격·파괴·외부 비용·상위 계약 변경의 사용자 결정 경계는 유지한다.
@@ -0,0 +1,24 @@
# 공통 기준과 기능별 상세 계약
- 상태: 기존 승인·인터뷰 합의의 의미 유지
- 결정 주체: 사용자와 기존 승인 계약의 담당자
## 배경
공통 기준에 모든 기능 진행상태를 누적하거나 같은 checklist를 여러 파일에 두면
어느 기록이 현재 요구와 상태인지 모호해진다.
## 결정
공통 제품·수치 기준과 기능별 요구·정식화·I/O·결정을 구별한다. Feature의
FEATURED_AGENTS·PRD·ADR을 유지하고 현재 checklist는 Feature PRD 한 곳에 둔다.
## 대안과 선택 이유
모든 기능에 빈 보고서·requirements·matrix를 일괄 만드는 방식은 중복을 늘린다.
기존 계약을 새 파일명 규칙에 맞춰 자동 이동·재번호화하면 승인·evidence의 추적성을 잃는다.
## 영향
복잡한 상세 내용만 분리한다. 기존 ID·승인 근거·reference와 과거 운영 이력을 보존한다.
전체 상태 요약이 기능별 필수 검사를 대체하지 않으며 공통 기준 변경은 별도 요청으로 다룬다.
@@ -0,0 +1,24 @@
# MITC4 고유치 첫 구현의 경계
- 상태: 기존 승인·인터뷰 합의의 의미 유지
- 결정 주체: 사용자와 기존 승인 계약의 담당자
## 배경
MITC4 고유치의 첫 구현에서 외부 값 차이와 추가 정확도 개선을 분리해 진행할
필요가 있었고, 사용자가 모드별 5% 범위의 첫 구현을 승인했다.
## 결정
실제 FEAST와 consistent에서 유도한 lumped mass를 사용한다. 외부 Value는 mode별
singleton family의 상대오차·RMS 모두 5%로 판정하는 named policy를 적용한다.
## 대안과 선택 이유
공통 RMS 1%를 이 첫 구현에 그대로 요구하는 선택 대신 범위를 명시한 예외를
채택했다. 다른 모드의 scale로 차이를 흡수하거나 reference를 보정하는 방식은 허용하지 않는다.
## 영향
다른 해석의 RMS 1%와 내부 eigen 잔차·정규화·직교성 기준은 유지한다.
정확도 개선·보류한 검증은 해결된 것으로 취급하지 않고 과거 1% 실패 기록도 보존한다.
@@ -0,0 +1,24 @@
# HHT의 consistent kinetic mass
- 상태: 기존 승인·인터뷰 합의의 의미 유지
- 결정 주체: 사용자와 기존 승인 계약의 담당자
## 배경
유한회전 shell 동역학에서는 회전관성과 configuration에 따른 kinetic kinematics를
다뤄야 한다. 고유치 계산의 질량 선택을 그대로 옮기면 다른 물리를 해석할 수 있다.
## 결정
HHT에는 사용자 선택인 consistent kinetic mass를 사용하고 analytic null·
부분구속·회전 관성·convective 항을 보존한다. 물리 가속도와 알고리즘 보조 가속도를 구분한다.
## 대안과 선택 이유
Lumped mass는 비교 연구로 남겼으며 현 HHT 지원의 fallback으로 채택하지 않았다.
임의 drilling inertia나 부분구속의 full-clamp 치환은 원래 모델을 바꾼다.
## 영향
비대칭 접선·moving null·regularity와 실제 shell temporal 검증 부담이 있다.
현재 시간수렴 실패를 유지하며 가속도 복구 후보는 독립 검증·채택 전 승인된 해법으로 간주하지 않는다.
@@ -0,0 +1,24 @@
# Uncoupled shell 열해석부터 구현
- 상태: 기존 승인·인터뷰 합의의 의미 유지
- 결정 주체: 사용자와 기존 승인 계약의 담당자
## 배경
최종 목표는 양방향 열-구조 연성이지만, 현재는 온도장 자체의 transient 해석과
검증 범위를 먼저 확정해야 한다.
## 결정
첫 범위는 단일 step uncoupled shell 열해석, 균질 단면의 온도점 5개와 상수 물성,
고정 증분이다. 초기에 검토한 두께 방향 등온 범위는 5점 온도장으로 대체한다.
## 대안과 선택 이유
즉시 양방향 연성을 구현하는 방식은 현재 요구 범위를 넘는다. 두께 등온 모델은
아랫면·윗면의 독립 지정 온도와 두께 방향 열전달 요구를 충족하지 못한다.
## 영향
열행렬·flux·반력·에너지·시간수렴을 별도로 검증해야 한다. 두 구간 이차 보간,
Backward Euler, geometry 근사와 결과 schema는 제안 상태이며 이 범위 결정만으로 채택되지 않는다.
+20
View File
@@ -0,0 +1,20 @@
# 프로젝트 결정 목록
현재 유지하는 선택과 그 비용을 구분한다. 과거 승인 이력과 수치 기준은 그대로 보존하며,
아래 기록은 새로운 physics·acceptance 승인이 아니다. 열해석의 제안 방법은 채택 목록에 넣지 않는다.
| 파일 | 유지하는 선택 |
| --- | --- |
| `0001-independent-solver.md` | 외부 입력 subset과 독립 솔버 |
| `0002-build-and-backends.md` | 검증 환경과 private backend |
| `0003-model-and-equations.md` | 모델 정의와 equation 소유권 |
| `0004-ordered-assembly.md` | Local contribution과 결정적인 조립 |
| `0005-state-and-output.md` | Candidate 검증과 공식 HDF5 |
| `0006-procedure-lifecycle.md` | Procedure별 lifecycle과 full residual |
| `0007-reference-evidence.md` | 원본 reference와 승인된 비교 정책 |
| `0008-layered-verification.md` | 수치·물리·외부 비교의 분리 |
| `0009-explicit-development.md` | 필요한 전문 작업과 명시적 검증 실행 |
| `0010-feature-contract-ownership.md` | 공통 기준과 기능별 상세 계약 |
| `0011-eigen-first-implementation.md` | MITC4 고유치 첫 구현의 경계 |
| `0012-hht-kinetic-mass.md` | HHT의 consistent kinetic mass |
| `0013-thermal-staged-scope.md` | Uncoupled shell 열해석부터 구현 |
+47
View File
@@ -0,0 +1,47 @@
# 미해결 문제
## HHT shell의 시간수렴
- 조건·현상: 실제 shell의 두 시간수렴 사례에서 요구한 수렴 성능을 만족하지 못한
재현 기록이 남아 있다. 원본 변위 reference 통과와 함께 존재하는 실패다.
- 영향: 변위 일치만으로 동적 가속도·관성·에너지·전체 시간 정확성을 보장할 수 없다.
HHT 전체 기능 완료를 선언할 수 없다.
- 현재 해결하지 않는 이유: 문서 재구성 범위를 벗어나는 수치 알고리즘 변경이며,
가속도 복구 후보의 정식화·독립 검증·채택 판단이 선행되어야 한다.
- 후속 방향: 기존 물리 질량·허용 오차를 유지한 재현에서 dt refinement별 q/v/물리 a와
hidden constraint 차수를 분리하고 후보 변경의 영향을 검증한다.
## Python 운영 계약 검사의 기대값 불일치
- 조건·현상: `tests/test_agent_skill_workflow_contract.py`의 inventory 검사는 11개
profile을 기대하지만 현재 `.codex/agents`에는 7개가 있다. 같은 파일은 루트 지침의
고정 단계 표를 parsing하고, 과거 phase 실행 예제를 검사한다. 현재 명시 실행기와
필요한 전문 작업만 호출하는 운영 원칙에 맞지 않는다.
- 영향: 이 검사를 현행 운영의 통과 증거로 쓰거나 통과시키기 위해 삭제된 절차를
복원하면 잘못된 개발 흐름을 다시 도입한다. 루트 문서 재구성 이후에는 옛 표 위치에
의존하는 검사도 조정 대상이다.
- 현재 해결하지 않는 이유: 기존 불일치는 source 정적 대조로 확인했지만 이번 요청은
문서 변경이다. Python 검사를 실행하거나 테스트 코드를 수정하지 않았다.
- 후속 방향: 유효한 동작·권한·검증 범위를 검사하도록 기대값을 정리하고 Python suite를
별도로 실행한다. 현재 CTest의 성공으로 대체하지 않는다.
## 열 reference의 작업 사본 내 부재
- 조건·현상: 열해석 계획은 기존 `shell-thermal.inp`와 `shell-thermal NodalTemperature.csv`를
지정하지만 이 작업 사본의 `reference/shell-thermal`에는 해당 파일이 없다. 앞선 계획
작업에서는 별도 기존 저장소의 원본을 읽기 전용으로 확인했다.
- 영향: 이 작업 사본만으로 열 reference 비교를 재현할 수 없다. CSV는 t=37의 NT11
한 frame만 포함하므로 원본 확보 뒤에도 flux·반력·두께 온도 분포의 검증을 대신하지 않는다.
- 현재 해결하지 않는 이유: Reference 생성·복원·복사는 현재 요청에 포함되지 않는다.
명명 규칙 때문에 새 artifact나 보조 metadata를 만들지 않는다.
- 후속 방향: 실제 비교 작업 시 사용할 기존 원본 경로를 명시하고 허용된 접근으로
읽는다. 보존된 원본의 행·identity·값을 수정하지 않는다.
## 외부 배포 결정의 공백
- 조건·현상: 외부 사용자 배포는 장기 목표지만 배포 형태·지원 환경·dependency 재배포
조건과 외부 입력의 신뢰 범위는 정해져 있지 않다. 사용자가 별도 보안 정책은 없다고 확인했다.
- 영향: 현재 로컬 실행·개인 연구 범위를 외부 서비스의 보안·설치·지원 보장으로 설명할 수 없다.
- 현재 해결하지 않는 이유: 제품 배포 범위와 권리 검토는 아직 요청되지 않았으며 코드만으로
사용자의 배포 방식을 정할 수 없다.
- 후속 방향: 배포를 실제 추진할 때 형식·대상·설치·검증·데이터 취급 조건을 구체화한다.
+40
View File
@@ -0,0 +1,40 @@
# 개발 현황
기준일은 2026-09-28이다. 현재 주목적은 개인 연구용 솔버 개발이며 외부 사용자 배포는
장기 목표다. 아래 검증 상태는 기존 실행 기록의 범위이며 이번 문서 작업에서 solver나
검증 suite를 새로 실행한 결과가 아니다.
## 구현과 검증 상태
| 영역 | 구현 상태 | 확인된 evidence와 한계 |
| --- | --- | --- |
| Abaqus 입력·Domain·source identity | 구현됨 | Reader/mapper/invalid input 테스트가 존재. 최신 전체 suite 통과를 새로 주장하지 않음 |
| B33·MITC4 선형 정적 | 구현됨 | Local·integration·reference 검사가 존재. 과거 readiness는 이후 기준 변경으로 재검증 대기 표시가 있으므로 현재 release 통과로 승계하지 않음 |
| MITC4 비선형 정적·표면 압력 | 구현됨 | Newton·pressure tangent·result/reference 관련 검사와 실행 기록이 있음. 현 checkout 전체 재검증 없음 |
| MITC4 frequency | 승인된 첫 구현 완료 기록 | 당시 전체 417개 검사와 모드별 외부 Value 5% 비교·독립 검토 통과. 추가 검증 S3와 정확도 향상은 보류 |
| HHT 동해석 | 입력부터 HDF5까지 구현, 기능 검증 미완료 | 101-frame U 비교 PASS 기록, UR 경고 200건. Shell 시간수렴 두 사례 실패와 잔여 physics coverage 유지 |
| HHT 굽힘 단면력 복구 | 두께 계수 수정됨 | 관련 Debug 14 tests와 원본 HDF5 재생성·독립 식 대조 완료 기록. 전체 동해석 완료와 별개 |
| HHT 관련 전체 CTest | 일부 실패·미실행 범위 존재 | 최근 기록은 두 시간수렴 검사를 제외한 475 PASS/1 SKIP. 제외한 검사를 통과로 계산하지 않음 |
| Shell transient heat transfer | 요구사항·상세 수치 계획 작성, solver 미구현 | 5개 온도점·uncoupled 범위 합의. 수식 검산은 제한된 algebra evidence이며 solver/reference 통과 아님 |
| Python 검증 실행기 | 구현됨 | 명시 build/test runner와 별도 Python suite가 존재. 일부 운영 계약 검사는 현행 절차와 맞지 않는 기대값을 유지 |
| 외부 사용자 배포 | 계획 | 배포 방식·설치·지원 정책과 dependency 재배포 검토가 아직 정해지지 않음 |
## 남은 작업과 의존성
1. Shell 열해석은 geometry·두께 station 접속·시간 종료 규칙·초기 온도 jump·edge 입력·
결과 schema를 확정한다. 채택된 정식화의 독립 검토 이후 semantic mapping, DOF,
행렬·시간 적분·recovery·HDF5와 검증을 연결한다. 단일 시점 NT11 비교 외 물리 검증을
별도로 마련해야 한다. 현재 진행 요청에 가장 가까운 구현 준비 작업이다.
2. HHT는 기존 시간수렴 실패를 유지한 상태에서 물리 가속도 복구 후보의 정식화·독립
검증·채택 여부를 결정한다. 강체 병진 전체 이력, Newton 경계·실패 보존, 반복 결정론,
partition·좌표변환 coverage를 완료하고 필수 전체 검사를 다시 수행해야 한다.
3. Python 운영 계약 검사는 폐기된 profile·고정 단계·phase 인자 기대값을 현행 명시
실행 절차에 맞게 정리하는 별도 작업이 필요하다. 현재 문서 수정에 테스트 코드 변경을
포함하지 않는다.
4. Eigen 첫 구현 이후 정확도 개선과 보류한 검증을 별도 범위로 정한다. 현재 승인된
5% 기준을 다른 해석으로 확대하거나 과거 실패 기록을 수정하지 않는다.
5. 이후 양방향 열-구조 연성과 외부 사용자 배포의 구체적인 요구·지원 범위를 정한다.
두 장기 목표 간 순서나 일정은 정해지지 않았다.
각 기능의 세부 checklist와 승인 이력은 기존 기능 단위로 유지한다. 전체 요약의 상태가
상세 계약·필수 검사·실패 기록을 대체하지 않는다.