VeraGridEngine.Utils.Symbolic package

Submodules

VeraGridEngine.Utils.Symbolic.block module

class VeraGridEngine.Utils.Symbolic.block.Block(state_vars: List[Var] | None = None, state_eqs: List[Expr] | None = None, algebraic_vars: List[Var] | None = None, algebraic_eqs: List[Expr] | None = None, inequalities: List[Expr | Comparison] | None = None, diff_vars: List[Var] | None = None, reformulated_vars: List[Var] | None = None, differential_eqs: List[Expr] | None = None, parameters: Dict[Var, Const] | None = None, init_values: Dict[Var, Const] | None = None, init_eqs: Dict[Var, Expr] | None = None, diff_init_eqs: Dict[Var, Expr] | None = None, discrete_eqs: Dict[Var, Expr] | None = None, children: List[Block] | None = None, in_vars: List[Var] | None = None, out_vars: List[Var] | None = None, event_dict: Dict[Var, Expr] | None = None, mode_dict: Dict[Var, Expr] | None = None, boolean_guards: Dict[Var, Expr | Comparison] | None = None, procedural_logic: List[Any] | None = None, external_mapping: Dict[VarPowerFlowReferenceType, Var] | None = None, api_obj_mapping: Dict[ParamPowerFlowReferenceType, Var] | None = None, is_decomposable: bool = True, name: str = '', uid: int | None = None)[source]

Bases: object

Class representing a Block

E(d: VarPowerFlowReferenceType) Var[source]

returns the value of the external mapping corresponding to the VarPowerFlowReferenceType

Parameters:

d

Returns:

V(d: str) Var[source]
Parameters:

d

Returns:

add(val: Block)[source]

Add another block to children of the model :param val: Block

can_use_bulk_connect_update(pairs: List[Tuple[Var, Var]]) bool[source]

Return whether one connection batch can be substituted safely in one pass.

Bulk substitution is used only when the old and new variable sets are both unique and disjoint. If the mappings overlap, the original sequential behaviour is preserved because the substitution order can be semantically relevant.

Parameters:

pairs – Connection pairs (old_var, new_var).

Returns:

True when the fast bulk path is safe.

check_empty() bool[source]

check if a block is an empty block :return: :rtype: bool

check_valid_init_method()[source]
compare(block2: Block) bool[source]

Compare two blocks. :param block2: :return:

connect(vars_to_subs: List[Var], incoming_vars: List[Var])[source]

Function to connect two blocks by variables sharing

copy() Block[source]

Deep-copy this block while preserving symbolic UIDs.

Returns:

Copied block.

property diagram: BlockDiagram
Returns:

empty() bool[source]

check if a model is empty :return:

find_var_in_block(var: Var) bool[source]

Replace variables :param var: :return:

find_var_in_equations(var: Var) bool[source]

find a var in the equations of a block :param var: :return:

get_all_blocks() List[Block][source]

Depth-first collection of all primitive Blocks.

get_all_equations_list()[source]
get_all_vars()[source]

returns all the variables of a block :return:

get_vars() List[Var][source]

returns variables of the flat block :return: List[Var]

is_eq_decomposable() bool[source]
merge_incoming_block(block: Block)[source]
static parse(data: Dict[str, Any]) Block[source]

Parse the dictionary representation of a block :param data: :return:

remove(val: Block)[source]

Remove a block from block children :param val: Block

set_parameter_in_model(var_name: str, new_value: float)[source]

updates parameter value given a name and a value

Parameters:
  • var_name

  • new_value

Returns:

to_dict() Dict[str, Any][source]

Get dictionary representation of this block :return: Dictionary

unify_blocks()[source]

This function collects all variables and equations of a block, returns a flat block Returns β€”β€”- Union[None, VeraGridEngine.Utils.Symbolic.block.Block]

update_equations(old: Var | Expr, new: Var | Expr) None[source]

this function changes the variable old for the variable new in the block equations :param old: :param new: :return:

update_equations_bulk(var_mapping: Dict[Var, Var]) None[source]

Replace several variables in block equations and mappings in one pass.

Parameters:

var_mapping – Old-to-new variable mapping.

Returns:

None.

update_model(old: Var | Expr, new: Var | Expr) None[source]

Replace variables :param old: :param new: :return:

update_model_bulk(var_mapping: Dict[Var, Var]) None[source]

Replace several variables across the block hierarchy in one pass.

Parameters:

var_mapping – Old-to-new variable mapping.

Returns:

None.

update_variables(old: Var | Expr, new: Var | Expr) None[source]

this function changes the variable old for the variable new in the block variables :param old: :type old: :param new: :type new: :return: :rtype:

update_variables_bulk(var_mapping: Dict[Var, Var]) None[source]

Replace several variables in the block variable lists in one pass.

Parameters:

var_mapping – Old-to-new variable mapping.

Returns:

None.

VeraGridEngine.Utils.Symbolic.block.build_name_to_var_lookup(block: Block) Dict[str, Var][source]

Build one variable lookup table by symbolic name for a block hierarchy.

The first occurrence of each name is preserved, matching the effective search order of find_name_in_block() while avoiding repeated recursive scans when many variables must be resolved from the same block.

Parameters:

block – Root block to inspect.

Returns:

Name-to-variable lookup.

VeraGridEngine.Utils.Symbolic.block.compare_blocks_structurally(block1: Block, block2: Block) bool[source]
VeraGridEngine.Utils.Symbolic.block.compare_n_blocks_structurally(blocks: List[Block]) Tuple[Dict[int, List[int]], Dict[int, List[int]]][source]

Compare n blocks structurally and group equivalent blocks by their uid.

Two blocks are considered structurally equivalent if: 1. Their unified equation systems are equivalent 2. Variables can be aligned between them 3. Corresponding variables are located in corresponding attributes

Parameters:

blocks – List of n blocks to compare

Returns:

Tuple of: - Dict with new uid (uuid.uuid4().int) as keys and lists of equivalent block uids as values - Dict with variable uid as keys and lists of equivalent variable uids as values

VeraGridEngine.Utils.Symbolic.block.find_connections(mdl1: Block, mdl2: Block) tuple[List[tuple[Var, Var]], List[tuple[Var, Var]]][source]

find connections between the two blocks by vars searching :return: :rtype:

VeraGridEngine.Utils.Symbolic.block.find_connections_pf(mdl1: Block, mdl2: Block) List[tuple[Var, Var]][source]

find connections between the two blocks by vars searching :return: :rtype:

VeraGridEngine.Utils.Symbolic.block.find_name_in_block(name: str, block: Block) Var | None[source]
Parameters:
  • name

  • block

Returns:

VeraGridEngine.Utils.Symbolic.block.set_parameter(blk: Block, var_name: str, new_value: float)[source]
VeraGridEngine.Utils.Symbolic.block.variables_in_corresponding_attributes(blocks: List[Block], variables_mappings: List[Dict[int, int]]) bool[source]

Check if corresponding variables are located in corresponding attributes of n blocks.

For each pair (blocks[i], blocks[j]) with variables_mappings[k] (where k corresponds to the pair), and for every pair (uid1, uid2) in variables_mapping: - If the variable with uid1 is in blocks[i].state_vars, the variable with uid2 must be in blocks[j].state_vars - And so on for all attribute types

The order of variables within each attribute does not matter.

Parameters:
  • blocks – List of n blocks to check

  • variables_mappings – List of Dict mappings from block i to block j for each pair comparison

Returns:

True if all corresponding variables are in corresponding attributes for all pairs

VeraGridEngine.Utils.Symbolic.block_helpers module

VeraGridEngine.Utils.Symbolic.block_helpers.deadband_block(var_factory: VarFactory, x: Var | Expr, y: Var = None, name: str | None = '', deadband: Expr = 0.1) Tuple[Block, Var][source]

Creates a deadband function block.

The deadband function returns: - 0 when input is within the deadband [-deadband, +deadband] - input - deadband when input > deadband - input + deadband when input < -deadband

Parameters:

var_factory: VarFactory instance for creating variables x: input signal (Var or Expr) y: output variable (optional, created if None) name: name prefix for variables deadband: deadband threshold (default 0.1)

Returns:

Tuple of (Block, output_var)

VeraGridEngine.Utils.Symbolic.block_helpers.discrete_control_block(var_factory: VarFactory, m: Var, delta_m: Var, m_max: Var, m_min: Var, v: Var, v_ref: Var, delta_v: Var, ts: Var, name: str | None = '') Tuple[Block, Var][source]
VeraGridEngine.Utils.Symbolic.block_helpers.integrator_with_non_windup(var_factory: VarFactory, x: Var | Expr, T: Expr | float, y: Var = None, name: str | None = '', sat_min: Expr = -1000000.0, sat_max: Expr = 1000000.0, multilinear: bool = False)[source]

Integrator with non-windup limiter (Figure E.2 style):

dy/dt = (1/T) * x

with clamping logic: - if y >= sat_max and dy/dt would be positive -> dy/dt = 0 - if y <= sat_min and dy/dt would be negative -> dy/dt = 0 - otherwise dy/dt = (1/T) * x

VeraGridEngine.Utils.Symbolic.block_helpers.integrator_with_windup(var_factory: VarFactory, x: Var | Expr, T: Expr | float, y: Var = None, name: str | None = '', sat_min: Expr = -1000000.0, sat_max: Expr = 1000000.0, multilinear: bool = False)[source]

Simple 1/(sT) integrator followed by output saturation (windup behavior).

Internal state:

dz/dt = x / T

Output:

y = sat(z)

VeraGridEngine.Utils.Symbolic.block_helpers.tf_to_block(var_factory: VarFactory, num: List[Var | float], den: List[Var | float], x: Var | Expr, y: Var = None, create_state: bool = False, name: str | None = '', output_var_name: str = 'y_') Tuple[Block, Var][source]

β€œtransform definition” to block num: list of numerator coefficients [b0, b1, …, bm] den: list of denominator coefficients [a0, a1, …, an] x: sympy symbol for input y: sympy function of t for output

VeraGridEngine.Utils.Symbolic.block_helpers.tf_to_block2(var_factory: VarFactory, num: List[Var | float], den: List[Var | float], x: Var | float, y: Var = None, name: str = '')[source]

num: numerator coefficients [b0,…,bm] den: denominator coefficients [a0,…,an], with an != 0 u: input Expr or Var y: output Var

VeraGridEngine.Utils.Symbolic.block_helpers.tf_to_block_with_states(var_factory: VarFactory, num: List[Var | float], den: List[Var | float], x: Var | Expr, y: Var = None, name: str | None = '')[source]

num: numerator coefficients [b0,…,bm] den: denominator coefficients [a0,…,an], with an != 0 u: input Var y: output Var

VeraGridEngine.Utils.Symbolic.block_helpers.tf_to_diffblock_with_antiwindup(var_factory: VarFactory, num: List[Var | float], den: List[Var | float], x: Var, y: Var = None, name: str | None = '', sat_min: Expr = -1000000.0, sat_max: Expr = 1000000.0, multilinear=False, PI: bool = False)[source]

num: numerator coefficients [b0, …, bm] den: denominator coefficients [a0, …, an] x: input (Var or Expr) y: output Var sat_min, sat_max: saturation limits for anti-windup

VeraGridEngine.Utils.Symbolic.block_helpers.tf_to_diffblock_with_antiwindup_by_feedback(var_factory: VarFactory, num: List[Var | float], den: List[Var | float], x: Var, y: Var = None, name: str | None = '', sat_min: Expr = -1000000.0, sat_max: Expr = 1000000.0, Kaw: Expr = 10.0)[source]

Implements a back-calculation anti-windup controller using (u_sat - u) as feedback input. Works better for implicit solvers num: numerator coefficients [b0, …, bm] den: denominator coefficients [a0, …, an] x: input signal y: output (saturated)

VeraGridEngine.Utils.Symbolic.block_helpers.tf_to_diffblock_with_output(var_factory: VarFactory, num: List[Var | float], den: List[Var | float], x: Var | Expr, y: Var = None, create_state: bool = False, name: str | None = '')[source]

num: list of numerator coefficients [b0, b1, …, bm] den: list of denominator coefficients [a0, a1, …, an] x: sympy symbol for input y: sympy function of t for output

VeraGridEngine.Utils.Symbolic.block_helpers.to_explicit(block: Block, vfactory: VarFactory) Block[source]

Convert an implicit DAE-like block back to explicit state equations.

For each diff var dt_x in block.diff_vars, look for an algebraic equation equivalent to dt_x - f(…) = 0. When found: - create/ensure state equation dx/dt = f(…) for base var x - remove that implicit algebraic equation - substitute dt_x by f(…) in remaining algebraic equations - remove all recovered diff vars from block.diff_vars

Recurses through child blocks.

VeraGridEngine.Utils.Symbolic.block_helpers.to_implicit(block: Block, vfactory: VarFactory) Block[source]

Convert a block with explicit state equations to implicit form.

For each state variable x with equation dx/dt = f(x, y): - Create a new algebraic variable dt_x representing the derivative - Add dt_x to algebraic_vars - Add equation: diff(x) - f(x, y) = 0 to algebraic_eqs - Move x from state_vars to algebraic_vars - Remove the state equation from state_eqs

This transforms the explicit ODE form into DAE implicit form suitable for solvers that expect algebraic equations.

VeraGridEngine.Utils.Symbolic.bus_emt_template module

class VeraGridEngine.Utils.Symbolic.bus_emt_template.BusEmtTemplate(vf: VarFactory, mask: list[bool], is_dc: bool = False, name: str = 'emt_bus_template')[source]

Bases: EmtModelTemplate

CLASS_NON_EDITABLE_PROPERTIES = ('idtag', 'selected_to_merge', 'diff_changes', 'device_idtag', 'tpe', 'device_name', 'block')
CLASS_PROPERTIES_WITH_PROFILE = {}
CLASS_PROPERTY_DECLARATIONS = (prop:idtag, prop:name, prop:code, prop:rdfid, prop:action, prop:selected_to_merge, prop:comment, prop:diff_changes, prop:device_idtag, prop:tpe, prop:device_name, prop:block, prop:tpe)
CLASS_PROPERTY_LIST = (prop:idtag, prop:name, prop:code, prop:rdfid, prop:action, prop:selected_to_merge, prop:comment, prop:diff_changes, prop:device_idtag, prop:tpe, prop:device_name, prop:block, prop:tpe)
CLASS_REGISTERED_PROPERTIES = {'action': prop:action, 'block': prop:block, 'code': prop:code, 'comment': prop:comment, 'device_idtag': prop:device_idtag, 'device_name': prop:device_name, 'diff_changes': prop:diff_changes, 'idtag': prop:idtag, 'name': prop:name, 'rdfid': prop:rdfid, 'selected_to_merge': prop:selected_to_merge, 'tpe': prop:tpe}
property block: Block
Returns:

