18 KiB
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 검증을 별도로 수행한다.
이번 병합의 현재 검증 상태
T2/T3 단계에서 직접 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 검증·독립 수치 검토·정식 자료 비교의 현재 진행은 아래 T5 중간 기록과 구분한다.
정리 전 필수 검증을 충족하지 못하면 테스트 삭제와 최종 병합 완료 판정을 진행하지 않는다.
T4 문서 갱신 자체로 build/test를 추가 실행하지 않았다.
T5 최초 중간 snapshot — 2026-10-18 03:00 UTC, 이후 범위 변경 전 이력
2026-10-18에 전체 Native Debug 솔루션, CMake Debug configure/build와 Ninja dependency
검사를 새로 실행해 모두 exit0을 확인했다. 제품102 compile unit의 dependency가 유효하고,
양쪽 세 테스트 executable의 실제 identity는 unit849·integration72·reference43,
CTest964개로 일치한다. Public header111개는 각각 독립 TU로 private/vendor include 경로 없이
MSVC C++17 /EHsc /W4 /WX /MDd /Zs 검사를 통과했다. CLI·test의 네 runtime 디렉터리에서
DLL7개의 SHA256이 같다. 제품274개와 정식 reference32개 bytes도 중간 기록 전에 재확인했다.
reference/temp의12개 경로는 byte 검증 대상에서 제외했고 입력·CSV·결과를 사용하지 않았다.
Native unit 전체는 필터 없이 계속 실행 중이며 전체 종료 코드와 XML은 아직 없다. 중간 stdout에서 완료57개 identity를 관측했으며 다음 개별 검사는 새로 PASS 종료했다.
ReducedManufacturedControllerKeepsExactInitialOrbit: 396862ms.C08aRigidManufacturedOrbitReducedCoordinateTimeConvergence: 7-grid, 7153515ms.C08bInitialPhysicalSpectrumProbe: 716ms.PredictorStartCompletesPreviouslyFailingLumpedFreePlateGrid: 539678ms.
현재 C08bFreeFiniteRotationPlateSelfConvergenceAndPhysicalInvariants의8-grid를 수행한다.
h=1/64·1/128·1/256·1/512·1/1024의 계산 요약이 생성됐으나 남은8192·16384·32768증분
fine-grid와 최종 시간수렴·물리 gate는 미완료다. 모든 grid의 총 증분수는57840이다.
CPU/RSS 상승이나 부분 로그를 전체 통과 근거로 삼지 않는다. Native 나머지 executable,
전체 CTest와 Python suite는 같은 직렬 큐에서 대기하며 임의 timeout·skip·필터를 추가하지 않았다.
Refactor 원본 밖 별도 source snapshot304개에서 Native Debug 기준 solver/CLI를 새로 빌드해 exit0과 DLL7개 일치를 확인했다. 정적5모델을 포함한 정식 입력11개에 대해 기준·Native· CMake 실행물을 같은 scratch 입력 경로와 bytes에서 직렬 실행하고 schema·identity·각 field를 대조하는 후속 큐를 준비했다. 새 실제 모델 실행·비교는 아직 시작하지 않았다. 보고서 JSON의 case·policy·quantity와 실제 exit를 확인하며, parity의 빈 결과·자료 부재·dtype 차이·불일치는 nonzero로 남긴다. Exact field assertion의 불일치를 새 물리 허용치 위반으로 승격하지 않고 출처·dtype·identity·rounding 차이를 분류한 뒤 기존 승인 기준과 대조한다. 임시 도구의 합성 증거 하한 검사9건은 솔버나 물리 검증 통과가 아니다. 빈 결과·자료 누락의 옛 false-green을 각각 exit0으로 재현하고 수정 후 exit1·exit2가 되는 것을 확인했다.
독립 수치 검토는 명백한 식 오류나 승인 기준 변경을 발견하지 못했으나 CONCERNS다.
inverse→factor solve·Jet·eigen whitening·paired 산술과 spatial RM 변환은 rounding graph에
영향이 있어 비트 보존을 가정하지 않는다. 특히 hdf5_primitives.cpp, dynamic/nonlinear HDF5
writer의 J^T m=g LU action은 T2 영향 routing 누락을 T5 manifest에 보충하고 finite-rotation
virtual-work·완전 inverse action·HDF5 reaction readback 검사 identity에 연결했다.
이 정적 검토를 실제 전체 실행·reference closure의 승인으로 해석하지 않는다.
정식 shellNL-meshfine·shellNL-meshfine-pressure는 자료 미확보로 미실행이고,
shellNL-meshfine_02는 자료 부재와 현재 comparator 연결 부재를 함께 남긴다.
Thermal 새 필수 reference 부재와 기존 NT11 diagnostic/nonblocking 불일치도 유지한다.
필수 gate를 충족하지 않았으므로 테스트 삭제·T6 진입·최종 병합 완료 판정을 진행하지 않는다.
중간 근거는 .build/merge-verification/t5-20261018-01/before-prune/에 있으며
running-checkpoint.json과 progress.jsonl이 실행 큐·PID·현재 관측을 보존한다.
파일 manifest의 t5_before_prune_verification은 이 중간 snapshot을 기록하며 T1/T2/T3 원필드는 보존했다.
T5 사용자 승인 정적 범위 — 검증 완료, 제한 유지
사용자는 장시간 HHT 동해석 검증을 중단하고 정적 해석 검증 후 다음 단계로 진행하도록
범위를 변경했다. 위 최초 snapshot의 전체 큐·미완료 gate 설명은 당시 이력이다. 현재는
HHT·solid dynamic·eigen/frequency·transient thermal 실제 수치 실행을 유예하고 해당 테스트를
보존한다. 기존 전체 큐와 후속 watcher는 user_cancelled_static_only로 종료했으며,
부분 stdout·미생성 XML·취소 근거를 보존했다. 이를 수치 실패나 통과로 계산하지 않는다.
현재964개 identity를 source body·경로·행·SHA256에 대응시켜 정적·공통631개(unit555,
integration35, reference41)를 선택하고333개를 유예했다. 과거 정적553개는 분류 근거로만
읽었으며 그중11개를 유예하고 현재 추가 공통89개를 포함했다. 순수 SO3 미분·좌표변환,
mock 수명·dispatch, parser/mapping 및 합성 comparator 정책 검사는 포함하고 실제 비정적
procedure를 호출하는 검사는 제외했다. 선택표는 before-prune/static-only/selection.json에 있다.
새 직렬 실행은 Native·CMake의 선택631개, 명시적 목록 CTest631개 및 Python 합성·정책
검사다. 고유 C++ 검사 수는631개이며 실행 경로별 수를 합쳐 고유 검사 수로 보고하지 않는다.
Native·CMake 각631개 및 CTest631개가 실제 exit0·skip0으로 확인됐다. Native/CMake의
unit555·reference41은 처음 실행에서 통과했고 integration35는 아래 환경 대조 후 전부 통과했다.
CTest JUnit의 실제 이름을 canonical identity로 역매핑해 선택631개와 누락·중복0을 확인했다.
Python 합성·정책145개도 exit0·failure/error/skip0이며 실제 비정적 물리 검증으로 세지 않는다.
정식 정적5모델도 fresh Refactor 기준·통합 Native·통합 CMake에서 같은 scratch 입력 bytes/경로로
총15번 실행했고 등록 비교15개·보고서 검증15개·schema/identity/field parity5개가 모두 exit0이다.
추가 정식 shellNL 자료의 부재와 _02 comparator 연결 부재는 미완료로 유지하며, 확보된
정적 범위의 gate가 충족되면 다음 단계로 진행할 수 있다는 사용자 지시를 따른다.
임시 parity 도구의0길이 dataset만 있는 파일 false-green도 실제 exit0으로 재현했다.
필수 inventory와 파일 전체의 비어있지 않은 data 검사를 추가한 도구는 같은 경우 exit1,
의미있는 합성 동일값 exit0·불일치 exit1을 보였다. 개별0길이 dataset은 허용한다.
이는 임시 도구 검증이며 제품 물리·reference 통과를 대신하지 않는다. 현재 근거 경로는
.build/merge-verification/t5-20261018-01/before-prune/static-only/run-20261018-01/이다.
정적 모델의 beam은 U/UR·RF/RM·section actions6가족212행, shell은 U blocking·UR warning-only
2가족294행을 기존 기준으로 비교했다. ShellNL은 translation blocking·rotation warning-only와
내부 force/moment balance·accepted free residual을 통과했다. RF/RM3가족의 수치 비교는
false/review-only로 보존하며 stress mapping은 여전히 미판정이다. Hex8 선형·비선형 정적은
각 Step-1/increment10의 U(length)·RF(force)·S(force/length²)를 원본 CSV·source identity와
기존5%/1% 기준으로 비교했다. 개별 quantity/frame/policy·원본/실행물/결과 hash 및 literal
argv/cwd/env는 manifest와 raw final-static-summary.json·각 closed execution record에 있다.
초기 Native/CMake integration에서는 같은 application 검사1개가 각각 output-busy로 실패했다. Native 실패 lock 경로261자, CMake260자였으며 동일 Native exe·동일 identity에서 TMP/TEMP만 바꾼 대조가 긴 경로 exit1→짧은 task-owned 경로 exit0을 보였다. 짧은 고유 TMP에서 양쪽 integration35개 전체를 다시 실행해 identity35·exit0·failure/error/skip0을 확인했다. 원래 실패 XML/log와 최초 큐 aggregate exit1은 환경/경로 한계로 보존했다. 제품·테스트·허용치는 바꾸지 않았다. 모델 input/result/lock 길이도 사전 확인했으며 최대193자다.
독립 정적 수치 보충 검토는 CONCERNS / required_static_missing=false다. 선택631개의
정적 수치 필수 coverage 누락은 발견하지 못했으며, 이를 RF/RM·stress mapping 또는 유예
기능의 물리 승인으로 확대하지 않는다. 사용자 수정 범위의 정리 전 정적 gate는 충족했으므로
다음 단계로 진행할 수 있다. 비정적333개·누락 정식 fine/_02/pressure 비교·열해석 새 reference
부재와 기존 NT11 diagnostic 제한은 미완료로 유지한다. 테스트 정리·최종 병합은 아직 수행하지 않았다.