完成仿真系统IR-schema规定
This commit is contained in:
1 parent
03b86f52ba
commit
ce353d2dd2
8 files changed
+5949
-4
No files matched your search
@@ -0,0 +1,40 @@
|
||||
"""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
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,973 @@
|
||||
"""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
Reference in new issue
Block a user