Block

tpe: DeviceType
v_A
v_B
v_C
v_DC
v_N
VeraGridEngine.Utils.Symbolic.bus_emt_template.get_bus_emt_algebraic_vars(bus_emt_model: Block) Tuple[Var | None, Var | None, Var | None, Var | None][source]

Return the EMT bus algebraic voltage variables.

For AC buses:

returns (v_N, v_A, v_B, v_C) Missing phases are returned as None.

For DC buses:

returns (Vdc, None, None, None)

Parameters:

bus_emt_model – EMT bus block

Returns:

Tuple with four positions to preserve a stable API

VeraGridEngine.Utils.Symbolic.bus_emt_template.get_bus_emt_template(grid: MultiCircuit, bus: Bus)[source]

Initialize 3ph bus block A bus will have the phases of the branches connected to it :param grid: Multicircuit :param bus: Bus :return:

VeraGridEngine.Utils.Symbolic.bus_rms_template module

class VeraGridEngine.Utils.Symbolic.bus_rms_template.BusRmsTemplate(vf: VarFactory, is_dc: bool = False, name: str = 'rms_bus_template')[source]

Bases: RmsModelTemplate

CLASS_NON_EDITABLE_PROPERTIES = ('idtag', 'selected_to_merge', 'diff_changes', 'device_idtag', 'tpe', 'device_name', 'block')
CLASS_PROPERTIES_WITH_PROFILE = {}
CLASS_PROPERTY_DECLARATIONS = (prop:idtag, prop:name, prop:code, prop:rdfid, prop:action, prop:selected_to_merge, prop:comment, prop:diff_changes, prop:device_idtag, prop:tpe, prop:device_name, prop:block, prop:tpe)
CLASS_PROPERTY_LIST = (prop:idtag, prop:name, prop:code, prop:rdfid, prop:action, prop:selected_to_merge, prop:comment, prop:diff_changes, prop:device_idtag, prop:tpe, prop:device_name, prop:block, prop:tpe)
CLASS_REGISTERED_PROPERTIES = {'action': prop:action, 'block': prop:block, 'code': prop:code, 'comment': prop:comment, 'device_idtag': prop:device_idtag, 'device_name': prop:device_name, 'diff_changes': prop:diff_changes, 'idtag': prop:idtag, 'name': prop:name, 'rdfid': prop:rdfid, 'selected_to_merge': prop:selected_to_merge, 'tpe': prop:tpe}
Va
Vm
tpe: DeviceType
VeraGridEngine.Utils.Symbolic.bus_rms_template.get_bus_rms_algebraic_vars(bus_rms_model: Block) Tuple[Var, Var] | Tuple[Var, Var, Var][source]

Return the RMS bus algebraic voltage variables.

For AC buses:

returns (Vm, Va)

For DC buses:

returns (Vdc, None)

Parameters:

bus_rms_model – RMS bus block

Returns:

Tuple with two positions to preserve the project API

VeraGridEngine.Utils.Symbolic.bus_rms_template.initialize_bus_rms(bus: Bus, vf: VarFactory)[source]
Parameters:
  • bus

  • vf

Returns:

VeraGridEngine.Utils.Symbolic.compare_expressions_structure module

Symbolic Expression Equivalence Engine.

Provides canonicalization, structural hashing, DAG representation, and equivalence checking for symbolic expressions without modifying the original expression trees.

class VeraGridEngine.Utils.Symbolic.compare_expressions_structure.DAGNode(op: str, children: List[DAGNode], structural_hash: str, expr: Expr | None = None)[source]

Bases: object

Node in a Directed Acyclic Graph representation of an expression.

Attributes:

op: Operator type (str for BinOp/UnOp/Func, or node type name) children: List of child DAGNode references structural_hash: Precomputed structural hash string

children: List[DAGNode]
op: str
structural_hash: str
VeraGridEngine.Utils.Symbolic.compare_expressions_structure.canonical(expr: Expr, depth: int = 0) Expr[source]

Transform an expression into canonical form.

Applies: - Flatten associative operators (+, *) - Sort commutative operands - Constant folding - Remove neutral elements (a+0=a, a*1=a, a*0=0) - Normalize powers (a**1=a, a**0=1)

Does NOT mutate the original expression.

Parameters:
  • expr – Expression to canonicalize

  • depth – Current recursion depth for cycle detection

Returns:

New canonical expression

VeraGridEngine.Utils.Symbolic.compare_expressions_structure.dag_to_string(node: DAGNode, indent: int = 0) str[source]

Generate a string representation of a DAG for debugging.

VeraGridEngine.Utils.Symbolic.compare_expressions_structure.equations_equivalent(eq1: Expr, eq2: Expr) bool[source]

Check if two equations are equivalent.

An equation is treated as a BinOp with operator β€œ=”. Two equations are equivalent if their canonical forms match.

Parameters:
  • eq1 – First equation (typically BinOp with op=”=”)

  • eq2 – Second equation

Returns:

True if equivalent

VeraGridEngine.Utils.Symbolic.compare_expressions_structure.equivalent(e1: Expr, e2: Expr) bool[source]

Check if two expressions are mathematically equivalent.

Uses canonicalization and structural hashing for O(1) comparison after canonical form is computed.

Parameters:
  • e1 – First expression

  • e2 – Second expression

Returns:

True if equivalent

VeraGridEngine.Utils.Symbolic.compare_expressions_structure.equivalent_expanded(e1: Expr, e2: Expr) bool[source]

Check if two expressions are mathematically equivalent using expansion.

This version uses algebraic expansion before comparison, so that (x+1)^2 and x^2+2x+1 are considered equivalent.

Parameters:
  • e1 – First expression

  • e2 – Second expression

Returns:

True if equivalent

VeraGridEngine.Utils.Symbolic.compare_expressions_structure.equivalent_systems(sys1: List[Expr], sys2: List[Expr]) bool[source]

Check if two systems of equations are equivalent.

Systems are equivalent if they contain the same equations in any order. Each equation is compared using structural canonical hashing.

Parameters:
  • sys1 – First list of equations

  • sys2 – Second list of equations

Returns:

True if equivalent systems

VeraGridEngine.Utils.Symbolic.compare_expressions_structure.expand(expr: Expr, max_terms: int = 200) Expr[source]

Fully expand an algebraic expression.

Applies: - Product of sums expansion: (a+b)*(c+d) -> a*c + a*d + b*c + b*d - Power of sum expansion: (a+b)^2 -> a^2 + 2*a*b + b^2

Parameters:
  • expr – Expression to expand

  • max_terms – Maximum number of terms before bailing out

Returns:

Fully expanded expression

VeraGridEngine.Utils.Symbolic.compare_expressions_structure.expand_and_canonicalize(expr: Expr, max_terms: int = 500) Expr[source]

Expand and then canonicalize an expression.

This is the recommended function for getting a canonical form that handles algebraic expansion.

Parameters:
  • expr – Expression to process

  • max_terms – Maximum number of terms before bailing out (prevents exponential blowup)

Returns:

Expanded and canonicalized expression

VeraGridEngine.Utils.Symbolic.compare_expressions_structure.get_canonical_form(expr: Expr) Expr[source]

Get the canonical form of an expression.

This is a convenience alias for canonical().

Parameters:

expr – Expression to canonicalize

Returns:

Canonical expression

VeraGridEngine.Utils.Symbolic.compare_expressions_structure.get_structural_hash(expr: Expr) str[source]

Get the structural hash of an expression.

This is a convenience alias for structural_hash().

Parameters:

expr – Expression to hash

Returns:

Hex string hash

VeraGridEngine.Utils.Symbolic.compare_expressions_structure.simplify_deep(expr: Expr) Expr[source]

Deep simplification with algebraic expansion and canonicalization.

Unlike the built-in simplify(), this applies expansion and canonicalization recursively and handles more cases including polynomial equivalence.

Parameters:

expr – Expression to simplify

Returns:

Simplified expression

VeraGridEngine.Utils.Symbolic.compare_expressions_structure.structural_hash(expr: Expr) str[source]

Compute a deterministic structural hash for an expression.

Properties: - Independent of node UIDs - Order-invariant for commutative operators (+, *) - Includes operator type and structure

Parameters:

expr – Expression to hash

Returns:

Hex string hash (32 chars)

VeraGridEngine.Utils.Symbolic.compare_expressions_structure.structural_hash_expanded(expr: Expr) str[source]

Compute structural hash with algebraic expansion.

This version expands expressions before hashing, so that (x+1)^2 and x^2+2x+1 produce the same hash.

Parameters:

expr – Expression to hash

Returns:

Hex string hash (32 chars)

VeraGridEngine.Utils.Symbolic.compare_expressions_structure.to_dag(expr: Expr, memo: Dict[str, DAGNode] | None = None) DAGNode[source]

Convert an expression to a DAG with deduplication.

Nodes are deduplicated by structural hash, so identical subexpressions share the same DAG node.

Parameters:
  • expr – Expression to convert

  • memo – Optional memoization dict (structural_hash -> DAGNode)

Returns:

DAGNode root

VeraGridEngine.Utils.Symbolic.compiled_functions module

class VeraGridEngine.Utils.Symbolic.compiled_functions.SymbolicDerivative(vars: Sequence[Var], uid2idx_vars: Dict[int, int], diff_vars: Sequence[Var], compiler_names_dict: Dict[int, str], use_jit: bool = True)[source]

Bases: object

SymbolicFunction

data: ndarray[tuple[Any, ...], dtype[float64]]
func: Callable[[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], float, ndarray[tuple[Any, ...], dtype[float64]]], ndarray[tuple[Any, ...], dtype[float64]]] | None
index_map: ndarray[tuple[Any, ...], dtype[int64]]
namespace: Dict[str, Any]
class VeraGridEngine.Utils.Symbolic.compiled_functions.SymbolicJacobian(eqs: list, variables: list, compiler_names_dict: dict, alias_names_dict: dict, VARS_NAME: str, DIFF_NAME: str, EVENT_PARAMS_NAME: str, PARAMS_NAME: str, dt=None, use_jit=True, batch_size=500, n_jobs=4, static=False)[source]

Bases: object

Class to store and evaluate a symbolic jacobian

J
block_offsets
funcs: List[Callable[[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], float, ndarray[tuple[Any, ...], dtype[float64]]], None] | None]
namespace: Dict[str, Any]
nvar
class VeraGridEngine.Utils.Symbolic.compiled_functions.SymbolicParamsVector(eqs: Sequence[Expr], compiler_names_dict: Dict[int, str], alias_names_dict: Dict[int, str], EVENT_PARAMS_NAME: str, TIME_NAME: str, use_jit: bool = True)[source]

Bases: object

SymbolicFunction

data
func: Callable[[ndarray[tuple[Any, ...], dtype[float64]], float, ndarray[tuple[Any, ...], dtype[float64]]], None] | None
namespace: Dict[str, Any]
class VeraGridEngine.Utils.Symbolic.compiled_functions.SymbolicParamsVectorInit(eqs: Sequence[Expr], compiler_names_dict: Dict[int, str], alias_names_dict: Dict[int, str], VARS_NAME: str, EVENT_PARAMS_NAME: str, TIME_NAME: str, use_jit: bool = True)[source]

Bases: object

SymbolicFunction

data
func: Callable[[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], float, ndarray[tuple[Any, ...], dtype[float64]]], None] | None
namespace: Dict[str, Any]
class VeraGridEngine.Utils.Symbolic.compiled_functions.SymbolicVector(eqs: List[Expr], compiler_names_dict: Dict[int, str], alias_names_dict: Dict[int, str], VARS_NAME: str, DIFF_NAME: str, EVENT_PARAMS_NAME: str, PARAMS_NAME: str, use_jit: bool = True)[source]

Bases: object

SymbolicFunction

data: ndarray[tuple[Any, ...], dtype[float64]]
func: Callable[[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]], None] | None
namespace: Dict[str, Any]
VeraGridEngine.Utils.Symbolic.compiled_functions.compile_jac_block(block_id, block_eqs, block_offsets, used_vars_count, compiler_names_dict, alias_names_dict, namespace, VARS_NAME: str, DIFF_NAME: str, EVENT_PARAMS_NAME: str, PARAMS_NAME: str, use_jit)[source]

function that builds the compiled functions

Parameters:
  • block_id

  • block_eqs

  • block_offsets

  • used_vars_count

  • compiler_names_dict

  • alias_names_dict

  • namespace

  • VARS_NAME

  • DIFF_NAME

  • EVENT_PARAMS_NAME

  • PARAMS_NAME

  • use_jit

Returns:

VeraGridEngine.Utils.Symbolic.compiled_functions.get_compiled_functions_cache_stats() Dict[str, float][source]

Return cache statistics for compiled symbolic helper functions.

The legacy compiled-function module does not yet expose a persistent cache, so the reported cache entry count is zero. The function exists so EMT build reports can depend on a stable interface while the cache work remains staged.

Returns:

Cache statistics.

Return type:

Dict[str, float]

VeraGridEngine.Utils.Symbolic.diagnostic module

VeraGridEngine.Utils.Symbolic.diagnostic.Array1D

Per-solve context containing state, metrics, and diagnostics for the Newton solver.

β€” DEV NOTE (Architecture & C++ Porting):

  1. PYTHON IMPLEMENTATION: We use @dataclass(slots=True) here to optimize memory footprint (eliminating internal __dict__ per instance) and strictly define the schema. This is critical when generating thousands of context objects during simulation steps.

  2. C++ MIGRATION GUIDE: If porting this structure to C++, treat it as a POD struct. - Nullables: Optional[float] must be converted to std::optional<double>. - Logging: You will lose the auto-generated __repr__. You MUST manually

    implement friend std::ostream& operator << to support logging.

    • Equality: Implement operator== (or use C++20 default) to match Python’s behavior.

    • Initialization: Use C++20 designated initializers (.field = val) to mimic Python’s keyword arguments.

β€”

class VeraGridEngine.Utils.Symbolic.diagnostic.NewtonDiagnosticsConfig(step_norm_explode: float = 1000000.0, dense_cond_warn: float = 1000000000000.0, compute_dense_cond: bool = True, dense_cond_max_n: int = 600, enable_fallback: bool = True, enable_index1_check: bool = False, index1_max_block_n: int = 128, index1_warn_pivot_ratio: float = 1e-10, index1_fail_pivot_ratio: float = 1e-14, enable_backtracking: bool = False, backtracking_beta: float = 0.5, backtracking_min_alpha: float = 0.0001, backtracking_max_iter: int = 6, log_level: int = 30)[source]

