Files
FESADev/docs/cpp-object-oriented-modular-refactoring

C++ 모듈화와 공개 API 정리

기존 B33/MITC4 솔버의 모델·local 계산·assembly·procedure·backend·I/O 책임을 분리하고 공개 header의 vendor 의존을 격리한 리팩터링이다. 새 물리·입력·해법·결과 schema 또는 tolerance를 도입하는 기능이 아니다. 현재 재사용할 구조·CLI·I/O·수치 비교 계약은 solver-core에 모았다.

설계와 실제 데이터 흐름

Domain은 의미 모델을 소유하고 AnalysisModel은 더 짧게 사는 non-owning view다. DofManager는 equation·partition·pattern을 소유한다. Element의 typed local contribution은 SparseAssembler에서 결정적 순서로 조립된다. LinearStaticProcedureExecutor는 caller-owned 실행/선형해법 adapter를 참조하고 실행에 필요한 state만 만든다. ResultRecovery는 위치·단위·부호를 가진 결과를 복구하고 HDF5 writer는 직렬화한다.

FesaApplication이 객체·lexical output path·lease·실행 수명을 조합한다. 공개 API는 include/fesa/, 구현은 대응 src/fesa/에 두며 vendor handle과 오류 번호는 private 수치/I/O adapter 뒤에 둔다. 공개 API 이름을 예전 .hpp 시절 표기로 복원하거나 parser에서 concrete numerical storage를 직접 소유하지 않는다. Polymorphic base의 public virtual destructor, 단독 소유의 unique_ptr·RAII, self-contained include guard와 source identity를 유지한다.

이 경계는 현재 eigen·dynamic·thermal·solid가 확장한 구조의 기반이다. 당시 static 리팩터링 성공을 나중에 추가된 모든 절차의 재검증으로 해석하지 않는다. 특히 trial/commit과 파일 final replacement는 다른 실패 경계다. 내부 accepted frame이 있어도 전체 해석이 실패하면 미완성 정상 final을 공개하지 않는다.

보존한 입력·출력과 비교 의미

CLI는 입력 .inp 하나, lexical sibling HDF5·log, warning/오류 진단과 exit 의미를 유지했다. B33는 node·element endpoint·section point를, MITC4는 instance/node·element/point identity를 보존한다. 같은 node에 모인 endpoint action을 평균하거나 physical shell strain에 numerical drilling 값을 섞지 않는다. 정적 schema0·canonical frame0의 mandatory dataset·dtype·shape는 리팩터링 편의를 위해 바꾸지 않는다.

현재 수치 비교는 common family의 row5%·RMS1% 및 identity/finite 사전검사를 따른다. 과거 리팩터링 보고서에는 B33 absolute_floor+1e-6*reference_scale와 S4 fixed absolute1e-5로 수행한 당시 비교가 있다. B33176/176행, S4294/294행 통과 기록은 그 옛 기준·revision의 evidence이며 현재 common policy로 다시 판정한 결과가 아니다. Beam stress는 당시 Abaqus 외부 비교 N/A였고 analytical/unit·HDF5 schema evidence와 구분한다.

교훈과 검증 한계

  • Naming·format·header guard·Doxygen와 dependency 경계를 정리해도 displacement만으로 stress/reaction·수명·실패 보존이 증명되지는 않는다. Header 변경은 대응 src consumer까지 함께 확인한다.
  • Dense 크기 곱 overflow는 할당 전에 확인한다. Public API의 Status/Result와 backend exception 변환은 원래 실패 의미를 보존해야 한다.
  • 상속된 환경 변수가 검사 실패의 원인이었던 사례가 있다. 환경 오류와 solver 결함을 구분한다. Formatter의 변경 유무와 native exit, link 성공과 runtime DLL 준비를 따로 판단한다.
  • 과거 실행 절차를 현재 실행 계획으로 복원하지 않는다. CTest와 별도 Python suite의 성공을 합치지 않는다.

이 문서 작업에서는 build/test를 실행하지 않았다. 당시 모듈화와 reference의 bounded 검증은 남기되 최신 전체 회귀·외부 배포 준비 완료를 선언하지 않는다. 현재 물리적 미해결 사항은 각 기능 README가 소유한다.

