{ "$schema": "http://json-schema.org/draft-07/schema#", "title": "ScenarioConfig", "description": "Root configuration for a simulation scenario.", "type": "object", "required": [ "fluid" ], "properties": { "circuits": { "description": "Circuit configurations.", "default": [], "type": "array", "items": { "$ref": "#/definitions/CircuitConfig" } }, "connections": { "description": "External connections between instance ports (and/or literal `component:port` endpoints). Resolved and routed into the appropriate circuit during flattening.", "default": [], "type": "array", "items": { "$ref": "#/definitions/EdgeConfig" } }, "controls": { "description": "Steady-state control loops (co-solved saturated-PI controllers).", "default": [], "type": "array", "items": { "$ref": "#/definitions/ControlConfig" } }, "fluid": { "description": "Fluid name (e.g., \"R134a\", \"R410A\", \"R744\").", "type": "string" }, "fluid_backend": { "description": "Fluid backend to use (e.g., \"CoolProp\", \"Test\"). Defaults to \"Test\".", "default": null, "type": [ "string", "null" ] }, "instances": { "description": "Instantiations of `subsystems` templates. Each instance is expanded into concrete, name-prefixed components/edges in its target circuit.", "default": [], "type": "array", "items": { "$ref": "#/definitions/InstanceConfig" } }, "metadata": { "description": "Optional metadata.", "default": null, "type": [ "object", "null" ], "additionalProperties": true }, "name": { "description": "Scenario name.", "default": null, "type": [ "string", "null" ] }, "schema_version": { "description": "Model IR schema version (`\"1\"` legacy flat graph, `\"2\"` adds controls/subsystems/instances/connections). Absent ⇒ `\"1\"`.", "default": "1", "type": "string" }, "solver": { "description": "Solver configuration.", "default": { "max_iterations": 100, "strategy": "fallback", "timeout_ms": 0, "tolerance": 1e-6, "verbose": false }, "allOf": [ { "$ref": "#/definitions/SolverConfig" } ] }, "subsystems": { "description": "Reusable subsystem templates (parameterized assemblies of components + internal edges, exposing a reduced external port set). Flattened into `circuits` at load time — the solver never sees the hierarchy.", "default": {}, "type": "object", "additionalProperties": { "$ref": "#/definitions/SubsystemTemplate" } }, "thermal_couplings": { "description": "Thermal couplings between circuits.", "default": [], "type": "array", "items": { "$ref": "#/definitions/ThermalCouplingConfig" } } }, "definitions": { "ActuatorConfig": { "description": "Reference to a manipulated actuator on a component.", "type": "object", "required": [ "component", "factor", "max", "min" ], "properties": { "component": { "description": "Name of the component carrying the actuator.", "type": "string" }, "factor": { "description": "Calibration Z-factor to manipulate: `z_flow`, `z_dp`, `z_ua`, `z_power`, or `z_etav` (BOLT `Z_flow_suc`, `Z_dpc`, `Z_UA`, `Z_power`; legacy `f_*` names accepted).", "type": "string" }, "initial": { "description": "Initial actuator value (nominal, e.g. 1.0).", "default": 1.0, "type": "number", "format": "double" }, "max": { "description": "Upper bound for the actuator.", "type": "number", "format": "double" }, "min": { "description": "Lower bound for the actuator.", "type": "number", "format": "double" } } }, "CircuitConfig": { "description": "Configuration for a single circuit.", "type": "object", "required": [ "components" ], "properties": { "components": { "description": "Components in this circuit.", "type": "array", "items": { "$ref": "#/definitions/ComponentConfig" } }, "edges": { "description": "Edge connections between components.", "default": [], "type": "array", "items": { "$ref": "#/definitions/EdgeConfig" } }, "id": { "description": "Circuit ID (default: 0).", "default": 0, "type": "integer", "format": "uint", "minimum": 0.0 }, "initial_state": { "description": "Initial state for edges.", "default": null, "anyOf": [ { "$ref": "#/definitions/InitialStateConfig" }, { "type": "null" } ] } } }, "ComponentConfig": { "description": "Configuration for a component.", "type": "object", "required": [ "name", "type" ], "properties": { "air_inlet_temp_c": { "description": "Air inlet temperature in Celsius.", "default": null, "type": [ "number", "null" ], "format": "double" }, "condenser_bank": { "description": "Condenser bank spec identifier (used for creating multiple instances).", "default": null, "anyOf": [ { "$ref": "#/definitions/CondenserBankConfig" }, { "type": "null" } ] }, "fan_speed": { "description": "Fan speed ratio (0.0 to 1.0).", "default": null, "type": [ "number", "null" ], "format": "double" }, "n_air_exponent": { "description": "Air side heat transfer exponent.", "default": null, "type": [ "number", "null" ], "format": "double" }, "name": { "description": "Component name for referencing in edges.", "type": "string" }, "type": { "description": "Component type (e.g., \"Compressor\", \"Condenser\", \"Evaporator\", \"ExpansionValve\", \"HeatExchanger\").", "type": "string" }, "ua_nominal_kw_k": { "description": "Nominal UA value (kW/K). Maps to ua_nominal_kw_k.", "default": null, "type": [ "number", "null" ], "format": "double" } }, "additionalProperties": true }, "CondenserBankConfig": { "description": "Configuration for a condenser bank (multi-circuit, multi-coil).", "type": "object", "required": [ "circuits", "coils_per_circuit" ], "properties": { "circuits": { "description": "Number of circuits.", "type": "integer", "format": "uint", "minimum": 0.0 }, "coils_per_circuit": { "description": "Number of coils per circuit.", "type": "integer", "format": "uint", "minimum": 0.0 } } }, "ControlConfig": { "description": "A steady-state control loop declaration.\n\nCurrently supports the `SaturatedController` type: a saturated-PI loop with anti-windup that is co-solved inside the Newton system. It drives a measured plant output (`measure`) to `target` by manipulating an actuator factor (`actuator`) within `[min, max]` bounds.", "type": "object", "required": [ "actuator", "id", "measure", "target" ], "properties": { "actuator": { "description": "The manipulated actuator.", "allOf": [ { "$ref": "#/definitions/ActuatorConfig" } ] }, "band": { "description": "Saturation band half-width `Q > 0`.", "default": 1.0, "type": "number", "format": "double" }, "gain": { "description": "Loop gain `K` (sign must match actuator→output sensitivity).", "default": 1.0, "type": "number", "format": "double" }, "id": { "description": "Unique identifier for this control loop.", "type": "string" }, "measure": { "description": "The measured plant output to regulate.", "allOf": [ { "$ref": "#/definitions/MeasureConfig" } ] }, "smooth_eps": { "description": "If set, uses the C¹ smooth saturation with this `eps`; otherwise hard clamp.", "default": null, "type": [ "number", "null" ], "format": "double" }, "target": { "description": "Target value for the measured output (SI units: W, K, Pa, kg/s).", "type": "number", "format": "double" }, "type": { "description": "Controller type. Only `\"SaturatedController\"` is supported today.", "default": "SaturatedController", "type": "string" } } }, "EdgeConfig": { "description": "Configuration for an edge between components.", "type": "object", "required": [ "from", "to" ], "properties": { "from": { "description": "Source component and port (e.g., \"comp1:outlet\").", "type": "string" }, "to": { "description": "Target component and port (e.g., \"cond1:inlet\").", "type": "string" } } }, "InitialStateConfig": { "description": "Initial state configuration.", "type": "object", "properties": { "enthalpy_kj_kg": { "description": "Initial enthalpy in kJ/kg.", "type": [ "number", "null" ], "format": "double" }, "pressure_bar": { "description": "Initial pressure in bar.", "type": [ "number", "null" ], "format": "double" }, "temperature_k": { "description": "Initial temperature in Kelvin.", "type": [ "number", "null" ], "format": "double" } } }, "InstanceConfig": { "description": "An instantiation of a [`SubsystemTemplate`].", "type": "object", "required": [ "name", "of" ], "properties": { "circuit": { "description": "Target circuit id the expanded components/edges are placed into (default 0).", "default": 0, "type": "integer", "format": "uint", "minimum": 0.0 }, "name": { "description": "Unique instance name; becomes the `\"{name}.\"` prefix on expanded components.", "type": "string" }, "of": { "description": "Name of the template to instantiate (key in `subsystems`).", "type": "string" }, "params": { "description": "Parameter overrides for this instance (override template defaults).", "default": {}, "type": "object", "additionalProperties": true } } }, "MeasureConfig": { "description": "Reference to a measurable component output.", "type": "object", "required": [ "component", "output" ], "properties": { "component": { "description": "Name of the component whose output is measured.", "type": "string" }, "output": { "description": "Output kind: one of `capacity`, `heatTransferRate`, `superheat`, `subcooling`, `saturationTemperature`, `massFlowRate`, `pressure`, `temperature`.", "type": "string" } } }, "SolverConfig": { "description": "Solver configuration.", "type": "object", "properties": { "max_iterations": { "description": "Maximum iterations.", "default": 100, "type": "integer", "format": "uint", "minimum": 0.0 }, "strategy": { "description": "Solver strategy: \"newton\", \"picard\", or \"fallback\".", "default": "fallback", "type": "string" }, "timeout_ms": { "description": "Timeout in milliseconds (0 = no timeout).", "default": 0, "type": "integer", "format": "uint64", "minimum": 0.0 }, "tolerance": { "description": "Convergence tolerance.", "default": 1e-6, "type": "number", "format": "double" }, "verbose": { "description": "Enable verbose output.", "default": false, "type": "boolean" } } }, "SubsystemTemplate": { "description": "A reusable subsystem template: a parameterized assembly of components and internal edges, exposing a reduced set of external ports.\n\nThis is Modelica-style `model` composition. Templates are declared once under `subsystems` and instantiated any number of times via `instances`, each with its own parameter overrides. At load time every instance is **flattened** into the flat `circuits/components/edges` graph (component names prefixed by `\"{instance}.\"`), so the solver and every downstream consumer are unchanged.\n\n# Parameter substitution Any component parameter whose JSON value is a string of the form `\"$name\"` is replaced by the resolved value of parameter `name` (instance override, falling back to the template default in `params`). Because `ua`, `secondary_*`, `isentropic_efficiency`, `t_cond_k`, … all flow through the component `params` catch-all, this covers essentially every physical knob.", "type": "object", "required": [ "components" ], "properties": { "components": { "description": "Components inside the template (names are local to the template).", "type": "array", "items": { "$ref": "#/definitions/ComponentConfig" } }, "edges": { "description": "Internal edges between the template's own components.", "default": [], "type": "array", "items": { "$ref": "#/definitions/EdgeConfig" } }, "params": { "description": "Default parameter values, overridable per instance.", "default": {}, "type": "object", "additionalProperties": true }, "ports": { "description": "External ports: maps an exposed port name to an internal `\"component:port\"` endpoint. `connections` reference these as `\"{instance}.{external_port}\"`.", "default": {}, "type": "object", "additionalProperties": { "type": "string" } } } }, "ThermalCouplingConfig": { "description": "Thermal coupling configuration between two circuits.", "type": "object", "required": [ "cold_circuit", "hot_circuit", "ua" ], "properties": { "cold_circuit": { "description": "Cold circuit ID.", "type": "integer", "format": "uint", "minimum": 0.0 }, "efficiency": { "description": "Heat exchanger efficiency (0.0 to 1.0).", "default": 0.95, "type": "number", "format": "double" }, "hot_circuit": { "description": "Hot circuit ID.", "type": "integer", "format": "uint", "minimum": 0.0 }, "ua": { "description": "Thermal conductance in W/K.", "type": "number", "format": "double" } } } } }