Bases: object

Configuration for Newton linear-solve diagnostics.

Attributes:

step_norm_explode: Threshold on ||dx||_2 to flag an exploding Newton step. dense_cond_warn: Condition number threshold to warn about ill-conditioning (dense only). compute_dense_cond: If True, compute np.linalg.cond(A) for dense matrices. dense_cond_max_n: Avoid cond(A) if matrix dimension > this value (O(n^3) cost). enable_fallback: If True, attempt a least-squares fallback when the primary solve fails. enable_index1_check: If True, validate the algebraic Jacobian block on refresh. index1_max_block_n: Skip explicit index-1 checks for algebraic blocks larger than this size. index1_warn_pivot_ratio: Warn threshold for the minimum pivot ratio of the algebraic block. index1_fail_pivot_ratio: Failure threshold for the minimum pivot ratio of the algebraic block. enable_backtracking: If True, apply backtracking when a full Newton step fails to reduce the residual. backtracking_beta: Shrink factor used during backtracking. backtracking_min_alpha: Minimum accepted Newton step scaling. backtracking_max_iter: Maximum number of backtracking reductions. log_level: Logging level for warnings.

backtracking_beta
backtracking_max_iter
backtracking_min_alpha
compute_dense_cond
dense_cond_max_n
dense_cond_warn
enable_backtracking
enable_fallback
enable_index1_check
index1_fail_pivot_ratio
index1_max_block_n
index1_warn_pivot_ratio
log_level
step_norm_explode
class VeraGridEngine.Utils.Symbolic.diagnostic.NewtonSolveContext(t: float, step_idx: int, newton_iter: int, phase: str, method: str = '', solver: str = '', used_fallback: bool = False, cond_est: float | None = None, step_norm2: float | None = None, step_norm_inf: float | None = None, failure_msg: str | None = None, res_norm_inf: float | None = None, index1_pivot_ratio: float | None = None)[source]

Bases: object

Per-solve context, passed by the caller.

The decorator updates diagnostic fields (used_fallback, cond_est, step_norm, failure_msg).

Attributes:

t: Current simulation time. step_idx: Time-step index. newton_iter: Newton iteration index within the time-step. phase: Text label (e.g. β€œjit”, β€œimplicit”, β€œpseudo”, β€œinit”). method: Integration method label, if available. solver: Text label (e.g. β€œdense”, β€œsparse”). used_fallback: Set True if fallback was used. cond_est: Estimated condition number (dense only, optional). step_norm2: ||dx||_2 step_norm_inf: ||dx||_inf failure_msg: If the primary solver failed, store a short error description.

cond_est
failure_msg
index1_pivot_ratio
method
newton_iter
phase
res_norm_inf
solver
step_idx
step_norm2
step_norm_inf
t
used_fallback
class VeraGridEngine.Utils.Symbolic.diagnostic.NewtonTraceCollector[source]

Bases: object

Collects numerical diagnostics during a simulation run. Designed for post-analysis and research purposes.

record(*, ctx: NewtonSolveContext, res_norm: float | None = None, dx: ndarray | None = None, cond: float | None = None, fallback: bool = False) None[source]

Append one Newton diagnostics record.

Parameters:
  • ctx – Per-iteration Newton context.

  • res_norm – Residual infinity norm.

  • dx – Newton correction vector.

  • cond – Optional dense Jacobian condition estimate.

  • fallback – Whether the least-squares fallback was used.

Returns:

None

record_residual_vector(*, ctx: NewtonSolveContext, residual: ndarray, top_k: int = 5, debug_info: list[dict[str, Any]] | None = None) None[source]

Record one residual snapshot with top offending equation indices.

Parameters:
  • ctx – Per-iteration Newton context.

  • residual – Full nonlinear residual vector.

  • top_k – Number of largest-magnitude residual entries to keep.

  • debug_info – Optional residual metadata aligned with residual indices.

Returns:

None.

records: list[dict[str, Any]]
residual_records: list[dict[str, Any]]
to_dataframe()[source]

Convert the collected records into a pandas DataFrame.

Returns:

DataFrame with Newton diagnostics records.

VeraGridEngine.Utils.Symbolic.diagnostic.dense_lstsq_fallback(A: Any, b: ndarray) ndarray[source]

Dense least-squares fallback using np.linalg.lstsq.

Args:

A: Dense matrix. b: RHS vector.

Returns:

x: Least-squares solution.

VeraGridEngine.Utils.Symbolic.diagnostic.maybe_apply_backtracking(x_iter: ndarray, delta: ndarray, res_norm: float, trial_x: ndarray, trial_res: ndarray, *, evaluate_residual: Callable[[ndarray, ndarray], float], config: NewtonDiagnosticsConfig | None = None) None[source]

Optionally apply backtracking to a Newton step.

The full Newton step is kept as the default behavior. When backtracking is enabled, the routine tries geometrically reduced step sizes and accepts the first one that decreases the residual norm. If none succeeds, the original full step is applied.

Parameters:
  • x_iter – Current Newton iterate. Updated in place.

  • delta – Full Newton correction.

  • res_norm – Residual norm at the current iterate.

  • trial_x – Reusable state buffer for trial iterates.

  • trial_res – Reusable residual buffer for trial iterates.

  • evaluate_residual – Callback evaluate_residual(trial_x, trial_res) -> res_norm.

  • config – Newton diagnostics configuration.

Returns:

None

VeraGridEngine.Utils.Symbolic.diagnostic.maybe_check_index1(jacobian: Any, n_state: int, *, ctx: NewtonSolveContext | None = None, config: NewtonDiagnosticsConfig | None = None, logger: Logger | None = None) float | None[source]

Optionally validate the algebraic Jacobian block associated with an index-1 DAE.

The check is intentionally conservative and size-limited so it does not penalize normal runtime performance. It is only active when config.enable_index1_check is set to True.

Parameters:
  • jacobian – Dense or sparse Jacobian matrix of the monolithic residual.

  • n_state – Number of differential states; rows/columns after this offset belong to g_y.

  • ctx – Optional Newton context for diagnostics bookkeeping.

  • config – Newton diagnostics configuration.

  • logger – Optional logger.

Returns:

Estimated pivot-ratio indicator or None when the check is skipped.

VeraGridEngine.Utils.Symbolic.diagnostic.sparse_lsqr_fallback(A: Any, b: ndarray) ndarray[source]

Sparse least-squares fallback using scipy.sparse.linalg.lsqr.

Args:

A: Sparse matrix. b: RHS vector.

Returns:

x: LSQR solution.

VeraGridEngine.Utils.Symbolic.diagnostic.with_newton_diagnostics(primary_solve: Callable[[Any, ndarray], ndarray], *, fallback_solve: Callable[[Any, ndarray], ndarray] | None = None, collector: NewtonTraceCollector | None = None, config: NewtonDiagnosticsConfig | None = None, logger: Logger | None = None, solver_name: str = '', matrix_getter: Callable[[Any], Any] | None = None) Callable[[Any, ndarray, NewtonSolveContext], ndarray][source]

Decorate a linear solver with Jacobian conditioning diagnostics and fallback LS solve.

Args:

primary_solve: Function implementing the primary solve (e.g. np.linalg.solve, spla.spsolve). fallback_solve: Least-squares fallback (e.g. np.linalg.lstsq(…)[0], spla.lsqr(…)[0]). collector: Optional Newton trace collector receiving per-iteration records. config: Diagnostics configuration. logger: Optional logger (uses print fallback if not configured). solver_name: Human-readable solver label. matrix_getter: Optional callback to extract the diagnostic matrix from a bundled solver object.

Returns:

A callable solve(A, b, ctx) -> x, which updates ctx with diagnostics info.

VeraGridEngine.Utils.Symbolic.explicit_initialization_symbolic module

class VeraGridEngine.Utils.Symbolic.explicit_initialization_symbolic.RmsSingleEquationCompiler(rms_compiler: RMSCompiler, func_name_prefix: str = 'equation')[source]

Bases: object

Compile one self-implicit equation using the RMS JIT backend.

compile_equation(eq: Expr | Const) Callable[[ndarray, ndarray, ndarray, ndarray], ndarray][source]

Compile one symbolic equation with the RMS JIT backend.

Parameters:

eq (Union[Expr, Const]) – Equation to compile.

Returns:

Evaluator with signature (x, dx, event_params, params).

Return type:

Callable[[np.ndarray, np.ndarray, np.ndarray, np.ndarray], np.ndarray]

Raises:

TypeError – If the equation is not symbolic.

class VeraGridEngine.Utils.Symbolic.explicit_initialization_symbolic.SymbolicVectorSingleEquationCompiler(compiler_names_dict: Dict[int, str], alias_names_dict: Dict[int, str], vars_name: str, diff_name: str, event_params_name: str, params_name: str)[source]

Bases: object

Compile one self-implicit equation using the EMT symbolic-vector backend.

compile_equation(eq: Expr | Const) Callable[[ndarray, ndarray, ndarray, ndarray], ndarray][source]

Compile one symbolic equation with the EMT symbolic-vector backend.

Parameters:

eq (Union[Expr, Const]) – Equation to compile.

Returns:

Evaluator with signature (x, dx, event_params, params).

Return type:

Callable[[np.ndarray, np.ndarray, np.ndarray, np.ndarray], np.ndarray]

Raises:

TypeError – If the equation is not symbolic.

VeraGridEngine.Utils.Symbolic.explicit_initialization_symbolic.add_items(blk, init_vars, init_event)[source]

adds items from a block to the dictionary :param blk: :type blk: :param init_vars: :param init_event: init_dict :return: :rtype:

VeraGridEngine.Utils.Symbolic.explicit_initialization_symbolic.build_explicit_init_graph(mdl: Block) Tuple[Dict[Var, Expr | Const], Dict[Var, List[Var]], List[Var], Dict[Var, Expr | Const]][source]

Build the unified dependency graph used by the explicit initializer.

Parameters:

mdl (Block) – Symbolic block containing event, init, and diff-init equations.

Returns:

Unified equation dictionary, dependency map, and topological order.

Return type:

Tuple[Dict[Var, Union[Expr, Const]], Dict[Var, List[Var]], List[Var]]

Raises:

RuntimeError – If a cross-variable cycle is detected.

VeraGridEngine.Utils.Symbolic.explicit_initialization_symbolic.build_init_dict(mdl, init_vars, init_event)[source]

builds initialization dictionary from mdl :param mdl: :type mdl: :param init_vars: :param init_event: :type init_vars: init_dict :return: :rtype:

VeraGridEngine.Utils.Symbolic.explicit_initialization_symbolic.build_rms_single_equation_compiler(rms_compiler: RMSCompiler, func_name_prefix: str = 'equation') RmsSingleEquationCompiler[source]

Build the RMS single-equation compiler wrapper.

Parameters:
  • rms_compiler (RMSCompiler) – Configured RMS compiler instance.

  • func_name_prefix (str) – Prefix used to name generated callables.

Returns:

Wrapper object compiling one equation to the common four-array signature.

Return type:

RmsSingleEquationCompiler

VeraGridEngine.Utils.Symbolic.explicit_initialization_symbolic.build_symbolic_vector_single_equation_compiler(compiler_names_dict: Dict[int, str], alias_names_dict: Dict[int, str], vars_name: str, diff_name: str, event_params_name: str, params_name: str) SymbolicVectorSingleEquationCompiler[source]

Build the EMT single-equation compiler wrapper.

Parameters:
  • compiler_names_dict (Dict[int, str]) – Compiler variable name map.

  • alias_names_dict (Dict[int, str]) – Compiler alias name map.

  • vars_name (str) – SymbolicVector state or algebraic array name.

  • diff_name (str) – SymbolicVector derivative array name.

  • event_params_name (str) – SymbolicVector event parameter array name.

  • params_name (str) – SymbolicVector constant parameter array name.

Returns:

Wrapper object compiling one equation to the common four-array signature.

Return type:

SymbolicVectorSingleEquationCompiler

VeraGridEngine.Utils.Symbolic.explicit_initialization_symbolic.build_uid_bindings(eq: Expr | Const, event_params_array: ndarray, x: ndarray, params_array: ndarray, dx: ndarray, uid2idx_event_params: Dict[int, int], uid2idx_vars: Dict[int, int], uid2idx_params: Dict[int, int], uid2idx_diff: Dict[int, int]) Dict[int, float][source]

Build the UID-to-value bindings needed to evaluate one symbolic expression.

Parameters:
  • eq (Union[Expr, Const]) – Symbolic expression to analyze.

  • event_params_array (np.ndarray) – Runtime parameter values.

  • x (np.ndarray) – Algebraic or state vector.

  • params_array (np.ndarray) – Constant parameter vector.

  • dx (np.ndarray) – Differential initialization vector.

  • uid2idx_event_params (Dict[int, int]) – Runtime parameter index map.

  • uid2idx_vars (Dict[int, int]) – Variable index map.

  • uid2idx_params (Dict[int, int]) – Constant parameter index map.

  • uid2idx_diff (Dict[int, int]) – Differential variable index map.

Returns:

Numeric bindings for the expression variables.

Return type:

Dict[int, float]

VeraGridEngine.Utils.Symbolic.explicit_initialization_symbolic.compile_single_explicit_equation(compile_single_equation: SymbolicVectorSingleEquationCompiler | RmsSingleEquationCompiler, eq: Expr | Const) Callable[[ndarray, ndarray, ndarray, ndarray], ndarray | float][source]

Compile one equation through the explicit wrapper object.

Parameters:
Returns:

Evaluator with signature (x, dx, event_params, params).

Return type:

Callable[[np.ndarray, np.ndarray, np.ndarray, np.ndarray], Union[np.ndarray, float]]

Raises:

TypeError – If the wrapper object type is unsupported.

VeraGridEngine.Utils.Symbolic.explicit_initialization_symbolic.evaluate_explicit_init_equation(eq: Expr | Const, event_params_array: ndarray, x: ndarray, params_array: ndarray, dx: ndarray, uid2idx_event_params: Dict[int, int], uid2idx_vars: Dict[int, int], uid2idx_params: Dict[int, int], uid2idx_diff: Dict[int, int]) float | int | complex | None[source]

Evaluate one explicit initialization equation using the shared bindings.

Parameters:
  • eq (Union[Expr, Const]) – Symbolic expression or constant.

  • event_params_array (np.ndarray) – Runtime parameter values.

  • x (np.ndarray) – Algebraic or state vector.

  • params_array (np.ndarray) – Constant parameter vector.

  • dx (np.ndarray) – Differential initialization vector.

  • uid2idx_event_params (Dict[int, int]) – Event parameter index map.

  • uid2idx_vars (Dict[int, int]) – Variable index map.

  • uid2idx_params (Dict[int, int]) – Constant parameter index map.

  • uid2idx_diff (Dict[int, int]) – Differential variable index map.

