feat(cpp-object-oriented-modular-refactoring): step 2 - architecture-boundaries
This commit is contained in:
+132
-38
@@ -32,7 +32,7 @@ src/
|
||||
assembly/ # deterministic stiffness/load assembly, ParallelFor adapter
|
||||
constraints/ # essential-constraint elimination and reconstruction
|
||||
core/ # source identity, status, diagnostics
|
||||
elements/ # V0 EulerBeam3D kernel and recovery
|
||||
elements/ # current B33/MITC4 kernels and recovery
|
||||
fem/ # DOF/equation numbering and sparse pattern
|
||||
io/
|
||||
abaqus/ # .inp syntax reader and semantic Domain mapper
|
||||
@@ -62,9 +62,11 @@ scripts/
|
||||
phases/ # Optional generated phase plans
|
||||
```
|
||||
|
||||
`materials/`, nonlinear/dynamic analysis, MPC/penalty policies, general element factories,
|
||||
history output과 production validation module은 장기 확장 경계이지 현재 구현된 module이
|
||||
아니다. 새 디렉토리와 추상 계층은 승인된 기능이 실제로 필요로 할 때 추가한다.
|
||||
`materials/`, `properties/`, `loads/`와 checked `ElementFactory`는 승인된 C++ modular
|
||||
refactoring의 target boundary이며 후속 implementation Step에서 추가한다. 이
|
||||
documentation-only Step 시점에는 현재 구현 디렉토리로 표시하지 않는다. Density,
|
||||
plasticity, anisotropy, nonlinear/dynamic analysis, MPC/penalty, history output과 production
|
||||
validation module은 계속 장기 확장 경계이며 별도 승인 기능이 필요하다.
|
||||
|
||||
## Harness Execution Layer
|
||||
|
||||
@@ -109,16 +111,86 @@ CMake source에 기록하지 말고 config package와 imported target metadata
|
||||
## 모듈 경계
|
||||
- `core`는 외부 라이브러리에 의존하지 않는다.
|
||||
- `io/abaqus`는 syntax와 semantic mapping만 담당하고 해석 알고리즘을 알지 않는다.
|
||||
- `model`은 Abaqus keyword 문자열이 아니라 solver semantic model을 가진다.
|
||||
- `model`은 Abaqus keyword 문자열이 아니라 solver semantic model을 가지며 `Domain`과
|
||||
non-owning `AnalysisModel`의 수명 경계를 소유한다.
|
||||
- `materials`와 `properties`는 Domain이 소유하는 semantic identity와 현재 승인된
|
||||
isotropic elasticity 및 beam/shell property data만 제공한다.
|
||||
- `elements`는 Domain-owned `ElementDefinition`, runtime numerical `Element`, checked
|
||||
`ElementFactory`와 element-local stiffness/recovery contract를 제공한다.
|
||||
- `fem`의 `DofManager`는 DOF, equation ordering, scatter와 sparse pattern을 소유한다.
|
||||
- `elements`는 local/global stiffness, transformation, optional load kernel과 recovery를 제공한다. V0 material/section은 concrete Domain record다.
|
||||
- `assembly`는 element-local contribution과 full nodal load를 stable full-DOF space에 조립한다.
|
||||
- `constraints`는 V0 essential BC elimination과 full/reduced vector 변환을 담당한다. MPC와 penalty는 현재 범위가 아니다.
|
||||
- `assembly`는 runtime element contribution과 ordered load contribution을 stable full-DOF
|
||||
space에 조립한다. Contribution producer는 global storage를 직접 갱신하지 않는다.
|
||||
- `loads`는 semantic target과 magnitude를 소유하고 ordered `LoadContribution`을 생성한다.
|
||||
- `constraints`는 `ConstraintDefinition` 생성과 V0 essential BC elimination 및 full/reduced
|
||||
vector 변환을 분리한다. MPC와 penalty는 현재 범위가 아니다.
|
||||
- `solvers`는 `LinearSolver` 뒤에 MKL PARDISO 세부 구현을 감춘다. TBB는 `assembly/ParallelFor`, HDF5는 `results/ResultsWriter` 경계 뒤에 각각 격리된다.
|
||||
- `analysis`는 step/history data를 받아 procedure를 실행하고 solver backend와 result writer를 조율한다.
|
||||
- `results`는 full residual과 beam rows를 복구하고 backend-neutral writer contract를 제공한다. HDF5 schema 구현은 `io/hdf5`가 담당한다.
|
||||
- `results`는 full residual과 B33/MITC4 rows를 복구하고 backend-neutral writer contract를
|
||||
제공한다. HDF5 schema 구현은 `io/hdf5`가 담당한다.
|
||||
- test helper는 production parser/solver 내부 상태를 우회하지 않는다.
|
||||
|
||||
## 승인된 리팩터링 dependency와 ownership
|
||||
|
||||
다음 graph는 C++ object-oriented modular refactoring의 구현 방향을 고정한다. `owns`는
|
||||
단독 수명 소유권을, 나머지 화살표는 왼쪽 consumer가 오른쪽 contract를 사용한다는
|
||||
뜻이다. 이 graph는 기존 B33/MITC4 물리 기능을 늘리지 않는다.
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
승인된 B33/MITC4 formulation, operation/reduction order, sign, units, coordinates와 row
|
||||
identity는 이 ownership 리팩터링보다 우선한다. HDF5 schema, reference artifact와
|
||||
ADR-014/ADR-020 tolerance도 변경하지 않는다.
|
||||
|
||||
`Domain`은 `ElementDefinition`, `ElementProperty`, `Material`과 `StepDefinition` base
|
||||
object를 `std::unique_ptr`로 단독 소유하고 const access를 제공한다. Collection position은
|
||||
기존 stable `EntityIndex` 의미를 유지한다. `AnalysisModel`과 solver consumer는 ownership을
|
||||
가져오지 않고 Domain 수명 안에서 stable index 또는 const reference만 사용한다.
|
||||
`std::shared_ptr`, speculative `Clone()`과 global registry는 이 계약에 포함되지 않는다.
|
||||
|
||||
`ElementDefinition`은 source identity, source element type, connectivity와
|
||||
property/material identity를 보존하는 semantic object다. Runtime `Element`는 active
|
||||
`ElementDofLayout`, `ElementStiffnessContribution`과 `ElementResultBundle`을 제공하는
|
||||
numerical kernel이다. `ElementFactory`만 compatible definition/property/material 조합을
|
||||
검사해 runtime candidate를 만들며 unknown 또는 incompatible 조합을 기존
|
||||
`Status`/`Result<T>` diagnostic으로 fail-closed 처리한다. `DofManager`,
|
||||
`SparseAssembler`와 `ResultRecovery`는 B33/MITC4 concrete storage가 아니라 위 runtime
|
||||
contract를 소비한다. Linear-static candidate는 runtime `Element`를
|
||||
`std::vector<std::unique_ptr<Element>>`로 소유하고, consumer에는 그 owner 수명 안에서만
|
||||
유효한 non-owning `ElementView`를 제공한다.
|
||||
|
||||
`Material` base는 identity, source location과 수명 의미만 공유한다. 현재 concrete
|
||||
isotropic linear elasticity에 필요한 capability만 사용하며 density, anisotropy, plastic
|
||||
state, temperature 또는 rate dependency를 optional field나 no-op method로 미리 추가하지
|
||||
않는다. `ElementProperty`도 beam/shell이 실제 사용하는 data만 각 concrete type에 둔다.
|
||||
|
||||
`Load`는 semantic target과 magnitude를 소유하고 source order가 보존된
|
||||
`LoadContribution`을 생성한다. Global vector의 deterministic accumulation은
|
||||
`LoadAssembler`만 수행한다. `BoundaryCondition`은 `ConstraintDefinition`을 생성하고
|
||||
`EssentialConstraintPolicy`가 prescribed displacement의 stable elimination과
|
||||
reconstruction을 수행한다. Future distributed/body load와 MPC enforcement는 구현된
|
||||
기능이 아니며 별도 승인 계약 없이 이 경계에 branch나 optional state를 추가하지 않는다.
|
||||
|
||||
책임이 큰 facade는 외부 계약을 유지한 채 private implementation만 다음 owner로 나눈다.
|
||||
|
||||
- Abaqus Domain mapping: topology, material/property, step/load/boundary mapping과 final
|
||||
Domain assembly
|
||||
- Result recovery: global equilibrium, beam recovery, shell recovery와 atomic state commit
|
||||
- HDF5 writing: RAII/primitives, model datasets, result datasets, self-check와 atomic
|
||||
finalization
|
||||
|
||||
이 분할은 parser diagnostic, `ResultsWriter` boundary, HDF5 schema 또는 final-file
|
||||
atomicity를 변경하지 않는다.
|
||||
|
||||
## V0 입력 경계
|
||||
|
||||
V0 parser는 keyword와 parameter를 case-insensitive하게 해석하되 source label의 원문을
|
||||
@@ -174,14 +246,23 @@ CLI pipeline에서는 이 kernel을 호출하지 않는다. Stiffness와 recover
|
||||
|
||||
```text
|
||||
Domain
|
||||
├── owns nodes, B33 elements, materials, beam sections, sets
|
||||
├── owns boundary conditions, nodal loads, one static step
|
||||
├── owns nodes, sets and source identity
|
||||
├── owns unique_ptr<ElementDefinition / ElementProperty / Material>
|
||||
├── owns StepDefinition with Load / BoundaryCondition definitions
|
||||
└── owns source path/identity and mapping warnings
|
||||
|
||||
AnalysisModel
|
||||
├── non-owning view into Domain
|
||||
├── stable active element/BC/load indices
|
||||
└── reachable material/section indices
|
||||
├── non-owning stable-index view into Domain
|
||||
├── stable active element/BC/load definition indices
|
||||
└── reachable material/property indices
|
||||
|
||||
ElementFactory
|
||||
└── creates checked runtime Element candidates
|
||||
|
||||
Element
|
||||
├── exposes ElementDofLayout
|
||||
├── produces ElementStiffnessContribution
|
||||
└── recovers ElementResultBundle
|
||||
|
||||
DofManager
|
||||
├── owns node x [UX,UY,UZ,URX,URY,URZ] full-DOF numbering
|
||||
@@ -205,12 +286,15 @@ Matrix
|
||||
SparseMatrix
|
||||
```
|
||||
|
||||
Nonlinear/static, dynamic, frequency, heat-transfer procedure와 general element/material/load
|
||||
base hierarchy는 이 구조 위의 가능한 확장 방향일 뿐 현재 public API가 아니다. 사용 사례가
|
||||
승인되기 전에 V0 concrete record를 speculative hierarchy로 감싸지 않는다.
|
||||
위 abstract boundary는 현재 B33/MITC4, isotropic linear elasticity, beam/shell property,
|
||||
concentrated nodal load, prescribed displacement와 linear static procedure를 연결하는 데
|
||||
필요한 최소 계약이다. MITC3, solid, dynamic, frequency, heat-transfer와 plastic behavior는
|
||||
구현된 기능이 아니며 승인된 사용 사례 전에 future-only method나 state를 base에 추가하지
|
||||
않는다.
|
||||
|
||||
## 상태 관리
|
||||
- `Domain`은 입력 파일에서 만들어진 전체 모델 정의를 소유한다. 파싱 이후에는 가능한 한 불변으로 취급한다.
|
||||
- `Domain`은 입력 파일에서 만들어진 전체 모델 정의를 `std::unique_ptr`로 단독 소유한다.
|
||||
파싱 이후에는 가능한 한 불변으로 취급하고 stable collection index를 바꾸지 않는다.
|
||||
- `LinearStaticAnalysis`가 `Domain`을 소유하고, 그 뒤에 `AnalysisModel`, `DofManager`, `AnalysisState`, stiffness/RHS를 순서대로 만든다. 재사용 시에는 역순으로 해제하여 이전 Domain을 가리키는 view를 남기지 않는다.
|
||||
- `AnalysisModel`은 현재 step에서 활성화되는 해석 객체들의 실행 view이다. `Domain`을 복사하지 않으므로 Domain이 반드시 더 오래 살아야 한다.
|
||||
- `DofManager`는 자유도와 방정식 번호를 전담한다. `Node` 또는 `Element` 내부에 equation id를 분산 저장하지 않는다.
|
||||
@@ -223,15 +307,16 @@ Abaqus input file
|
||||
-> syntax parse and semantic mapping
|
||||
-> immutable Domain 생성
|
||||
-> 단일 step AnalysisModel view 생성
|
||||
-> DofManager DOF/scatter map/sparse pattern 생성
|
||||
-> element stiffness 계산과 deterministic COO-to-CSR 조립
|
||||
-> free/constrained partition 생성
|
||||
-> ElementFactory가 compatible definition에서 runtime Element candidate 생성
|
||||
-> DofManager가 ElementDofLayout으로 DOF/scatter map/sparse pattern 생성
|
||||
-> ElementStiffnessContribution의 deterministic COO-to-CSR 조립
|
||||
-> ConstraintDefinition의 stable essential-constraint partition 생성
|
||||
-> LinearSolver::factorize(Kff)
|
||||
-> full nodal load vector 조립
|
||||
-> ordered LoadContribution의 full nodal load vector 조립
|
||||
-> effective RHS = Ff - Kfc * dc
|
||||
-> LinearSolver::solve(rhs, df) substitution
|
||||
-> full displacement 복구
|
||||
-> full residual/reaction = K*d - F 및 element result 복구
|
||||
-> full residual/reaction = K*d - F 및 ElementResultBundle 복구
|
||||
-> ResultsWriter로 results.h5 atomic finalization
|
||||
```
|
||||
|
||||
@@ -240,28 +325,37 @@ Abaqus input file
|
||||
reaction이고 free component는 equilibrium residual evidence로 full-index vector에 남긴다.
|
||||
|
||||
## 해석 실행 흐름
|
||||
`Analysis::run()`은 Template Method로 다음 여덟 hook의 순서와 fail-fast 경계를 고정한다.
|
||||
|
||||
| 순서 | Hook | 주요 작업과 생성되는 소유 객체 | 순서/실패 불변식 |
|
||||
`Analysis` base는 procedure-specific protected hook을 정의하지 않고 최소 실행 계약인
|
||||
`Analysis::Run(const AnalysisRequest&)`만 제공한다. 다음 여덟 단계의 순서와 fail-fast
|
||||
경계는 `LinearStaticAnalysis::Run()`의 private lifecycle이며 다른 procedure에 강제되지
|
||||
않는다.
|
||||
|
||||
| 순서 | Private stage | 주요 작업과 생성되는 소유 객체 | 순서/실패 불변식 |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | `initialize(request)` | `.inp` syntax read, semantic map, owned immutable `Domain`, sorted warnings | 이전 run의 dependent object를 역순으로 제거하고 parse/map 실패를 input category로 반환한다. |
|
||||
| 2 | `buildAnalysisModel()` | non-owning `AnalysisModel` view | Domain을 복사하지 않으며 Domain lifetime 안에서만 사용한다. |
|
||||
| 3 | `buildDofMapAndSparsePattern()` | `DofManager`, zero-initialized `AnalysisState` | Stable full/free/constrained numbering과 structural pattern을 한 소유자에게 둔다. |
|
||||
| 4 | `assembleAndPartitionStiffness()` | full CSR K와 `Kff/Kfc/Kcf/Kcc` | Element-local buffer를 deterministic하게 reduce하고 structural zero와 stable order를 보존한다. |
|
||||
| 5 | `factorize()` | retained `Kff` factorization | 모든 load assembly보다 먼저 호출한다. Valid fully constrained model의 `0 x 0 Kff`는 trivial success다. |
|
||||
| 6 | `assembleLoadsAndEffectiveRhs()` | full F와 `Ff-Kfc*dc` | Semantic load source order와 finite sum을 보존하며 solver를 호출하지 않는다. |
|
||||
| 7 | `substituteAndReconstruct()` | free solution과 full displacement | Factorization을 재수행하지 않고 substitution한 뒤 prescribed value를 stable order로 복구한다. |
|
||||
| 8 | `recoverAndWriteResults()` | full residual/reaction, beam rows, final HDF5 | Recovery candidate를 원자적으로 commit하고 writer 성공 뒤에만 최종 output을 교체한다. |
|
||||
| 1 | `Initialize(request)` | `.inp` syntax read, semantic map, owned immutable `Domain`, sorted warnings | 이전 run의 dependent object를 역순으로 제거하고 parse/map 실패를 input category로 반환한다. |
|
||||
| 2 | `BuildAnalysisModel()` | non-owning `AnalysisModel` view | Domain을 복사하지 않으며 Domain lifetime 안에서만 사용한다. |
|
||||
| 3 | `BuildDofMapAndSparsePattern()` | `DofManager`, zero-initialized `AnalysisState` | Stable full/free/constrained numbering과 structural pattern을 한 소유자에게 둔다. |
|
||||
| 4 | `AssembleAndPartitionStiffness()` | full CSR K와 `Kff/Kfc/Kcf/Kcc` | Element-local buffer를 deterministic하게 reduce하고 structural zero와 stable order를 보존한다. |
|
||||
| 5 | `Factorize()` | retained `Kff` factorization | 모든 load assembly보다 먼저 호출한다. Valid fully constrained model의 `0 x 0 Kff`는 trivial success다. |
|
||||
| 6 | `AssembleLoadsAndEffectiveRhs()` | full F와 `Ff-Kfc*dc` | Semantic load source order와 finite sum을 보존하며 solver를 호출하지 않는다. |
|
||||
| 7 | `SubstituteAndReconstruct()` | free solution과 full displacement | Factorization을 재수행하지 않고 substitution한 뒤 prescribed value를 stable order로 복구한다. |
|
||||
| 8 | `RecoverAndWriteResults()` | full residual/reaction, B33/MITC4 rows, final HDF5 | Recovery candidate를 원자적으로 commit하고 writer 성공 뒤에만 최종 output을 교체한다. |
|
||||
|
||||
비선형 정적 및 동적 해석은 V0 범위가 아니며 별도 ADR과 formulation을 승인한 뒤 이
|
||||
lifecycle과 state/equation 계약을 확장한다. 기존 hook 사이에 조용히 반복·증분·시간 적분
|
||||
동작을 삽입하지 않는다.
|
||||
lifecycle과 state/equation 계약을 별도 procedure에 정의한다. LinearStaticAnalysis의
|
||||
private stage 사이에 조용히 반복·증분·시간 적분 동작을 삽입하지 않는다.
|
||||
|
||||
## 설계 패턴
|
||||
- Strategy/Adapter Pattern: 현재 교체 가능한 public 경계는 `LinearSolver`, `ParallelFor`, `ResultsWriter`다. Vendor API는 concrete adapter implementation 안에만 둔다.
|
||||
- Template Method Pattern: `Analysis::run()`은 공통 실행 흐름을 고정하고 세부 단계는 procedure별로 재정의한다.
|
||||
- Strategy/Adapter Pattern: `Analysis::Run(const AnalysisRequest&)`, `LinearSolver`,
|
||||
`ParallelFor`, `ResultsWriter`가 현재 승인된 public 실행/backend 경계다. Vendor API는
|
||||
concrete adapter implementation 안에만 둔다.
|
||||
- Procedure-owned lifecycle: `Analysis`는 protected Template Method hook을 공유하지 않고
|
||||
`LinearStaticAnalysis`가 승인된 여덟 단계 lifecycle을 private하게 소유한다.
|
||||
- Syntax/Semantic separation: `AbaqusInputReader`는 syntax record를 만들고 `AbaqusDomainMapper`가 승인된 keyword 의미를 concrete Domain record로 변환한다.
|
||||
- Runtime Polymorphism: V0에서는 backend 경계에만 사용한다. 요소/재료/하중 base hierarchy와 factory/registry는 두 번째 실제 구현이 필요해질 때 trade-off를 다시 결정한다.
|
||||
- Runtime Polymorphism: backend와 승인된 analysis/element/material/property/load/boundary
|
||||
경계에만 사용한다. Factory compatibility는 중앙에서 fail-closed로 검사하며 global
|
||||
registry 또는 future-only capability를 추가하지 않는다.
|
||||
- RAII: MKL handle, HDF5 file/dataset, temporary solver workspace의 수명과 오류 처리를 wrapper에 묶는다.
|
||||
|
||||
## Sparse Matrix Policy
|
||||
|
||||
Reference in New Issue
Block a user