Source code for VeraGridEngine.Templates.Emt.transient_source_emt_template

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
# SPDX-License-Identifier: MPL-2.0

from __future__ import annotations

from typing import Dict, List

from VeraGridEngine.Devices.Dynamic.emt_template import EmtModelTemplate
from VeraGridEngine.Devices.Dynamic.var_factory import VarFactory
from VeraGridEngine.Templates.Emt.source_emt_template import _build_external_mapping
from VeraGridEngine.Templates.Emt.source_emt_template import _build_source_template_name
from VeraGridEngine.Templates.Emt.source_emt_template import _get_active_nabc_labels
from VeraGridEngine.Templates.Emt.source_emt_template import _get_current_reference
from VeraGridEngine.Templates.Emt.source_emt_template import _get_voltage_reference
from VeraGridEngine.Utils.Symbolic.block import Expr, Var
from VeraGridEngine.Utils.Symbolic import symbolic as sym
from VeraGridEngine.Utils.Symbolic.symbolic import CmpOp, Comparison
from VeraGridEngine.enumerations import DeviceType, VarPowerFlowReferenceType


def _build_time_state(vf: VarFactory, template: EmtModelTemplate, resolved_name: str) -> Var:
    """
    Build the internal source time state used by transient sources.

    :param vf: EMT variable factory.
    :param template: Target EMT template.
    :param resolved_name: Symbolic block name.
    :return: Internal source-time state variable.
    """
    time_var: Var = vf.add_var(name=f"t_src_{resolved_name}")
    diff_time_var: Var = vf.add_diff_var(name=f"d_t_src_{resolved_name}", base_var=time_var)
    template.block.state_vars = [time_var]
    template.block.diff_vars = [diff_time_var]
    template.block.state_eqs = [sym.Const(1.0)]
    template.block.init_eqs[time_var] = sym.Const(0.0)
    return time_var


def _comparison_expr(lhs: Expr, op: CmpOp, rhs: Expr) -> Expr:
    """
    Build one boolean-like expression from one symbolic comparison.

    :param lhs: Left-hand side expression.
    :param op: Comparison operator.
    :param rhs: Right-hand side expression.
    :return: Symbolic 0/1 expression.
    """
    return Comparison(lhs=lhs, op=op, rhs=rhs).to_expression()


def _build_step_expression(time_var: Var,
                           initial_value_var: Var,
                           final_value_var: Var,
                           step_time_var: Var) -> Expr:
    """
    Build one step waveform expression.

    :param time_var: Internal source time state.
    :param initial_value_var: Value before the step.
    :param final_value_var: Value after the step.
    :param step_time_var: Step time in seconds.
    :return: Step waveform expression.
    """
    step_selector: Expr = _comparison_expr(time_var, CmpOp.GE, step_time_var)
    return initial_value_var + step_selector * (final_value_var - initial_value_var)


def _build_ramp_expression(time_var: Var,
                           initial_value_var: Var,
                           final_value_var: Var,
                           start_time_var: Var,
                           end_time_var: Var) -> Expr:
    """
    Build one ramp waveform expression.

    :param time_var: Internal source time state.
    :param initial_value_var: Value before the ramp.
    :param final_value_var: Value after the ramp.
    :param start_time_var: Ramp start time in seconds.
    :param end_time_var: Ramp end time in seconds.
    :return: Ramp waveform expression.
    """
    progress_expr: Expr = sym.hard_sat(
        (time_var - start_time_var) / (end_time_var - start_time_var),
        sym.Const(0.0),
        sym.Const(1.0),
    )
    return initial_value_var + progress_expr * (final_value_var - initial_value_var)