Returns:

Evaluated scalar value.

Return type:

float

Raises:

RuntimeError – If a constant equation has no concrete value.

VeraGridEngine.Utils.Symbolic.explicit_initialization_symbolic.evaluate_single_equation_fn(eq_fn: Callable[[ndarray, ndarray, ndarray, ndarray], ndarray | float], x: ndarray, dx: ndarray, event_params_array: ndarray, params_array: ndarray) float[source]

Evaluate one compiled single-equation callable and normalize its scalar output.

The backend callable may return a length-one numpy vector or a scalar-like numeric value. The common initializer always consumes it as a float.

Parameters:
  • eq_fn (Callable[[np.ndarray, np.ndarray, np.ndarray, np.ndarray], Union[np.ndarray, float]]) – Compiled single-equation callable.

  • x (np.ndarray) – Algebraic or state vector.

  • dx (np.ndarray) – Differential initialization vector.

  • event_params_array (np.ndarray) – Runtime parameter values.

  • params_array (np.ndarray) – Constant parameter vector.

Returns:

Evaluated scalar value.

Return type:

float

VeraGridEngine.Utils.Symbolic.explicit_initialization_symbolic.init_explicit_common(mdl: Block, sys_vars: Dict[int, Var], sys_diff_vars: Dict[int, Var], variable_parameters: List[Var], event_parameters_eqs: List[Expr | Const], constant_parameters: List[Var], init_guess: Dict[int, float | int | complex | None], event_param_init_dict: Dict[int, float | int | complex | None], diff_init_guess: Dict[int, float | int | complex | None], uid2idx_vars: Dict[int, int], uid2idx_diff: Dict[int, int], uid2idx_params: Dict[int, int], uid2idx_event_params: Dict[int, int], params_array: ndarray, compile_single_equation: SymbolicVectorSingleEquationCompiler | RmsSingleEquationCompiler, verbose: bool = False) Tuple[Dict[int, float | int | complex | None], Dict[int, float | int | complex | None]][source]

Run the universal explicit initialization core shared by RMS and EMT flows.

Parameters:
  • sys_diff_vars

  • sys_vars

  • mdl (Block) – Symbolic model block.

  • variable_parameters (List[Var]) – Runtime or event parameters.

  • event_parameters_eqs (List[Union[Expr, Const]]) – Runtime parameter equations storage.

  • constant_parameters (List[Var]) – Constant parameters list.

  • init_guess (Dict[int, float]) – Initialization guesses for algebraic or state variables.

  • event_param_init_dict – Event parameter initialization dictionary.

  • diff_init_guess (Dict[int, float]) – Initialization guesses for differential variables.

  • uid2idx_vars (Dict[int, int]) – Variable index map.

  • uid2idx_diff (Dict[int, int]) – Differential variable index map.

  • uid2idx_params (Dict[int, int]) – Constant parameter index map.

  • uid2idx_event_params (Dict[int, int]) – Event parameter index map.

  • params_array (np.ndarray) – Constant parameter vector.

  • compile_single_equation (Union[SymbolicVectorSingleEquationCompiler, RmsSingleEquationCompiler]) – Backend-specific single-equation compiler wrapper.

  • verbose (bool) – Print initialization progress.

Returns:

Updated algebraic or state and differential guesses.

Return type:

Tuple[Dict[int, float], Dict[int, float]]

VeraGridEngine.Utils.Symbolic.explicit_initialization_symbolic.solve_self_implicit(eq_fn: Callable[[ndarray, ndarray, ndarray, ndarray], ndarray | float], x: ndarray, dx: ndarray, target_idx: int, target_array: ndarray, event_params_array: ndarray, params_array: ndarray, tol: float = 1e-08, max_iter: int = 50) float[source]

Solve a scalar self-implicit initialization equation with the shared signature.

Parameters:
  • eq_fn (Callable[[np.ndarray, np.ndarray, np.ndarray, np.ndarray], Union[np.ndarray, float]]) – Compiled single-equation callable.

  • x (np.ndarray) – Algebraic or state vector.

  • dx (np.ndarray) – Differential initialization vector.

  • target_idx (int) – Target index inside target_array.

  • target_array (np.ndarray) – Array holding the unknown being solved.

  • event_params_array (np.ndarray) – Runtime parameter values.

  • params_array (np.ndarray) – Constant parameter vector.

  • tol (float) – Secant convergence tolerance.

  • max_iter (int) – Maximum secant iterations.

Returns:

Solved scalar value.

Return type:

float

VeraGridEngine.Utils.Symbolic.explicit_initialization_symbolic.store_resolved_event_parameter(event_param: Var, event_params_init_dict: Dict[int, float | int | complex | None], event_parameters_eqs: List[Expr | Const], event_eq_idx: int, result: float | int | complex | None) None[source]

Store the calculated value in the equations array

param event_param:

type event_param:

param event_params_init_dict:

type event_params_init_dict:

param event_parameters_eqs:

Global runtime-parameter equation list.

type event_parameters_eqs:

List[Union[Expr, Const]]

param event_eq_idx:

Index of the runtime parameter in the global list.

type event_eq_idx:

int

param result:

Resolved scalar value.

type result:

float

return:

None

rtype:

None

VeraGridEngine.Utils.Symbolic.jit_compiler module

Module: JIT Equation Compiler & Numerical Discretization Engine

Abstract

This module implements a symbolic-to-numeric translation engine designed to generate optimized executable kernels for Differential-Algebraic Equation (DAE) systems. It operates by traversing the symbolic Abstract Syntax Tree (AST) of the model and injecting discrete time-stepping schemes (e.g., Implicit Trapezoidal, BDF2) directly into the residual evaluation code.

Architectural Rationale

The decoupling of the compilation logic from the DiffBlockSolver enforces a strict separation of concerns between the network topology management (Solver) and the numerical discretization strategy (Compiler). This abstraction allows for the interchangeability of integration methodsβ€”facilitating the switch between A-stable and L-stable schemesβ€”without altering the solver’s core iterative algorithms.

Performance Optimization

intermediate memory allocations typical of vectorized Numpy operations. This results in a monolithic residual evaluation function optimized for the high-frequency computation requirements of Electromagnetic Transient (EMT) simulations.

class VeraGridEngine.Utils.Symbolic.jit_compiler.ADVisitor(var_map: Dict[int, int], param_map: Dict[int, int], method: DiscretizationMethod, seeds_var: str = 'seeds', active_indices: set | None = None)[source]

Bases: SymbolicToPythonVisitor

active_indices
cse_has_dot: Set[str]
generic_visit(node: Expr, _: int) Tuple[str, str][source]
seeds_var
visit(node: Expr, precedence: int = 0) Tuple[str, str][source]

Dispatches node processing for Automatic Differentiation using explicit type matching.

visit_binop(node: BinOp, prec: int) Tuple[str, str][source]

Emit Python code for a binary operation with correct parentheses.

Important: - We do NOT just compare prec numerically in a naive way; we also handle

associativity for β€˜-’, β€˜/’, and β€˜**’ to avoid sign/structure bugs.

visit_const(node: Const, _: int) Tuple[str, str][source]
visit_diffvar(node: Var, prec: int) Tuple[str, str][source]
visit_func(node: Func, _: int) Tuple[str, str][source]
visit_unop(node: UnOp, _: int) Tuple[str, str][source]
visit_var(node: Var, _precedence: int) Tuple[str, str][source]
class VeraGridEngine.Utils.Symbolic.jit_compiler.BDF2Method[source]

Bases: DiscretizationMethod

discretize(state_idx: int, h_var: str = 'h') str[source]
discretize_dot(state_idx: int, h_var: str = 'h', seeds_var: str = 'seeds') str[source]
class VeraGridEngine.Utils.Symbolic.jit_compiler.BackwardEulerMethod[source]

Bases: DiscretizationMethod

discretize(state_idx: int, h_var: str = 'h') str[source]
discretize_dot(state_idx: int, h_var: str = 'h', seeds_var: str = 'seeds') str[source]
class VeraGridEngine.Utils.Symbolic.jit_compiler.ContinuousMethod[source]

Bases: DiscretizationMethod

Strategy for continuous systems (RMS Small Signal). Does not discretize.

discretize(state_idx: int, h_var: str = 'h') str[source]
discretize_dot(state_idx: int, h_var: str = 'h', seeds_var: str = 'seeds') str[source]
class VeraGridEngine.Utils.Symbolic.jit_compiler.DerivativeFunctionWrapper(raw_fn: Callable, diff_var_count: int)[source]

Bases: object

Callable derivative wrapper around one generated lag-derivative kernel.

class VeraGridEngine.Utils.Symbolic.jit_compiler.DiscretizationMethod[source]

Bases: ABC

Abstract base class for discretization strategies.

abstractmethod discretize(state_idx: int, h_var: str = 'h') str[source]
abstractmethod discretize_dot(state_idx: int, h_var: str = 'h', seeds_var: str = 'seeds') str[source]
class VeraGridEngine.Utils.Symbolic.jit_compiler.EagerEquationCompiler(variables: List[Var], parameters: List[Var] | None = None, method: DynamicIntegrationMethod = DAE_Trapezoidal)[source]

Bases: EquationCompiler

Strict eager compiler that emits in-place kernels with explicit signatures.

The generated functions do not allocate or return temporary arrays. Instead, they receive a caller-provided data_out vector and write their results in place. This removes Numba’s type inference cost at first call and reduces the runtime allocation pressure inside Newton iterations.

compile(equations: List[Expr], func_name: str = 'step_fn', use_cse: bool = True, offset: int = 0, inplace: bool = True) Tuple[Callable, object][source]

Compile residual equations into an in-place eager kernel.

Parameters:
  • equations (List[Expr]) – Residual equations to be emitted.

  • func_name (str) – Deterministic function name used in the source file.

  • use_cse (bool) – Whether to emit common subexpressions.

  • offset (int) – Output offset inside data_out.

  • inplace (bool) – Compatibility argument that must stay True.

Returns:

Pair (python_function, eager_signature).

Return type:

Tuple[Callable, object]

compile_ad_kernel(equations: List[Expr], func_name: str = 'ad_step', use_cse: bool = True, active_indices: set | None = None) Tuple[Callable, object][source]

Compile a sparse forward-mode AD kernel into an in-place eager function.

Parameters:
  • equations (List[Expr]) – Residual equations to differentiate.

  • func_name (str) – Deterministic function name used in the source file.

  • use_cse (bool) – Whether to emit common subexpressions.

  • active_indices (set | None) – Colored column subset activated in the current JVP sweep.

Returns:

Pair (python_function, eager_signature).

Return type:

Tuple[Callable, object]

compile_matrix_kernel(template_eq: Expr, func_name: str, template_vars: List[Var]) Tuple[Callable, object][source]

Compile a vectorized matrix kernel into an in-place eager function.

Parameters:
  • template_eq (Expr) – Canonical template equation for a structural group.

  • func_name (str) – Deterministic function name used in the source file.

  • template_vars (List[Var]) – Ordered runtime variables of the structural group.

Returns:

Pair (python_function, eager_signature).

Return type:

Tuple[Callable, object]

generate_signature(kernel_tpe: EagerKernelKind, n_variables: int, n_parameters: int, nnz: int, with_history2: bool = True) object[source]

Build the eager Numba signature for a generated kernel.

Parameters:
  • kernel_tpe (EagerKernelKind) – Kernel family to be compiled eagerly.

  • n_variables (int) – Number of runtime variables of the DAE system.

  • n_parameters (int) – Number of parameters visible to the kernel.

  • nnz (int) – Number of output values written by the kernel.

  • with_history2 (bool) – Whether the generated ABI includes history2.

Returns:

Numba eager signature object.

Return type:

object

class VeraGridEngine.Utils.Symbolic.jit_compiler.EagerKernelKind(value)[source]

Bases: Enum

Enumeration of eager kernel application binary interfaces.

The eager compiler needs an explicit kernel family because the Python source and the Numba signature differ between residual kernels, AD kernels and vectorized matrix kernels.

AutomaticDifferentiation = 'automatic_differentiation'
MatrixVectorized = 'matrix_vectorized'
Residual = 'residual'
class VeraGridEngine.Utils.Symbolic.jit_compiler.EmptySparseJacobianEvaluator(matrix: csc_matrix)[source]

Bases: object

Reusable callable returning one prebuilt empty CSC Jacobian matrix.

class VeraGridEngine.Utils.Symbolic.jit_compiler.EmptyVecSparseJacobianEvaluator(n_rows: int, n_cols: int)[source]

Bases: object

Reusable callable returning a zero 2D data array for vectorized Jacobians.

get_sparsity() Tuple[ndarray, ndarray, int, int][source]
class VeraGridEngine.Utils.Symbolic.jit_compiler.EquationCompiler(variables: List[Var], parameters: List[Var] | None = None, method: DynamicIntegrationMethod = DAE_Trapezoidal)[source]

Bases: object

Main interface for compiling symbolic equations into executable functions.

METHODS = {DAE_BackEuler: <VeraGridEngine.Utils.Symbolic.jit_compiler.BackwardEulerMethod object>, DAE_Continuous: <VeraGridEngine.Utils.Symbolic.jit_compiler.ContinuousMethod object>, DAE_Trapezoidal: <VeraGridEngine.Utils.Symbolic.jit_compiler.TrapezoidalMethod object>, DAE_bdf2: <VeraGridEngine.Utils.Symbolic.jit_compiler.BDF2Method object>}
compile(equations: List[Expr], func_name: str = 'step_fn', use_cse: bool = True, offset: int = 0, inplace: bool = False) Callable[source]
compile_ad_kernel(equations: List[Expr], func_name: str = 'ad_step', use_cse: bool = True, active_indices: set | None = None) Callable[source]
param_map
parameters_objs
strategy
var_map
variables_objs
visitor
class VeraGridEngine.Utils.Symbolic.jit_compiler.EventParameterFunctionWrapper(raw_fn: Callable, equation_count: int)[source]

Bases: object

Callable runtime-parameter wrapper around one generated event-parameter kernel.

class VeraGridEngine.Utils.Symbolic.jit_compiler.GeneratedKernelCache[source]

Bases: object

In-process cache for generated eager kernels keyed by structural signature.

get_entry(cache_kind: str, cache_key: str) GeneratedKernelCacheEntry | None[source]

Return one cached kernel entry.

Parameters:
  • cache_kind (str) – Cache family identifier.

  • cache_key (str) – Deterministic cache key.

