docs: define C++ modular refactoring design
This commit is contained in:
@@ -0,0 +1,256 @@
|
|||||||
|
# FESA C++ Coding Style
|
||||||
|
|
||||||
|
## 목적
|
||||||
|
|
||||||
|
이 문서는 FESA production 및 test C++의 코드 스타일, 객체 설계, 문서화와 검증 규칙을
|
||||||
|
정의하는 project-local source of truth다. 새 C++를 작성하거나 기존 C++를 리팩터링하는
|
||||||
|
사람과 Implementation Agent는 작업 전에 이 문서를 읽어야 한다.
|
||||||
|
|
||||||
|
[Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html)를 baseline으로
|
||||||
|
사용한다. 이 문서, `AGENTS.md`, 승인된 feature contract와 architecture/ADR이 Google guide의
|
||||||
|
일반 규칙보다 우선한다.
|
||||||
|
|
||||||
|
## 적용 범위와 우선순위
|
||||||
|
|
||||||
|
규칙 충돌 시 다음 순서로 해석한다.
|
||||||
|
|
||||||
|
1. 승인된 feature requirements, formulation, numerical-review, I/O와 reference contract
|
||||||
|
2. `AGENTS.md`, `docs/ARCHITECTURE.md`와 `docs/ADR.md`
|
||||||
|
3. 이 문서의 FESA-specific rule과 exception
|
||||||
|
4. Google C++ Style Guide
|
||||||
|
5. 기존 local style
|
||||||
|
|
||||||
|
새 코드는 이 문서를 즉시 준수한다. 기존 코드는 승인된 refactoring plan의 module slice
|
||||||
|
단위로 전환한다. 요청 범위 밖의 file을 style-only 이유로 함께 수정하지 않는다.
|
||||||
|
|
||||||
|
## Language와 Toolchain
|
||||||
|
|
||||||
|
- Production language는 C++17 이상이며 MSVC x64를 지원해야 한다.
|
||||||
|
- 승인된 build 기준은 CMake, Visual Studio generator와 Debug configuration이다.
|
||||||
|
- C++ compiler extension에 의존하지 않는다.
|
||||||
|
- MKL, TBB, HDF5와 Win32 type은 public solver core header에 노출하지 않는다.
|
||||||
|
- Standard library와 RAII를 manual lifetime management보다 우선한다.
|
||||||
|
- Google guide가 현재 권장하는 C++20 language target은 FESA의 C++17 contract를 바꾸지
|
||||||
|
않는다.
|
||||||
|
|
||||||
|
## File 이름과 Header
|
||||||
|
|
||||||
|
- File 이름은 소문자 snake_case를 사용한다.
|
||||||
|
- Production 및 test source extension은 기존 FESA/CMake 관례인 `.cpp`를 유지한다.
|
||||||
|
- Header extension은 `.h`를 사용한다. 기존 `.hpp`는 승인된 migration slice에서 `.h`로
|
||||||
|
바꾼다.
|
||||||
|
- Header는 self-contained여야 하며 include consumer의 transitive include에 의존하지
|
||||||
|
않는다.
|
||||||
|
- Header는 `#pragma once` 대신 full repository path 기반 include guard를 사용한다.
|
||||||
|
|
||||||
|
예:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#ifndef FESA_MATH_VECTOR3_H_
|
||||||
|
#define FESA_MATH_VECTOR3_H_
|
||||||
|
|
||||||
|
namespace fesa {
|
||||||
|
|
||||||
|
class Vector3 {};
|
||||||
|
|
||||||
|
} // namespace fesa
|
||||||
|
|
||||||
|
#endif // FESA_MATH_VECTOR3_H_
|
||||||
|
```
|
||||||
|
|
||||||
|
Include 순서는 다음과 같다.
|
||||||
|
|
||||||
|
1. 대응하는 header
|
||||||
|
2. C system header
|
||||||
|
3. C++ standard library header
|
||||||
|
4. Third-party header
|
||||||
|
5. FESA project header
|
||||||
|
|
||||||
|
각 non-empty group 사이에는 빈 줄을 두고 group 안에서는 알파벳순으로 정렬한다. 사용하는
|
||||||
|
symbol의 declaration을 제공하는 header를 직접 include한다.
|
||||||
|
|
||||||
|
## 이름 규칙
|
||||||
|
|
||||||
|
| 대상 | 규칙 | 예 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| class, struct, enum, alias | PascalCase | `ElementProperty`, `EntityIndex` |
|
||||||
|
| function, method, accessor | PascalCase | `ComputeStiffness()`, `NodeCount()` |
|
||||||
|
| local variable, parameter | snake_case | `element_index`, `source_order` |
|
||||||
|
| class data member | snake_case + trailing `_` | `youngs_modulus_` |
|
||||||
|
| struct data member | snake_case | `source_id` |
|
||||||
|
| compile-time/static constant | `kPascalCase` | `kNodeCount` |
|
||||||
|
| enumerator | `kPascalCase` | `FailureCategory::kModel` |
|
||||||
|
| namespace | snake_case | `fesa::hdf5_internal` |
|
||||||
|
| macro | UPPER_SNAKE_CASE | `FESA_MATH_VECTOR3_H_` |
|
||||||
|
|
||||||
|
Google guide는 accessor의 snake_case를 허용하지만 FESA는 사용자 승인에 따라 production
|
||||||
|
및 test 호출부를 포함한 모든 function name에 PascalCase를 적용한다. Constructor,
|
||||||
|
destructor와 operator 이름은 C++ language 규칙을 따른다.
|
||||||
|
|
||||||
|
이름은 물리 및 수치 의미를 드러내야 한다. `value`, `data`, `handler`, `manager`처럼 문맥이
|
||||||
|
없는 generic name을 넓은 scope에서 사용하지 않는다. Source label, internal entity index와
|
||||||
|
equation index를 이름에서 구분한다.
|
||||||
|
|
||||||
|
## Formatting
|
||||||
|
|
||||||
|
- `.clang-format`의 `BasedOnStyle: Google`을 사용한다.
|
||||||
|
- 들여쓰기는 space 2개이며 tab을 사용하지 않는다.
|
||||||
|
- 최대 line length는 80자다. Include, guard, URL과 분할할 수 없는 contract string은 Google
|
||||||
|
guide의 예외를 따른다.
|
||||||
|
- Opening brace는 declaration/control statement의 마지막 줄에 둔다.
|
||||||
|
- Namespace body는 들여쓰지 않고 closing namespace comment를 작성한다.
|
||||||
|
- 한 statement에 한 declaration만 둔다.
|
||||||
|
- Variable은 가능한 가장 좁은 scope에서 선언과 동시에 초기화한다.
|
||||||
|
- `const`와 `constexpr`를 의미가 허용하는 범위에서 사용한다.
|
||||||
|
- `override`, `final`, `explicit`, `noexcept`와 `[[nodiscard]]`는 실제 contract를 표현할 때
|
||||||
|
사용한다.
|
||||||
|
|
||||||
|
Formatting-only 변경과 behavior/architecture 변경은 같은 commit에 섞지 않는다.
|
||||||
|
|
||||||
|
## Class와 Interface 설계
|
||||||
|
|
||||||
|
- Class는 하나의 명확한 책임과 invariant를 가져야 한다.
|
||||||
|
- Polymorphic base는 public virtual destructor를 가져야 한다.
|
||||||
|
- Abstract interface에는 현재 concrete 구현이 공유하지 않는 future method를 추가하지
|
||||||
|
않는다.
|
||||||
|
- 단독 ownership은 `std::unique_ptr`로 표현한다. 실제 shared lifetime이 없는
|
||||||
|
`std::shared_ptr`는 사용하지 않는다.
|
||||||
|
- Non-owning pointer/reference의 lifetime은 Doxygen contract에 기록한다.
|
||||||
|
- Downcast와 type switch를 주요 확장 mechanism으로 사용하지 않는다.
|
||||||
|
- State가 없는 함수를 묶기 위한 static-only class를 만들지 않는다. Internal namespace와
|
||||||
|
focused module을 사용한다.
|
||||||
|
- Base class에 optional field와 no-op method를 누적하지 않는다. Material density, plastic
|
||||||
|
state와 anisotropic constitutive law처럼 독립적인 의미는 별도 capability 또는 구성
|
||||||
|
객체로 설계한다.
|
||||||
|
- Public header가 implementation/vendor dependency를 역으로 끌어오지 않도록 한다.
|
||||||
|
|
||||||
|
Data-only record는 struct를 사용할 수 있다. Invariant, encapsulation, lifetime 또는 behavior가
|
||||||
|
있으면 class를 사용한다.
|
||||||
|
|
||||||
|
## FEM Module 책임
|
||||||
|
|
||||||
|
- `model`: immutable semantic definition과 stable source/internal identity
|
||||||
|
- `elements`: element numerical kernel, local contribution과 element recovery
|
||||||
|
- `properties`: element property identity와 concrete section data
|
||||||
|
- `materials`: constitutive capability와 concrete material behavior
|
||||||
|
- `fem`: DOF/equation numbering, scatter와 sparse pattern
|
||||||
|
- `assembly`: deterministic element/load contribution reduction
|
||||||
|
- `constraints`: constraint definition 적용과 equation policy
|
||||||
|
- `analysis`: procedure-specific lifecycle과 backend orchestration
|
||||||
|
- `results`: backend-neutral recovery record와 physical result identity
|
||||||
|
- `io`: Abaqus syntax/semantic mapping과 HDF5 schema implementation
|
||||||
|
- `math`: backend-neutral value/storage type와 private numerical adapter
|
||||||
|
|
||||||
|
한 module의 class가 다른 module의 owner 책임을 가져가지 않는다. Element가 global CSR을
|
||||||
|
직접 쓰거나 Node가 equation ID를 저장하거나 Material이 analysis state를 임의로 소유하면
|
||||||
|
안 된다.
|
||||||
|
|
||||||
|
## 중복과 공통화
|
||||||
|
|
||||||
|
같은 의미, units, coordinate, failure policy와 ownership을 가진 logic을 한 번만 구현한다.
|
||||||
|
현재 승인된 공통화 방향은 다음과 같다.
|
||||||
|
|
||||||
|
- 3D coordinate/axis/director 연산은 `Vector3` value class
|
||||||
|
- source label/set/instance 해석은 `SourceTargetResolver`
|
||||||
|
- full/free/constrained invariant는 `DofManager` owner validation
|
||||||
|
- MKL size/copy helper는 private dense-BLAS adapter
|
||||||
|
- ASCII case-insensitive comparison과 label parsing은 focused core utility
|
||||||
|
|
||||||
|
두 코드 block이 비슷해 보여도 formulation sign, result location, source identity 또는
|
||||||
|
tolerance가 다르면 공통화하지 않는다. 단 한 번 사용하는 logic을 future flexibility만을
|
||||||
|
위해 framework로 만들지 않는다.
|
||||||
|
|
||||||
|
## Error와 Ownership
|
||||||
|
|
||||||
|
- Expected failure는 `Status` 또는 `Result<T>`로 반환한다.
|
||||||
|
- Public solver API를 통해 backend exception이 그대로 새지 않게 한다.
|
||||||
|
- Unknown type/property/material 조합은 structured diagnostic으로 fail-closed 처리한다.
|
||||||
|
- Invalid input을 silent default, clamp, average 또는 fallback으로 숨기지 않는다.
|
||||||
|
- Candidate를 완성하고 검증한 뒤 Domain state, AnalysisState 또는 final HDF5에 commit한다.
|
||||||
|
- Stable ordering과 failure atomicity는 optimization option이 아니라 correctness contract다.
|
||||||
|
|
||||||
|
## Doxygen
|
||||||
|
|
||||||
|
Doxygen coverage는 production code에만 요구한다. Test function과 test helper에는 Doxygen를
|
||||||
|
요구하지 않는다.
|
||||||
|
|
||||||
|
Public/protected class와 function declaration은 다음 내용을 필요한 만큼 기록한다.
|
||||||
|
|
||||||
|
- `@brief`: 무엇을 하는지 동사형 한 문장
|
||||||
|
- `@param`: 이름만으로 드러나지 않는 units, coordinates, ownership 또는 valid range
|
||||||
|
- `@return`: success value와 failure 의미
|
||||||
|
- `@throws`: 실제로 경계를 넘어가는 exception
|
||||||
|
- `@pre`: caller가 보장해야 하는 invariant
|
||||||
|
- `@note`: deterministic order, lifetime 또는 backend constraint
|
||||||
|
- `@warning`: sign, physical/numerical distinction 또는 destructive side effect
|
||||||
|
|
||||||
|
예:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
/// @brief Computes the element stiffness in stable global DOF order.
|
||||||
|
/// @return A finite symmetric contribution or a structured model failure.
|
||||||
|
/// @note The returned matrix does not include nonphysical result terms.
|
||||||
|
virtual Result<Matrix> ComputeStiffness() const = 0;
|
||||||
|
```
|
||||||
|
|
||||||
|
Private/internal production function은 declaration 또는 definition에 목적을 기록한다. 수식,
|
||||||
|
sign, coordinate transform, lifetime, ordered reduction이나 failure preservation이
|
||||||
|
비자명하면 그 이유를 설명한다. Header declaration의 사용법을 `.cpp` definition에서 그대로
|
||||||
|
반복하지 않는다.
|
||||||
|
|
||||||
|
Comment는 코드 한 줄을 한국어 또는 영어로 번역하는 방식으로 작성하지 않는다. Public API
|
||||||
|
Doxygen는 일관된 tool output을 위해 영어를 기본으로 한다. Diagnostic message와 existing
|
||||||
|
contract language는 현재 외부 계약을 유지한다.
|
||||||
|
|
||||||
|
## Determinism과 수치 코드
|
||||||
|
|
||||||
|
- Element contribution은 stable source/internal index 순서로 생성한다.
|
||||||
|
- Parallel worker는 index-owned output만 수정한다.
|
||||||
|
- Floating-point reduction 순서는 명시적으로 고정한다.
|
||||||
|
- Refactoring 중 expression/reduction 순서를 편의상 바꾸지 않는다.
|
||||||
|
- Arbitrary `max(1, ...)`, zero clamp 또는 missing-row ignore를 추가하지 않는다.
|
||||||
|
- End action, section resultant, generalized result와 stress의 identity/sign을 구분한다.
|
||||||
|
- Reference mapping은 row order가 아니라 승인된 source identity와 component를 사용한다.
|
||||||
|
|
||||||
|
수치식을 공통화할 때는 현재 formulation과 test가 정의한 operation order 및 tolerance를
|
||||||
|
먼저 확인한다.
|
||||||
|
|
||||||
|
## Test와 변경 관리
|
||||||
|
|
||||||
|
- Production C++ 변경은 관련 C++ test와 같은 patch에 있어야 한다.
|
||||||
|
- Behavior 또는 interface 변경은 `RED -> observed failure -> minimal GREEN -> VERIFY`를
|
||||||
|
따른다.
|
||||||
|
- Refactoring test는 base interface 사용, ownership/lifetime, invalid combination,
|
||||||
|
deterministic order와 current numerical result preservation을 검증한다.
|
||||||
|
- Focused test 뒤에 full MSVC x64 Debug build와 CTest를 실행한다.
|
||||||
|
- B33/MITC4 output 경계를 건드린 변경은 승인된 reference comparison을 다시 실행한다.
|
||||||
|
- Reference artifact, input path와 tolerance를 리팩터링에 맞춰 수정하지 않는다.
|
||||||
|
- Commit은 review 가능한 module slice로 제한하고 Conventional Commits를 사용한다.
|
||||||
|
|
||||||
|
## Tooling
|
||||||
|
|
||||||
|
Repository가 제공하는 설정을 우선한다.
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
clang-format --dry-run --Werror <changed-cpp-and-header-files>
|
||||||
|
clang-tidy <changed-cpp-files> -- -std=c++17
|
||||||
|
doxygen Doxyfile
|
||||||
|
```
|
||||||
|
|
||||||
|
실제 build/test command는 `.harness/config.json`이 있으면 그 설정을 우선하고, 없으면
|
||||||
|
`AGENTS.md`와 Harness의 MSVC/CMake/CTest entry point를 따른다. 필요한 tool이 설치되지 않아
|
||||||
|
검증을 실행할 수 없으면 성공으로 간주하지 않고 environment limitation을 보고한다.
|
||||||
|
|
||||||
|
Generated Doxygen HTML과 tool cache/build output은 source control에 넣지 않는다.
|
||||||
|
|
||||||
|
## Implementation Agent Checklist
|
||||||
|
|
||||||
|
Implementation Agent는 C++ Step을 시작하기 전에 다음을 확인한다.
|
||||||
|
|
||||||
|
- 이 문서와 feature implementation plan을 읽었다.
|
||||||
|
- 변경할 base/concrete/module owner가 승인 설계와 일치한다.
|
||||||
|
- 관련 test file과 RED condition이 Step에 명시되어 있다.
|
||||||
|
- Public API naming과 production Doxygen가 이 문서에 맞는다.
|
||||||
|
- Vendor dependency와 ownership direction이 역전되지 않는다.
|
||||||
|
- Stable identity, numerical order, HDF5와 reference contract가 보존된다.
|
||||||
|
- Formatting, Doxygen, focused/full MSVC/CTest acceptance command가 계획되어 있다.
|
||||||
@@ -0,0 +1,355 @@
|
|||||||
|
# FESA C++ Object-Oriented Modular Refactoring Design
|
||||||
|
|
||||||
|
## 상태
|
||||||
|
|
||||||
|
- 설계 대화 승인: 2026-08-16
|
||||||
|
- 서면 spec 리뷰: 이 문서에 대한 사용자 검토 필요
|
||||||
|
- 구현 상태: not-started
|
||||||
|
|
||||||
|
## 목적
|
||||||
|
|
||||||
|
현재 B33 Euler beam, MITC4 shell과 linear static solver의 수치 및 외부 동작을
|
||||||
|
유지하면서 C++ production code를 객체 책임 중심으로 재구성한다. 이번 리팩터링은
|
||||||
|
Google C++ Style Guide 기반의 일관된 코드 스타일, 중복 제거, production Doxygen 문서화,
|
||||||
|
명시적인 추상 경계와 응집된 모듈을 제공해야 한다.
|
||||||
|
|
||||||
|
효율성은 runtime 성능 향상이 아니라 다음 유지보수 특성을 의미한다.
|
||||||
|
|
||||||
|
- 새 element, element property, material, analysis, load 또는 boundary condition을 추가할
|
||||||
|
때 기존 concrete 구현을 수정하는 범위를 줄인다.
|
||||||
|
- 하나의 의미를 여러 translation unit에서 다시 구현하지 않는다.
|
||||||
|
- parser semantic data, numerical kernel, assembly, recovery와 output 책임을 구분한다.
|
||||||
|
- 수치식과 I/O 계약을 사람이 직접 대조할 수 있는 단순한 dependency direction을 유지한다.
|
||||||
|
|
||||||
|
## 범위
|
||||||
|
|
||||||
|
### 포함
|
||||||
|
|
||||||
|
- production 및 test C++ 전체의 Google-style naming과 formatting 전환
|
||||||
|
- production header의 `.hpp`에서 `.h`로 전환과 header guard 적용
|
||||||
|
- production 함수와 class의 Doxygen 문서화
|
||||||
|
- `ElementDefinition`, `Element`, `ElementProperty`, `Material`, `Analysis`, `Load`,
|
||||||
|
`BoundaryCondition` 추상 경계
|
||||||
|
- B33, MITC4, isotropic linear elasticity, beam/shell property, linear static analysis,
|
||||||
|
concentrated nodal load와 prescribed displacement의 concrete 구현 연결
|
||||||
|
- `Vector3`, source-target resolution, DOF invariant validation과 dense-BLAS adapter의
|
||||||
|
중복 제거
|
||||||
|
- `domain_mapper.cpp`, `hdf5_results_writer.cpp`, `result_recovery.cpp`의 책임별 분할
|
||||||
|
- style, Doxygen, MSVC/CTest와 reference comparison 검증
|
||||||
|
- `docs/CODINGSTYLE.md` 유지관리 문서와 Implementation Agent 필수 참조 연결
|
||||||
|
|
||||||
|
### 제외
|
||||||
|
|
||||||
|
- MITC3, solid hexa/tetra 또는 다른 element 구현
|
||||||
|
- density, plasticity, anisotropic material 동작 구현
|
||||||
|
- dynamic, eigenvalue, response spectrum 또는 random vibration analysis 구현
|
||||||
|
- distributed load, body force 또는 MPC 구현
|
||||||
|
- 승인된 formulation, sign, units, coordinate, HDF5 schema, reference artifact 또는
|
||||||
|
tolerance 변경
|
||||||
|
- runtime 성능 최적화 또는 parallel reduction policy 변경
|
||||||
|
- general plugin registry, global static registration 또는 shared ownership framework
|
||||||
|
|
||||||
|
## 근거와 제약
|
||||||
|
|
||||||
|
현재 production code는 semantic record와 numerical kernel을 이미 구분하지만 Domain은
|
||||||
|
element, material, property, load와 boundary를 concrete vector로 각각 소유한다.
|
||||||
|
`SparseAssembler`, `DofManager`와 `ResultRecovery`는 B33/MITC4 concrete storage를 직접
|
||||||
|
알아야 한다. B33과 MITC4라는 두 실제 element가 있으므로 element abstraction은 현재
|
||||||
|
구현으로 검증할 수 있다.
|
||||||
|
|
||||||
|
반면 아직 구현되지 않은 plastic integration, dynamic state, MPC enforcement의 메서드를
|
||||||
|
base class에 미리 추가할 근거는 없다. 추상 class는 현재 concrete 구현이 실제로 공유하는
|
||||||
|
계약만 제공하고 future capability는 해당 기능의 requirements/formulation/ADR이 승인될 때
|
||||||
|
추가한다.
|
||||||
|
|
||||||
|
다음 기존 계약은 리팩터링보다 우선한다.
|
||||||
|
|
||||||
|
- Domain은 semantic definition을 단독 소유하고 parsing 이후 불변으로 취급한다.
|
||||||
|
- AnalysisModel은 Domain을 복사하지 않는 non-owning stable-index view다.
|
||||||
|
- DofManager는 DOF와 equation numbering 및 sparse pattern을 단독 소유한다.
|
||||||
|
- assembly worker는 global CSR storage를 직접 수정하지 않는다.
|
||||||
|
- stiffness partition과 factorization은 load assembly보다 먼저 수행한다.
|
||||||
|
- reaction과 free-equilibrium evidence는 full residual `K*d-F`에서 구한다.
|
||||||
|
- result recovery와 final HDF5는 candidate validation 후 commit한다.
|
||||||
|
- B33 및 MITC4 reference identity와 tolerance는 변경하지 않는다.
|
||||||
|
|
||||||
|
## 추상 계층과 소유권
|
||||||
|
|
||||||
|
```text
|
||||||
|
Domain
|
||||||
|
├─ ElementDefinition*
|
||||||
|
│ ├─ EulerBeam3DDefinition
|
||||||
|
│ └─ Mitc4ShellDefinition
|
||||||
|
├─ ElementProperty*
|
||||||
|
│ ├─ GeneralBeamSection
|
||||||
|
│ └─ ShellSection
|
||||||
|
├─ Material*
|
||||||
|
│ └─ IsotropicLinearElasticMaterial
|
||||||
|
└─ StepDefinition
|
||||||
|
├─ Load*
|
||||||
|
│ └─ ConcentratedNodalLoad
|
||||||
|
└─ BoundaryCondition*
|
||||||
|
└─ PrescribedDisplacementBoundaryCondition
|
||||||
|
|
||||||
|
Analysis
|
||||||
|
└─ LinearStaticAnalysis
|
||||||
|
|
||||||
|
Element
|
||||||
|
├─ EulerBeam3D
|
||||||
|
└─ Mitc4Shell
|
||||||
|
```
|
||||||
|
|
||||||
|
Domain은 각 base type을 `std::unique_ptr`로 단독 소유한다. Public access는 const이며
|
||||||
|
collection의 vector position은 기존 stable `EntityIndex` 의미를 유지한다. AnalysisModel과
|
||||||
|
후속 solver object는 raw ownership을 획득하지 않고 Domain 수명 안에서 index 또는 const
|
||||||
|
reference만 사용한다. Copy를 지원하기 위한 speculative `Clone()`과 `std::shared_ptr`는
|
||||||
|
추가하지 않는다.
|
||||||
|
|
||||||
|
`ElementDefinition`과 `Element`는 서로 다른 책임이다.
|
||||||
|
|
||||||
|
- `ElementDefinition`은 source identity, source element type, node connectivity와
|
||||||
|
property/material identity를 제공하는 semantic model이다.
|
||||||
|
- `Element`는 active DOF layout, stiffness contribution, transformation과 result recovery를
|
||||||
|
제공하는 numerical kernel이다.
|
||||||
|
- `ElementFactory`는 definition, property와 material compatibility를 검증한 뒤 concrete
|
||||||
|
kernel을 만든다.
|
||||||
|
- 잘못된 조합은 `dynamic_cast` 실패나 undefined behavior로 넘기지 않고 기존
|
||||||
|
`Status`/`Result<T>` diagnostic으로 fail-closed 처리한다.
|
||||||
|
|
||||||
|
Element result는 모든 element에 의미 없는 field를 추가한 비대한 base record가 아니다.
|
||||||
|
공통 step/frame/source identity를 가진 backend-neutral result bundle이 beam 및 shell row를
|
||||||
|
각자의 명확한 record로 보관한다. ResultRecovery와 ResultsWriter는 stable row identity를
|
||||||
|
보존하며 서로 다른 result location을 평균하거나 합치지 않는다.
|
||||||
|
|
||||||
|
## Material과 Element Property
|
||||||
|
|
||||||
|
`Material` base는 identity, source location과 수명 계약만 제공한다. 현재 concrete type은
|
||||||
|
물리 의미를 드러내도록 `IsotropicLinearElasticMaterial`로 명명한다. 현재 element factory가
|
||||||
|
필요로 하는 isotropic elastic capability만 노출한다.
|
||||||
|
|
||||||
|
다음 future concern은 이번 interface에 빈 메서드나 optional field로 미리 넣지 않는다.
|
||||||
|
|
||||||
|
- density와 inertia contribution
|
||||||
|
- anisotropic elastic constitutive data
|
||||||
|
- plastic history state와 return mapping
|
||||||
|
- temperature 또는 rate dependency
|
||||||
|
|
||||||
|
이 concern은 각 기능이 승인될 때 별도의 capability 또는 구성 객체로 추가한다. 같은
|
||||||
|
원칙으로 `ElementProperty`는 identity를 제공하고 `GeneralBeamSection`과 `ShellSection`은
|
||||||
|
각자 필요한 기하 property를 소유한다. Solid property를 예상해 비어 있는 thickness/area
|
||||||
|
accessor를 base에 추가하지 않는다.
|
||||||
|
|
||||||
|
## Analysis 계층
|
||||||
|
|
||||||
|
현재 `Analysis` base의 8개 protected hook은 linear-static lifecycle에 특화되어 있다.
|
||||||
|
이를 모든 future procedure에 강제하지 않는다.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Analysis {
|
||||||
|
public:
|
||||||
|
virtual ~Analysis() = default;
|
||||||
|
virtual Status Run(const AnalysisRequest& request) = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
현재 승인 순서는 `LinearStaticAnalysis::Run()`의 private 단계로 유지한다.
|
||||||
|
|
||||||
|
```text
|
||||||
|
initialize
|
||||||
|
-> build analysis model
|
||||||
|
-> build DOF map and sparse pattern
|
||||||
|
-> assemble and partition stiffness
|
||||||
|
-> factorize Kff
|
||||||
|
-> assemble loads and effective RHS
|
||||||
|
-> substitute and reconstruct
|
||||||
|
-> recover and write results
|
||||||
|
```
|
||||||
|
|
||||||
|
Dynamic, eigenvalue와 stochastic procedure는 추가될 때 별도 state, equation, solver와 output
|
||||||
|
lifecycle을 정의한다. 기존 linear-static hook 사이에 condition이나 unused future state를
|
||||||
|
추가하지 않는다. 이 책임 변경은 구현 전에 ADR-007을 대체하거나 개정하는 ADR로 기록한다.
|
||||||
|
|
||||||
|
## Load와 Boundary Condition
|
||||||
|
|
||||||
|
`Load` concrete object는 자신의 semantic target과 magnitude를 소유하고 ordered full-DOF
|
||||||
|
contribution을 생성한다. `LoadAssembler`는 active source order로 contribution을 모아 기존
|
||||||
|
fixed accumulation order로 global vector에 반영한다. Polymorphic load가 global vector를
|
||||||
|
직접 병렬 갱신하지 않는다.
|
||||||
|
|
||||||
|
현재 concrete load는 `ConcentratedNodalLoad`다. Future distributed load와 body force는
|
||||||
|
element-local contribution을 생성할 수 있지만 stable global reduction은 계속 assembler가
|
||||||
|
소유한다.
|
||||||
|
|
||||||
|
`BoundaryCondition`은 enforcement algorithm을 직접 수행하지 않고 constraint definition을
|
||||||
|
생성한다. 현재 concrete type은 nonzero 값을 포함하는
|
||||||
|
`PrescribedDisplacementBoundaryCondition`이다. `EssentialConstraintPolicy`가 기존 stable
|
||||||
|
elimination과 full/reduced reconstruction을 수행한다.
|
||||||
|
|
||||||
|
Future MPC는 별도 constraint equation과 enforcement policy를 요구한다. Prescribed
|
||||||
|
displacement, MPC, penalty와 Lagrange multiplier를 하나의 bool/enum branch가 누적된 class로
|
||||||
|
합치지 않는다.
|
||||||
|
|
||||||
|
## 공통 수학과 중복 제거
|
||||||
|
|
||||||
|
### Vector3
|
||||||
|
|
||||||
|
좌표, local axis, shell director와 cross-product는 고정 크기 `Vector3` 값 class를 사용한다.
|
||||||
|
동적 크기와 MKL-backed storage를 소유하는 기존 `Vector`와 역할을 섞지 않는다.
|
||||||
|
|
||||||
|
`Vector3`는 현재 반복되는 다음 연산을 한 번만 정의한다.
|
||||||
|
|
||||||
|
- component access
|
||||||
|
- addition, subtraction과 scalar multiplication
|
||||||
|
- `Dot()`
|
||||||
|
- `Cross()`
|
||||||
|
- `Norm()`
|
||||||
|
- `Normalized()`
|
||||||
|
- `IsFinite()`
|
||||||
|
|
||||||
|
Normalization failure policy는 호출 위치에서 기존 scale-aware diagnostic을 유지한다.
|
||||||
|
`Vector3`가 임의 tolerance, zero clamp 또는 solver diagnostic을 소유하지 않는다.
|
||||||
|
|
||||||
|
### 다른 공통 책임
|
||||||
|
|
||||||
|
- `SourceTargetResolver`: source label, instance와 set target을 stable identity로 해석한다.
|
||||||
|
- `DofManager::ValidateInvariants()`: full/free/constrained ordering과 equation mapping을 owner가
|
||||||
|
한 번 검증한다.
|
||||||
|
- private dense-BLAS adapter: Matrix와 Vector의 MKL integer conversion 및 copy operation을
|
||||||
|
공유한다. Vendor type은 public header에 노출하지 않는다.
|
||||||
|
- ASCII utility: case-insensitive name comparison과 positive source-label parsing을 공유한다.
|
||||||
|
|
||||||
|
중복 제거는 같은 의미와 failure policy가 반복될 때만 적용한다. 이름만 비슷하지만 units,
|
||||||
|
identity 또는 diagnostic owner가 다른 계산을 하나로 합치지 않는다. State가 없는 helper를
|
||||||
|
static-only class로 포장하지 않고 internal namespace/module을 사용한다.
|
||||||
|
|
||||||
|
## 모듈 구조
|
||||||
|
|
||||||
|
```text
|
||||||
|
include/fesa/
|
||||||
|
├─ analysis/
|
||||||
|
│ ├─ analysis.h
|
||||||
|
│ └─ linear_static_analysis.h
|
||||||
|
├─ elements/
|
||||||
|
│ ├─ element.h
|
||||||
|
│ ├─ element_definition.h
|
||||||
|
│ ├─ element_factory.h
|
||||||
|
│ ├─ euler_beam_3d.h
|
||||||
|
│ └─ mitc4_shell.h
|
||||||
|
├─ properties/
|
||||||
|
│ ├─ element_property.h
|
||||||
|
│ ├─ general_beam_section.h
|
||||||
|
│ └─ shell_section.h
|
||||||
|
├─ materials/
|
||||||
|
│ ├─ material.h
|
||||||
|
│ └─ isotropic_linear_elastic_material.h
|
||||||
|
├─ loads/
|
||||||
|
│ ├─ load.h
|
||||||
|
│ └─ concentrated_nodal_load.h
|
||||||
|
├─ constraints/
|
||||||
|
│ ├─ boundary_condition.h
|
||||||
|
│ ├─ prescribed_displacement.h
|
||||||
|
│ └─ essential_constraint_policy.h
|
||||||
|
├─ math/
|
||||||
|
│ ├─ vector.h
|
||||||
|
│ ├─ vector3.h
|
||||||
|
│ ├─ matrix.h
|
||||||
|
│ └─ sparse_matrix.h
|
||||||
|
└─ model/
|
||||||
|
├─ domain.h
|
||||||
|
├─ analysis_model.h
|
||||||
|
└─ source_target_resolver.h
|
||||||
|
```
|
||||||
|
|
||||||
|
`model_types.hpp`의 unrelated record는 각 owner module로 이동한다. Top-level orchestration
|
||||||
|
file은 다음과 같이 분리한다.
|
||||||
|
|
||||||
|
- Abaqus mapping: topology, material/property, step/load/BC와 final Domain assembly
|
||||||
|
- HDF5 output: RAII/primitives, model dataset, result dataset, self-check와 atomic finalization
|
||||||
|
- Result recovery: global equilibrium, beam recovery, shell recovery와 atomic state commit
|
||||||
|
|
||||||
|
Public header와 implementation dependency direction을 역전하지 않는다. MKL, TBB, HDF5와
|
||||||
|
Win32 type은 기존 adapter/private implementation 경계 안에 남는다.
|
||||||
|
|
||||||
|
## 코드 스타일과 문서화
|
||||||
|
|
||||||
|
`docs/CODINGSTYLE.md`를 FESA C++ style의 project-local source of truth로 사용한다. Google
|
||||||
|
C++ Style Guide가 baseline이고 FESA 계약이 우선한다.
|
||||||
|
|
||||||
|
주요 결정은 다음과 같다.
|
||||||
|
|
||||||
|
- C++17/MSVC 호환을 유지한다. Google guide의 현재 C++20 language target은 적용하지 않는다.
|
||||||
|
- 함수와 accessor를 포함한 production API는 PascalCase로 전면 전환한다.
|
||||||
|
- type은 PascalCase, 변수는 snake_case, constant/enumerator는 `kPascalCase`, class member는
|
||||||
|
trailing underscore를 사용한다.
|
||||||
|
- Header는 `.h`와 full-path Google header guard를 사용한다.
|
||||||
|
- Source는 기존 FESA/CMake 관례인 `.cpp`를 유지하는 project exception으로 둔다.
|
||||||
|
- Formatting은 `BasedOnStyle: Google`, 2-space indentation과 80-column limit를 사용한다.
|
||||||
|
- Production public/protected declaration에는 Doxygen contract를 기록한다.
|
||||||
|
- Production internal function은 definition에 목적과 비자명한 수치/순서 의미를 기록한다.
|
||||||
|
- Test code에는 Doxygen coverage를 요구하지 않는다.
|
||||||
|
|
||||||
|
Repository는 `.clang-format`, selected C++17-compatible `.clang-tidy`, `Doxyfile`과 optional
|
||||||
|
CMake docs target을 제공한다. Generated HTML은 source control에 넣지 않는다.
|
||||||
|
|
||||||
|
Implementation Agent의 profile은 구현 전에 `docs/CODINGSTYLE.md`를 mandatory global input으로
|
||||||
|
읽도록 변경한다. Agent workflow contract test는 해당 profile이 문서를 직접 참조하는지
|
||||||
|
검증한다.
|
||||||
|
|
||||||
|
## 오류 처리
|
||||||
|
|
||||||
|
- 모든 polymorphic base는 public virtual destructor를 갖는다.
|
||||||
|
- Factory는 null object를 성공 결과로 반환하지 않는다.
|
||||||
|
- Element/property/material incompatibility는 structured model diagnostic으로 거부한다.
|
||||||
|
- Public solver 경계는 기존 `Status`/`Result<T>`를 사용한다.
|
||||||
|
- Backend exception은 현재 failure category와 atomicity contract를 유지해 번역한다.
|
||||||
|
- Unknown future kind를 silent fallback이나 default concrete type으로 바꾸지 않는다.
|
||||||
|
- Failed candidate는 Domain, AnalysisState 또는 final HDF5를 부분 변경하지 않는다.
|
||||||
|
|
||||||
|
## 단계적 마이그레이션
|
||||||
|
|
||||||
|
1. 기존 unit/integration/reference 및 HDF5 contract baseline을 기록하고 architecture ADR을
|
||||||
|
갱신한다.
|
||||||
|
2. `.clang-format`, header rename/guard와 PascalCase를 module slice별 mechanical change로
|
||||||
|
적용한다.
|
||||||
|
3. `Vector3`, ASCII utility, SourceTargetResolver, DOF invariant validation과 private BLAS
|
||||||
|
adapter를 도입한다.
|
||||||
|
4. Domain semantic hierarchy와 current concrete material/property/load/boundary type을
|
||||||
|
연결한다.
|
||||||
|
5. Element runtime hierarchy와 factory를 DofManager, SparseAssembler와 ResultRecovery에
|
||||||
|
연결한다.
|
||||||
|
6. Ordered load contribution과 essential constraint policy를 연결한다.
|
||||||
|
7. Minimal Analysis base와 LinearStaticAnalysis-owned lifecycle로 전환한다.
|
||||||
|
8. Mapper, HDF5 writer와 recovery를 책임별로 분할하고 Doxygen/style coverage를 완료한다.
|
||||||
|
|
||||||
|
Mechanical formatting, API rename와 semantic restructuring을 같은 review unit에 섞지 않는다.
|
||||||
|
각 slice는 buildable하고 독립 검증 가능해야 한다.
|
||||||
|
|
||||||
|
## TDD와 검증
|
||||||
|
|
||||||
|
각 production change는 관련 C++ test와 같은 Step에서 `RED -> GREEN -> VERIFY`를 수행한다.
|
||||||
|
|
||||||
|
- abstract base와 concrete polymorphic use를 검증하는 compile-time/unit test
|
||||||
|
- factory success와 incompatible property/material rejection test
|
||||||
|
- base interface를 통한 B33/MITC4 stiffness 및 recovery test
|
||||||
|
- stable element, load와 boundary source-order test
|
||||||
|
- Domain ownership, AnalysisModel lifetime와 stable identity test
|
||||||
|
- Vector3 arithmetic, finite and normalization-boundary test
|
||||||
|
- 기존 parser/I/O, HDF5 schema와 atomicity test
|
||||||
|
- B33 및 MITC4 integration/reference comparison
|
||||||
|
- repeated execution의 sparse structure, result row와 diagnostic order test
|
||||||
|
- Doxygen warning, formatting과 selected lint check
|
||||||
|
- full MSVC x64 Debug `/W4 /WX` build와 CTest
|
||||||
|
|
||||||
|
수치 산술 순서를 의도적으로 변경하지 않은 slice는 가능한 한 exact equality를 요구한다.
|
||||||
|
Feature-approved reference tolerance는 최종 external comparison에만 그대로 적용한다.
|
||||||
|
|
||||||
|
## 완료 기준
|
||||||
|
|
||||||
|
- 승인된 abstraction과 current concrete implementation이 base interface를 통해 연결된다.
|
||||||
|
- DofManager, assembler와 recovery에 B33/MITC4 type branch 또는 duplicate geometry helper가
|
||||||
|
남지 않는다.
|
||||||
|
- Production 및 test C++가 `docs/CODINGSTYLE.md`의 naming/formatting 규칙을 만족한다.
|
||||||
|
- Production API와 non-obvious internal function에 요구된 Doxygen가 존재한다.
|
||||||
|
- Implementation Agent profile이 `docs/CODINGSTYLE.md`를 mandatory input으로 참조한다.
|
||||||
|
- 전체 MSVC x64 Debug build/CTest와 B33/MITC4 reference comparison이 통과한다.
|
||||||
|
- HDF5 schema, stable identity, diagnostic, tolerance와 reference artifact에 변경이 없다.
|
||||||
Reference in New Issue
Block a user