349 lines
29 KiB
Markdown
349 lines
29 KiB
Markdown
# Architecture Decision Records
|
||
|
||
## 철학
|
||
FESA의 architecture decision은 solver correctness, verification traceability, implementation testability를 우선한다. Harness는 제품이 아니라 C++/MSVC 기반 FEM 구조해석 솔버 개발을 통제하는 운영 인프라이다.
|
||
|
||
---
|
||
|
||
### ADR-001: FESA는 구조해석 솔버 프로젝트이고 Harness는 운영 인프라로 둔다
|
||
**결정**: 저장소의 주 목적은 유한요소법 기반 구조해석 솔버 개발이다. Harness는 승인된 Step 계획, 독립 세션 실행, PreToolUse guardrail, Stop MSVC build/test 검증을 제공하는 보조 계층으로 유지한다.
|
||
|
||
**이유**: 기존 문서가 Harness 중심이면 agent가 solver architecture, FEM verification, Abaqus/HDF5 계약보다 운영 스크립트에 과도하게 맞춰 행동한다.
|
||
|
||
**트레이드오프**: Harness 문서의 비중은 낮아지지만, `docs/HARNESS_WORKFLOW.md`의 실행 계약과 `.codex/hooks.json`의 검증 정책은 계속 필수 운영 규칙으로 유지한다.
|
||
|
||
### ADR-002: C++17/MSVC/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다. VS17과 VS18을
|
||
승인하면 현재 지원되는 MSVC 개발 환경에서 같은 C++17/x64/Debug 계약을 검증할 수 있다.
|
||
|
||
**트레이드오프**: 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을 남긴다.
|
||
|
||
**이유**: full Abaqus compatibility는 초기 solver 범위와 검증 비용을 과도하게 키운다. 기능별 subset은 요구조건, I/O contract, reference validation을 추적 가능하게 만든다.
|
||
|
||
**트레이드오프**: 사용자는 기존 Abaqus input file을 그대로 사용할 수 없을 수 있다. 대신 지원 범위와 실패 원인이 명확해진다.
|
||
|
||
### ADR-004: Domain, AnalysisModel, DofManager, AnalysisState를 분리한다
|
||
**결정**: `Domain`은 `ElementDefinition`, `ElementProperty`, `Material`과
|
||
`StepDefinition` 입력 모델 정의를 `std::unique_ptr`로 단독 소유하고 const access와
|
||
stable collection index를 제공한다. `AnalysisModel`은 Domain 수명 안에서 stable index와
|
||
const reference만 사용하는 non-owning current-step view다. `DofManager`는 equation
|
||
numbering과 constrained/free mapping을 전담하고, `AnalysisState`는 해석 중 변하는
|
||
물리량을 소유한다.
|
||
|
||
**이유**: 모델 정의, step activation, equation system, transient/nonlinear state가 섞이면 parser, assembler, solver, result writer가 강하게 결합된다. 분리된 상태 모델은 선형 정적 해석에서 시작해 비선형, 동적, thermal coupling으로 확장하기 쉽다.
|
||
|
||
**트레이드오프**: 초기 class 수가 늘어난다. V0에서는 interface를 얇게 유지하고 실제 선형 정적 frame에 필요한 state만 구현한다.
|
||
|
||
### ADR-005: 공식 결과 파일은 HDF5로 하고 reference 결과는 Abaqus CSV로 둔다
|
||
**상태**: HDF5 authoritative output 결정은 유지하며 reference bundle governance 부분은 ADR-019로 대체됨.
|
||
|
||
**결정**: 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 계층 뒤에 둔다. `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가 다소 장황해 보일 수 있다. Row-major dense storage와 CSR sparse storage를 따로 유지해야 하지만 backend 의존성과 dense/sparse 의미가 core 모델에 섞이지 않는다.
|
||
|
||
### ADR-007: Analysis base는 최소 실행 계약만 제공한다
|
||
**결정**: `Analysis` base는 virtual `Analysis::Run(const AnalysisRequest&)`만 제공하고
|
||
linear-static-specific protected hook을 정의하지 않는다. 승인된 선형 정적 순서인
|
||
`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`는
|
||
`LinearStaticAnalysis::Run()`의 private lifecycle로 유지한다. 강성행렬 factorization은
|
||
하중벡터 조립보다 먼저 수행하고 factorization과 substitution을 하나의 불투명한 solve
|
||
호출로 합치지 않는다.
|
||
|
||
**이유**: 현재 여덟 단계는 linear static equation, state와 failure taxonomy에 특화되어
|
||
있다. 최소 base contract는 이 순서의 검증 가능성을 보존하면서 승인되지 않은 dynamic,
|
||
eigenvalue 또는 nonlinear procedure에 같은 protected hook과 사용하지 않는 state를
|
||
강제하지 않는다. Factorization과 substitution 분리는 동일 강성행렬에 여러 RHS를 적용할
|
||
수 있고 각 실패 단계를 구조화된 diagnostic으로 분류하게 한다.
|
||
|
||
**트레이드오프**: Procedure 사이의 lifecycle code는 base Template Method로 자동 재사용되지
|
||
않는다. 두 번째 procedure가 승인되면 실제로 같은 단계만 focused collaborator로 추출하되,
|
||
linear-static hook 사이에 조건문으로 새 physics를 삽입하지 않는다.
|
||
|
||
### ADR-008: Sparse assembly는 deterministic COO-to-CSR 경로로 시작한다
|
||
**결정**: 초기 assembly는 element-local contribution을 COO triplet으로 수집한 뒤 CSR로 finalize한다. MKL PARDISO backend는 CSR input contract를 받는다.
|
||
|
||
**이유**: CSR은 MKL PARDISO와 잘 맞고, COO-to-CSR 경로는 구현과 테스트가 명확하다. deterministic reduction은 reference comparison의 재현성을 지킨다.
|
||
|
||
**트레이드오프**: 대규모 모델에서는 메모리와 변환 비용이 생길 수 있다. 성능 문제가 실제로 확인되면 typed batch assembly 또는 kernel 분리를 추가한다.
|
||
|
||
### ADR-009: TBB 병렬화는 element-local computation부터 적용한다
|
||
**결정**: 첫 oneTBB 적용 지점은 element-local matrix/residual 계산이다. 전역 sparse write는 thread-local buffer 또는 deterministic reduction으로 제한한다.
|
||
|
||
**이유**: element-local 계산은 독립성이 높고 병렬화 효과가 명확하다. 전역 sparse matrix에 직접 병렬 write하면 재현성, race, ordering 문제가 생긴다.
|
||
|
||
**트레이드오프**: 초기 병렬화 범위가 제한된다. MKL 내부 thread와 TBB task arena의 oversubscription 정책을 별도로 문서화해야 한다.
|
||
|
||
### ADR-010: Abaqus reference artifact는 사람이 생성하거나 명시 승인된 절차로만 갱신한다
|
||
**상태**: Artifact read-only 및 실행 제한은 유지하며 metadata/provenance/naming 계약은 ADR-019로 대체됨.
|
||
|
||
**결정**: Agent는 Abaqus, Nastran 또는 reference solver를 직접 실행하지 않는다. reference artifact 생성, 수정, 복원은 명시 승인된 phase에서만 수행한다. 모든 bundle의 provenance, generator/version, units, coordinate system, step/frame identity, schema, tolerance와 limitations는 승인된 기능별 Reference Model Contract에 기록한다. `metadata.json`은 선택 reference artifact이며, 부재만으로 bundle을 불완전하다고 판정하지 않는다. 파일이 존재하면 read-only 보조 자료로 inventory하고 계약 및 실제 artifact와 일치하는지 확인하며, 충돌은 숨기지 않고 upstream 계약 문제로 보고한다. 승인된 `cantilever-beam-b33` legacy baseline의 space-containing filename과 `README.md` N/A 예외는 유지한다.
|
||
|
||
**이유**: reference 결과는 solver correctness의 기준이다. 생성 절차가 불명확하면 구현 결함과 reference artifact 오류를 구분할 수 없다.
|
||
|
||
**트레이드오프**: Reference Model Contract가 필수 provenance의 단일 source of truth가 되어 별도 JSON 파일 없이도 bundle을 사용할 수 있다. 선택 `metadata.json`이 계약과 중복될 수 있으므로 존재 시 일관성 검사가 필요하다. Legacy filename과 `README.md` 예외는 일반 artifact 규칙을 복잡하게 하지만 exact path와 source commit을 고정하고 read-only로 취급해 감사 가능성을 유지한다.
|
||
|
||
### ADR-011: 구형 단일 검증 진입점 계약을 폐기한다
|
||
|
||
**상태**: ADR-012로 대체됨.
|
||
|
||
**결정**: 삭제된 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로 비교한다
|
||
|
||
**상태**: Artifact inventory와 component mapping의 역사적 결정은 유지하며 tolerance와
|
||
node-station projection 결정은 ADR-022로 대체됨.
|
||
|
||
**결정**: `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인 기능을 정확하게 표현할 수 있다.
|
||
|
||
### ADR-019: Abaqus는 입력 형식과 외부 수치 reference이며 FESA 내부 동작 계약이 아니다
|
||
|
||
**결정**: FESA는 Abaqus와 독립적인 솔버다. 기능별 승인 `.inp` subset을 입력으로
|
||
사용하고, 기능이 blocking으로 선언한 FESA HDF5 quantity만 기존 Abaqus CSV와 승인
|
||
tolerance로 비교한다. Abaqus 요소 정식화, 적분, stabilization, 내부 상태와 결과 생성
|
||
절차를 재현하거나 동등하게 구현하지 않는다. Exact numerical equality는 허용되지만
|
||
내부 동작 동등성의 evidence가 아니다.
|
||
|
||
Reference case readiness에는 선언된 `.inp`, 실제 비교에 필요한 CSV, deterministic
|
||
source-ID/component matching과 tolerance만 필요하다. 기존 path와 filename을 그대로
|
||
사용하며 canonical naming, legacy-alias 승인, bundle `README.md`, `metadata.json`, Abaqus
|
||
version/provenance, 중복 units/coordinates/model/step/frame/material/section 정보와 CSV schema
|
||
version은 요구하지 않는다. Reference artifact는 계속 read-only이며 누락, 추가, 중복,
|
||
nonfinite required row는 tolerance 전에 실패한다.
|
||
|
||
**이유**: Reference comparison의 목적은 FESA의 독립 정식화가 승인된 observable quantity를
|
||
충분히 가깝게 계산하는지 판정하는 것이다. 수치 비교에 사용되지 않는 artifact
|
||
거버넌스가 formulation review나 implementation planning을 차단하면 제품 검증보다 문서
|
||
형식 준수가 우선된다. 같은 정보는 `.inp`, CSV header와 feature contract에서 직접 얻을
|
||
수 있다.
|
||
|
||
**트레이드오프**: Reference 생성 환경을 사후에 완전히 재구성하는 감사 기능은 줄어든다.
|
||
대신 비교 대상과 source-row/component mapping, tolerance, artifact immutability는 유지해
|
||
false match와 결과 보정을 방지한다. 더 강한 provenance가 필요한 기능은 해당 요구조건이
|
||
명시적으로 추가할 수 있으나 프로젝트 기본 gate로 자동 승격하지 않는다.
|
||
|
||
### ADR-020: MITC4 displacement reference는 고정 절대오차로 판정한다
|
||
|
||
**상태**: S4 artifact 선택과 U blocking/UR warning-only 분류는 유지하며 고정 절대오차
|
||
결정은 ADR-022로 대체됨.
|
||
|
||
**결정**: Full-integration FESA-MITC4의 sole S4 reference comparison은 matched global
|
||
`U1/U2/U3` row에 고정 절대오차 `1.0e-5`를 적용해 pass/fail을 판정한다.
|
||
`UR1/UR2/UR3`도 고정 절대오차 `1.0e-5`로 비교하지만 초과는 deterministic warning만
|
||
생성한다. Reference scale은 보고용 통계로 남을 수 있으나 MITC4 row tolerance 또는
|
||
normalized error의 분모를 결정하지 않는다. ADR-014의 B33 component-scale 혼합
|
||
tolerance는 변경하지 않는다.
|
||
|
||
**이유**: Abaqus S4는 FESA-MITC4와 동일한 요소 정식화가 아니므로 B33에서 승인한 매우
|
||
엄격한 component-scale tolerance를 그대로 재사용하는 것은 독립 솔버의 observable
|
||
displacement 검증 목적에 맞지 않는다. 고정 절대오차는 현재 사용자 단위계에서 승인된
|
||
차이를 명시적으로 제한하면서 zero clamp나 row omission 없이 모든 displacement row를
|
||
동일하게 판정한다.
|
||
|
||
**트레이드오프**: Model scale이 크게 달라지면 고정 절대오차의 상대적 엄격도가 달라질 수
|
||
있다. 따라서 이 값은 현재 승인된 MITC4 S4 case의 기능 완료 기준이며 개발 완료 후
|
||
별도 reference-verification evidence와 함께 재점검한다.
|
||
|
||
### ADR-021: Semantic definition과 runtime solver contract를 분리한다
|
||
|
||
**결정**: Domain-owned semantic definition과 analysis-time numerical object를 다음
|
||
dependency 방향으로 분리한다.
|
||
|
||
```text
|
||
Domain owns ElementDefinition / ElementProperty / Material / StepDefinition
|
||
AnalysisModel is a non-owning stable-index view into Domain
|
||
ElementFactory creates runtime Element candidates from compatible definitions
|
||
DofManager -> ElementDofLayout
|
||
SparseAssembler -> ElementStiffnessContribution
|
||
ResultRecovery -> ElementResultBundle
|
||
LoadAssembler -> ordered LoadContribution
|
||
EssentialConstraintPolicy -> ConstraintDefinition
|
||
Analysis <- LinearStaticAnalysis
|
||
```
|
||
|
||
`Domain`의 polymorphic semantic collection은 `std::unique_ptr` 단독 ownership과 stable
|
||
vector position을 사용한다. `ElementDefinition`은 source identity, connectivity와
|
||
property/material identity를 제공하고 runtime `Element`는 DOF layout, stiffness와 result
|
||
recovery를 제공한다. `ElementFactory`가 definition/property/material compatibility를
|
||
중앙에서 검사하며 unknown 또는 incompatible 조합은 fail-closed diagnostic으로 거부한다.
|
||
Consumer는 B33/MITC4 concrete type branch를 분산시키지 않고 runtime contract를 사용한다.
|
||
Linear-static candidate가 runtime `Element`를 `std::unique_ptr`로 소유하고 consumer는 그
|
||
수명에 한정된 non-owning view만 사용한다.
|
||
|
||
`Material` base에는 identity, source location과 lifetime 이외의 future capability를
|
||
추가하지 않는다. 현재 isotropic linear elasticity가 실제로 요구하는 data는 concrete
|
||
material에 둔다. Density, anisotropy, plastic state, temperature와 rate dependency는
|
||
optional field 또는 no-op virtual method로 미리 할당하지 않는다. `ElementProperty`도
|
||
현재 beam/shell 의미를 각 concrete type에 둔다.
|
||
|
||
`Load`는 ordered `LoadContribution`을 생성하고 global full-DOF accumulation은
|
||
`LoadAssembler`가 단독 소유한다. `BoundaryCondition`은 `ConstraintDefinition`을 생성하고
|
||
`EssentialConstraintPolicy`가 prescribed-displacement elimination과 reconstruction을
|
||
소유한다. Distributed/body load와 MPC/penalty/Lagrange-multiplier enforcement는 이번
|
||
결정으로 구현된 기능이 아니다.
|
||
|
||
Abaqus Domain mapper, result recovery와 HDF5 writer는 기존 public facade를 유지하면서
|
||
각각 topology/material-property/step-final-assembly, equilibrium/beam/shell/atomic-state,
|
||
RAII/model-result-dataset/self-check/atomic-finalization 책임으로 private implementation을
|
||
나눈다.
|
||
|
||
**이유**: Semantic identity와 runtime kernel을 같은 concrete record에 두면 DofManager,
|
||
SparseAssembler, ResultRecovery, parser와 output이 B33/MITC4 storage를 함께 알아야 한다.
|
||
Definition/factory/runtime contract와 contribution/policy 경계를 분리하면 stable source
|
||
identity와 deterministic reduction owner를 유지하면서 실제 두 element 구현을 공통
|
||
consumer로 연결할 수 있다. Focused facade 분할은 외부 계약을 바꾸지 않고 큰 translation
|
||
unit의 서로 다른 failure-atomicity 책임을 검토 가능하게 한다.
|
||
|
||
**트레이드오프**: Base object, factory와 contribution record가 늘고 checked compatibility에
|
||
한 단계의 indirection이 생긴다. 대신 `std::shared_ptr`, speculative `Clone()`, global
|
||
registry와 future-only material/analysis capability는 도입하지 않는다. B33/MITC4의 승인된
|
||
formulation, 연산·reduction 순서, sign, units, coordinates와 result identity가 이
|
||
리팩터링보다 우선하며 HDF5 schema, reference artifact와 ADR-014/ADR-020 tolerance는
|
||
변경하지 않는다. MITC3, solid, dynamic과 plastic behavior는 별도 feature gate 전까지
|
||
구현된 것으로 간주하지 않는다.
|
||
|
||
### ADR-022: 외부 reference comparison은 공통 family-scale 정책을 사용한다
|
||
|
||
운영 상수, 검증 순서, report schema와 변경 관리는 `docs/TOLERANCE.md`를 따른다.
|
||
|
||
**결정**: B33, MITC4와 이후 기능의 외부 reference comparison은 동일한 무차원 수치
|
||
정책을 사용한다. 같은 model/case, step/frame, logical quantity, unit dimension, coordinate
|
||
system과 blocking behavior의 component family에 대해 reference-only scale
|
||
`S=max(abs(reference))`를 계산한다. `abs(reference)<=0.01*S`인 행은
|
||
`abs(fesa-reference)<=0.01*S`, 나머지 행은 `abs(fesa-reference)/abs(reference)<=0.05`를
|
||
만족해야 한다. 모든 행과 함께 family scale-relative RMS `RMS(error)/S<=0.01`도
|
||
통과해야 한다. 독립 absolute-error gate는 두지 않으며 `S=0`이면 모든 FESA 값도 exact
|
||
zero일 때만 통과한다.
|
||
|
||
B33 family는 translation, rotation, reaction force, reaction moment, section force와
|
||
section moment로 구분한다. 2026-08-18에 다시 생성된 elemental-force CSV의
|
||
`Element Label`과 `Node Label`을 사용해 `(instance, element, endpoint node, component)`를
|
||
HDF5 endpoint에 직접 대응하고 node-station collapse나 평균을 사용하지 않는다. MITC4는
|
||
translation `U1/U2/U3` family를 blocking으로, rotation `UR1/UR2/UR3` family를
|
||
warning-only로 유지한다.
|
||
|
||
**이유**: Feature별 absolute floor와 fixed absolute tolerance는 모델 단위와 크기에 따라
|
||
서로 다른 엄격도를 만들었다. 개별 component scale은 물리적으로 zero-like인 MITC4
|
||
`U1/U2` residue를 자체 scale로 만들어 잘못 실패시킨다. 동일 차원의 family scale,
|
||
near-zero 대체 분기와 relative RMS를 결합하면 zero row의 불안정한 raw relative error를
|
||
피하면서 모든 행과 전체 오차 수준을 함께 검사할 수 있다. B33의 element-endpoint identity는
|
||
reference와 HDF5가 제공하는 실제 source identity를 보존한다.
|
||
|
||
**트레이드오프**: Family 최대값이 작은 component의 허용폭을 결정하므로 행별 relative
|
||
gate와 family RMS gate를 모두 유지해야 한다. Reference family 전체가 zero이면 별도
|
||
절대 scale이 없으므로 exact-zero만 허용하는 엄격한 fail-closed 정책이 된다. 기존 B33과
|
||
MITC4 verification report 및 comparator schema는 새 정책에 맞춰 다시 생성해야 하지만
|
||
reference artifact, HDF5 schema, element formulation과 blocking/warning 분류는 변경하지
|
||
않는다.
|