Integrate Hex8 mass verification and fixed-null-basis shell dynamics with numerical and physics handoff evidence. Preserve interrupted reference and full-validation status; full integration validation is deferred until after performance optimization.
23 KiB
HHT I/O 계약
- 상태:
reduced-shell-schema-v2-approved; implementation-and-readback-pending, 2026-10-12. 기존 v1 계약은 아래에 이력으로 보존한다. - Owner:
io-definition-agent. 메인 인계로 새 procedure의 아래 공개 subset/schema를 확정한다. 물리·수치 기준의 원본은 formulation, inertia, numerical-controls다. - 기준: AGENTS, 프로젝트 PRD, 공통 ADR, ARCHITECTURE, Feature PRD, Feature ADR. 기존 문서의
I/O pending은 본 계약 이전 상태다.
현재 승인 계약과 과거 계약의 구분
2026-10-12 사용자는 실제 shell의 reduced-coordinate HHT 구현·검증과, 채택 시 public full A를 진단용 filter combination으로 표시하는 shell schema v2를 승인했다. 새 shell 결과의 권위 계약은 reduced-coordinate I/O이며, 아래 §1–2의 입력·identity·physical quantity와 §3–4의 dataset inventory·비교 mapping을 해당 문서의 변경사항과 함께 적용한다. 아래 schema_version=1 및 predictor-driver A 의미는 과거 full-coordinate shell 결과의 계약이다. v1 파일과 당시 evidence를 보존하며 v2 결과로 재표시하지 않는다.
v2는 shell HHT에 한정한다. Solid HHT, static, eigen 결과와 입력 subset·질량·시간 schedule·source identity·U/UR tolerance는 변경하지 않는다. 계약 승인과 writer/readback/reference 검증 완료는 구분한다.
1. 입력과 호환성
기존 비선형 I/O의 lexical parsing, source target resolution, part/identity instance, node/set, S4/S4R → FESA-MITC4, centered homogeneous shell, isotropic elastic material, geometry와 chart 검증을 상속한다. 아래 절차 차이만 dynamic에 적용한다. 기존 static/frequency 입력·결과의 의미나 schema는 바꾸지 않는다. Source S4/S4R 표기는 보존하며 Abaqus 내부 요소·관성·시간 알고리즘 동등성을 주장하지 않는다. 공개 Abaqus 관례의 근거는 이미 조사한 research의 관측 가능한 입력 의미에 한정한다.
| 구문 | 이번 지원 의미 / 검증 |
|---|---|
*STEP, NAME=<name>, NLGEOM=YES, INC=<integer> |
한 step만 허용. NAME은 기존 규칙, 생략 시 Step-1; NLGEOM=YES 필수. INC 생략값 100, 명시값 양의 uint32. INC는 시간 increment 상한이며 Newton 반복 상한이 아님 |
*DYNAMIC, DIRECT |
step의 첫 procedure. DIRECT는 값 없는 flag, 다른 parameter는 거부. ALPHA/BETA/GAMMA, APPLICATION, INITIAL, EXPLICIT, 자동 증분은 미지원 |
data h,T 또는 h,T, |
정확히 한 row, 두 finite positive 값. h≤T. N=round(T/h)가 uint32 범위의 양의 정수이고 double(N)*h == T, N≤INC일 때만 허용. 중간 누적 덧셈·끝 증분 단축·time tolerance 없음. 그 밖의 nonempty field/row 거부 |
*DENSITY 아래 rho 또는 rho, |
활성 material마다 정확히 한 finite positive density; temperature/dependency/추가 field 미지원. 질량 단위는 force*time^2/length, density는 force*time^2/length^4. Frequency의 기존 허용 유지, static에 새 허용하지 않음 |
*BOUNDARY |
모델 앞 또는 procedure 뒤/하중 앞. 기존 target, DOF 1–6 범위; magnitude 생략 또는 exact 0. 전체 시간에 q/v/a/A constrained 성분 exact 0. 초기 q/v와 충돌하는 값, AMPLITUDE/OP/TYPE/변경 경계 거부 |
| partial zero BC | component selector 의미를 그대로 보존. 전 DOF clamp/free 필수 지원, 부분구속은 N4 analytic null과 free 공간 교집합 사용. Rank-changing branch/regularity 실패는 오류이며 부분구속을 full clamp로 바꾸지 않음 |
*CLOAD |
step 내 global dead force DOF 1–3만 허용. finite magnitude; 동일 resolved node/DOF의 여러 row는 source order로 합산. DOF 4–6은 값이 0이어도 미지원. AMPLITUDE/FOLLOWER/OP 및 모델-level 하중 미지원 |
*PREPRINT, ECHO=NO, MODEL=NO, HISTORY=NO, CONTACT=NO |
정확한 flags, data 없음: ignored-output-request warning. 출력 제어 효과 없음 |
*RESTART, WRITE, FREQUENCY=0 |
data 없는 이 조합만 warning no-op. Restart 생성·읽기 지원 아님 |
*OUTPUT, FIELD, VARIABLE=PRESELECT, FREQUENCY=1 |
data 없음. HISTORY도 같은 조합 허용, FIELD/HISTORY 둘 중 하나. FREQUENCY 생략도 1 의미로 수용. 요청마다 warning no-op; FESA 필수 전 frame 출력을 바꾸지 않음 |
*NODE OUTPUT, *ELEMENT OUTPUT 등 child selectors와 다른 OUTPUT parameter/frequency는 미지원이다. 원본 INP는 위 root 요청만 사용한다. 초기조건 keyword, amplitude, damping, distributed/follower load, contact, 비탄성, 다른 dynamic 요소, 다중 step/restart는 fail closed다. 기존 shell section의 source integration-point field 5는 기존 allowlisted warning 의미를 유지하며 FESA 관성 적분 선택이 아니다.
공개 계수는 기본 alpha=-0.05,beta=0.275625,gamma=0.55만 제공한다. Internal 검증용 alpha=0은 formulation의 결합계수로 실행할 수 있으나 INP 지원 확대가 아니다. 2026-10-11 사용자 승인에 따라 HHT 질량은 nodal-lumped-kinetic이다. rho*N_i*dV0의 절점별 운동에너지 측도로 M, I, c, 관성 접선, kinetic energy와 physical momentum/rates를 일관되게 계산한다. 이는 shell 회전 관성을 포함한 절점 block이며 scalar diagonal 질량이나 Hex8의 full reference matrix row-sum을 뜻하지 않는다. 질량 선택 keyword/API는 추가하지 않는다. 초기 frame은 0+, q0=v0=0, F0=F*, A0=a0이며 physical a0와 null 일관성은 N3에 따라 구한다. 하중은 이후 모든 endpoint에도 전값이다.
2. Identity, 시간, state 경계
Canonical storage slot은 /steps/Step-1이다. 실제 source name을 별도 source_step_name에 저장한다. Reference의 실제 name은 Step-1이다. Instance는 기존 ASCII case-insensitive canonical identity와 raw label text를 보존하고, logical label은 positive int64다. Internal node/element ID와 equation ID를 source label 대신 사용하지 않는다.
N increments의 완성 결과는 frame 0..N, increment 0..N을 각각 한 번 포함한다. Frame n의 time=double(n)*h, frame0=+0, is_initial=(n==0)이며 n≥1에서 시간이 strictly increasing해야 한다. 종료시각은 T와 exact 일치한다. Frame0 iteration_count=0; 이후 0..100 corrections, 초기 추정 수렴/empty free solve는 0 허용. INC에 frame0는 포함하지 않는다. Original h=.1,T=10,INC=1000은 N=100/101 frames다.
Domain이 dynamic semantic 정의를 소유한다. AnalysisModel은 non-owning view, DofManager는 full/free/constraint mapping을 소유한다. State vector의 node-major 6성분은 [u1,u2,u3,phi1,phi2,phi3]이며 node inventory는 Domain 선언 순서다. Rotation은 fixed-initial global total rotation-vector chart다. Trial은 committed state/history와 alias되지 않는다. Candidate의 time, q/v/a/A, orientation, force, recovery와 evidence가 모두 검증된 뒤 한 번에 commit한다. Failure는 마지막 committed frame과 history를 보존하며 failed/trial frame을 노출하지 않는다.
구현 인계용 C++ 경계
이는 backend-neutral 경계이며 vendor type을 포함하지 않는다. Default-constructed record는 구성 중 candidate일 뿐 유효한 완료 state가 아니다.
struct DynamicStepDefinition {
std::string source_step_name_raw, source_step_name_canonical;
SourceLocation step_location, dynamic_location, data_location;
double initial_increment = 0.0, time_period = 0.0;
std::uint32_t increment_count = 0, maximum_increments = 100;
double alpha = -0.05, beta = 0.275625, gamma = 0.55;
std::vector<PrescribedDisplacementDefinition> boundaries;
std::vector<NodalLoad> loads;
};
struct DynamicAcceptedFrameState {
std::uint32_t frame_index = 0, increment_index = 0, iteration_count = 0;
double time = 0.0;
bool is_initial = false;
std::vector<EntityIndex> nodal_internal_order;
std::vector<SourceEntityId> nodal_source_ids;
Vector generalized_coordinates, velocity, acceleration;
Vector algorithmic_acceleration; // Each 6*N; physical a != auxiliary A.
std::vector<std::array<std::array<double, 3>, 3>> nodal_triad;
std::vector<std::array<double, 3>> nodal_director;
Vector angular_velocity, angular_acceleration; // Each 3*N, spatial.
Vector inertia_force, internal_force, external_force, residual, reaction;
Vector residual_scale; // Each 6*N, N2 uncancelled per-row scale.
std::vector<ShellResultRow> shell_results;
double kinetic_energy = 0.0, physical_strain_energy = 0.0;
double drilling_energy = 0.0, external_work = 0.0, energy_defect = 0.0;
std::array<double, 6> global_equilibrium{};
std::array<double, 3> linear_momentum{}, angular_momentum{};
std::array<double, 3> linear_momentum_rate{}, angular_momentum_rate{};
std::array<double, 2> free_residual_metrics{}; // u, phi channels.
Vector hidden_constraint, hidden_velocity_defect, hidden_acceleration_defect;
Vector hidden_constraint_scale, hidden_velocity_defect_scale;
Vector hidden_acceleration_defect_scale; // Each analytic null count nz.
};
ModelDefinition.dynamic_step:optional<DynamicStepDefinition>, StepDefinition::IsDynamic(), StepDefinition::Dynamic() 및 Domain::Dynamic() accessor를 추가한다. Dynamic과 static/frequency 정의는 상호배타적이다. DynamicAnalysisState::Create(const Domain&,const DofManager&):Result<DynamicAnalysisState>는 immutable inventory/schedule을 검증한다. 기본 empty 구성이 가능하되 Create 전 commit/실행/Write를 거부한다. BeginTrialFromCommitted():Result<DynamicAcceptedFrameState>는 deep copy, CommitAcceptedFrame(const DynamicAcceptedFrameState&):Status는 강한 실패 보존, DiscardTrial():void는 caller-owned trial 폐기를 위한 no-op이다. AcceptedFrames():const vector<DynamicAcceptedFrameState>&, CommittedState():const DynamicAcceptedFrameState&를 제공한다. Frame0는 Create 후 완성하여 같은 commit 검사를 통과해야 한다. 첫 commit 전 CommittedState 읽기는 금지다. Full q6N이 authority이며 displacement/rotation state를 중복 소유하지 않는다.
DynamicExecutionResult { DynamicAnalysisState state; vector<Diagnostic> diagnostics; }를 PreparedAnalysisOutcome에 추가하고 별도 dynamic executor를 dispatch한다. DynamicResultsWriter::Write(const filesystem::path&, const Domain&, const DynamicAnalysisState&, const vector<Diagnostic>&):Status 및 DynamicHdf5ResultsWriter를 추가한다. Existing static writer에 time 또는 static load_factor로 dynamic을 위장하지 않는다.
Momentum/rates는 전체 두께 volume kinetic kinematics로 구한 physical quantities, 원점 O=(0,0,0)에 대한 global angular momentum이다. Chart generalized momentum을 spatial angular momentum으로 표시하지 않는다. global_equilibrium은 N6의 applied+support minus momentum-rate이며 current arms와 spatial moments를 사용한다. Hidden vectors는 N3의 raw ψ/1차/2차 defects, _scale는 그 항별 uncancelled norm scale다. n_z=0은 empty vector, empty free channel metric 저장값 0은 해당 constraint inventory와 함께 N/A로 해석한다. NaN sentinel을 사용하지 않는다. Hidden 1·2차 defect는 진단/시간수렴 대상이며 Newton 수렴 기준으로 임의 승격하지 않는다.
3. 과거 full-coordinate shell HDF5 schema v1
공식 경로는 input lexical sibling <stem>_results.h5, CLI/lock/log/atomic file lifecycle은 기존 I/O §7.1을 상속한다. Dynamic log는 nsnr-log-v1 또는 target_factor를 사용하지 않는다. 기존 log stream에 dynamic diagnostic을 기록할 경우 record=dynamic-newton-iteration, schema=hht-log-v1, increment/time/iteration/stage와 N2 metric의 raw numerator/scale/branch/pass를 명시한다. 정적 전용 tolerance를 재사용하지 않는다.
Schema identity는 (feature_id,analysis_procedure,schema_version)다. /metadata attribute: feature_id=hht-implicit-dynamics, analysis_procedure=hht-implicit-dynamics, schema_version:uint64=1, mass_formulation=nodal-lumped-kinetic, internal_formulation=FESA-MITC4-total-lagrangian, initial_state=zero-q-v-step-load-0+, acceleration_convention=physical-endpoint-and-auxiliary-separated, source_step_name, step_name=Step-1, alpha/beta/gamma:float64, initial_increment/time_period:float64, increment_count/maximum_increments:uint64. 기존 solver_version/source_input_identity/unit_system_label도 필수, 단위 label은 consistent-input-units이며 SI로 추정하지 않는다.
이번 승인은 mass_formulation의 공개 값과 그 물리 의미를 변경한다. Dataset path/field/shape/dtype 및 schema_version=1은 유지한다. 과거 consistent-kinetic 결과 파일은 당시 계산의 evidence로 보존하며 현재 계약의 reader/self-check/comparator에서는 mass identity mismatch로 실패한다. Metadata만 바꾸어 과거 결과를 재사용하거나 같은 schema_version을 같은 mass 의미로 간주하지 않는다. 입력·출력 identity와 단위·component·reference projection, 승인 tolerance 및 HHT 계수는 그대로다. 기존 MITC4 고유치의 nodal block lumped 정책은 변경하지 않는다.
모든 numeric data는 finite-first, float64=IEEE binary64 little-endian, integer는 fixed width little-endian, string은 UTF-8 variable length다. Mandatory datasets는 contiguous/uncompressed. 아래 N=nodes, E=elements, F=Nincrements+1이다. Paths의 <n>은 leading-zero 없는 decimal ordinal이다.
Model schema는 기존 I/O §7.3의 /model/nodes, /model/elements, /model/shell/materials, /model/shell/sections, /model/shell/nodal_director, /model/shell/nodal_frame, /model/nodal_constraint_mask, /model/shell/midsurface_locations, /model/shell/section_positions의 정확한 dtype/shape/identity를 재사용한다. /model/prescribed_displacement_start/target은 dynamic에서 쓰지 않는다. 추가 /model/prescribed_displacement:[N,6] float64는 전값 0, /model/material_density:[material_count] compound는 internal_material_id:uint64,rho:float64로 materials 행 순서다. 활성 material의 rho는 finite positive다.
/steps/Step-1/accepted_frames:[F] compound fields는 frame_index:uint64,increment_index:uint64,time:float64,iteration_count:uint64,is_initial:uint8. Table의 시간과 모든 frame attrs가 일치해야 한다. Load factor는 없다.
각 /steps/Step-1/frames/<n> 아래 필수 dataset은 다음과 같다.
| 상대 path | shape, dtype | component / 의미 / 차원 |
|---|---|---|
nodal/displacement |
[N,6] float64 | UX,UY,UZ,URX,URY,URZ; q; length×3,1×3 (UR는 rad) |
nodal/velocity |
[N,6] float64 | V1,V2,V3,PHIDOT1,PHIDOT2,PHIDOT3; chart v; length/time×3,1/time×3 |
nodal/acceleration |
[N,6] float64 | A1,A2,A3,PHIDDOT1,PHIDDOT2,PHIDDOT3; physical chart a; length/time²×3,1/time²×3 |
nodal/algorithmic_acceleration |
[N,6] float64 | AUX1,AUX2,AUX3,AUX4,AUX5,AUX6; auxiliary A; a와 같은 차원 |
nodal/angular_velocity |
[N,3] float64 | OMEGA1,OMEGA2,OMEGA3; J_l(phi) phidot; 1/time |
nodal/angular_acceleration |
[N,3] float64 | OMEGADOT1,OMEGADOT2,OMEGADOT3; J_l phiddot+DJ_l[phidot]phidot; 1/time² |
nodal/triad, nodal/director |
[N,3,3], [N,3] float64 | 기존 current triad/director 의미, axis row A,B,D / global XYZ |
nodal/generalized_inertia_force |
[N,6] float64 | I=M(q)a+c(q,v), physical endpoint |
nodal/generalized_internal_force |
[N,6] float64 | physical+objective drilling internal force |
nodal/generalized_external_force |
[N,6] float64 | F*, frame0에도 full value |
nodal/generalized_residual |
[N,6] float64 | E=I+f_int-F, free와 constrained 전체 |
nodal/generalized_reaction |
[N,6] float64 | constrained selector를 E에 적용, free 성분 exact zero |
nodal/reaction |
[N,6] float64 | RF1,RF2,RF3,RM1,RM2,RM3; support-on-structure; moment=J_l^-T generalized reaction |
element/shell/local_frame |
[E,4,3,3] float64 | 기존 GP1..4, local axes E1,E2,E3 |
element/shell/generalized_strain |
[E,4,8] float64 | 기존 E11,E22,G12,K11,K22,K12,G13,G23 |
element/shell/section_resultant |
[E,4,8] float64 | 기존 N11,N22,N12,M11,M22,M12,Q13,Q23 |
element/shell/stress |
[E,4,3,3] float64 | 기존 BOTTOM,MIDDLE,TOP × S11,S22,S12 |
global/energy |
[5] float64 | KINETIC_ENERGY,PHYSICAL_STRAIN_ENERGY,DRILLING_ENERGY,EXTERNAL_WORK,ENERGY_DEFECT; 모두 force*length |
global/equilibrium |
[6] float64 | FORCE_1..3,MOMENT_1..3; N6 관성 포함 balance error |
Generalized force 계열 component_names=F1,F2,F3,MPHI1,MPHI2,MPHI3, units=force,force,force,force*length,force*length,force*length, coordinate_system=fixed-initial-global-chart. Spatial U/omega/reaction은 global-cartesian; q/v/a/A는 translation global 및 rotation chart임을 rotation_representation=total-rotation-vector-chart와 quantity_semantics로 명시한다. Shell units, local_frame/source_element_type/midsurface/section_position 참조 attrs는 기존 I/O §7.5 그대로다. Numerical drill force를 physical shell stress/resultant에 섞지 않는다.
모든 result dataset에 schema_version, component_names, component_unit_dimensions, coordinate_system, location, step_name, source_step_name, frame_index, increment_index, time, is_initial attr를 쓴다. Scalar numeric attrs는 위 dtype, flags uint8이다. Location은 nodal, shell 기존 location, global/global-balance-error다. 모든 nodal row는 /model/nodes, element row는 /model/elements 행을 참조한다.
Energy의 W=F*ᵀ(qn-q0), defect=T+Uphys+Udrill-E0-W다. Initial physical energy E0는 frame0의 첫 세 성분 합이며 W0/defect0=0. A를 kinetic energy나 physical inertia에 쓰지 않는다. Algorithmic dissipation을 physical damping energy로 이름 붙이지 않는다. Raw momentum/hidden diagnostics는 위 internal frame의 필수 evidence이며 이번 persistent schema에는 별도 필수 dataset을 추가하지 않는다. HDF5에서 계산할 수 없는 상세 검증은 실행 보고서가 internal evidence를 기록한다.
/diagnostics는 기존 diagnostic의 의미·dtype·정렬을 재사용하되 dynamic compound field 이름을 severity/code/source_file/source_line/keyword/entity_identity/message로 명시한다. 기존 static writer의 file/line 이름은 이 dynamic schema에 적용하지 않는다. Writer는 전체 frames/node/element inventory, dtype/rank/component/attrs/time/finite/constraint, complete final frame를 검사하고 write/flush/close/reopen/self-check 후 원자 replace한다. 기존 final file은 실패 시 보존한다. Live log의 이미 flush된 prefix는 rollback하지 않는다. No-op warning이 있어도 필수 dataset을 생략할 수 없다.
4. 진단과 비교 binding
기존 Diagnostic의 severity/code/location/keyword/entity_identity/message를 사용하며 SortDiagnostics 순서 유지. 위치는 가능한 source keyword/data row, runtime에서는 step+increment와 node/element source identity를 message/entity_identity에 포함한다. Parser/model/output/backend의 기존 FailureCategory/CLI exit mapping을 유지하고 새 exit code를 만들지 않는다.
| code | 발생 조건 |
|---|---|
unsupported-dynamic-parameter |
DIRECT 외 dynamic parameter, 잘못된 flag, 계수 입력 |
invalid-dynamic-data |
h/T/nonfinite/arity/범위 오류 |
invalid-dynamic-schedule |
N*h≠T, N>INC, uint32 초과, 시간 비증가 |
unsupported-dynamic-boundary |
비영/시간변화/BC option |
unsupported-dynamic-load |
CLOAD4–6, follower/amplitude/distributed load |
invalid-density-data |
누락/중복/nonpositive/비상수 density; 기존 code 재사용 |
unsupported-analysis-procedure, unsupported-multiple-step, unsupported-keyword |
잘못된 procedure/NLGEOM, 다중 step, allowlist 밖 의미 |
ignored-output-request |
위 정확한 allowlisted no-op만 warning |
dynamic-initial-consistency, dynamic-mass-regularity |
N3 초기화/숨은 조건 또는 N4 rank/positive block/regularity 실패 |
dynamic-nonconvergence, dynamic-linear-solve |
N2 correction 한도 또는 solve/backward-error 실패 |
dynamic-invalid-state, dynamic-output-schema |
chart/geometry/nonfinite/inventory/update 또는 저장/재독 계약 위반 |
기존 geometry/backend code가 더 구체적이면 보존하며 위 code로 감싸 원래 source context를 버리지 않는다. 질량 singularity 자체는 오류가 아니다. Formulation에 정의된 허용 null을 제거하거나 epsilon mass를 주지 않는다.
Reference 계약의 source step/instance/node/increment/time/component authority를 그대로 적용한다. Binding: /model/nodes의 (instance_name,source_label)와 frame table을 조인하고 nodal/displacement[:,0:3]→U-U1/U2/U3, [:,3:6]→UR-UR1/UR2/UR3. 먼저 전체 729-node 101-frame identity/finite 검사를 수행하고 고정 9-node subset으로 projection한다. Decimal CSV time=n/10 검증과 binary HDF5 time=double(n)*double(.1) 검증을 각각 수행한다. Nearest-time/보간/평균/row-index matching은 금지다. Wrong procedure/mass/coefficient/초기 convention, missing/extra/duplicate/nonfinite는 tolerance 전에 실패다. Frame별 U blocking/UR warning-only 202 families와 공통 TOLERANCE는 변경하지 않는다.
5. 인계 및 확인 상태
2026-10-11 질량 정책 변경의 I/O 계약을 반영했다. 새 mass identity에 대한 production write/readback와 원본 비교는 메인이 새 실행 evidence로 확인해야 하며, 아래 최초 계약 정의 당시의 상태나 과거 consistent 결과를 현재 통과로 승계하지 않는다.
입력 원본의 procedure/density/BC/CLOAD/output 요청과 기존 semantic/prepared_analysis/state/writer 경계를 대조했다. 이번 변경은 이 문서뿐이며 source/test/reference artifact는 수정하지 않았다. 문서 링크와 diff를 정적 검사한다. Build/test·dynamic HDF5 readback·reference 비교는 문서 owner의 작업이 아니므로 미실행이다.
상위 물리 선택 충돌은 없다. 구현에 아직 필요한 upstream quantity는 별도 Udrill energy, exact inertia/kinetic energy, spatial rates, physical momentum/rates, N2 uncancelled per-row scale 및 N3 hidden defects다. 기존 nonlinear recovery가 Uphys만 반환한다는 이유로 Udrill=0 또는 누락으로 바꾸면 안 된다. 메인은 이 문서를 main report에서 연결하고 공개 subset/schema 결정 근거를 Feature ADR에 기록한다. 이 계약 정의만으로 solver/physics gate가 통과한 것은 아니다.