Returns:

Cached entry or None.

Return type:

GeneratedKernelCacheEntry | None

set_entry(cache_kind: str, cache_key: str, entry: GeneratedKernelCacheEntry) None[source]

Store one cached kernel entry.

Parameters:
  • cache_kind (str) – Cache family identifier.

  • cache_key (str) – Deterministic cache key.

  • entry (GeneratedKernelCacheEntry) – Cache entry.

Returns:

None.

Return type:

None

class VeraGridEngine.Utils.Symbolic.jit_compiler.GeneratedKernelCacheEntry(python_function: Callable, signature_tpe: object)[source]

Bases: object

In-process cache entry for one generated eager kernel.

get_python_function() Callable[source]

Return the generated Python function.

Returns:

Generated Python function.

Return type:

Callable

get_signature_tpe() object[source]

Return the eager Numba signature.

Returns:

Eager Numba signature.

Return type:

object

class VeraGridEngine.Utils.Symbolic.jit_compiler.MatrixVectorizedCompiler(variables: List[Var], parameters: List[Var] | None = None, method: DynamicIntegrationMethod = DAE_Trapezoidal)[source]

Bases: EquationCompiler

Compiler utilizing the Matrix Vectorized Visitor. Generates kernels that accept β€˜indices’ as a 2D int32 array for batch processing.

compile_matrix_kernel(template_eq: Expr, func_name: str, template_vars: List[Var]) Callable[source]
class VeraGridEngine.Utils.Symbolic.jit_compiler.MatrixVectorizedVisitor(var_map: Dict[int, int], param_map: Dict[int, int], method: DiscretizationMethod, col_map: Dict[str, int])[source]

Bases: SymbolicToPythonVisitor

HPC-optimized visitor. Instead of performing dictionary lookups (slow), it accesses state variable indices directly from a mapping matrix (fast). Generates code such as: states[indices[:, 5]]

col_map
visit_diffvar(node: Var, prec: int) str[source]
visit_var(node: Var, _precedence: int) str[source]
class VeraGridEngine.Utils.Symbolic.jit_compiler.RMSCompiler(variables: List[Var], diff_vars: List[Var], v_params: List[Var], c_params: List[Var], dt_var: Var, compiler_names_dict: Dict[int, str])[source]

Bases: EquationCompiler

O(N) compiler for RMS (Root Mean Square) Continuous-Time Simulations.

This compiler generates highly optimized Right-Hand Side (RHS) vectors and Sparse Jacobian matrices using a structural analysis approach. By leveraging the official expression2numba translator, it ensures 100% mathematical consistency with legacy systems while drastically reducing symbolic evaluation and compilation times.

compile_derivative_fn(uid2idx_vars: Dict[int, int], func_name: str = 'derivative_fn') Callable[[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], float, ndarray[tuple[Any, ...], dtype[float64]]], ndarray[tuple[Any, ...], dtype[float64]]][source]

Compiles the derivative evaluation function for differential variables.

This is the equivalent of SymbolicDerivative.

Args:

uid2idx_vars (Dict[int, int]): Dictionary mapping var UIDs to their indices. func_name (str): The desired name for the compiled target function.

Returns:

Callable: An executable function with signature (vrs, lagvars, lagdx, h, out) -> out.

compile_event_params_fn(eqs: List[Expr], alias_names_dict: Dict[int, str], EVENT_PARAMS_NAME: str, TIME_NAME: str, func_name: str = 'event_params_fn') Callable[[ndarray[tuple[Any, ...], dtype[float64]], float, ndarray[tuple[Any, ...], dtype[float64]]], ndarray[tuple[Any, ...], dtype[float64]]][source]

Compiles event parameters equations into a fast, executable JIT function.

This is the equivalent of SymbolicParamsVector.

Args:

eqs (List[Expr]): The list of symbolic expressions for event parameters. alias_names_dict (Dict[int, str]): Dictionary mapping var UIDs to alias names. EVENT_PARAMS_NAME (str): Name of the event parameters array (e.g., β€œvprms”). TIME_NAME (str): Name of the time variable (e.g., β€œglob_time”). func_name (str): The desired name for the compiled target function.

Returns:

Callable: An executable function with signature (event_params, time, out) -> out.

compile_rhs(equations: List[Expr], func_name: str) Callable[[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]], ndarray[tuple[Any, ...], dtype[float64]]][source]

Compiles the residual equations (RHS) into a fast, executable JIT function.

Args:

equations (List[Expr]): The list of symbolic expressions to evaluate. func_name (str): The desired name for the compiled target function.

Returns:

Callable: An executable function computing the RHS residuals.

compile_sparse_jacobian(eqs: List[Expr], wrt_vars: List[Var], func_name: str) Callable[[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], float], csc_matrix][source]

Compiles a sparse Jacobian evaluator using an O(N) structural extraction algorithm.

Args:

eqs (List[Expr]): The list of symbolic equations (F or G). wrt_vars (List[Var]): The variables to differentiate with respect to (x or y). func_name (str): The desired name for the compiled target function.

Returns:

Callable: A function that populates and returns a scipy.sparse.csc_matrix.

compiler_names_dict
diff_vars
dt_var
v_params
class VeraGridEngine.Utils.Symbolic.jit_compiler.RMSCompilerVec(variables: List[Var], diff_vars: List[Var], v_params: List[Var], c_params: List[Var], dt_var: Var, compiler_names_dict: Dict[int, str])[source]

Bases: EquationCompiler

O(N) compiler for RMS (Root Mean Square) Continuous-Time Simulations.

This compiler generates highly optimized Right-Hand Side (RHS) vectors and Sparse Jacobian matrices using a structural analysis approach. By leveraging the official expression2numba translator, it ensures 100% mathematical consistency with legacy systems while drastically reducing symbolic evaluation and compilation times.

compile_derivative_fn(uid2idx_vars: Dict[int, int], func_name: str = 'derivative_fn') Callable[[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], float, ndarray[tuple[Any, ...], dtype[float64]]], ndarray[tuple[Any, ...], dtype[float64]]][source]

Compiles the derivative evaluation function for differential variables.

This is the equivalent of SymbolicDerivative.

Args:

uid2idx_vars (Dict[int, int]): Dictionary mapping var UIDs to their indices. func_name (str): The desired name for the compiled target function.

Returns:

Callable: An executable function with signature (vrs, lagvars, lagdx, h, out) -> out.

compile_event_params_fn(eqs: List[Expr], alias_names_dict: Dict[int, str], EVENT_PARAMS_NAME: str, TIME_NAME: str, func_name: str = 'event_params_fn') Callable[[ndarray[tuple[Any, ...], dtype[float64]], float, ndarray[tuple[Any, ...], dtype[float64]]], ndarray[tuple[Any, ...], dtype[float64]]][source]

Compiles event parameters equations into a fast, executable JIT function.

This is the equivalent of SymbolicParamsVector.

Args:

eqs (List[Expr]): The list of symbolic expressions for event parameters. alias_names_dict (Dict[int, str]): Dictionary mapping var UIDs to alias names. EVENT_PARAMS_NAME (str): Name of the event parameters array (e.g., β€œvprms”). TIME_NAME (str): Name of the time variable (e.g., β€œglob_time”). func_name (str): The desired name for the compiled target function.

Returns:

Callable: An executable function with signature (event_params, time, out) -> out.

compile_rhs(equations: List[Expr], func_name: str) Callable[[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]], ndarray[tuple[Any, ...], dtype[float64]]][source]

Compiles the residual equations (RHS) into a fast, executable JIT function.

Args:

equations (List[Expr]): The list of symbolic expressions to evaluate. func_name (str): The desired name for the compiled target function.

Returns:

Callable: An executable function computing the RHS residuals.

compile_sparse_jacobian(eqs: List[Expr], wrt_vars: List[Var], func_name: str) Callable[[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], float], ndarray][source]

Compiles a vectorized sparse Jacobian evaluator.

Args:

eqs (List[Expr]): The list of symbolic equations (F or G). wrt_vars (List[Var]): The variables to differentiate with respect to (x or y). func_name (str): The desired name for the compiled target function.

Returns:

Callable: A function that returns a 2D data array (nnz, n_instances).

compiler_names_dict
diff_vars
dt_var
v_params
class VeraGridEngine.Utils.Symbolic.jit_compiler.SparseJacobianEvaluatorVecWrapper(filler_fn: Callable, nnz: int, n_rows: int, n_cols: int, rows: List[int], cols: List[int], indices: ndarray, indptr: ndarray)[source]

Bases: object

Callable wrapper around a vectorized sparse Jacobian filler.

The filler function fills a 2D data_out array of shape (nnz, n_instances). This wrapper allocates the output array, calls the filler, and returns it. It also exposes the sparsity pattern (row indices, column pointers) so the problem class can assemble the global sparse Jacobian.

get_sparsity() Tuple[ndarray, ndarray, int, int][source]
class VeraGridEngine.Utils.Symbolic.jit_compiler.SparseJacobianEvaluatorWrapper(filler_fn: Callable, matrix: csc_matrix)[source]

Bases: object

Callable sparse Jacobian wrapper around one generated CSC filler function.

class VeraGridEngine.Utils.Symbolic.jit_compiler.SubexpressionAnalyzer(threshold: int = 2)[source]

Bases: object

Find and catalog subexpressions that appear multiple times. OPTIMIZED: Uses memoization for complexity calc and string generation.

analyze(equations: List[Expr]) Dict[str, str][source]
expr_complexity: Dict[str, int]
expr_counts: Dict[str, int]
expr_objects: Dict[str, Expr]
hash_expr(node: Expr) str[source]
memo_canonical: Dict[int, str]
memo_complexity: Dict[int, int]
threshold: int
visited_traversal: Set[int]
class VeraGridEngine.Utils.Symbolic.jit_compiler.SymbolicToPythonVisitor(var_map: Dict[int, int], param_map: Dict[int, int], method: DiscretizationMethod)[source]

Bases: object

OP_PRECEDENCE = {'*': 20, '**': 30, '+': 10, '-': 10, '/': 20}
analyzer
cse_map: Dict[str, str]
generic_visit(node: Expr, _: int) str[source]
in_cse_def
method
param_map
var_map
visit(node: Expr, precedence: int = 0) str[source]

Dispatches node processing using explicit type matching to avoid reflection.

Parameters:
  • node (Expr) – The symbolic expression node to visit.

  • precedence (int) – Operator precedence level.

Returns:

Python code string representation of the node.

Return type:

str

visit_binop(node: BinOp, prec: int) str[source]

Emit Python code for a binary operation with correct parentheses.

Important: - We do NOT just compare prec numerically in a naive way; we also handle

associativity for β€˜-’, β€˜/’, and β€˜**’ to avoid sign/structure bugs.

visit_const(node: Const, _precedence: int) str[source]
visit_diffvar(node: Var, prec: int) str[source]
visit_func(node: Func, _precedence: int) str[source]
visit_unop(node: UnOp, _precedence: int) str[source]
visit_var(node: Var, prec: int) str[source]
class VeraGridEngine.Utils.Symbolic.jit_compiler.TrapezoidalMethod[source]

Bases: DiscretizationMethod

discretize(state_idx: int, h_var: str = 'h') str[source]
discretize_dot(state_idx: int, h_var: str = 'h', seeds_var: str = 'seeds') str[source]

VeraGridEngine.Utils.Symbolic.lp_model module

class VeraGridEngine.Utils.Symbolic.lp_model.Constraint(expr: "'LinExpr'", lhs: 'float' = -1e+20, rhs: 'float' = 1e+20)[source]

Bases: object

classmethod eq(expr: LinExpr | Expr, rhs: int | float) Constraint[source]
expr: LinExpr
static from_sides(lhs: LinExpr | Expr | int | float, op: CmpOp, rhs: LinExpr | Expr | int | float) Constraint[source]
classmethod geq(expr: LinExpr | Expr, rhs: int | float) Constraint[source]
classmethod leq(expr: LinExpr | Expr, rhs: int | float) Constraint[source]
lhs: float
rhs: float
class VeraGridEngine.Utils.Symbolic.lp_model.LPModel[source]

Bases: object

add_var(name: str, low: float = -1e+20, up: float = 1e+20, integer: bool = False, start: float = 0.0) Var[source]
maximise(expr: Expr) None[source]
minimise(expr: Expr) None[source]
solve() Result[source]
class VeraGridEngine.Utils.Symbolic.lp_model.LinExpr(coeffs: Dict[Var, float], constant: float = 0.0)[source]

Bases: object

Linear expression

coeffs: Dict[Var, float]
constant: float
static from_expr(expr: Expr) LinExpr[source]
class VeraGridEngine.Utils.Symbolic.lp_model.Result(status: 'str', objective: 'float | None', primal: 'Dict[Var, float]', dual_row: 'List[float]')[source]

Bases: object

dual_row: List[float]
objective: float | None
primal: Dict[Var, float]
status: str
VeraGridEngine.Utils.Symbolic.lp_model.diet_problem() None[source]
VeraGridEngine.Utils.Symbolic.lp_model.knapsack_demo() None[source]

VeraGridEngine.Utils.Symbolic.static_parameter_mapping module

VeraGridEngine.Utils.Symbolic.static_parameter_mapping_rms module

VeraGridEngine.Utils.Symbolic.symbolic module

class VeraGridEngine.Utils.Symbolic.symbolic.BinOp(left: Expr, op: str, right: Expr, uid: int | None = None)[source]

Bases: Expr

Binary operation expression

contains_var(var: Var) bool[source]

Check if this expression contains the given variable. :param var: Variable to search for. :return: True if var is in this expression.

eval(**bindings: int | float | complex) int | float | complex[source]

Evaluation using names :param bindings: :return:

eval_uid(uid_bindings: Dict[int, float]) int | float | complex[source]

Evaluate using uuid’s :param uid_bindings: :return:

left: Expr
op: str
static parse(data: Dict[str, Any]) Expr[source]
right: Expr
simplify() Expr[source]

Simplify expression :return: Simplified expression

subs(mapping: Dict[Any, Expr]) Expr[source]

Substitution :param mapping: mapping of variables to expressions :return:

to_dict() Dict[str, Any][source]
Returns:

class VeraGridEngine.Utils.Symbolic.symbolic.CmpOp(value)[source]

Bases: Enum

comparisons

EQ = '='
GE = 'β‰₯'
GT = '>'
LE = '≀'
LT = '<'
class VeraGridEngine.Utils.Symbolic.symbolic.Comparison(lhs: Expr, op: CmpOp, rhs: Expr | int | float | complex)[source]

Bases: object

Symbolic comparison wrapper.