Refactor 코드 채택 후 구조

2026-10-18 통합은 FESADev 7438c827 이력에 Refactor 11f09eeb의 제품 .h/.cpp 274개와 직접 MSVC 빌드를 선별 도입한다. 옛 구현을 섞는 호환 계층이나 새 정식화는 추가하지 않는다. 파일 manifest는 원본 Git blob과 working bytes, 보존·도입 방침을 구분하고, 테스트 이관표는 양쪽 기존 identity·assertion·oracle와 최종 위치를 연결한다.

  • AnalysisProcedure와 factory는 shell linear/nonlinear static, eigen, HHT, thermal과 solid static/frequency/HHT를 선택한다. 실행 수명은 호출자 adapter보다 짧다. PreparedAnalysisOutcome은 family별 typed completed payload를 유지하고, 결과 dispatch는 검증된 payload를 해당 writer로 보낸다. 기존 schema·atomic finalize 의미는 유지한다.
  • Element capabilities는 ShellTrialElement, SolidTrialElement, ShellInertiaElement, ThermalElement, ShellReferenceElement를 분리한다. Adapter는 immutable kernel을 빌리므로 kernel의 수명과 주소가 안정적이어야 한다. Equation·accepted history는 요소에 두지 않는다. Local layout과 full response를 typed로 보존한다.
  • EquilibriumAlgorithm/EquilibriumStep는 iteration 순서와 procedure-local typed pending candidate를 분리한다. Algorithm은 candidate를 소유하거나 type-erase하지 않는다. Static은1, mechanical HHT는0에서 시작하는 inclusive 순서를 유지하고, procedure의 검증·commit 경계가 accepted state를 바꾼다.
  • ShellHhtIntegrator는 predictor·rate 계산· physical-rate 복원을 분리한다. Chart/root/solver와 callback은 동기 borrowed view이며 rate 출력 buffer는 호출자 소유로 입력·서로와 alias하지 않는다. RunReducedHhtStep은 predictor→pending endpoint→commit 순서만 조정하고 accepted history를 소유하지 않는다.
  • PARDISO Session은 private factor/solve/release 수명을 공통화한다. 기존1×1 TLS 회피의 범위를 vendor 전체 해결로 확대하지 않는다. SparsePattern은 CSR 값 구조이며 지속 backend cache가 아니다. SpMV는 여전히 호출마다 변환 배열·값 복사·handle을 소유한다.

수식·적분·reduction 순서·cache 수명에 영향이 있는 도입 차이는 manifest에 따로 분류했다. 출처 일치·compile·테스트 통과만으로 수치 동등성을 선언하지 않으며 독립 수치 검토와 영향받은 analytical/invariant·물리·reference 검증을 별도로 수행한다.

이번 병합의 현재 검증 상태

직접 MSVC와 CMake/Ninja의 Debug solver/CLI 및 세 테스트 target build가 완료됐다. 제품274개는 Refactor working bytes와 일치한다. 양쪽 실제 discovery는 unit849, integration72, reference43으로 총964개이며 canonical identity가 일치한다. 최종 선별 실행은 CMake176개, Native15개, 합성 reference comparator28개, Python145개가 failure/error/skip 없이 통과했다. 이는 전체964개 실행·실제 모델 비교 완료가 아니다. 근거는 작업 공간의 .build/merge-verification/t2-20261018-01/와 t3-20261018-01/에 있다. 원래 dev와 Refactor 저장소 및 기준자료는 보존했다.

2026-10-18 사용자 지시로 reference/temp는 검증에 사용하지 않는다. 정식 경로에 없는 shellNL-meshfine, shellNL-meshfine_02, shellNL-meshfine-pressure 자료는 복사·복원하지 않는다. 해당 실제 비교는 자료 미확보로 미완료이며 테스트를 skip 처리하거나 통과로 바꾸지 않는다. 전체 Debug 검증·독립 수치 검토·정식 자료의 필수 비교는 후속 실행 대상이다. 정리 전 필수 검증을 충족하지 못하면 테스트 삭제와 최종 병합 완료 판정을 진행하지 않는다. 문서 갱신 자체로 build/test를 추가 실행하지 않았다.