Python内核代码移除,建模界面缩放bug修复

This commit is contained in:
ljz committed 2026-09-10 11:57:39 +08:00
1 parent 743663e3a6
commit 0dcb465d84
27 files changed
+354 -6092

No files matched your search

+2
View File
@@ -14,4 +14,6 @@
旧 Python 积分器、数值组件方法和固定算例专用求解器已经退役。旧 `/api/reactflow/simulate-testmodel`、`/api/reactflow/simulate-test-mql` 返回 410;使用 `/api/system-xml/simulate` 或流式接口。
旧 `ir/` 包、专属 schema、规范与测试已删除。当前 C 生成器直接使用经过校验的网络结构,不依赖旧 System IR v2。
运行、支持范围与依赖见 [C 后端说明](../../native/README.md)。模型开发规则见 [组件规范](../../docs/standard/component-model-authoring-spec-v1.md)。历史性能、Amesim 差异和旧公式说明位于 `docs/other/` 及 Git 历史,不能作为当前运行入口。
-40
View File
@@ -1,40 +0,0 @@
"""Whole-system numeric intermediate representation."""
from .compiler import compile_system_ir
from .schema import * # noqa: F403 - this package is the public schema facade.
from .schema import __dict__ as _schema_namespace
from .validation import (
IRValidationIssue,
IRValidationReport,
SystemIRValidationError,
require_valid_system_ir,
validate_system_ir,
)
__all__ = [
"compile_system_ir",
"IRValidationIssue",
"IRValidationReport",
"SystemIRValidationError",
"require_valid_system_ir",
"validate_system_ir",
*sorted(
name
for name in _schema_namespace
if name.startswith("IR")
or name.startswith("SystemIR")
or name.startswith("SYSTEM_NUMERIC_IR")
or name
in {
"CURRENT_SYSTEM_IR_VERSION",
"NATIVE_NUMERIC_ABI_VERSION",
"canonical_json_bytes",
"native_artifact_key",
"operation_read_slots",
"operation_write_slots",
}
),
]
del _schema_namespace
-14
View File
@@ -1,14 +0,0 @@
"""Retired object-engine IR adapter; the independent v2 schema is retained.
Current native execution is generated by native_codegen.compile_native_program.
It does not yet emit the separate System IR v2 execution-plan format.
"""
def compile_system_ir(*args, **kwargs):
"""Fail explicitly for callers of the removed GenericFluidSystem adapter."""
raise NotImplementedError(
"The GenericFluidSystem to System IR v2 exporter was retired with the Python "
"numerical engine. Use native_codegen.compiler.compile_native_program(network) "
"for the current C executable path. System IR v2 schema and validation remain available."
)
-973
View File
@@ -1,973 +0,0 @@
"""Callback-free data contract for the whole-system numeric IR.
System IR v2 describes a compiled simulation model. It is intentionally a
pure, immutable data graph: Python functions, model objects, object addresses,
and run-local diagnostic state are not part of this module's wire contract.
"""
from __future__ import annotations
from dataclasses import dataclass, fields, is_dataclass
from enum import StrEnum
from hashlib import sha256
import json
from math import isfinite
from struct import pack
from typing import ClassVar
from unicodedata import normalize
SYSTEM_NUMERIC_IR_SCHEMA_ID = "system-numeric-ir"
SYSTEM_NUMERIC_IR_SCHEMA_MAJOR = 2
SYSTEM_NUMERIC_IR_SCHEMA_MINOR = 0
SYSTEM_NUMERIC_IR_COMPILER_ID = "generic-fluid-system"
SYSTEM_NUMERIC_IR_COMPILER_VERSION = "2.0.0"
NATIVE_NUMERIC_ABI_VERSION = 1
class IRDType(StrEnum):
FLOAT64 = "float64"
INT32 = "int32"
class IRBufferKind(StrEnum):
TIME = "time"
STATE_INPUT = "state_input"
DERIVATIVE_OUTPUT = "derivative_output"
LOCAL_STATE = "local_state"
LOCAL_DERIVATIVE = "local_derivative"
ALGEBRAIC = "algebraic"
SIGNAL = "signal"
PARAMETER = "parameter"
CONSTANT = "constant"
MODE = "mode"
WORK_FLOAT = "work_float"
WORK_INT = "work_int"
EVENT_OUTPUT = "event_output"
JACOBIAN_VALUE = "jacobian_value"
RESULT_OUTPUT = "result_output"
RUNTIME_INPUT = "runtime_input"
class IRKernelPhase(StrEnum):
PRIMAL = "primal"
RESIDUAL = "residual"
DERIVATIVE = "derivative"
PROPERTY = "property"
EVENT = "event"
RESET = "reset"
JACOBIAN = "jacobian"
OUTPUT = "output"
class IRKernelAvailability(StrEnum):
NATIVE = "native"
REFERENCE_ONLY = "reference_only"
class IRPortKind(StrEnum):
PHYSICAL = "physical"
SIGNAL = "signal"
class IRPortNominalRole(StrEnum):
INLET = "inlet"
OUTLET = "outlet"
BIDIRECTIONAL = "bidirectional"
INPUT = "input"
OUTPUT = "output"
class IRPositiveFlowDirection(StrEnum):
INTO_COMPONENT = "intoComponent"
class IRVariableRole(StrEnum):
EFFORT = "effort"
FLOW = "flow"
STREAM = "stream"
SIGNAL = "signal"
class IRConnectionRule(StrEnum):
EQUAL = "equal"
SUM_TO_ZERO = "sumToZero"
STREAM_MIX = "streamMix"
DIRECTED = "directed"
class IREquationOwner(StrEnum):
COMPONENT = "component"
CONNECTION = "connection"
class IREquationRelation(StrEnum):
EQUAL = "equal"
SUM_TO_ZERO = "sumToZero"
CONSTITUTIVE = "constitutive"
STATE = "state"
class IRPressureFlowScopeKind(StrEnum):
NETWORK = "network"
PHYSICAL_ISLAND = "physical_island"
EQUATION_BLOCK = "equation_block"
class IRStageKind(StrEnum):
STATE_REDUCE = "state_reduce"
SIGNAL = "signal"
MECHANICAL_EQUIVALENCE = "mechanical_equivalence"
DYNAMIC_VOLUME = "dynamic_volume"
PROPERTY = "property"
PRESSURE_FLOW = "pressure_flow"
STREAM = "stream"
TEMPERATURE_REFERENCE = "temperature_reference"
THERMOFLUID_FIXED_POINT = "thermofluid_fixed_point"
MECHANICAL_ACCELERATION = "mechanical_acceleration"
DERIVATIVE_REDUCE = "derivative_reduce"
EVENT = "event"
JACOBIAN = "jacobian"
OUTPUT = "output"
RESET = "reset"
class IREntryPointKind(StrEnum):
RHS = "rhs"
EVENTS = "events"
JACOBIAN = "jacobian"
OUTPUTS = "outputs"
class IRBlockKind(StrEnum):
SEQUENCE = "sequence"
FIXED_POINT = "fixed_point"
STREAM_SCC = "stream_scc"
class IRStepKind(StrEnum):
STAGE = "stage"
BLOCK = "block"
class IRStateMapKind(StrEnum):
SCATTER = "scatter"
DERIVATIVE_GATHER = "derivative_gather"
class IREventDirection(StrEnum):
DECREASING = "decreasing"
ANY = "any"
INCREASING = "increasing"
class IRFailurePolicy(StrEnum):
FAIL = "fail"
RETRY_SMALLER_STEP = "retry_smaller_step"
class IRCacheKind(StrEnum):
PROPERTY = "property"
PRESSURE_FLOW = "pressure_flow"
STREAM = "stream"
JACOBIAN = "jacobian"
OUTPUT = "output"
class IRCapabilityLevel(StrEnum):
NATIVE = "native"
REFERENCE_ONLY = "reference_only"
UNSUPPORTED = "unsupported"
class IRDiagnosticSeverity(StrEnum):
INFO = "info"
WARNING = "warning"
ERROR = "error"
class IROpcode(StrEnum):
FILL = "fill"
COPY = "copy"
SCATTER = "scatter"
LINEAR_COMBINATION = "linear_combination"
STATE_MAP = "state_map"
KERNEL_CALL = "kernel_call"
EFFORT_BROADCAST = "effort_broadcast"
FLOW_ASSIGN = "flow_assign"
CHECK_FINITE = "check_finite"
@dataclass(frozen=True, slots=True)
class IRSchemaVersion:
schema_id: str = SYSTEM_NUMERIC_IR_SCHEMA_ID
major: int = SYSTEM_NUMERIC_IR_SCHEMA_MAJOR
minor: int = SYSTEM_NUMERIC_IR_SCHEMA_MINOR
CURRENT_SYSTEM_IR_VERSION = IRSchemaVersion()
@dataclass(frozen=True, slots=True)
class IRSlotRef:
buffer: IRBufferKind
index: int
@dataclass(frozen=True, slots=True)
class IRBufferSpec:
kind: IRBufferKind
dtype: IRDType
size: int
initial_float_values: tuple[float, ...] = ()
initial_int_values: tuple[int, ...] = ()
@dataclass(frozen=True, slots=True)
class IRValueSpec:
value_id: str
slot: IRSlotRef
semantic: str
role: str
quantity: str
unit: str
scale: float
lower_bound: float | None = None
upper_bound: float | None = None
owner_component_index: int | None = None
@dataclass(frozen=True, slots=True)
class IRKernelPhaseSpec:
"""Phase capability tag; each call's ordered slot lists define its C-01 ABI.
Fixed component-kernel signatures deliberately belong to the C-02 contract.
Recording placeholder arities here would make the current reference-only
kernels look more strictly specified than they are.
"""
phase: IRKernelPhase
@dataclass(frozen=True, slots=True)
class IRKernelSpec:
kernel_id: str
model_type: str
model_version: str
implementation_version: str
availability: IRKernelAvailability
unavailable_reason: str | None
phases: tuple[IRKernelPhaseSpec, ...]
parameter_count: int
state_count: int
mode_count: int
workspace_float_count: int
workspace_int_count: int
@dataclass(frozen=True, slots=True)
class IRComponentInstance:
instance_id: str
kernel_index: int
parameter_slots: tuple[IRSlotRef, ...]
state_slots: tuple[IRSlotRef, ...]
derivative_slots: tuple[IRSlotRef, ...]
mode_slots: tuple[IRSlotRef, ...]
port_indices: tuple[int, ...]
port_slots: tuple[IRSlotRef, ...]
output_indices: tuple[int, ...]
workspace_float_slots: tuple[IRSlotRef, ...]
workspace_int_slots: tuple[IRSlotRef, ...]
@dataclass(frozen=True, slots=True)
class IRPortVariable:
variable_id: str
name: str
role: IRVariableRole
connection_rule: IRConnectionRule
quantity: str
unit: str
result_visible: bool
slot: IRSlotRef
@dataclass(frozen=True, slots=True)
class IRPortSpec:
port_id: str
component_index: int
name: str
kind: IRPortKind
domain: str
nominal_role: IRPortNominalRole
positive_flow_direction: IRPositiveFlowDirection | None
variables: tuple[IRPortVariable, ...]
@dataclass(frozen=True, slots=True)
class IRConnectionVariable:
name: str
rule: IRConnectionRule
endpoint_a_slot: IRSlotRef
endpoint_b_slot: IRSlotRef
@dataclass(frozen=True, slots=True)
class IRConnectionSpec:
connection_id: str
kind: IRPortKind
domain: str
endpoint_a_port_index: int
endpoint_b_port_index: int
variables: tuple[IRConnectionVariable, ...]
@dataclass(frozen=True, slots=True)
class IRMediumSpec:
medium_id: str
name: str
implementation_id: str
implementation_version: str
parameter_slots: tuple[IRSlotRef, ...]
component_indices: tuple[int, ...]
@dataclass(frozen=True, slots=True)
class IRCSRPattern:
row_count: int
column_count: int
row_pointers: tuple[int, ...]
column_indices: tuple[int, ...]
@property
def nonzero_count(self) -> int:
return len(self.column_indices)
@dataclass(frozen=True, slots=True)
class IRCSRMatrix:
pattern: IRCSRPattern
values: tuple[float, ...]
@dataclass(frozen=True, slots=True)
class IRStateReducer:
solver_state_count: int
local_state_slots: tuple[IRSlotRef, ...]
raw_derivative_slots: tuple[IRSlotRef, ...]
state_scatter: IRCSRMatrix
derivative_gather: IRCSRMatrix
initial_state: tuple[float, ...]
absolute_tolerances: tuple[float, ...]
@dataclass(frozen=True, slots=True)
class IRFillOperation:
opcode: ClassVar[IROpcode] = IROpcode.FILL
target_slots: tuple[IRSlotRef, ...]
value: float
@dataclass(frozen=True, slots=True)
class IRCopyOperation:
opcode: ClassVar[IROpcode] = IROpcode.COPY
source_slot: IRSlotRef
target_slot: IRSlotRef
@dataclass(frozen=True, slots=True)
class IRScatterOperation:
opcode: ClassVar[IROpcode] = IROpcode.SCATTER
source_slot: IRSlotRef
target_slots: tuple[IRSlotRef, ...]
@dataclass(frozen=True, slots=True)
class IRLinearCombinationOperation:
opcode: ClassVar[IROpcode] = IROpcode.LINEAR_COMBINATION
source_slots: tuple[IRSlotRef, ...]
weights: tuple[float, ...]
target_slot: IRSlotRef
bias: float = 0.0
@dataclass(frozen=True, slots=True)
class IRStateMapOperation:
opcode: ClassVar[IROpcode] = IROpcode.STATE_MAP
map_kind: IRStateMapKind
source_slots: tuple[IRSlotRef, ...]
target_slots: tuple[IRSlotRef, ...]
@dataclass(frozen=True, slots=True)
class IRKernelCallOperation:
opcode: ClassVar[IROpcode] = IROpcode.KERNEL_CALL
kernel_index: int
component_index: int | None
phase: IRKernelPhase
read_slots: tuple[IRSlotRef, ...]
write_slots: tuple[IRSlotRef, ...]
equation_indices: tuple[int, ...] = ()
@dataclass(frozen=True, slots=True)
class IREffortBroadcastOperation:
opcode: ClassVar[IROpcode] = IROpcode.EFFORT_BROADCAST
variable: str
anchor_slot: IRSlotRef
residual_slot: IRSlotRef
result_slot: IRSlotRef
scatter_slots: tuple[IRSlotRef, ...]
equation_id: str
lower_bound: float | None = None
upper_bound: float | None = None
@dataclass(frozen=True, slots=True)
class IRFlowAssignmentOperation:
opcode: ClassVar[IROpcode] = IROpcode.FLOW_ASSIGN
value_slot: IRSlotRef
result_slot: IRSlotRef
scatter_slots: tuple[IRSlotRef, ...]
equation_id: str
@dataclass(frozen=True, slots=True)
class IRCheckFiniteOperation:
opcode: ClassVar[IROpcode] = IROpcode.CHECK_FINITE
slots: tuple[IRSlotRef, ...]
error_code: str
IROperation = (
IRFillOperation
| IRCopyOperation
| IRScatterOperation
| IRLinearCombinationOperation
| IRStateMapOperation
| IRKernelCallOperation
| IREffortBroadcastOperation
| IRFlowAssignmentOperation
| IRCheckFiniteOperation
)
def operation_read_slots(operation: IROperation) -> tuple[IRSlotRef, ...]:
if isinstance(operation, IRFillOperation):
return ()
if isinstance(operation, (IRCopyOperation, IRScatterOperation)):
return (operation.source_slot,)
if isinstance(operation, (IRLinearCombinationOperation, IRStateMapOperation)):
return operation.source_slots
if isinstance(operation, IRKernelCallOperation):
return operation.read_slots
if isinstance(operation, IREffortBroadcastOperation):
return (operation.anchor_slot, operation.residual_slot)
if isinstance(operation, IRFlowAssignmentOperation):
return (operation.value_slot,)
if isinstance(operation, IRCheckFiniteOperation):
return operation.slots
raise TypeError(f"Unsupported IR operation: {type(operation).__name__}.")
def operation_write_slots(operation: IROperation) -> tuple[IRSlotRef, ...]:
if isinstance(operation, IRFillOperation):
return operation.target_slots
if isinstance(operation, IRCopyOperation):
return (operation.target_slot,)
if isinstance(operation, IRScatterOperation):
return operation.target_slots
if isinstance(operation, IRLinearCombinationOperation):
return (operation.target_slot,)
if isinstance(operation, IRStateMapOperation):
return operation.target_slots
if isinstance(operation, IRKernelCallOperation):
return operation.write_slots
if isinstance(operation, IREffortBroadcastOperation):
return (operation.result_slot, *operation.scatter_slots)
if isinstance(operation, IRFlowAssignmentOperation):
return (operation.result_slot, *operation.scatter_slots)
if isinstance(operation, IRCheckFiniteOperation):
return ()
raise TypeError(f"Unsupported IR operation: {type(operation).__name__}.")
@dataclass(frozen=True, slots=True)
class IRStage:
stage_id: str
kind: IRStageKind
operations: tuple[IROperation, ...]
declared_read_slots: tuple[IRSlotRef, ...]
declared_write_slots: tuple[IRSlotRef, ...]
@dataclass(frozen=True, slots=True)
class IRStepRef:
kind: IRStepKind
index: int
@dataclass(frozen=True, slots=True)
class IRConvergenceSpec:
monitor_slots: tuple[IRSlotRef, ...]
absolute_tolerance: float
relative_tolerance: float
max_iterations: int
relaxation: float
rollback_slots: tuple[IRSlotRef, ...]
failure_policy: IRFailurePolicy
@dataclass(frozen=True, slots=True)
class IRExecutionBlock:
block_id: str
kind: IRBlockKind
steps: tuple[IRStepRef, ...]
convergence: IRConvergenceSpec | None = None
@dataclass(frozen=True, slots=True)
class IREntryPoint:
kind: IREntryPointKind
steps: tuple[IRStepRef, ...]
input_slots: tuple[IRSlotRef, ...]
output_slots: tuple[IRSlotRef, ...]
@dataclass(frozen=True, slots=True)
class IRCausalEffortStageRef:
variable: str
stage_index: int
@dataclass(frozen=True, slots=True)
class IRCausalPlan:
plan_id: str
scope_component_indices: tuple[int, ...]
source_schema_version: int
source_structural_signature: str | None
fallback_reason: str | None
canonical_slots: tuple[IRSlotRef, ...]
compatibility_slots: tuple[IRSlotRef, ...]
reset_slots: tuple[IRSlotRef, ...]
external_effort_slots: tuple[IRSlotRef, ...]
effort_stages: tuple[IRCausalEffortStageRef, ...]
flow_stage_indices: tuple[int, ...]
@dataclass(frozen=True, slots=True)
class IRAlgebraicUnknown:
unknown_id: str
component_index: int
port_index: int
variable: str
role: IRVariableRole
slot: IRSlotRef
scale: float
lower_bound: float | None = None
upper_bound: float | None = None
@dataclass(frozen=True, slots=True)
class IRPressureFlowEquation:
equation_id: str
owner: IREquationOwner
owner_index: int
relation: IREquationRelation
role: IRVariableRole | None
variable_slots: tuple[IRSlotRef, ...]
residual_slot: IRSlotRef
scale: float
@dataclass(frozen=True, slots=True)
class IRPressureFlowBlock:
block_id: str
unknown_indices: tuple[int, ...]
equation_indices: tuple[int, ...]
jacobian_pattern: IRCSRPattern
@dataclass(frozen=True, slots=True)
class IRPressureFlowScope:
scope_id: str
kind: IRPressureFlowScopeKind
component_indices: tuple[int, ...]
unknown_indices: tuple[int, ...]
equation_indices: tuple[int, ...]
block_indices: tuple[int, ...]
causal_plan_index: int | None
residual_tolerance: float
max_evaluations: int
sparse_pattern_trusted: bool
sparse_fallback_reason: str | None
@dataclass(frozen=True, slots=True)
class IRPressureFlowPlan:
unknowns: tuple[IRAlgebraicUnknown, ...]
equations: tuple[IRPressureFlowEquation, ...]
blocks: tuple[IRPressureFlowBlock, ...]
scopes: tuple[IRPressureFlowScope, ...]
global_scope_index: int
secondary_scope_indices: tuple[int, ...]
pressure_lower_bound: float
@dataclass(frozen=True, slots=True)
class IRStreamSCC:
scc_id: str
node_slots: tuple[IRSlotRef, ...]
block_index: int
@dataclass(frozen=True, slots=True)
class IRStreamEdge:
source_scc_index: int
target_scc_index: int
@dataclass(frozen=True, slots=True)
class IRStreamPlan:
plan_id: str
node_slots: tuple[IRSlotRef, ...]
strongly_connected_components: tuple[IRStreamSCC, ...]
condensed_edges: tuple[IRStreamEdge, ...]
topological_scc_indices: tuple[int, ...]
@dataclass(frozen=True, slots=True)
class IRThermofluidPlan:
physical_port_indices: tuple[int, ...]
global_component_indices: tuple[int, ...]
stream_plan_index: int
secondary_pressure_scope_indices: tuple[int, ...]
sensitive_component_indices: tuple[int, ...]
maximum_iterations: int
flow_relative_tolerance: float
uses_conservative_global_solver: bool
conservative_fallback_reason: str | None
@dataclass(frozen=True, slots=True)
class IRTransactionPlan:
snapshot_slots: tuple[IRSlotRef, ...]
flow_slots: tuple[IRSlotRef, ...]
cache_component_indices: tuple[int, ...]
cache_attribute_ids: tuple[str, ...]
diagnostic_owner_ids: tuple[str, ...]
restores_on_recoverable_failure: bool
restores_on_fatal_failure: bool
@dataclass(frozen=True, slots=True)
class IRModeValueSpec:
value: int
name: str
@dataclass(frozen=True, slots=True)
class IRModeSpec:
mode_id: str
slot: IRSlotRef
owner_component_indices: tuple[int, ...]
values: tuple[IRModeValueSpec, ...]
initial_value: int
@dataclass(frozen=True, slots=True)
class IRFiniteDifferenceColumn:
column_index: int
value_indices: tuple[int, ...]
relative_step: float
@dataclass(frozen=True, slots=True)
class IRJacobianPlan:
pattern: IRCSRPattern
value_slots: tuple[IRSlotRef, ...]
color_groups: tuple[tuple[int, ...], ...]
fill_steps: tuple[IRStepRef, ...]
analytic_value_indices: tuple[int, ...]
local_finite_difference_columns: tuple[IRFiniteDifferenceColumn, ...]
@dataclass(frozen=True, slots=True)
class IRModeGuard:
mode_slot: IRSlotRef
allowed_values: tuple[int, ...]
@dataclass(frozen=True, slots=True)
class IREventSpec:
event_id: str
event_kind: str
owner_component_indices: tuple[int, ...]
root_slot: IRSlotRef
direction: IREventDirection
terminal: bool
priority: int
mode_guards: tuple[IRModeGuard, ...]
reset_steps: tuple[IRStepRef, ...]
invalidated_caches: tuple[IRCacheKind, ...]
restarts_integrator: bool
@dataclass(frozen=True, slots=True)
class IROutputSpec:
output_id: str
component_index: int
scope: str
port_name: str | None
name: str
label: str
category: str
quantity: str
unit: str
order: int
source_slot: IRSlotRef
output_slot: IRSlotRef
scale: float = 1.0
offset: float = 0.0
@dataclass(frozen=True, slots=True)
class IRComponentCapability:
component_index: int
level: IRCapabilityLevel
supported_phases: tuple[IRKernelPhase, ...]
missing_features: tuple[str, ...]
@dataclass(frozen=True, slots=True)
class IRCapabilityIssue:
code: str
severity: IRDiagnosticSeverity
scope_id: str
message: str
@dataclass(frozen=True, slots=True)
class IRCapabilityReport:
system_level: IRCapabilityLevel
components: tuple[IRComponentCapability, ...]
issues: tuple[IRCapabilityIssue, ...]
@dataclass(frozen=True, slots=True)
class SystemIR:
version: IRSchemaVersion
model_id: str
model_version: str
compiler_id: str
compiler_version: str
numeric_dtype: IRDType
buffers: tuple[IRBufferSpec, ...]
values: tuple[IRValueSpec, ...]
kernels: tuple[IRKernelSpec, ...]
components: tuple[IRComponentInstance, ...]
mediums: tuple[IRMediumSpec, ...]
ports: tuple[IRPortSpec, ...]
connections: tuple[IRConnectionSpec, ...]
state_reducer: IRStateReducer
causal_plans: tuple[IRCausalPlan, ...]
pressure_flow: IRPressureFlowPlan
stream_plans: tuple[IRStreamPlan, ...]
thermofluid: IRThermofluidPlan
stages: tuple[IRStage, ...]
blocks: tuple[IRExecutionBlock, ...]
entry_points: tuple[IREntryPoint, ...]
transaction: IRTransactionPlan
modes: tuple[IRModeSpec, ...]
jacobian: IRJacobianPlan
events: tuple[IREventSpec, ...]
outputs: tuple[IROutputSpec, ...]
capabilities: IRCapabilityReport
required_features: tuple[str, ...] = ()
def canonical_json_bytes(self) -> bytes:
return canonical_json_bytes(self)
def calculate_structural_signature(self) -> str:
return sha256(self.canonical_json_bytes()).hexdigest()
@property
def structural_signature(self) -> str:
return self.calculate_structural_signature()
@dataclass(frozen=True, slots=True)
class IRNativeBuildIdentity:
abi_version: int
target_triple: str
compiler_id: str
compiler_version: str
compile_flags: tuple[str, ...]
floating_point_policy: str
kernel_library_signature: str
@dataclass(frozen=True, slots=True)
class _IRNativeArtifactKeyInput:
program_signature: str
build: IRNativeBuildIdentity
_CANONICAL_TYPE_NAMES: tuple[tuple[type[object], str], ...] = (
(IRSchemaVersion, "schema_version"),
(IRSlotRef, "slot_ref"),
(IRBufferSpec, "buffer"),
(IRValueSpec, "value"),
(IRKernelPhaseSpec, "kernel_phase"),
(IRKernelSpec, "kernel"),
(IRComponentInstance, "component"),
(IRPortVariable, "port_variable"),
(IRPortSpec, "port"),
(IRConnectionVariable, "connection_variable"),
(IRConnectionSpec, "connection"),
(IRMediumSpec, "medium"),
(IRCSRPattern, "csr_pattern"),
(IRCSRMatrix, "csr_matrix"),
(IRStateReducer, "state_reducer"),
(IRFillOperation, "operation"),
(IRCopyOperation, "operation"),
(IRScatterOperation, "operation"),
(IRLinearCombinationOperation, "operation"),
(IRStateMapOperation, "operation"),
(IRKernelCallOperation, "operation"),
(IREffortBroadcastOperation, "operation"),
(IRFlowAssignmentOperation, "operation"),
(IRCheckFiniteOperation, "operation"),
(IRStage, "stage"),
(IRStepRef, "step_ref"),
(IRConvergenceSpec, "convergence"),
(IRExecutionBlock, "block"),
(IREntryPoint, "entry_point"),
(IRCausalEffortStageRef, "causal_effort_stage"),
(IRCausalPlan, "causal_plan"),
(IRAlgebraicUnknown, "algebraic_unknown"),
(IRPressureFlowEquation, "pressure_flow_equation"),
(IRPressureFlowBlock, "pressure_flow_block"),
(IRPressureFlowScope, "pressure_flow_scope"),
(IRPressureFlowPlan, "pressure_flow_plan"),
(IRStreamSCC, "stream_scc"),
(IRStreamEdge, "stream_edge"),
(IRStreamPlan, "stream_plan"),
(IRThermofluidPlan, "thermofluid_plan"),
(IRTransactionPlan, "transaction_plan"),
(IRModeValueSpec, "mode_value"),
(IRModeSpec, "mode"),
(IRFiniteDifferenceColumn, "finite_difference_column"),
(IRJacobianPlan, "jacobian_plan"),
(IRModeGuard, "mode_guard"),
(IREventSpec, "event"),
(IROutputSpec, "output"),
(IRComponentCapability, "component_capability"),
(IRCapabilityIssue, "capability_issue"),
(IRCapabilityReport, "capability_report"),
(SystemIR, "system_ir"),
(IRNativeBuildIdentity, "native_build"),
(_IRNativeArtifactKeyInput, "native_artifact_key_input"),
)
_OPERATION_TYPES = (
IRFillOperation,
IRCopyOperation,
IRScatterOperation,
IRLinearCombinationOperation,
IRStateMapOperation,
IRKernelCallOperation,
IREffortBroadcastOperation,
IRFlowAssignmentOperation,
IRCheckFiniteOperation,
)
def _canonical_type_name(value: object) -> str:
value_type = type(value)
for candidate, name in _CANONICAL_TYPE_NAMES:
if value_type is candidate:
return name
raise TypeError(f"Unsupported IR schema object: {value_type.__name__}.")
def _canonical_float(value: float) -> object:
numeric = float(value)
if not isfinite(numeric):
raise ValueError("Canonical IR JSON does not permit NaN or infinity.")
if numeric == 0.0:
numeric = 0.0
return {"$float64": pack(">d", numeric).hex()}
def _canonical_value(value: object) -> object:
if value is None or isinstance(value, bool):
return value
if isinstance(value, StrEnum):
return value.value
if isinstance(value, int):
return value
if isinstance(value, float):
return _canonical_float(value)
if isinstance(value, str):
return normalize("NFC", value)
if isinstance(value, tuple):
return [_canonical_value(item) for item in value]
if is_dataclass(value) and not isinstance(value, type):
payload: dict[str, object] = {"$type": _canonical_type_name(value)}
if isinstance(value, _OPERATION_TYPES):
payload["opcode"] = value.opcode.value
for item in fields(value):
payload[item.name] = _canonical_value(getattr(value, item.name))
return payload
raise TypeError(
"Canonical IR JSON accepts only schema dataclasses, tuples, enums, and "
f"scalar values; received {type(value).__name__}."
)
def canonical_json_bytes(value: object) -> bytes:
"""Return the exact platform-independent canonical JSON byte sequence."""
return json.dumps(
_canonical_value(value),
ensure_ascii=True,
allow_nan=False,
sort_keys=True,
separators=(",", ":"),
).encode("utf-8")
def native_artifact_key(
program: SystemIR,
build: IRNativeBuildIdentity,
) -> str:
"""Build cache key; target details never contaminate the program hash."""
if build.abi_version != NATIVE_NUMERIC_ABI_VERSION:
raise ValueError(
"Native build ABI does not match NATIVE_NUMERIC_ABI_VERSION."
)
for field_name, value in (
("target_triple", build.target_triple),
("compiler_id", build.compiler_id),
("compiler_version", build.compiler_version),
("floating_point_policy", build.floating_point_policy),
):
if not value:
raise ValueError(f"Native build {field_name} must not be empty.")
if any(not flag for flag in build.compile_flags):
raise ValueError("Native build flags must not contain empty entries.")
if (
len(build.kernel_library_signature) != 64
or any(
character not in "0123456789abcdef"
for character in build.kernel_library_signature
)
):
raise ValueError(
"Native kernel library signature must be lowercase SHA-256 hex."
)
payload = _IRNativeArtifactKeyInput(program.structural_signature, build)
return sha256(canonical_json_bytes(payload)).hexdigest()
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -280,7 +280,7 @@ def _compile_storage_anchored_program(network: SimulationNetwork) -> NativeProgr
put(c, "port_3.h_outflow", get(a, "h"))
for pname in ("port_2", "port_3"):
other = adjacent[c.name, pname]
# A resistance-to-resistance stream path requires a fuller IR.
# Resistance-to-resistance streams need the extended pressure/enthalpy closure.
if network.components[other[0]] not in chambers:
raise NativeCapabilityError(f"{c.name}: native v1 requires valve ports directly connected to storage.")
lines.append(f"{w(f'{other[0]}.{other[1]}.m_flow')} = -{get(c, pname + '.m_flow')};")