Parameters:
  • lhs – Left-hand side symbolic expression.

  • op – Comparison operator.

  • rhs – Right-hand side symbolic expression or numeric value.

lhs: Expr
op: CmpOp
rhs: Expr | int | float | complex
subs(mapping: Dict[Any, Expr]) Comparison[source]
to_expression() Expr[source]

Convert the comparison into a heaviside-based symbolic expression.

Returns:

Equivalent symbolic expression.

to_residual() Expr[source]
class VeraGridEngine.Utils.Symbolic.symbolic.Const(value: int | float | complex | None = None, uid: int | None = None, name: str = '')[source]

Bases: Expr

contains_var(var: Var) bool[source]

Check if this expression contains the given variable. :param var: Variable to search for. :return: True if var is in this expression.

eval(**bindings: int | float | complex) int | float | complex | None[source]

Numeric evaluation :param bindings: :return:

eval_uid(uid_bindings: Dict[int, float]) int | float | complex | None[source]
Parameters:

uid_bindings

Returns:

name: str
subs(mapping: Dict[Any, Expr]) Expr[source]

substitute variables :param mapping: :type mapping: :return: :rtype:

to_dict() Dict[str, Any][source]

returns a dictionary

Returns:

Return type:

value: int | float | complex | None
class VeraGridEngine.Utils.Symbolic.symbolic.Expr(uid: int | None = None)[source]

Bases: object

Abstract base class for all expression nodes.

contains_var(var: Var) bool[source]

Check if this expression contains the given variable. :param var: Variable to search for. :return: True if var is in this expression.

diff(var: Var | str, order: int = 1, dt: Var | None = None) Expr[source]

Differentiation (higher‑order) :param var: :param order: :param dt: :return:

eval(**bindings: float | int) float | int[source]

Numeric evaluation :param bindings: :return:

eval_uid(uid_bindings: Dict[int, float]) int | float | complex[source]
Parameters:

uid_bindings

Returns:

static from_dict(data: Dict[str, Any]) Expr[source]
static from_json(blob: str) Expr[source]
get_vars() List[Var][source]

Get all variables in this expression. :return: List of Var objects

simplify() Expr[source]

Simplification & substitution (no‑ops by default) :return:

subs(mapping: Dict[Any, Expr]) Expr[source]

substitute variables :param mapping: :type mapping: :return: :rtype:

to_dict() Dict[str, Any][source]

returns a dictionary

Returns:

Return type:

to_json(**json_kwargs: Any) str[source]
uid: int
class VeraGridEngine.Utils.Symbolic.symbolic.Func(arg: Expr, op: str = '', uid: int | None = None)[source]

Bases: Expr

arg: Expr
contains_var(var: Var) bool[source]

Check if this expression contains the given variable. :param var: Variable to search for. :return: True if var is in this expression.

eval(**bindings: int | float | complex) int | float | complex[source]

Numeric evaluation :param bindings: :return:

eval_uid(uid_bindings: Dict[int, int | float | complex]) int | float | complex[source]
Parameters:

uid_bindings

Returns:

op: str
static parse(data: Dict[str, Any]) Expr[source]
subs(mapping: Dict[Any, Expr]) Expr[source]

substitute variables :param mapping: :type mapping: :return: :rtype:

to_dict() Dict[str, Any][source]
Returns:

class VeraGridEngine.Utils.Symbolic.symbolic.Func2(name: str, arg1: Expr, arg2: Expr, uid: int | None = None)[source]

Bases: Expr

Symbolic binary function node.

Parameters:
  • name – Binary function name.

  • arg1 – First symbolic argument.

  • arg2 – Second symbolic argument.

  • uid – Optional node uid.

arg1: Expr
arg2: Expr
contains_var(var: Var) bool[source]

Check if this expression contains the given variable. :param var: Variable to search for. :return: True if var is in this expression.

eval(**bindings: int | float | complex) int | float | complex[source]

Numeric evaluation :param bindings: :return:

eval_uid(uid_bindings: Dict[int, int | float | complex]) int | float | complex[source]
Parameters:

uid_bindings

Returns:

name: str
simplify() Expr[source]

simplification

Returns:

Return type:

subs(mapping: Dict[Any, Expr]) Expr[source]

substitude

Parameters:

mapping

Returns:

Return type:

class VeraGridEngine.Utils.Symbolic.symbolic.SharedVarReferenceType(name: str, uid: int | None = None)[source]

Bases: object

name
uid: int
class VeraGridEngine.Utils.Symbolic.symbolic.UnOp(op: str, operand: Expr, uid: int | None = None)[source]

Bases: Expr

Unary operation expression

contains_var(var: Var) bool[source]

Check if this expression contains the given variable. :param var: Variable to search for. :return: True if var is in this expression.

eval(**bindings: int | float | complex) int | float | complex[source]
Parameters:

bindings

Returns:

eval_uid(uid_bindings: Dict[int, int | float | complex]) int | float | complex[source]
Parameters:

uid_bindings

Returns:

op: str
operand
static parse(data: Dict[str, Any]) Expr[source]
simplify() Expr[source]
Returns:

subs(mapping: Dict[Any, Expr]) Expr[source]
Parameters:

mapping

Returns:

to_dict() Dict[str, Any][source]
Returns:

class VeraGridEngine.Utils.Symbolic.symbolic.Var(name: str, reference: VarPowerFlowReferenceType | None = None, network_conn: bool = False, shared_reference: SharedVarReferenceType | None = None, non_mutable_uid: int | None = None, uid: int | None = None, diff_var: Var | None = None, base_var: Var | None = None)[source]

Bases: Expr

Any variable

approximation_expr(dt: Var | None, central: bool = False) Tuple[Expr, int][source]

Computes the n-th backward finite difference approximation of the derivative using the closed-form backward difference formula.

base_var: Var | None
contains_var(var: Var) bool[source]

Check if this expression contains the given variable. :param var: Variable to search for. :return: True if var is in this expression.

property diff_order: int
diff_var
eval(**bindings: float) float[source]

Evaluate this variable :param bindings: dictionary like mapping Var: float :return:

eval_uid(uid_bindings: Dict[int, float]) float[source]

Evaluate using the uid :param uid_bindings: :return:

name: str
property network_conn: bool
non_mutable_uid: int
property origin_var: Var
static parse(data: Dict[str, Any]) Var[source]

Parse the data :param data: :return:

populate_initial_lag(x0: float, dx0: ndarray, lag_x: float, dt: Const | None) float[source]

Populate the numeric lag state for the current derivative order.

Parameters:
  • x0 – Initial state value.

  • dx0

  • lag_x – Current lag value used as accumulation base.

  • dt

Returns:

Numeric lag initialization value.

property ref: VarPowerFlowReferenceType | None
property shared_ref: SharedVarReferenceType | None
subs(mapping: Dict[Var | str, Expr]) Expr[source]

Substitute this variable :param mapping: :return:

uid: int
VeraGridEngine.Utils.Symbolic.symbolic.abs(x: Expr) Expr[source]

Public symbolic absolute-value helper kept for API compatibility.

Parameters:

x – Symbolic argument.

Returns:

Symbolic absolute-value node.

VeraGridEngine.Utils.Symbolic.symbolic.acos(x: Expr) Expr[source]
VeraGridEngine.Utils.Symbolic.symbolic.asin(x: Expr) Expr[source]
VeraGridEngine.Utils.Symbolic.symbolic.atan(x: Expr) Expr[source]
VeraGridEngine.Utils.Symbolic.symbolic.atan2(x: Expr, y: Expr) Expr[source]
VeraGridEngine.Utils.Symbolic.symbolic.cos(x: Expr) Expr[source]
VeraGridEngine.Utils.Symbolic.symbolic.cosh(x: Expr) Expr[source]
VeraGridEngine.Utils.Symbolic.symbolic.diff(expr: Expr, var: Var | str, order: int = 1) Expr[source]

Return βˆ‚^order(expr)/βˆ‚var^order. :param expr: Expression :param var: Variable to differentiate against :param order: Derivative order :return: Derivative expression

VeraGridEngine.Utils.Symbolic.symbolic.eval_uid(expr: Expr, uid_bindings: Dict[int, int | float | complex]) int | float | complex[source]

Evaluate expr with a mapping from node UID β†’ numeric value. :param expr: :param uid_bindings: :return:

VeraGridEngine.Utils.Symbolic.symbolic.exp(x: Expr) Expr[source]
VeraGridEngine.Utils.Symbolic.symbolic.expression2numba(expr: Expr, compiler_names_dict: Dict[int, str], parent_prec: int = 0) str[source]

Emit a precedence-aware, Numba-friendly Python expression. Parentheses are added only when required.

VeraGridEngine.Utils.Symbolic.symbolic.f_exc(In: Expr) Expr[source]
VeraGridEngine.Utils.Symbolic.symbolic.find_vars_order(expressions: Expr | Sequence[Expr], ordering: Sequence[Var] | None = None, var_dict: Dict[int, Var] | None = None) List[Var][source]

Return the variable list that positional JIT functions will expect. :param expressions: Single expression or any iterable of expressions. :param ordering: Is provided, it overrides the default left‑to‑right order.

Items in ordering can be Var objects or variable names (strings).

Parameters:

var_dict – Dictionary of var uid to var ({v.uid: v for v in vars_list})

Returns:

VeraGridEngine.Utils.Symbolic.symbolic.get_expression_vars(expr: Expr, vars_found: List[Var] | None = None) List[Var][source]

Get the list of variables from any expression :param expr: Expression Expr :param vars_found: already existing list of vars :return: Final list of vars

VeraGridEngine.Utils.Symbolic.symbolic.get_namespace() Dict[str, Any][source]

Build the evaluation namespace used by generated expressions.

Returns:

Namespace dictionary for generated expressions.

VeraGridEngine.Utils.Symbolic.symbolic.get_symbolic_parser_function_names() List[str][source]

Return the public function names accepted by string_to_symbolic().

Returns:

VeraGridEngine.Utils.Symbolic.symbolic.hard_sat(x: Expr, x_min: Expr | int | float | complex, x_max: Expr | int | float | complex) Expr[source]

Apply a symbolic hard saturation to an expression.

Parameters:
  • x – Input expression.

  • x_min – Lower saturation limit.

  • x_max – Upper saturation limit.

Returns:

Symbolic saturation expression.

VeraGridEngine.Utils.Symbolic.symbolic.heaviside(x: Expr) Expr[source]
VeraGridEngine.Utils.Symbolic.symbolic.heaviside_num(x)[source]
VeraGridEngine.Utils.Symbolic.symbolic.log(x: Expr) Expr[source]
VeraGridEngine.Utils.Symbolic.symbolic.piecewise(time_var: Expr, t_events: ndarray, new_values: ndarray, default_value: Any) Expr[source]

Symbolic piecewise function. Returns default_value before the first event, then switches to corresponding new_values after each t_event.

Parameters

time_varExpr

Symbolic time expression

t_eventsnp.ndarray

1D array of event times (must be sorted ascending)

new_valuesnp.ndarray

1D array of values after each event time

default_valueAny

Value before the first event

VeraGridEngine.Utils.Symbolic.symbolic.sin(x: Expr) Expr[source]
VeraGridEngine.Utils.Symbolic.symbolic.sinh(x: Expr) Expr[source]
VeraGridEngine.Utils.Symbolic.symbolic.sqrt(x: Expr) Expr[source]
VeraGridEngine.Utils.Symbolic.symbolic.string_to_symbolic(expression_text: str, symbol_namespace: Mapping[str, Expr | int | float | complex]) Expr | Comparison[source]

Parse a textual symbolic expression into a symbolic tree using a safe AST walk.

Parameters:
  • expression_text

  • symbol_namespace

Returns:

VeraGridEngine.Utils.Symbolic.symbolic.symbolic_to_string(expr: Expr) str[source]

Convert a symbolic expression into a string (parsable by parse_expr).

VeraGridEngine.Utils.Symbolic.symbolic.tan(x: Expr) Expr[source]

VeraGridEngine.Utils.Symbolic.symbolic_io module

class VeraGridEngine.Utils.Symbolic.symbolic_io.BlockParser(var_factory: VarFactory)[source]

Bases: object

block_dict: Dict[int, Block]
parse_block(blocks_data: Dict[int, Dict[str, Any]], main_block_uid: int) Block[source]

Parse block as :param main_block_uid: :param blocks_data: :return:

parse_connections(data: Dict[int, List[Any]])[source]
Parameters:

data

Returns:

Return type:

parse_consts(data: List[Dict[str, Any]])[source]
Parameters:

data

Returns:

parse_diff_vars(data: List[Dict[str, Any]])[source]
Parameters:

data

Returns:

parse_references(data: List[Dict[str, Any]])[source]
Parameters:

data

Returns:

Return type:

parse_vars(data: List[Dict[str, Any]])[source]
Parameters:

data

Returns:

var_factory
class VeraGridEngine.Utils.Symbolic.symbolic_io.BlockSaver(var_factory: VarFactory)[source]

Bases: object

blocks: Dict[int, Dict[str, Any]]
get_blocks() Dict[int, Dict[str, Any]][source]
get_connections_to_save() Dict[int, List[Any]][source]
Returns:

Return type:

get_const_to_save() List[Dict[str, Any]][source]
Returns:

get_diff_vars_to_save() List[Dict[str, Any]][source]
Returns:

get_shared_references_to_save() List[Dict[str, Any]][source]
Returns:

Return type:

get_vars_to_save() List[Dict[str, Any]][source]
Returns:

main_block_uids: List[int]
save_block(blk: Block, main: bool = False) Dict[str, Any][source]

Get a dictionary representing the block All β€œglobal references” such a as Conts, Var and DiffVar are stored in the class for later :param blk: Block :param main: is it the main block? :return: Dictionary representing the block

var_factory
VeraGridEngine.Utils.Symbolic.symbolic_io.block_deep_copy(block: Block, var_factory: VarFactory)[source]

Create depp copy of a block :param block: :param var_factory: :return:

VeraGridEngine.Utils.Symbolic.symbolic_io.compare_blocks(block1: Block, block2: Block, var_factory1: VarFactory, var_factory2: VarFactory, testing=False)[source]

Create depp copy of a block :param block1: :param block2: :param var_factory: :param testing: :return:

VeraGridEngine.Utils.Symbolic.symbolic_io.connections_to_dict(obj_dict: Dict[int, List[Connection]]) Dict[int, List[Any]][source]
VeraGridEngine.Utils.Symbolic.symbolic_io.duplicate_block(block: Block, var_factory: VarFactory | None) Block[source]

Create a duplicate of this block with new variable UIDs.

The new block contains variables with the same names but different UIDs, and equations rebuilt using those new variables.

