16 KiB
FESA C++ Object-Oriented Modular Refactoring Design
상태
- 설계 대화 승인: 2026-08-16
- 서면 spec 리뷰: 승인 완료 (2026-08-16)
- 구현 상태: 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는 변경하지 않는다.
추상 계층과 소유권
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에 강제하지 않는다.
class Analysis {
public:
virtual ~Analysis() = default;
virtual Status Run(const AnalysisRequest& request) = 0;
};
현재 승인 순서는 LinearStaticAnalysis::Run()의 private 단계로 유지한다.
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을 사용한다.
모듈 구조
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를 부분 변경하지 않는다.
단계적 마이그레이션
- 기존 unit/integration/reference 및 HDF5 contract baseline을 기록하고 architecture ADR을 갱신한다.
.clang-format, header rename/guard와 PascalCase를 module slice별 mechanical change로 적용한다.Vector3, ASCII utility, SourceTargetResolver, DOF invariant validation과 private BLAS adapter를 도입한다.- Domain semantic hierarchy와 current concrete material/property/load/boundary type을 연결한다.
- Element runtime hierarchy와 factory를 DofManager, SparseAssembler와 ResultRecovery에 연결한다.
- Ordered load contribution과 essential constraint policy를 연결한다.
- Minimal Analysis base와 LinearStaticAnalysis-owned lifecycle로 전환한다.
- 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 /WXbuild와 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에 변경이 없다.