def _build_double_exponential_expression(time_var: Var,
                                         amplitude_var: Var,
                                         alpha_var: Var,
                                         beta_var: Var,
                                         delay_var: Var) -> Expr:
    """
    Build one delayed double-exponential waveform expression.

    :param time_var: Internal source time state.
    :param amplitude_var: Overall amplitude scale.
    :param alpha_var: Slow exponential coefficient.
    :param beta_var: Fast exponential coefficient.
    :param delay_var: Emission delay in seconds.
    :return: Double-exponential waveform expression.
    """
    active_expr: Expr = _comparison_expr(time_var, CmpOp.GE, delay_var)
    delayed_time_expr: Expr = (time_var - delay_var) * active_expr
    return amplitude_var * (sym.exp(-alpha_var * delayed_time_expr) - sym.exp(-beta_var * delayed_time_expr)) * active_expr


def _build_heidler_expression(time_var: Var,
                              peak_var: Var,
                              front_time_var: Var,
                              tail_time_var: Var,
                              order_var: Var,
                              delay_var: Var) -> Expr:
    """
    Build one delayed Heidler current waveform expression.

    :param time_var: Internal source time state.
    :param peak_var: Peak-current scale.
    :param front_time_var: Front-time parameter in seconds.
    :param tail_time_var: Tail-time parameter in seconds.
    :param order_var: Heidler order exponent.
    :param delay_var: Emission delay in seconds.
    :return: Heidler waveform expression.
    """
    active_expr: Expr = _comparison_expr(time_var, CmpOp.GE, delay_var)
    delayed_time_expr: Expr = (time_var - delay_var) * active_expr
    ratio_expr: Expr = delayed_time_expr / front_time_var + sym.Const(1.0e-12)
    numerator_expr: Expr = ratio_expr ** order_var
    denominator_expr: Expr = sym.Const(1.0) + numerator_expr
    return peak_var * (numerator_expr / denominator_expr) * sym.exp(-delayed_time_expr / tail_time_var) * active_expr


def _build_cigre_expression(time_var: Var,
                            a_var: Var,
                            b_var: Var,
                            n_var: Var,
                            tn_var: Var,
                            i1_var: Var,
                            t1_var: Var,
                            i2_var: Var,
                            t2_var: Var,
                            delay_var: Var) -> Expr:
    """
    Build one delayed CIGRE surge waveform expression.

    :param time_var: Internal source time state.
    :param a_var: Front linear coefficient.
    :param b_var: Front nonlinear coefficient.
    :param n_var: Front exponent.
    :param tn_var: Front-to-tail transition time in seconds.
    :param i1_var: First tail amplitude.
    :param t1_var: First tail time constant in seconds.
    :param i2_var: Second tail amplitude.
    :param t2_var: Second tail time constant in seconds.
    :param delay_var: Emission delay in seconds.
    :return: CIGRE waveform expression.
    """
    active_expr: Expr = _comparison_expr(time_var, CmpOp.GE, delay_var)
    delayed_time_expr: Expr = (time_var - delay_var) * active_expr
    front_selector: Expr = _comparison_expr(delayed_time_expr, CmpOp.LT, tn_var)
    tail_selector: Expr = _comparison_expr(delayed_time_expr, CmpOp.GE, tn_var)
    tail_time_expr: Expr = (delayed_time_expr - tn_var) * tail_selector
    front_expr: Expr = a_var * delayed_time_expr + b_var * (delayed_time_expr ** n_var)
    tail_expr: Expr = i1_var * sym.exp(-tail_time_expr / t1_var) - i2_var * sym.exp(-tail_time_expr / t2_var)
    return active_expr * (front_expr * front_selector + tail_expr * tail_selector)