Parameters:
  • block – Source block.

  • var_factory – Variable factory used to allocate cloned variables and constants.

Returns:

A new Block with duplicated variables and equations.

VeraGridEngine.Utils.Symbolic.symbolic_io.duplicate_const(var_factory: VarFactory, old_to_new_const: Dict[int, Const], const: Const) Const[source]
Parameters:
  • var_factory

  • old_to_new_const

  • const

Returns:

VeraGridEngine.Utils.Symbolic.symbolic_io.duplicate_expr(var_factory: VarFactory, old_to_new_const: Dict[int, Const], old_to_new_var: Dict[int, Var], expr: Expr) Expr[source]
Parameters:
  • var_factory

  • old_to_new_const

  • old_to_new_var

  • expr

Returns:

VeraGridEngine.Utils.Symbolic.symbolic_io.duplicate_required_var(var_factory: VarFactory, old_to_new_var: Dict[int, Var], var: Var) Var[source]

Duplicate a variable that must exist in the source block structure.

Parameters:
  • var_factory – Variable factory used to allocate the cloned variable.

  • old_to_new_var – UID-to-variable clone map.

  • var – Source variable.

Returns:

Cloned variable.

VeraGridEngine.Utils.Symbolic.symbolic_io.duplicate_var(var_factory: VarFactory, old_to_new_var: Dict[int, Var], var: Var | None) Var | None[source]

Duplicate one symbolic variable while preserving UID-based reuse.

The helper now accepts None because some FMU/EMT external mappings intentionally leave optional references unresolved. In those cases the missing mapping must stay missing after the block clone.

Parameters:
  • var_factory – Variable factory used to allocate the cloned variable.

  • old_to_new_var – UID-to-variable clone map.

  • var – Source variable or None.

Returns:

Cloned variable or None.

VeraGridEngine.Utils.Symbolic.symbolic_io.expr_list_to_list(lst: List[Expr], const_dict: Dict[int, Const], var_dict: Dict[int, Var], diff_var_dict: Dict[int, Var]) List[Dict[str, Any]][source]
Parameters:
  • lst

  • const_dict

  • var_dict

  • diff_var_dict

Returns:

VeraGridEngine.Utils.Symbolic.symbolic_io.expr_to_dict(expr: Expr, const_dict: Dict[int, Const], var_dict: Dict[int, Var], diff_var_dict: Dict[int, Var]) Dict[str, Any][source]

Serialise any Expr tree into a plain Python dictionary that’s JSON-friendly. Each node type becomes a small dict that records:

  • its own type (β€œConst”, β€œVar”, β€œBinOp”, …)

  • the data it carries (value, name, operator…)

  • its unique uid (string, so it survives round-trip)

  • nested children (recursively serialised)

Parameters:
  • expr – Expression child

  • const_dict – Dictionary that keeps a reference of the Const objects already saved

  • var_dict – Dictionary that keeps a reference of the VAr objects already saved

  • diff_var_dict – Dictionary that keeps a reference of the DiffVar objects already saved

Returns:

Dict to save in jason

VeraGridEngine.Utils.Symbolic.symbolic_io.parse_expr(data: Dict[str, Any], const_dict: Dict[int, Const], var_dict: Dict[int, Var], diff_var_dict: Dict[int, Var]) Const | Var | UnOp | BinOp | Func | Func2[source]

De-Serialize expression from dictionary :param data: Some dictionary containing the expression :param const_dict: Dictionary that keeps a reference of the Const objects already saved :param var_dict: Dictionary that keeps a reference of the VAr objects already saved :param diff_var_dict: Dictionary that keeps a reference of the DiffVar objects already saved :return: Expression chil

VeraGridEngine.Utils.Symbolic.symbolic_io.parse_expr_list(lst: List[Dict[str, Any]], const_dict: Dict[int, Const], var_dict: Dict[int, Var], diff_var_dict: Dict[int, Var]) List[Const | Var | UnOp | BinOp | Func | Func2][source]
Parameters:
  • lst

  • const_dict

  • var_dict

  • diff_var_dict

Returns:

VeraGridEngine.Utils.Symbolic.symbolic_io.symbolic_objects_to_dict(obj_dict: Dict[int | str, Var | Const | SharedVarReferenceType]) List[Dict[str, Any]][source]

Save the list of all unique vars, diffvars and const :param obj_dict: Dictionary storing the unique objects :return: List of dictionaries representing each object

VeraGridEngine.Utils.Symbolic.symbolic_ml module

VeraGridEngine.Utils.Symbolic.symbolic_ml.exponential_ml(vf: VarFactory, x: Expr, name: str = '')[source]
VeraGridEngine.Utils.Symbolic.symbolic_ml.ml_f_exc(vf: VarFactory, In: Expr)[source]
VeraGridEngine.Utils.Symbolic.symbolic_ml.ml_hard_sat(vf: VarFactory, u: Expr, u_min: Expr, u_max: Expr, name: str = '', alternative_positive_part: bool = False, scale_balance: Expr | None = None, scale_complementarity: Expr | None = None, scale_equalities: Expr | None = None)[source]
VeraGridEngine.Utils.Symbolic.symbolic_ml.ml_hard_sat_sigmoid(vf: VarFactory, u: Expr, u_min: Expr, u_max: Expr, name: str = '', k: Expr = 20.0, exp_clip: Expr = 60.0)[source]
VeraGridEngine.Utils.Symbolic.symbolic_ml.ml_heaviside(vf: VarFactory, u: Expr, name: str = '')[source]
VeraGridEngine.Utils.Symbolic.symbolic_ml.ml_heaviside_sigmoid(vf: VarFactory, u: Expr, name: str = '', k: Expr = 20.0, exp_clip: Expr = 60.0)[source]
VeraGridEngine.Utils.Symbolic.symbolic_ml.ml_max(vf: VarFactory, u: Expr, v: Expr, alternative: bool = True, name: str = '')[source]
VeraGridEngine.Utils.Symbolic.symbolic_ml.ml_piecewise(vf: VarFactory, x: Expr, name: str = '', counter: int = 0) tuple[Expr, List[Block], int][source]

Recursively traverse expression x, replacing Heaviside() nodes with ml_heaviside() outputs and collecting Blocks. Each Heaviside gets a unique suffix via an integer counter.

VeraGridEngine.Utils.Symbolic.symbolic_ml.ml_piecewise_aux(vf: VarFactory, x: Expr, name: str = None)[source]
VeraGridEngine.Utils.Symbolic.symbolic_ml.ml_positive_part(vf: VarFactory, u: Expr, name: str = '', scale_balance: Expr | None = None, scale_complementarity: Expr | None = None, scale_equalities: Expr | None = None)[source]
VeraGridEngine.Utils.Symbolic.symbolic_ml.ml_positive_part_alt(vf: VarFactory, A: Expr, name: str = '')[source]
VeraGridEngine.Utils.Symbolic.symbolic_ml.mti_hard_sat(vf: VarFactory, u: Expr, ul: Expr, uu: Expr, yl: Expr, yu: Expr, name: str = '')[source]

MTI hard saturation following toolbox-style mixed constraints.

VeraGridEngine.Utils.Symbolic.symbolic_ml.mti_three_phase_carrier_pwm_direct(vf: VarFactory, ref_a: Expr, ref_b: Expr, ref_c: Expr, carrier: Expr, eps: Expr | float | int | None = None, name: str = '')[source]

Direct three-phase MTI carrier PWM comparator.

The generated gates follow the memoryless comparator rule gate = 1 when ref - carrier >= 0 and gate = 0 when ref - carrier <= 0. Inequalities use VeraGrid’s MTI convention G <= 0.

VeraGridEngine.Utils.Symbolic.symbolic_ml.mti_three_phase_carrier_pwm_direct_params(vf: VarFactory, name: str = '', eps: Expr | float | int | None = None, ref_a0: float = 0.0, ref_b0: float = 0.0, ref_c0: float = 0.0, carrier0: float = 0.0)[source]

Direct three-phase MTI carrier PWM comparator with input signals modeled as runtime parameters.

This mirrors toolbox-style u inputs in VeraGrid’s current block model by declaring u_ref_a, u_ref_b, u_ref_c and u_carrier in event_dict. The MTI inequalities then switch boolean gate modes from the parameter residuals u_ref_phase - u_carrier.

VeraGridEngine.Utils.Symbolic.symbolic_ml.mti_three_phase_carrier_pwm_internal_carrier_params(vf: VarFactory, name: str = '', omega_sw0: float = 6283.185307179586, direction_eps: Expr | float | int = 1e-09, ref_a0: float = 0.0, ref_b0: float = 0.0, ref_c0: float = 0.0, carrier0: float = -1.0, carrier_rising0: float = 1.0)[source]

Three-phase MTI PWM with runtime-parameter references and internal triangular carrier.

The reference signals are modeled as runtime parameters because the current VeraGrid MTI path has no first-class u input category. The triangular carrier direction is not external: it is represented by the internal boolean b_carrier_rise and the carrier is a continuous state with slope selected by that boolean.

VeraGridEngine.Utils.Symbolic.symbolic_ml.mti_three_phase_carrier_pwm_scheduled_params(vf: VarFactory, time: Expr, name: str = '', transition_eps: Expr | float | int = 1e-09, ref_a0: float = 0.0, ref_b0: float = 0.0, ref_c0: float = 0.0, interval_start0: float = 0.0, half_period0: float = 0.0005, carrier_rising0: float = 1.0)[source]

Scheduled-event MTI approximation of regular-sampled carrier PWM.

The block models the procedural PWM schedule explicitly: sampled references and interval timing are runtime parameters, while the phase transition modes are MTI booleans driven by time - t_cross inequalities.

VeraGridEngine.Utils.Symbolic.symbolic_ml.park_transform(vf: VarFactory, X: Var, ang: Var, delta: Var, multilinear: bool = False)[source]
VeraGridEngine.Utils.Symbolic.symbolic_ml.trig_transform(vf: VarFactory, u: Expr, type='usual')[source]
VeraGridEngine.Utils.Symbolic.symbolic_ml.trig_transform_diff(vf: VarFactory, delta1: Expr, delta2: Expr)[source]

VeraGridEngine.Utils.Symbolic.templates_common_functions module

VeraGridEngine.Utils.Symbolic.templates_common_functions.attach_emt_model_to_buses(device: Any, model: Block, var_factory: VarFactory, bus_mask: list[bool] | None = None, from_mask: list[bool] | None = None, to_mask: list[bool] | None = None) None[source]

Attach one EMT model to its bus shells using one shared engine workflow.

Parameters:
  • device – Device owning the EMT model.

  • model – Materialized EMT model block to attach.

  • var_factory – Shared symbolic variable factory.

  • bus_mask – Required single-bus mask for injection devices.

  • from_mask – Required from-side mask for branch devices.

  • to_mask – Required to-side mask for branch devices.

Returns:

None.

VeraGridEngine.Utils.Symbolic.templates_common_functions.build_emt_bus_mask_from_existing_model(bus_model: Block) list[bool][source]

Build the AC phase mask already materialized in one EMT bus model.

The shared EMT attachment flow must preserve the phases that already exist on one bus because other connected EMT devices may already depend on them. This helper reads the current bus external mapping and converts it into the canonical [N, A, B, C] phase mask used by the bus-shell ensure logic.

Parameters:

bus_model – Existing EMT bus block.

Returns:

Phase mask ordered as [N, A, B, C].

VeraGridEngine.Utils.Symbolic.templates_common_functions.cleanup_connected_emt_models_for_bus(bus: Any) None[source]

Remove stale EMT endpoint records from one bus-local registry.

The cleanup runs before every bus-driven reconnect so the algorithm only touches live endpoints that still belong to the bus and still reference the current device EMT model block.

Parameters:

bus – Bus whose EMT endpoint registry must be cleaned.

Returns:

None.

VeraGridEngine.Utils.Symbolic.templates_common_functions.connect_bus_variables_emt(device: Any, model: Block, var_factory: VarFactory | None, allow_deferred_connection: bool = False, grid: Any | None = None) None[source]

connect the bus variables of the model with the api_object bus variables :param device: :type device: :param model: :type model: :param var_factory: :type var_factory: :param allow_deferred_connection: :type allow_deferred_connection: :param grid: Owning circuit used for immediate EMT rebinding after bus rebuilds. :type grid: Any | None :return: :rtype:

VeraGridEngine.Utils.Symbolic.templates_common_functions.connect_bus_variables_rms(device: Any, model: Block, var_factory: VarFactory | None)[source]

connect the bus variables of the model with the api_object bus variables :param device: :type device: :param model: :type model: :param var_factory: :type var_factory: :return: :rtype:

VeraGridEngine.Utils.Symbolic.templates_common_functions.connect_injection_emt(mdl1: Block, mdl2: Block, var_factory: VarFactory) None[source]

Connect one bus EMT shell to one single-bus EMT injection model.

The bus shell exposes EMT bus voltages as outputs. Single-bus injection templates consume those same voltage references directly on their inputs, so the connection rule is one direct reference match per supported node.

Parameters:
  • mdl1 – Bus EMT model.

  • mdl2 – EMT model of one single-bus injection device.

  • var_factory

Returns:

None.

VeraGridEngine.Utils.Symbolic.templates_common_functions.connect_line_emt_from(mdl1: Block, mdl2: Block, var_factory: VarFactory)[source]

Connects the bus voltages (mdl1) to the β€œfrom” side of the line (mdl2) for simulations with explicit phases (e.g., EMT). It only connects the phases present in both models (any NABC combination).

Parameters:
  • mdl1 – Bus model (Block)

  • mdl2 – Line model (Block)

  • var_factory

Returns:

None

VeraGridEngine.Utils.Symbolic.templates_common_functions.connect_line_emt_to(mdl1: Block, mdl2: Block, var_factory: VarFactory)[source]

Connects the bus voltages (mdl1) to the β€œto” side of the line (mdl2) for simulations with explicit phases (e.g., EMT). It only connects the phases present in both models (any NABC combination).

Parameters:
  • mdl1 – Bus model (Block)

  • mdl2 – Line model (Block)

  • var_factory

Returns:

None

VeraGridEngine.Utils.Symbolic.templates_common_functions.connect_line_phasor_rms_from(mdl1: Block, mdl2: Block, var_factory: VarFactory)[source]

Connect phasor RMS models for the β€˜from’ end of a line. Connects Vr, Vi from bus to line inputs.

VeraGridEngine.Utils.Symbolic.templates_common_functions.connect_line_phasor_rms_to(mdl1: Block, mdl2: Block, var_factory: VarFactory)[source]

Connect phasor RMS models for the β€˜to’ end of a line. Connects Vr, Vi from bus to line inputs.

VeraGridEngine.Utils.Symbolic.templates_common_functions.connect_line_rms_from(mdl1: Block, mdl2: Block, var_factory: VarFactory)[source]

This function substitutes input variables for output variables to connect two rms models :param mdl1: :param mdl2: :param var_factory: :return:

VeraGridEngine.Utils.Symbolic.templates_common_functions.connect_line_rms_to(mdl1: Block, mdl2: Block, var_factory: VarFactory)[source]

This function substitutes input variables for output variables to connect two rms models :param mdl1: :param mdl2: :param var_factory: :return:

VeraGridEngine.Utils.Symbolic.templates_common_functions.connect_models(mdl1: Block, mdl2: Block, var_factory: VarFactory)[source]

This function substitutes input variables for output variables to connect two rms models :param mdl1: :param mdl2: :param var_factory: :return:

VeraGridEngine.Utils.Symbolic.templates_common_functions.connect_models_power_flow(mdl1: Block, mdl2: Block, var_factory: VarFactory)[source]

This function substitutes input variables for output variables to connect two rms models :param mdl1: :param mdl2: :param var_factory: :return:

VeraGridEngine.Utils.Symbolic.templates_common_functions.connect_pending_injection_bus_variables_emt(bus: Any, var_factory: VarFactory) None[source]

Connect deferred single-bus EMT devices once one bus shell exists.

The GUI can assign one injection EMT template before any branch template has created the bus EMT shell. In that case the device model is duplicated and queued on the bus. When one branch later materializes the bus shell, this helper completes the pending bus-to-device EMT connections.

Parameters:
  • bus – Bus whose pending EMT injection devices must be connected.

  • var_factory – Shared variable factory used to register rebinding connections.

Returns:

None.

VeraGridEngine.Utils.Symbolic.templates_common_functions.connect_vsc_emt_from(mdl1: Block, mdl2: Block, var_factory: VarFactory, is_dc_bus: bool = False)[source]

Connects the bus voltages to the β€œfrom” side of the VSC model. For DC buses, connects Vdc. For AC buses, connects abc voltages.

Parameters:
  • mdl1 – Bus model (Block)

  • mdl2 – VSC model (Block)

  • var_factory

  • is_dc_bus – True if bus_from is DC

Returns:

None

VeraGridEngine.Utils.Symbolic.templates_common_functions.connect_vsc_emt_to(mdl1: Block, mdl2: Block, var_factory: VarFactory, is_dc_bus: bool = False)[source]

Connects the bus voltages to the β€œto” side of the VSC model. For DC buses, connects Vdc. For AC buses, connects abc voltages.

Parameters:
  • mdl1 – Bus model (Block)

  • mdl2 – VSC model (Block)

  • var_factory

  • is_dc_bus – True if bus_to is DC

Returns:

None

VeraGridEngine.Utils.Symbolic.templates_common_functions.ensure_bus_emt_shell(bus: Any, required_mask: list[bool], var_factory: VarFactory) bool[source]

Ensure that one bus owns one EMT shell covering the required phases.

The EMT assignment algorithm must materialize a missing bus shell on first use and expand one existing AC shell only when one newly attached device requires additional phases.

Parameters:
  • bus – Bus whose EMT shell must exist.

  • required_mask – Required AC phase mask ordered as [N, A, B, C].

  • var_factory – Shared symbolic variable factory.

Returns:

True when the bus shell had to be rebuilt.

VeraGridEngine.Utils.Symbolic.templates_common_functions.reconnect_registered_emt_models_for_bus(bus: Any, var_factory: VarFactory) None[source]

Reconnect every live registered EMT endpoint for one rebuilt bus shell.

Rebuilding the bus shell changes the symbolic voltage variables. The bus must therefore rebind each registered EMT endpoint using the same connection rule that was used during the original device-to-bus attachment.

Parameters:
  • bus – Bus whose connected EMT endpoints must be rebound.

  • var_factory – Shared variable factory.

Returns:

None.

VeraGridEngine.Utils.Symbolic.templates_common_functions.register_connected_emt_model(bus: Any, device: Any, model: Block, side: EmtBusConnectionSide) None[source]

Register one live EMT endpoint on one bus.

The registry key is maintained at the bus level so future bus-shell rebuilds can rebind the connected model deterministically without requiring a global circuit scan.

Parameters:
  • bus – Bus that owns the registry.

  • device – Owning device of the EMT model.

  • model – Materialized EMT model block.

  • side – Semantic bus side used by the connection.

Returns:

None.

VeraGridEngine.Utils.Symbolic.templates_common_functions.register_saved_emt_model_vars_for_device(device: Any, var_factory: VarFactory) None[source]

Register the vars of one saved EMT model block in the shared variable factory.

Editor-driven EMT saves replace the concrete device.emt_model block vars through copy_block_state(). The saved block therefore contains fresh symbolic variables that are not automatically known by VarFactory. The subsequent bus-side reconnect step depends on var-factory identity propagation, so the saved model vars must be registered first.

Parameters:
  • device – Device whose saved EMT model vars must be registered.

  • var_factory – Shared variable factory.

Returns:

None.

VeraGridEngine.Utils.Symbolic.templates_common_functions.set_emt_model(device: Any, model: Block, var_factory: VarFactory)[source]

Sets the EMT model for a given device, connects it to the bus(es), and registers all its variables in the VarFactory.

Parameters:
  • device – The power system device (Line, Transformer, Generator, etc.)

  • model – The mathematical block model of the device

  • var_factory – Factory to register simulation variables

Returns:

None

VeraGridEngine.Utils.Symbolic.templates_common_functions.set_rms_model(device: Any, model: Block, var_factory: VarFactory)[source]

Set the RMS model :return: :rtype:

VeraGridEngine.Utils.Symbolic.templates_common_functions.synchronize_saved_emt_root_contract_from_bus(device: Any) None[source]

Copy live bus-shell identities into the saved EMT root contract.

The EMT validator compares the saved device external mapping directly against the live bus shell external mapping. After editor save, those saved device root contract vars can remain one disconnected clone from the live bus vars even when the graph structure and references are correct. Mirror the live bus-shell uid and name into the saved device contract in place so the saved editor graph remains unchanged while its bus bindings match the authoritative live bus shells.

Parameters:

device – Device whose saved EMT root contract must match the live buses.

Returns:

None.

VeraGridEngine.Utils.Symbolic.templates_common_functions.synchronize_saved_emt_root_contract_identity(device: Any) None[source]

Copy propagated root IO identities into the saved EMT external mapping.

After editor save, one EMT root external-mapping entry and the matching root IO var can still be distinct symbolic objects even when they represent the same power-flow reference. The bus connection helpers propagate the live bus identity through the root IO vars via VarFactory. The EMT validation reads the external mapping directly, so the saved external-mapping vars must mirror the propagated uid and name of the authoritative root IO vars without replacing the saved graph structure.

Parameters:

device – Device whose saved EMT root contract must mirror propagated identities.

Returns:

None.

VeraGridEngine.Utils.Symbolic.templates_common_functions.unify_saved_emt_model_root_contract(device: Any) None[source]

Unify one saved EMT model root external mapping with the actual root IO vars.

Editor-driven copy_block_state() can leave the saved EMT block with one root external_mapping var and a different root in_var/out_var for the same power-flow reference. The EMT checker reads the external mapping, while the reconnect helpers operate on root IO vars. Rewriting only the mapping dictionary is not enough; the whole saved symbolic graph must be updated so the authoritative root IO var becomes the single object used by the saved model for that contract reference.

Parameters:

device – Device whose saved EMT model root contract must be normalized.

Returns:

None.

VeraGridEngine.Utils.Symbolic.templates_common_functions.unregister_connected_emt_model(bus: Any, device: Any, side: EmtBusConnectionSide | None = None) None[source]

Remove one device EMT endpoint registration from one bus.

Parameters:
  • bus – Bus that owns the registry.

  • device – Device whose registration must be removed.

  • side – Optional side filter.

Returns:

None.

VeraGridEngine.Utils.Symbolic.templates_common_functions.unregister_connected_emt_model_from_attached_buses(device: Any) None[source]

Remove stale bus endpoint registrations for one device from all its attached buses.

This cleanup step runs before one device assigns or clears an EMT model so no bus registry keeps references to an obsolete block instance.

Parameters:

device – Device whose bus registrations must be removed.

Returns:

None.

VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence module

Standalone tests for symbolic expression equivalence system. This test file imports ONLY the minimal classes needed and does not trigger the full VeraGridEngine import chain.

class VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.BinOp(left, op, right, uid=None)[source]

Bases: object

left
op
right
uid
class VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.Const(value=None, uid=None, name='')[source]

Bases: object

name
uid
value
class VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.Func(arg, op='', uid=None)[source]

Bases: object

arg
op
uid
class VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.UnOp(op, operand, uid=None)[source]

Bases: object

op
operand
uid
class VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.Var(name, uid=None)[source]

Bases: object

name
uid
VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.canonical(expr)[source]
VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.cos(x)[source]
VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.equations_equivalent(eq1, eq2)[source]
VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.equivalent(e1, e2)[source]
VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.equivalent_expanded(e1, e2)[source]
VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.equivalent_systems(sys1, sys2)[source]
VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.expand(expr)[source]
VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.expand_and_canonicalize(expr)[source]
VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.run_all_tests()[source]
VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.sin(x)[source]
VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.structural_hash(expr)[source]
VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.structural_hash_expanded(expr)[source]
VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.test_associativity()[source]

Test (a + b) + c == a + (b + c)

VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.test_associativity_mult()[source]

Test (a * b) * c == a * (b * c)

VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.test_commutativity()[source]

Test a + b == b + a

VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.test_commutativity_mult()[source]

Test a * b == b * a

VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.test_complex_expression()[source]

Test more complex expressions

VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.test_constant_folding()[source]

Test constant folding

VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.test_equations_equivalent()[source]

Test equation equivalence considering a=b == b=a

VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.test_function_stability()[source]

Test sin(x + 0) == sin(x)

VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.test_neutral_elements()[source]

Test a + 0 = a, a * 1 = a

VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.test_polynomial_equivalence()[source]

Test (x + 1)^2 == x^2 + 2x + 1 using expanded comparison

VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.test_power_normalization()[source]

Test a**0 = 1, a**1 = a

VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.test_system_equivalence()[source]

Test that two systems with equations in different order are equivalent

VeraGridEngine.Utils.Symbolic.test_symbolic_equivalence.test_zero_product()[source]

Test a * 0 = 0

VeraGridEngine.Utils.Symbolic.test_variable_alignment module

Standalone tests for VariableAlignmentEngine. This test file imports ONLY the minimal classes needed.

class VeraGridEngine.Utils.Symbolic.test_variable_alignment.BinOp(left, op, right, uid=None)[source]

Bases: object

left
op
right
uid
class VeraGridEngine.Utils.Symbolic.test_variable_alignment.Const(value=None, uid=None, name='')[source]

Bases: object

name
uid
value
class VeraGridEngine.Utils.Symbolic.test_variable_alignment.DAGNode(op, children, structural_hash, expr=None)[source]

Bases: object

children
op
structural_hash
class VeraGridEngine.Utils.Symbolic.test_variable_alignment.Func(arg, op='', uid=None)[source]

Bases: object

arg
op
uid
class VeraGridEngine.Utils.Symbolic.test_variable_alignment.Func2(name, arg1, arg2, uid=None)[source]

Bases: object

arg1
arg2
name
uid
class VeraGridEngine.Utils.Symbolic.test_variable_alignment.UnOp(op, operand, uid=None)[source]

Bases: object

op
operand
uid
class VeraGridEngine.Utils.Symbolic.test_variable_alignment.Var(name, uid=None)[source]

Bases: object

name
uid
class VeraGridEngine.Utils.Symbolic.test_variable_alignment.VariableAlignmentEngine(sys1, sys2)[source]

Bases: object

compute_mapping()[source]
class VeraGridEngine.Utils.Symbolic.test_variable_alignment.VariableSignature(var_uid, occurrence_idx, context_hash, depth, path_signature)[source]

Bases: object

context_hash
depth
occurrence_idx
path_signature
var_uid
VeraGridEngine.Utils.Symbolic.test_variable_alignment.align_variables(sys1, sys2)[source]
VeraGridEngine.Utils.Symbolic.test_variable_alignment.canonical(expr)[source]
VeraGridEngine.Utils.Symbolic.test_variable_alignment.expand(expr)[source]
VeraGridEngine.Utils.Symbolic.test_variable_alignment.expand_and_canonicalize(expr)[source]
VeraGridEngine.Utils.Symbolic.test_variable_alignment.run_all_tests()[source]
VeraGridEngine.Utils.Symbolic.test_variable_alignment.structural_hash(expr)[source]
VeraGridEngine.Utils.Symbolic.test_variable_alignment.test_constants_ignored()[source]

Test that constants are properly ignored.

VeraGridEngine.Utils.Symbolic.test_variable_alignment.test_polynomial_system()[source]

Test polynomial system equivalence.

VeraGridEngine.Utils.Symbolic.test_variable_alignment.test_simple_linear_system()[source]

Test simple linear system with different variable names.

VeraGridEngine.Utils.Symbolic.test_variable_alignment.to_dag(expr, memo=None)[source]

VeraGridEngine.Utils.Symbolic.variable_alignment_engine module

VariableAlignmentEngine - Exact 1-to-1 Variable Mapping for Equivalent Systems.

Computes a deterministic bijection between variables of two mathematically equivalent systems of equations using structural hashing and backtracking.

class VeraGridEngine.Utils.Symbolic.variable_alignment_engine.VariableAlignmentEngine(sys1: List[Expr], sys2: List[Expr])[source]

Bases: object

Computes exact 1-to-1 mapping between variables of equivalent systems.

compute_mapping() Dict[int, int][source]

Main entry point. Computes the variable mapping.

class VeraGridEngine.Utils.Symbolic.variable_alignment_engine.VariableSignature(var_uid: int, occurrence_idx: int, context_hash: str, depth: int, path_signature: Tuple[str, ...])[source]

Bases: object

Immutable signature for a variable occurrence in an equation context.

context_hash
depth
occurrence_idx
path_signature
var_uid
VeraGridEngine.Utils.Symbolic.variable_alignment_engine.align_variables(sys1: List[Expr], sys2: List[Expr]) Dict[int, int][source]

Compute exact 1-to-1 variable mapping between two equivalent systems.

Args:

sys1: First system of equations sys2: Second system of equations

Returns:
Dict[int, int]: Mapping from sys1 variable uids to sys2 variable uids.

Empty dict if mapping fails.

Module contents