def _build_current_source_template_from_waveform(vf: VarFactory,
                                                 phN: bool,
                                                 phA: bool,
                                                 phB: bool,
                                                 phC: bool,
                                                 waveform_expr: Expr,
                                                 name: str) -> EmtModelTemplate:
    """
    Build one phase-selective EMT current source from one shared waveform expression.

    :param vf: EMT variable factory.
    :param phN: Whether neutral is active.
    :param phA: Whether phase A is active.
    :param phB: Whether phase B is active.
    :param phC: Whether phase C is active.
    :param waveform_expr: Shared waveform expression.
    :param name: Symbolic block name.
    :return: Configured EMT template.
    """
    active_labels: List[str] = _get_active_nabc_labels(phN=phN, phA=phA, phB=phB, phC=phC)
    resolved_name: str = _build_source_template_name(name, phN, phA, phB, phC, name)
    template: EmtModelTemplate = EmtModelTemplate()
    template.tpe = DeviceType.GeneratorDevice
    template.name = resolved_name
    template.block.name = resolved_name

    voltage_vars: Dict[str, Var] = dict()
    current_vars: Dict[str, Var] = dict()
    in_vars: List[Var] = list()
    algebraic_vars: List[Var] = list()
    algebraic_eqs: List[Expr] = list()
    out_vars: List[Var] = list()
    phase_label: str

    for phase_label in active_labels:
        voltage_var: Var = vf.add_var(name=f"v_{phase_label}_{resolved_name}", reference=_get_voltage_reference(phase_label))
        current_var: Var = vf.add_var(name=f"i_{phase_label}_{resolved_name}", reference=_get_current_reference(phase_label))
        voltage_vars[phase_label] = voltage_var
        current_vars[phase_label] = current_var
        in_vars.append(voltage_var)
        algebraic_vars.append(current_var)
        algebraic_eqs.append(current_var - waveform_expr)
        out_vars.append(current_var)
        template.block.init_eqs[current_var] = sym.Const(0.0)

    template.block.in_vars = in_vars
    template.block.algebraic_vars = algebraic_vars
    template.block.algebraic_eqs = algebraic_eqs
    template.block.out_vars = out_vars
    template.block.external_mapping = _build_external_mapping(voltage_vars, current_vars)
    return template


def _build_voltage_source_template_from_waveform(vf: VarFactory,
                                                 phN: bool,
                                                 phA: bool,
                                                 phB: bool,
                                                 phC: bool,
                                                 waveform_expr: Expr,
                                                 conductance_var: Var,
                                                 name: str) -> EmtModelTemplate:
    """
    Build one phase-selective EMT voltage source from one shared waveform expression.

    :param vf: EMT variable factory.
    :param phN: Whether neutral is active.
    :param phA: Whether phase A is active.
    :param phB: Whether phase B is active.
    :param phC: Whether phase C is active.
    :param waveform_expr: Shared waveform expression.
    :param conductance_var: Shared Norton conductance.
    :param name: Symbolic block name.
    :return: Configured EMT template.
    """
    active_labels: List[str] = _get_active_nabc_labels(phN=phN, phA=phA, phB=phB, phC=phC)
    resolved_name: str = _build_source_template_name(name, phN, phA, phB, phC, name)
    template: EmtModelTemplate = EmtModelTemplate()
    template.tpe = DeviceType.GeneratorDevice
    template.name = resolved_name
    template.block.name = resolved_name

    voltage_vars: Dict[str, Var] = dict()
    current_vars: Dict[str, Var] = dict()
    in_vars: List[Var] = list()
    algebraic_vars: List[Var] = list()
    algebraic_eqs: List[Expr] = list()
    out_vars: List[Var] = list()
    phase_label: str

    for phase_label in active_labels:
        voltage_var: Var = vf.add_var(name=f"v_{phase_label}_{resolved_name}", reference=_get_voltage_reference(phase_label))
        current_var: Var = vf.add_var(name=f"i_{phase_label}_{resolved_name}", reference=_get_current_reference(phase_label))
        voltage_vars[phase_label] = voltage_var
        current_vars[phase_label] = current_var
        in_vars.append(voltage_var)
        algebraic_vars.append(current_var)
        algebraic_eqs.append(current_var - conductance_var * (waveform_expr - voltage_var))
        out_vars.append(current_var)
        template.block.init_eqs[current_var] = sym.Const(0.0)

    template.block.in_vars = in_vars
    template.block.algebraic_vars = algebraic_vars
    template.block.algebraic_eqs = algebraic_eqs
    template.block.out_vars = out_vars
    template.block.external_mapping = _build_external_mapping(voltage_vars, current_vars)
    return template


[docs] def get_step_current_source_emt_template(vf: VarFactory, phN: bool = False, phA: bool = True, phB: bool = False, phC: bool = False, initial_value: float = 0.0, final_value: float = 1.0, step_time_s: float = 0.02, name: str | None = "step_current_source_emt") -> EmtModelTemplate: """ Build one phase-selective EMT step current source. :param vf: EMT variable factory. :param phN: Whether neutral is active. :param phA: Whether phase A is active. :param phB: Whether phase B is active. :param phC: Whether phase C is active. :param initial_value: Value before the step. :param final_value: Value after the step. :param step_time_s: Step time in seconds. :param name: Optional symbolic block name. :return: Configured EMT template. """ resolved_name: str = _build_source_template_name("step_current_source_emt", phN, phA, phB, phC, name) template = EmtModelTemplate() template.tpe = DeviceType.GeneratorDevice template.name = resolved_name template.block.name = resolved_name time_var: Var = _build_time_state(vf, template, resolved_name) initial_var: Var = vf.add_var(name=f"step_init_{resolved_name}") final_var: Var = vf.add_var(name=f"step_final_{resolved_name}") step_time_var: Var = vf.add_var(name=f"step_time_{resolved_name}") template.block.event_dict[initial_var] = vf.add_const(float(initial_value)) template.block.event_dict[final_var] = vf.add_const(float(final_value)) template.block.event_dict[step_time_var] = vf.add_const(float(step_time_s)) waveform_expr: Expr = _build_step_expression(time_var, initial_var, final_var, step_time_var) source_template: EmtModelTemplate = _build_current_source_template_from_waveform(vf, phN, phA, phB, phC, waveform_expr, resolved_name) source_template.block.state_vars = template.block.state_vars source_template.block.diff_vars = template.block.diff_vars source_template.block.state_eqs = template.block.state_eqs source_template.block.event_dict.update(template.block.event_dict) source_template.block.init_eqs.update(template.block.init_eqs) source_template.name = resolved_name source_template.block.name = resolved_name return source_template
[docs] def get_step_voltage_source_emt_template(vf: VarFactory, phN: bool = False, phA: bool = True, phB: bool = False, phC: bool = False, initial_value: float = 0.0, final_value: float = 1.0, step_time_s: float = 0.02, source_conductance_value: float = 100.0, name: str | None = "step_voltage_source_emt") -> EmtModelTemplate: """ Build one phase-selective EMT step voltage source. :param vf: EMT variable factory. :param phN: Whether neutral is active. :param phA: Whether phase A is active. :param phB: Whether phase B is active. :param phC: Whether phase C is active. :param initial_value: Value before the step. :param final_value: Value after the step. :param step_time_s: Step time in seconds. :param source_conductance_value: Norton conductance. :param name: Optional symbolic block name. :return: Configured EMT template. """ resolved_name: str = _build_source_template_name("step_voltage_source_emt", phN, phA, phB, phC, name) template = EmtModelTemplate() template.tpe = DeviceType.GeneratorDevice template.name = resolved_name template.block.name = resolved_name time_var: Var = _build_time_state(vf, template, resolved_name) initial_var: Var = vf.add_var(name=f"step_init_{resolved_name}") final_var: Var = vf.add_var(name=f"step_final_{resolved_name}") step_time_var: Var = vf.add_var(name=f"step_time_{resolved_name}") conductance_var: Var = vf.add_var(name=f"g_src_{resolved_name}") template.block.event_dict[initial_var] = vf.add_const(float(initial_value)) template.block.event_dict[final_var] = vf.add_const(float(final_value)) template.block.event_dict[step_time_var] = vf.add_const(float(step_time_s)) template.block.event_dict[conductance_var] = vf.add_const(float(source_conductance_value)) waveform_expr: Expr = _build_step_expression(time_var, initial_var, final_var, step_time_var) source_template: EmtModelTemplate = _build_voltage_source_template_from_waveform(vf, phN, phA, phB, phC, waveform_expr, conductance_var, resolved_name) source_template.block.state_vars = template.block.state_vars source_template.block.diff_vars = template.block.diff_vars source_template.block.state_eqs = template.block.state_eqs source_template.block.event_dict.update(template.block.event_dict) source_template.block.init_eqs.update(template.block.init_eqs) source_template.name = resolved_name source_template.block.name = resolved_name return source_template
[docs] def get_ramp_current_source_emt_template(vf: VarFactory, phN: bool = False, phA: bool = True, phB: bool = False, phC: bool = False, initial_value: float = 0.0, final_value: float = 1.0, start_time_s: float = 0.01, end_time_s: float = 0.03, name: str | None = "ramp_current_source_emt") -> EmtModelTemplate: """ Build one phase-selective EMT ramp current source. """ resolved_name: str = _build_source_template_name("ramp_current_source_emt", phN, phA, phB, phC, name) template = EmtModelTemplate() template.tpe = DeviceType.GeneratorDevice template.name = resolved_name template.block.name = resolved_name time_var: Var = _build_time_state(vf, template, resolved_name) initial_var: Var = vf.add_var(name=f"ramp_init_{resolved_name}") final_var: Var = vf.add_var(name=f"ramp_final_{resolved_name}") start_time_var: Var = vf.add_var(name=f"ramp_start_{resolved_name}") end_time_var: Var = vf.add_var(name=f"ramp_end_{resolved_name}") template.block.event_dict[initial_var] = vf.add_const(float(initial_value)) template.block.event_dict[final_var] = vf.add_const(float(final_value)) template.block.event_dict[start_time_var] = vf.add_const(float(start_time_s)) template.block.event_dict[end_time_var] = vf.add_const(float(end_time_s)) waveform_expr: Expr = _build_ramp_expression(time_var, initial_var, final_var, start_time_var, end_time_var) source_template: EmtModelTemplate = _build_current_source_template_from_waveform(vf, phN, phA, phB, phC, waveform_expr, resolved_name) source_template.block.state_vars = template.block.state_vars source_template.block.diff_vars = template.block.diff_vars source_template.block.state_eqs = template.block.state_eqs source_template.block.event_dict.update(template.block.event_dict) source_template.block.init_eqs.update(template.block.init_eqs) source_template.name = resolved_name source_template.block.name = resolved_name return source_template
[docs] def get_ramp_voltage_source_emt_template(vf: VarFactory, phN: bool = False, phA: bool = True, phB: bool = False, phC: bool = False, initial_value: float = 0.0, final_value: float = 1.0, start_time_s: float = 0.01, end_time_s: float = 0.03, source_conductance_value: float = 100.0, name: str | None = "ramp_voltage_source_emt") -> EmtModelTemplate: """ Build one phase-selective EMT ramp voltage source. """ resolved_name: str = _build_source_template_name("ramp_voltage_source_emt", phN, phA, phB, phC, name) template = EmtModelTemplate() template.tpe = DeviceType.GeneratorDevice template.name = resolved_name template.block.name = resolved_name time_var: Var = _build_time_state(vf, template, resolved_name) initial_var: Var = vf.add_var(name=f"ramp_init_{resolved_name}") final_var: Var = vf.add_var(name=f"ramp_final_{resolved_name}") start_time_var: Var = vf.add_var(name=f"ramp_start_{resolved_name}") end_time_var: Var = vf.add_var(name=f"ramp_end_{resolved_name}") conductance_var: Var = vf.add_var(name=f"g_src_{resolved_name}") template.block.event_dict[initial_var] = vf.add_const(float(initial_value)) template.block.event_dict[final_var] = vf.add_const(float(final_value)) template.block.event_dict[start_time_var] = vf.add_const(float(start_time_s)) template.block.event_dict[end_time_var] = vf.add_const(float(end_time_s)) template.block.event_dict[conductance_var] = vf.add_const(float(source_conductance_value)) waveform_expr: Expr = _build_ramp_expression(time_var, initial_var, final_var, start_time_var, end_time_var) source_template: EmtModelTemplate = _build_voltage_source_template_from_waveform(vf, phN, phA, phB, phC, waveform_expr, conductance_var, resolved_name) source_template.block.state_vars = template.block.state_vars source_template.block.diff_vars = template.block.diff_vars source_template.block.state_eqs = template.block.state_eqs source_template.block.event_dict.update(template.block.event_dict) source_template.block.init_eqs.update(template.block.init_eqs) source_template.name = resolved_name source_template.block.name = resolved_name return source_template
[docs] def get_double_exponential_current_source_emt_template(vf: VarFactory, phN: bool = False, phA: bool = True, phB: bool = False, phC: bool = False, amplitude_value: float = 1.0, alpha_value: float = 100.0, beta_value: float = 5000.0, delay_s: float = 0.0, name: str | None = "double_exponential_current_source_emt") -> EmtModelTemplate: """ Build one phase-selective EMT double-exponential current source. """ resolved_name: str = _build_source_template_name("double_exponential_current_source_emt", phN, phA, phB, phC, name) template = EmtModelTemplate() template.tpe = DeviceType.GeneratorDevice template.name = resolved_name template.block.name = resolved_name time_var: Var = _build_time_state(vf, template, resolved_name) amplitude_var: Var = vf.add_var(name=f"amp_{resolved_name}") alpha_var: Var = vf.add_var(name=f"alpha_{resolved_name}") beta_var: Var = vf.add_var(name=f"beta_{resolved_name}") delay_var: Var = vf.add_var(name=f"delay_{resolved_name}") template.block.event_dict[amplitude_var] = vf.add_const(float(amplitude_value)) template.block.event_dict[alpha_var] = vf.add_const(float(alpha_value)) template.block.event_dict[beta_var] = vf.add_const(float(beta_value)) template.block.event_dict[delay_var] = vf.add_const(float(delay_s)) waveform_expr: Expr = _build_double_exponential_expression(time_var, amplitude_var, alpha_var, beta_var, delay_var) source_template: EmtModelTemplate = _build_current_source_template_from_waveform(vf, phN, phA, phB, phC, waveform_expr, resolved_name) source_template.block.state_vars = template.block.state_vars source_template.block.diff_vars = template.block.diff_vars source_template.block.state_eqs = template.block.state_eqs source_template.block.event_dict.update(template.block.event_dict) source_template.block.init_eqs.update(template.block.init_eqs) source_template.name = resolved_name source_template.block.name = resolved_name return source_template
[docs] def get_heidler_current_source_emt_template(vf: VarFactory, phN: bool = False, phA: bool = True, phB: bool = False, phC: bool = False, peak_value: float = 1.0, front_time_s: float = 1.0e-4, tail_time_s: float = 5.0e-4, order_value: float = 4.0, delay_s: float = 0.0, name: str | None = "heidler_current_source_emt") -> EmtModelTemplate: """ Build one phase-selective EMT Heidler current source. """ resolved_name: str = _build_source_template_name("heidler_current_source_emt", phN, phA, phB, phC, name) template = EmtModelTemplate() template.tpe = DeviceType.GeneratorDevice template.name = resolved_name template.block.name = resolved_name time_var: Var = _build_time_state(vf, template, resolved_name) peak_var: Var = vf.add_var(name=f"peak_{resolved_name}") front_time_var: Var = vf.add_var(name=f"front_time_{resolved_name}") tail_time_var: Var = vf.add_var(name=f"tail_time_{resolved_name}") order_var: Var = vf.add_var(name=f"order_{resolved_name}") delay_var: Var = vf.add_var(name=f"delay_{resolved_name}") template.block.event_dict[peak_var] = vf.add_const(float(peak_value)) template.block.event_dict[front_time_var] = vf.add_const(float(front_time_s)) template.block.event_dict[tail_time_var] = vf.add_const(float(tail_time_s)) template.block.event_dict[order_var] = vf.add_const(float(order_value)) template.block.event_dict[delay_var] = vf.add_const(float(delay_s)) waveform_expr: Expr = _build_heidler_expression(time_var, peak_var, front_time_var, tail_time_var, order_var, delay_var) source_template: EmtModelTemplate = _build_current_source_template_from_waveform(vf, phN, phA, phB, phC, waveform_expr, resolved_name) source_template.block.state_vars = template.block.state_vars source_template.block.diff_vars = template.block.diff_vars source_template.block.state_eqs = template.block.state_eqs source_template.block.event_dict.update(template.block.event_dict) source_template.block.init_eqs.update(template.block.init_eqs) source_template.name = resolved_name source_template.block.name = resolved_name return source_template
[docs] def get_cigre_surge_current_source_emt_template(vf: VarFactory, phN: bool = False, phA: bool = True, phB: bool = False, phC: bool = False, a_value: float = 1000.0, b_value: float = 10000.0, n_value: float = 2.0, tn_s: float = 1.0e-4, i1_value: float = 1.0, t1_s: float = 5.0e-4, i2_value: float = 0.5, t2_s: float = 2.0e-4, delay_s: float = 0.0, name: str | None = "cigre_surge_current_source_emt") -> EmtModelTemplate: """ Build one phase-selective EMT CIGRE surge current source. """ resolved_name: str = _build_source_template_name("cigre_surge_current_source_emt", phN, phA, phB, phC, name) template = EmtModelTemplate() template.tpe = DeviceType.GeneratorDevice template.name = resolved_name template.block.name = resolved_name time_var: Var = _build_time_state(vf, template, resolved_name) a_var: Var = vf.add_var(name=f"a_{resolved_name}") b_var: Var = vf.add_var(name=f"b_{resolved_name}") n_var: Var = vf.add_var(name=f"n_{resolved_name}") tn_var: Var = vf.add_var(name=f"tn_{resolved_name}") i1_var: Var = vf.add_var(name=f"i1_{resolved_name}") t1_var: Var = vf.add_var(name=f"t1_{resolved_name}") i2_var: Var = vf.add_var(name=f"i2_{resolved_name}") t2_var: Var = vf.add_var(name=f"t2_{resolved_name}") delay_var: Var = vf.add_var(name=f"delay_{resolved_name}") template.block.event_dict[a_var] = vf.add_const(float(a_value)) template.block.event_dict[b_var] = vf.add_const(float(b_value)) template.block.event_dict[n_var] = vf.add_const(float(n_value)) template.block.event_dict[tn_var] = vf.add_const(float(tn_s)) template.block.event_dict[i1_var] = vf.add_const(float(i1_value)) template.block.event_dict[t1_var] = vf.add_const(float(t1_s)) template.block.event_dict[i2_var] = vf.add_const(float(i2_value)) template.block.event_dict[t2_var] = vf.add_const(float(t2_s)) template.block.event_dict[delay_var] = vf.add_const(float(delay_s)) waveform_expr: Expr = _build_cigre_expression(time_var, a_var, b_var, n_var, tn_var, i1_var, t1_var, i2_var, t2_var, delay_var) source_template: EmtModelTemplate = _build_current_source_template_from_waveform(vf, phN, phA, phB, phC, waveform_expr, resolved_name) source_template.block.state_vars = template.block.state_vars source_template.block.diff_vars = template.block.diff_vars source_template.block.state_eqs = template.block.state_eqs source_template.block.event_dict.update(template.block.event_dict) source_template.block.init_eqs.update(template.block.init_eqs) source_template.name = resolved_name source_template.block.name = resolved_name return source_template