Line-faults

within PowerSystems.AC3ph;
package Faults "Line-faults "
  extends Modelica.Icons.VariantsPackage;

  model Short_ABC "a, b, c to ground short, 3-phase dq0"
    extends Partials.FaultBase;

    Real[3] s;

  equation
    v_pos = v_abc[n_phRef] > 0;

    {v,i} = if on then {epsR*s,s} else {s,epsG*s};
  end Short_ABC;

                model Fault_bc "b to c fault, 3-phase dq0"
    extends Partials.Fault_pp(final n_ph=1);
                end Fault_bc;

  model Fault_ca "c to a fault, 3-phase dq0"
    extends Partials.Fault_pp(final n_ph=2);
  end Fault_ca;

  model Fault_ab "a to b fault, 3-phase dq0"
    extends Partials.Fault_pp(final n_ph=3);
  end Fault_ab;

  model Fault_abc "a to b to c fault, 3-phase dq0"
    extends Partials.FaultBase;

    parameter Integer n_ph=1 "double connected phase, 2=(1-2,2-3)";
    replaceable Common.Switching.Short fault_pp1(
      final on=on,
      final epsR=epsR,
      final epsG=epsG) "fault model"
    replaceable Common.Switching.Short fault_pp2(
      final on=on,
      final epsR=epsR,
      final epsG=epsG) "fault model"
  protected
    final parameter Integer[2] m_ph=pair[n_ph, :];

  equation
    fault_pp1.v = v_abc[m_ph[1]] - v_abc[n_ph];
    fault_pp1.i = i_abc[m_ph[1]];
    fault_pp2.v = v_abc[m_ph[2]] - v_abc[n_ph];
    fault_pp2.i = i_abc[m_ph[2]];

    v_pos = v_abc[n_phRef] > 0;
    i[3] = epsG*v[3];
  //  sum(i_abc) = epsG*sum(v_abc);
  end Fault_abc;

  model Fault_A "a to ground fault, 3-phase dq0"
    extends Partials.Fault_pg(final n_ph=1);
  end Fault_A;

  model Fault_B "b to ground fault, 3-phase dq0"
    extends Partials.Fault_pg(final n_ph=2);
  end Fault_B;

  model Fault_C "c to ground fault, 3-phase dq0"
    extends Partials.Fault_pg(final n_ph=3);
  end Fault_C;

  model Fault_bC "b to c to ground fault, 3-phase dq0"
    extends Partials.Fault_ppg(final n_ph=1);
  end Fault_bC;

  model Fault_cA "c to a to ground fault, 3-phase dq0"
    extends Partials.Fault_ppg(final n_ph=2);
  end Fault_cA;

  model Fault_aB "a to b to ground fault, 3-phase dq0"
    extends Partials.Fault_ppg(final n_ph=3);
  end Fault_aB;

  model Fault_Abc "b to a, c to a, a to ground fault, 3-phase dq0"
    extends Partials.Fault_pppg(final n_ph=1);
  end Fault_Abc;

  model Fault_aBc "a to b, c to b, b to ground fault, 3-phase dq0"
    extends Partials.Fault_pppg(final n_ph=2);
  end Fault_aBc;

  model Fault_abC "a to c, b to c, c to ground fault, 3-phase dq0"
    extends Partials.Fault_pppg(final n_ph=3);
  end Fault_abC;

  package Partials "Partial models"
    extends Modelica.Icons.BasesPackage;

    partial model FaultBase "Line fault base, 3-phase dq0"
      extends Ports.Port_f;

      parameter SI.Time t_on=0.1 "approx time fault on";
      parameter SI.Angle phi_on(min=0)=0 "voltage phase angle fault on";
      parameter Integer n_phRef(min=1,max=3)=1 "of reference phase"
      parameter SI.Resistance epsR=1e-4 "resistance 'fault'";
      parameter SI.Conductance epsG=1e-4 "conductance 'no fault'";

      parameter PS.Voltage[3] v_abc_start = zeros(3)
        "start value of voltage phase a, b, c"

      PS.Voltage[3] v "voltage";
      PS.Current[3] i "current";
      PS.Voltage[3] v_abc(each stateSelect=StateSelect.never, start = v_abc_start)
        "voltage phase a, b, c";
      PS.Current[3] i_abc(each stateSelect=StateSelect.never)
        "current phase a, b, c";
    protected
      constant Integer[3, 2] pair=[2, 3; 3, 1; 1, 2];
      discrete SI.Angle theta_zero(start=Modelica.Constants.inf, fixed=true);
      Boolean on(final start=false, fixed=true);
      Boolean v_pos(start=true, fixed=true);
      Boolean first(start=true, fixed=true);
      Real[3,3] Park=Utilities.Transforms.park(term.theta[2]);

    equation
      v = term.v;
      term.i = i;
      v = Park*v_abc;
      i_abc = transpose(Park)*i;

      when time > t_on and edge(v_pos) and pre(first) then
        theta_zero = sum(term.theta);
        first = false;
      end when;
      on = sum(term.theta) > pre(theta_zero) + phi_on;
    end FaultBase;

    partial model Fault_pp "Two-phase fault, 3-phase dq0"
      extends FaultBase(final n_phRef=n_ph);

      parameter Integer n_ph(min=1,max=3)=1 "faulted pair"
      replaceable Common.Switching.Short fault_pp(
        final on=on,
        final epsR=epsR,
        final epsG=epsG) "fault model"
    //extends Common.Switching.Partials.FaultBase
    protected
      final parameter Integer[2] m_ph=pair[n_ph, :];

    equation
      fault_pp.v=v_abc[m_ph[1]] - v_abc[m_ph[2]];
      fault_pp.i=i_abc[m_ph[1]];

      v_pos = v_abc[m_ph[1]] - v_abc[m_ph[2]] > 0;
      i_abc[n_ph] = epsG*v_abc[n_ph];
      sum(i_abc[m_ph]) = epsG*sum(v_abc[m_ph]);
    end Fault_pp;

    partial model Fault_pg "One-phase to ground fault, 3-phase dq0"
      extends FaultBase(final n_phRef=n_ph);

      parameter Integer n_ph(min=1,max=3)=1 "faulted phase"
      replaceable Common.Switching.Short fault_pg(
        final on=on,
        final epsR=epsR,
        final epsG=epsG) "fault model"
    //  extends Common.Switching.Partials.FaultBase
    protected
      final parameter Integer[2] m_ph=pair[n_ph, :];

    equation
      fault_pg.v=v_abc[n_ph];
      fault_pg.i=i_abc[n_ph];

      v_pos = v_abc[n_phRef] > 0;
      i_abc[m_ph] = epsG*v_abc[m_ph];
    end Fault_pg;

    partial model Fault_ppg "Two-phase to ground fault, 3-phase dq0"
      extends FaultBase(final n_phRef=n_ph);

      parameter Integer n_ph(min=1,max=3)=1 "faulted pair"
      replaceable Common.Switching.Short fault_pp(
        final on=on,
        final epsR=epsR,
        final epsG=epsG) "fault model"
    //  extends Common.Switching.Partials.FaultBase
      replaceable Common.Switching.Short fault_pg(
        final on=on,
        final epsR=epsR,
        final epsG=epsG) "fault model"
    //  extends Common.Switching.Partials.FaultBase
    protected
      final parameter Integer[2] m_ph=pair[n_ph, :];

    equation
      fault_pp.v=v_abc[m_ph[1]] - v_abc[m_ph[2]];
      fault_pp.i=i_abc[m_ph[1]];
      fault_pg.v=v_abc[m_ph[2]];
      fault_pg.i=sum(i_abc[m_ph]);

      v_pos = v_abc[m_ph[1]] - v_abc[m_ph[2]] > 0;
      i_abc[n_ph] = epsG*v_abc[n_ph];
    end Fault_ppg;

    partial model Fault_pppg "Three-phase to ground fault, 3-phase dq0"
      extends FaultBase;

      parameter Integer n_ph(min=1,max=3)=1 "which phase to ground"
      replaceable Common.Switching.Short fault_pp1(
        final on=on,
        final epsR=epsR,
        final epsG=epsG) "fault model"
    //  extends Common.Switching.Partials.FaultBase
      replaceable Common.Switching.Short fault_pp2(
        final on=on,
        final epsR=epsR,
        final epsG=epsG) "fault model"
    //  extends Common.Switching.Partials.FaultBase
      replaceable Common.Switching.Short fault_pg(
        final on=on,
        final epsR=epsR,
        final epsG=epsG) "fault model"
    //  extends Common.Switching.Partials.FaultBase
    protected
      final parameter Integer[2] m_ph=pair[n_ph, :];

    equation
      fault_pp1.v=v_abc[m_ph[1]] - v_abc[n_ph];
      fault_pp1.i=i_abc[m_ph[1]];
      fault_pp2.v=v_abc[m_ph[2]] - v_abc[n_ph];
      fault_pp2.i=i_abc[m_ph[2]];
      fault_pg.v = v_abc[n_ph];
      fault_pg.i = sum(i_abc);

      v_pos = v_abc[n_ph] > 0;
    end Fault_pppg;

  end Partials;
end Faults;


Turbo generator groups dq0

within PowerSystems.AC3ph;
package Generation "Turbo generator groups dq0"
  extends Modelica.Icons.VariantsPackage;

  model TurboGenerator "Turbo generator single mass"
    extends Partials.GenBase_el;

    replaceable model Rotor = PowerSystems.Mechanics.TurboGroups.SingleMassTG (
      final w_start=w_start,
      final H=H,
      final P_nom=generator.par.S_nom,
      final w_nom=w_nom) "single-mass rotor (turbine-rotor + generator-rotor)"
    Rotor rotor "single-mass rotor (turbine-rotor + generator-rotor)"

  equation
    connect(rotor.airgap, generator.airgap)
    connect(rotor.speed, governor.speed)
    connect(governor.power, rotor.power)
  end TurboGenerator;

  model TurboGrpGenerator "Example turbogroup generator"
    extends Partials.GenBase_el(final H=h);

    replaceable model Torque =
      PowerSystems.Mechanics.TurboGroups.PcontrolTorque (
        final w_nom=turboGroup.par.w_nom, final P_nom=turboGroup.par.P_nom)
      "torque-model"
    Torque turbTorq "torque-model"

    replaceable model TurboGroup =
      PowerSystems.Mechanics.TurboGroups.SteamTurboGroup (
        final w_start=w_start) "steam turbo-goup with generator-rotor"
    TurboGroup turboGroup "steam turbo-goup with generator-rotor"
  protected
    final parameter SI.Time h=(sum(turboGroup.par.J_turb) +
        turboGroup.par.J_gen + sum(turboGroup.par.J_aux))*w_nom^2/(2
        *generator.par.S_nom) "inertia cst turb + gen";

  equation
    connect(turbTorq.blades, turboGroup.blades)
    connect(turboGroup.airgap, generator.airgap)
    connect(turbTorq.speed, governor.speed)
    connect(governor.power, turbTorq.power)
  end TurboGrpGenerator;

  model GTGenerator "Example gas turbine generator"
    extends Partials.GenBase_el(final H=h);

    replaceable model Torque =
      PowerSystems.Mechanics.TurboGroups.PcontrolTorque (
        final w_nom=GT.par.w_nom, final P_nom=GT.par.P_nom) "torque-model"
    Torque turbTorq "torque-model"

    replaceable model Gear =
      PowerSystems.Mechanics.TurboGroups.GasTurbineGear(final w_start=w_start)
      "gas turbine with gear and generator-rotor"
    Gear GT "gas turbine with gear and generator-rotor"
  protected
    final parameter Real[3] gr2=diagonal(GT.par.ratio)*GT.par.ratio/GT.par.ratio[end]^2;
    final parameter SI.Inertia J_red=(GT.par.J_turb + GT.par.J_comp)
        *gr2[1] + GT.par.J_gear1*gr2[1:2] + GT.par.J_gear2*gr2[2:3] + (GT.par.J_acc
         + GT.par.J_cpl + GT.par.J_gen) "gear reduced inertia";
    final parameter SI.Time h=J_red*w_nom^2/(2*generator.par.S_nom);

  equation
    assert(abs(2*pi*generator.par.f_nom/(generator.par.pp*GT.par.w_nom) - 1) < 1e-3,
      "nominal rpm, frequency and pole-pair number seems to be incompatible");
    connect(turbTorq.blades, GT.blades)
    connect(GT.airgap, generator.airgap)
    connect(turbTorq.speed, governor.speed)
    connect(governor.power, turbTorq.power)
  end GTGenerator;

  model HydroGenerator "Hydro generator"
    extends Partials.GenBase_el(final H=h);

    replaceable model Torque =
      PowerSystems.Mechanics.TurboGroups.PcontrolTorque (
        final w_nom=hydro.par.w_nom, final P_nom={hydro.par.P_nom})
      "torque-model"
    Torque turbTorq "torque-model"

    replaceable model HydroTurbine =
      PowerSystems.Mechanics.TurboGroups.HydroTurbine(final w_start=w_start)
      "hydro turbine with generator-rotor"
    HydroTurbine hydro "hydro turbine with generator-rotor"
  protected
    final parameter SI.Time h=(hydro.par.J_turb + hydro.par.J_gen)
        *w_nom^2/(2*generator.par.S_nom);

  equation
    assert(abs(2*pi*generator.par.f_nom/(generator.par.pp*hydro.par.w_nom) - 1) < 1e-3,
      "nominal rpm, frequency and pole-pair number seems to be incompatible");
    connect(turbTorq.blades, hydro.blades)
    connect(hydro.airgap, generator.airgap)
    connect(turbTorq.speed, governor.speed)
    connect(governor.power, turbTorq.power)
  end HydroGenerator;

  model DieselGenerator "Diesel generator"
    extends Partials.GenBase_el(final H=h);

    replaceable model Torque =
      PowerSystems.Mechanics.TurboGroups.PcontrolTorque (
        final w_nom=diesel.par.w_nom, final P_nom={diesel.par.P_nom})
      "torque-model"
    Torque turbTorq "torque-model"

    replaceable model Diesel = PowerSystems.Mechanics.TurboGroups.Diesel (
      final w_start=w_start) "Diesel engine with generator-rotor"
    Diesel diesel "Diesel engine with generator-rotor"
  protected
    final parameter SI.Time h=(diesel.par.J_turb + diesel.par.J_gen)
        *w_nom^2/(2*generator.par.S_nom);

  equation
    assert(abs(2*pi*generator.par.f_nom/(generator.par.pp*diesel.par.w_nom) - 1) < 1e-3,
      "nominal rpm, frequency and pole-pair number seems to be incompatible");
    connect(turbTorq.blades, diesel.blades)
    connect(diesel.airgap, generator.airgap)
    connect(turbTorq.speed, governor.speed)
    connect(governor.power, turbTorq.power)
  end DieselGenerator;

  model TurboPMgenerator "Turbo generator single mass, permanent magnet"
    extends Partials.GenBase;

    parameter SI.AngularVelocity w_start=2*pi*generator.par.f_nom/generator.par.pp
      "initial angular velocity (start-value if ini='st')";
    AC3ph.Ports.ACdq0_n term "negative terminal"
    Modelica.Blocks.Interfaces.RealInput[2] setpts
      "setpoints {speed, power} pu"
    Modelica.Blocks.Interfaces.RealOutput phiRotor "rotor angle el"
    replaceable model Generator = PowerSystems.AC3ph.Machines.Synchron3rd_pm
      "synchron pm generator"
    Generator generator "synchron pm generator"
    replaceable model Governor = PowerSystems.Control.Governors.GovernorConst
      "governor (control)"
    Governor governor "governor (control)"
    parameter SI.Time H=10 "inertia cst turb + gen";
    replaceable model Rotor = PowerSystems.Mechanics.TurboGroups.SingleMassTG (
      final w_start=w_start,
      final H=H,
      final P_nom=generator.par.S_nom,
      final w_nom=w_nom) "single-mass rotor (turbine-rotor + generator-rotor)"
    Rotor rotor "single-mass rotor (turbine-rotor + generator-rotor)"
  protected
    final parameter SI.AngularVelocity w_nom=2*pi*generator.par.f_nom/generator.par.pp
      "nominal angular velocity";

  equation
    connect(setpts[1], governor.setptSpeed)
    connect(setpts[2], governor.setptPower)
    connect(rotor.speed, governor.speed)
    connect(governor.power, rotor.power)
    connect(rotor.airgap, generator.airgap)
    connect(generator.heat, heat)
    connect(generator.term, term)
    connect(generator.phiRotor, phiRotor)
  end TurboPMgenerator;

  model PMgenerator "Generator inverter time-average"
    extends Partials.GenBase_ctrl(heat_adapt(final m={2,inverter.heat.m}));

    replaceable model Generator =
      PowerSystems.AC3ph.Machines.Synchron3rd_pm_ctrl
        "synchron pm generator"
    Generator generator "synchron pm generator"
    replaceable model Inverter = PowerSystems.AC3ph.Inverters.InverterAverage
      constrainedby PowerSystems.AC3ph.Inverters.Partials.AC_DC_base
      "inverter (average or modulated)"
    Inverter inverter "inverter (average or modulated)"

  equation
    connect(rotor.flange_b, generator.airgap)
    connect(generator.term, inverter.AC)
    connect(inverter.DC, term)
    connect(generator.heat, heat_adapt.port_a)
    connect(inverter.heat, heat_adapt.port_b)
    connect(generator.phiRotor, inverter.theta)
    connect(generator.vPhasor,inverter.vPhasor)
    connect(generator.i_meas, i_meas)
    connect(i_act, generator.i_act)
  end PMgenerator;

  model WindGenerator "Wind generator"
    extends Partials.GenBase;

    parameter SI.AngularVelocity w_start=2*pi*generator.par.f_nom/generator.par.pp
      "initial angular velocity (start-value if ini='st')"
    AC3ph.Ports.ACdq0_n term "negative terminal"
    replaceable model Generator = PowerSystems.AC3ph.Machines.Asynchron
      "asynchron generator"
    Generator generator "asynchron generator"
    replaceable model Torque = PowerSystems.Mechanics.TurboGroups.WindTabTorque
        (
      final w_nom=WT.par.w_nom, final P_nom=WT.par.P_nom)
      "table: wind speed, torque"
    Torque turbTorq "table: wind speed, torque"
    replaceable model Gear =
      PowerSystems.Mechanics.TurboGroups.WindTurbineGear(final w_start= w_start)
      "wind turbine with generator-rotor"
    Gear WT "wind turbine with generator-rotor"
    Modelica.Blocks.Interfaces.RealInput windSpeed "wind speed m/s"
  equation
    connect(windSpeed, turbTorq.windSpeed)
    connect(turbTorq.blades, WT.blades[1])
    connect(WT.airgap, generator.airgap)
    connect(generator.term, term)
    connect(generator.heat, heat)
  end WindGenerator;

  package Partials "Partial models"
    partial model GenBase0 "Generation base"

      Interfaces.ThermalV_n heat(m=2) "heat source port {stator, rotor}"
    protected
      outer System system;
    end GenBase0;
    extends Modelica.Icons.BasesPackage;

    partial model GenBase "Generation base"
      extends GenBase0;

      AC3ph.Ports.ACdq0_n term "negative terminal"
    end GenBase;

    partial model GenBase_el "Generation base el, synchron machines"
      extends GenBase;

      parameter SI.AngularVelocity w_start=2*pi*generator.par.f_nom/generator.par.pp
        "initial angular velocity (start-value if steady-state)"
      parameter Types.Init initType=PowerSystems.Types.Init.v_alpha
        "initialisation type (if steady-state)"
      parameter SIpu.Voltage v_start(unit="1")=1 "initial terminal voltage"
      parameter SI.Angle alpha_start=system.alpha0 "initial voltage phase angle"
      parameter SIpu.Power p_start(unit="1")=1 "initial terminal active power"
      parameter SIpu.Power q_start(unit="1")=1 "initial terminal reactive power"
      parameter Boolean dispPA=false "display power angle"
      AC3ph.Ports.ACdq0_n term "negative terminal"
      Modelica.Blocks.Interfaces.RealInput[3] setpts
        "setpoints {speed, power, voltage} pu"
      replaceable model Generator = PowerSystems.AC3ph.Machines.Synchron3rd_ee
        "synchron generator"
      Generator generator "synchron generator"

      replaceable model Exciter = Control.Exciters.ExciterConst
        "exciter (control)"
      Exciter exciter "exciter (control)"

      replaceable model Excitation =
          PowerSystems.AC3ph.Machines.Control.Excitation (
        V_nom = generator.par.V_nom, Vf_nom = generator.Vf_nom)
        "exciter (electric)"
      Excitation excitation "exciter (electric)"

      replaceable model Governor = PowerSystems.Control.Governors.GovernorConst
        "governor (control)"
      Governor governor "governor (control)"

      parameter SI.Time H=10 "inertia cst turb + gen";
    protected
      final parameter SI.AngularVelocity w_nom=2*pi*generator.par.f_nom/generator.par.pp
        "nominal angular velocity";
      Interfaces.Sender sender(w=generator.w_el, H=H)
        "sends weighted frequency"
      function atan2 = Modelica.Math.atan2;

    initial equation
      if initType == PowerSystems.Types.Init.v_alpha then
        sqrt(term.v[1:2]*term.v[1:2]) = v_start*generator.par.V_nom;
        atan2(term.v[2], term.v[1]) = alpha_start;
      elseif initType == PowerSystems.Types.Init.v_p then
        sqrt(term.v[1:2]*term.v[1:2]) = v_start*generator.par.V_nom;
        -term.v[1:2]*term.i[1:2] = p_start*generator.par.S_nom;
      elseif initType == PowerSystems.Types.Init.v_q then
        sqrt(term.v[1:2]*term.v[1:2]) = v_start*generator.par.V_nom;
        -{term.v[2],-term.v[1]}*term.i[1:2] = q_start*generator.par.S_nom;
      elseif initType == PowerSystems.Types.Init.p_q then
        -term.v[1:2]*term.i[1:2] = p_start*generator.par.S_nom;
        -{term.v[2],-term.v[1]}*term.i[1:2] = q_start*generator.par.S_nom;
      end if;

    equation
      if initType == PowerSystems.Types.Init.v_alpha then
        Connections.potentialRoot(term.theta);
      end if;
      if Connections.isRoot(term.theta) then
        term.theta = if system.synRef then {0, system.theta} else {system.theta, 0};
      end if;
      connect(sender.sendFreq, system.receiveFreq);
      connect(term, generator.term)
      connect(exciter.fieldVoltage,excitation.fieldVoltage)
      connect(excitation.termVoltage, exciter.termVoltage)
      connect(setpts[1], governor.setptSpeed)
      connect(setpts[2], governor.setptPower)
      connect(setpts[3], exciter.setptVoltage)
      connect(generator.term, excitation.term)
      connect(excitation.field, generator.field)
      connect(generator.heat, heat)
    end GenBase_el;

    partial model GenBase_ctrl "Generation base pm, synchronous machines"
      extends GenBase0(heat(final m=sum(heat_adapt.m)));

      parameter SI.AngularVelocity w_start=0
        "initial rpm (start-value if steady init)"
      Interfaces.Rotation_p flange
      AC1ph_DC.Ports.TwoPin_n term "negative terminal"
      Common.Thermal.HeatV_a_b_ab heat_adapt
      replaceable model Gear = PowerSystems.Mechanics.Rotational.NoGear
        "type of gear"
      Gear gear "type of gear"

      replaceable model Rotor = PowerSystems.Mechanics.Rotational.Rotor (
        w(start=w_start)) "rotor generator"
      Rotor rotor "rotor generator"

      Modelica.Blocks.Interfaces.RealOutput[2] i_meas(each final unit="1")
        "measured current {i_d, i_q} pu"
      Modelica.Blocks.Interfaces.RealInput[2] i_act(each final unit="1")
        "actuated current {i_d, i_q} pu"

    equation
      connect(heat_adapt.port_ab, heat)
      connect(flange,gear.flange_a)
      connect(gear.flange_b,rotor.flange_a)
    end GenBase_ctrl;

  end Partials;
end Generation;


Impedance and admittance two terminal

within PowerSystems.AC3ph;
package Impedances "Impedance and admittance two terminal"
  extends Modelica.Icons.VariantsPackage;

  model Resistor "Resistor, 3-phase dq0"
    extends Partials.ImpedBase(final f_nom=0, final dynType=Types.Dynamics.SteadyState);

    parameter SIpu.Resistance r=1 "resistance";
  protected
    final parameter SI.Resistance R=r*Utilities.Precalculation.baseR(
          puUnits,
          V_nom,
          S_nom);

  equation
    R*i = v;
  end Resistor;

  model Conductor "Conductor, 3-phase dq0"
    extends Partials.ImpedBase(final f_nom=0, final dynType=Types.Dynamics.SteadyState);

    parameter SIpu.Conductance g=1 "conductance";
  protected
    final parameter SI.Conductance G=g/Utilities.Precalculation.baseR(
          puUnits,
          V_nom,
          S_nom);

  equation
    G*v = i;
  end Conductor;

  model Inductor "Inductor with series resistor, 3-phase dq0"
    extends Partials.ImpedBase;

    parameter SIpu.Resistance r=0 "resistance";
    parameter SIpu.Reactance x_s=1 "self reactance";
    parameter SIpu.Reactance x_m=0 "mutual reactance, -x_s/2 < x_m < x_s";
  protected
    final parameter Real[2] RL_base=Utilities.Precalculation.baseRL(
          puUnits,
          V_nom,
          S_nom,
          2*pi*f_nom);
    final parameter SI.Resistance R=r*RL_base[1];
    final parameter SI.Inductance L=(x_s-x_m)*RL_base[2];
    final parameter SI.Inductance L0=(x_s+2*x_m)*RL_base[2];

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(i) = omega[1]*j(i);
    elseif dynType == Types.Dynamics.FixedInitial then
      i = i_start;
    end if;

  equation
    if dynType <> Types.Dynamics.SteadyState then
      PS.map({L,L,L0}).*der(i) + omega[2]*L*j(i) + R*i = v;
    else
      omega[2]*L*j(i) + R*i = v;
    end if;
  end Inductor;

  model Capacitor "Capacitor with parallel conductor, 3-phase dq0"
    extends Partials.ImpedBase;

    parameter SIpu.Conductance g=0 "conductance";
    parameter SIpu.Susceptance b=1 "susceptance";
  protected
    final parameter SI.Resistance[2] GC_base=Utilities.Precalculation.baseGC(
          puUnits,
          V_nom,
          S_nom,
          2*pi*f_nom);
    final parameter SI.Conductance G=g*GC_base[1];
    final parameter SI.Capacitance C=b*GC_base[2];

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(v) = omega[1]*j(v);
    elseif dynType == Types.Dynamics.FixedInitial then
      v = v_start;
    end if;

  equation
    if dynType <> Types.Dynamics.SteadyState then
      C*der(v) + omega[2]*C*j(v) + G*v = i;
    else
      omega[2]*C*j(v) + G*v = i;
    end if;
  end Capacitor;

  model Impedance "Impedance (inductive) with series resistor, 3-phase dq0"
    extends Partials.ImpedBase;

    parameter SIpu.Impedance z_abs=1 "abs value of impedance";
    parameter Real cos_phi(min=0,max=1)=0.1 "cos-phi of impedance";
    parameter Real cpl(min=-0.5,max=1)=0
      "phase coupling x_m/x_s, -1/2 < cpl < 1";
  protected
    final parameter SI.Resistance[2] RL_base=Utilities.Precalculation.baseRL(
          puUnits,
          V_nom,
          S_nom,
          2*pi*f_nom);
    function acos = Modelica.Math.acos;
    final parameter SI.Resistance R=z_abs*cos_phi*RL_base[1];
    final parameter SI.Inductance L=z_abs*sin(acos(cos_phi))*RL_base[2];
    final parameter SI.Inductance L0=L*(1 + 2*cpl)/(1-cpl);

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(i) = omega[1]*j(i);
    elseif dynType == Types.Dynamics.FixedInitial then
      i = i_start;
    end if;

  equation
    if dynType <> Types.Dynamics.SteadyState then
      PS.map({L,L,L0}).*der(i) + omega[2]*L*j(i) + R*i = v;
    else
      omega[2]*L*j(i) + R*i = v;
    end if;
  end Impedance;

  model Admittance
    "Admittance (capacitive) with parallel conductor, 3-phase dq0"
    extends Partials.ImpedBase;

    parameter SIpu.Admittance y_abs=1 "abs value of admittance";
    parameter Real cos_phi(min=0,max=1)=0.1 "cos-phi of admittance";
  protected
    final parameter SI.Resistance[2] GC_base=Utilities.Precalculation.baseGC(
          puUnits,
          V_nom,
          S_nom,
          2*pi*f_nom);
    function acos = Modelica.Math.acos;
    final parameter SI.Conductance G=y_abs*cos_phi*GC_base[1];
    final parameter SI.Capacitance C=y_abs*sin(acos(cos_phi))*GC_base[2];

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(v) = omega[1]*j(v);
    elseif dynType == Types.Dynamics.FixedInitial then
      v = v_start;
    end if;

  equation
    if dynType <> Types.Dynamics.SteadyState then
      C*der(v) + omega[2]*C*j(v) + G*v = i;
    else
      omega[2]*C*j(v) + G*v = i;
    end if;
  end Admittance;

  model ResistorNonSym "Resistor non symmetric, 3-phase dq0."
    extends Partials.ImpedNonSymBase(final f_nom=0, final dynType=Types.Dynamics.SteadyState);

    parameter SIpu.Resistance[3] r={1,1,1} "resistance[3] abc";
  protected
    final parameter SI.Resistance[3] R_abc=r*Utilities.Precalculation.baseR(
          puUnits,
          V_nom,
          S_nom);
    SI.Resistance[3, 3] R;

  equation
    R = Park*diagonal(R_abc)*transpose(Park);
    R*i = v;
  end ResistorNonSym;

  model InductorNonSym
    "Inductor with series resistor non symmetric, 3-phase dq0."
    extends Partials.ImpedNonSymBase;

    parameter SIpu.Resistance[3] r={0,0,0} "resistance[3] abc";
    parameter SIpu.Reactance[3, 3] x=[1, 0, 0; 0, 1, 0; 0, 0, 1]
      "reactance[3,3] abc";
    SI.MagneticFlux[3] psi(each stateSelect=StateSelect.prefer) "magnetic flux";
  protected
    final parameter SI.Resistance[2] RL_base=Utilities.Precalculation.baseRL(
          puUnits,
          V_nom,
          S_nom,
          2*pi*f_nom);
    final parameter SI.Resistance[3] R_abc=r*RL_base[1];
    final parameter SI.Inductance[3, 3] L_abc=x*RL_base[2];
    SI.Resistance[3, 3] R;
    SI.Inductance[3, 3] L;

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(psi[1:2]) = omega[1]*j_dq0(psi[1:2]);
      psi[3] = 0;
    end if;

  equation
    L = Park*L_abc*transpose(Park);
    R = Park*diagonal(R_abc)*transpose(Park);

    psi = L*i;
    der(psi) + omega[2]*j_dq0(psi) + R*i = v;
  end InductorNonSym;

  model CapacitorNonSym
    "Capacitor with parallel conductor non symmetric, 3-phase dq0."
    extends Partials.ImpedNonSymBase;

    parameter SIpu.Conductance[3] g={0,0,0} "conductance[3] abc";
    parameter SIpu.Susceptance[3] b={1,1,1} "susceptance[3] abc";
    SI.ElectricCharge[3] q(each stateSelect=StateSelect.prefer)
      "electric charge";
  protected
    final parameter SI.Resistance[2] GC_base=Utilities.Precalculation.baseGC(
          puUnits,
          V_nom,
          S_nom,
          2*pi*f_nom);
    final parameter SI.Conductance[3] G_abc=g*GC_base[1];
    final parameter SI.Capacitance[3] C_abc=b*GC_base[2];
    SI.Conductance[3, 3] G;
    SI.Capacitance[3, 3] C;

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(q[1:2]) = omega[1]*j_dq0(q[1:2]);
      q[3] = 0;
    end if;

  equation
    C = Park*diagonal(C_abc)*transpose(Park);
    G = Park*diagonal(G_abc)*transpose(Park);

    q = C*v;
    der(q) + omega[2]*j_dq0(q) + G*v = i;
  end CapacitorNonSym;

  model Varistor "Varistor, 3-phase dq0"
    extends Partials.ImpedNonSymBase(final f_nom=0, final dynType=Types.Dynamics.SteadyState);

    parameter SIpu.Resistance r0=100 "small voltage resistance";
    parameter SIpu.Voltage v0=1 "saturation voltage";
    PS.Voltage[3] v_abc;
    PS.Current[3] i_abc(start=zeros(3));
  protected
    final parameter Real V0=(v0*Utilities.Precalculation.baseV(puUnits, V_nom));
    final parameter Real H0=(r0*Utilities.Precalculation.baseR(
          puUnits,
          V_nom,
          S_nom)/V0);

  equation
    i_abc = transpose(Park)*i;
    v_abc = V0*tanh(H0*i_abc);
    v = Park*v_abc;
  end Varistor;

  package Partials "Partial models"
    extends Modelica.Icons.BasesPackage;

    partial model ImpedBase "Impedance base, 3-phase dq0"
      extends Ports.Port_pn;
      extends Common.Nominal.NominalAC;

      parameter Types.Dynamics dynType=system.dynType "transient or steady-state model"
      parameter PS.Voltage[PS.n] v_start = zeros(PS.n)
        "start value of voltage drop"
      parameter PS.Current[PS.n] i_start = zeros(PS.n)
        "start value of current"

      PS.Voltage[PS.n] v(start = v_start);
      PS.Current[PS.n] i(start = i_start);

    protected
      SI.AngularFrequency[2] omega;

    equation
      omega = der(term_p.theta);
      v = term_p.v - term_n.v;
      i = term_p.i;
    end ImpedBase;

    partial model ImpedNonSymBase "Impedance base non symmetric, 3-phase dq0."
      extends ImpedBase;

    protected
      Real[3,3] Park=Utilities.Transforms.park(term_p.theta[2]);
    end ImpedNonSymBase;

    partial model ImpedHeat "Impedance base with heat port, 3-phase dq0"
      extends ImpedBase;
      extends PowerSystems.Interfaces.AddHeat;

    equation
      Q_flow = v*i;
    end ImpedHeat;

    partial model ImpedNonSymHeat
      "Impedance base non symmetric with heat port, 3-phase dq0"
      extends ImpedNonSymBase;
      extends PowerSystems.Interfaces.AddHeatV(final m_heat=3);

      PS.Voltage[3] v_abc=Park*v;
      PS.Current[3] i_abc=Park*i;

    equation
      Q_flow = v_abc.*i_abc;
    end ImpedNonSymHeat;

  end Partials;
end Impedances;


within PowerSystems.AC3ph;
package ImpedancesYD
  "Impedance and admittance one terminal, Y and Delta topology"
  extends Modelica.Icons.VariantsPackage;

  model Resistor "Resistor, 3-phase dq0"
    extends Partials.ImpedYDBase(final f_nom=0, final dynType=Types.Dynamics.SteadyState);

    parameter SIpu.Resistance r=1 "resistance";
  protected
    final parameter SI.Resistance R=r*Utilities.Precalculation.baseR(
          puUnits,
          V_nom,
          S_nom,
          top.scale);

  equation
    R*i = v;
  end Resistor;

  model Conductor "Conductor, 3-phase dq0"
    extends Partials.ImpedYDBase(final f_nom=0, final dynType=Types.Dynamics.SteadyState);

    parameter SIpu.Conductance g=1 "conductance";
  protected
    final parameter SI.Conductance G=g/Utilities.Precalculation.baseR(
          puUnits,
          V_nom,
          S_nom,
          top.scale);

  equation
    G*v = i;
  end Conductor;

  model Inductor "Inductor with series resistor, 3-phase dq0"
    extends Partials.ImpedYDBase;

    parameter SIpu.Resistance r=0 "resistance";
    parameter SIpu.Reactance x_s=1 "self reactance";
    parameter SIpu.Reactance x_m=0 "mutual reactance, -x_s/2 < x_m < x_s";
  protected
    final parameter SI.Resistance[2] RL_base=Utilities.Precalculation.baseRL(
          puUnits,
          V_nom,
          S_nom,
          2*pi*f_nom,
          top.scale);
    final parameter SI.Resistance R=r*RL_base[1];
    final parameter SI.Inductance L=(x_s-x_m)*RL_base[2];
    final parameter SI.Inductance L0=(x_s+2*x_m)*RL_base[2];

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(i) = omega[1]*j_dq0(i);
    end if;

  equation
    if dynType <> Types.Dynamics.SteadyState then
      diagonal({L,L,L0})*der(i) + omega[2]*L*j_dq0(i) + R*i = v;
    else
      omega[2]*L*j_dq0(i) + R*i = v;
    end if;
  end Inductor;

  model Capacitor "Capacitor with parallel conductor, 3-phase dq0"
    extends Partials.ImpedYDBase;

    parameter SIpu.Conductance g=0 "conductance";
    parameter SIpu.Susceptance b=1 "susceptance";
  protected
    final parameter SI.Resistance[2] GC_base=Utilities.Precalculation.baseGC(
          puUnits,
          V_nom,
          S_nom,
          2*pi*f_nom,
          top.scale);
    final parameter SI.Conductance G=g*GC_base[1];
    final parameter SI.Capacitance C=b*GC_base[2];

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(v) = omega[1]*j_dq0(v);
    end if;

  equation
    if dynType <> Types.Dynamics.SteadyState then
      C*der(v) + omega[2]*C*j_dq0(v) + G*v = i;
    else
      omega[2]*C*j_dq0(v) + G*v = i;
    end if;
  end Capacitor;

  model ResistorNonSym "Resistor non symmetric, 3-phase dq0"
    extends Partials.ImpedYDNonSymBase(final f_nom=0, final dynType=Types.Dynamics.SteadyState);

    parameter SIpu.Resistance[3] r={1,1,1} "resistance[3] abc";
  protected
    final parameter SI.Resistance[3] R_abc=r*Utilities.Precalculation.baseR(
          puUnits,
          V_nom,
          S_nom,
          top.scale);
    SI.Resistance[3, 3] R;

  equation
    R = Park*diagonal(R_abc)*transpose(Park);
    R*i = v;
  end ResistorNonSym;

  model InductorNonSym
    "Inductor with series resistor non symmetric, 3-phase dq0"
    extends Partials.ImpedYDNonSymBase;

    parameter SIpu.Resistance[3] r={0,0,0} "resistance[3] abc";
    parameter SIpu.Reactance[3, 3] x=[1, 0, 0; 0, 1, 0; 0, 0, 1]
      "reactance[3,3] abc";
    SI.MagneticFlux[3] psi(each stateSelect=StateSelect.prefer) "magnetic flux";
  protected
    final parameter SI.Resistance[2] RL_base=Utilities.Precalculation.baseRL(
          puUnits,
          V_nom,
          S_nom,
          2*pi*f_nom,
          top.scale);
    final parameter SI.Resistance[3] R_abc=r*RL_base[1];
    final parameter SI.Inductance[3, 3] L_abc=x*RL_base[2];
    SI.Resistance[3, 3] R;
    SI.Inductance[3, 3] L;

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(psi[1:2]) = omega[1]*j_dq0(psi[1:2]);
      psi[3] = 0;
    end if;

  equation
    L = Park*L_abc*transpose(Park);
    R = Park*diagonal(R_abc)*transpose(Park);

    psi = L*i;
    der(psi) + omega[2]*j_dq0(psi) + R*i = v;
  end InductorNonSym;

  model CapacitorNonSym
    "Capacitor with parallel conductor non symmetric, 3-phase dq0"
    extends Partials.ImpedYDNonSymBase;

    parameter SIpu.Conductance[3] g={0,0,0} "conductance[3] abc";
    parameter SIpu.Susceptance[3] b={1,1,1} "susceptance[3] abc";
    SI.ElectricCharge[3] q(each stateSelect=StateSelect.prefer)
      "electric charge";
  protected
    final parameter SI.Resistance[2] GC_base=Utilities.Precalculation.baseGC(
          puUnits,
          V_nom,
          S_nom,
          2*pi*f_nom,
          top.scale);
    final parameter SI.Conductance[3] G_abc=g*GC_base[1];
    final parameter SI.Capacitance[3] C_abc=b*GC_base[2];
    SI.Conductance[3, 3] G;
    SI.Capacitance[3, 3] C;

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(q[1:2]) = omega[1]*j_dq0(q[1:2]);
      q[3] = 0;
    end if;

  equation
    C = Park*diagonal(C_abc)*transpose(Park);
    G = Park*diagonal(G_abc)*transpose(Park);

    q = C*v;
    der(q) + omega[2]*j_dq0(q) + G*v = i;
  end CapacitorNonSym;

  model Varistor "Varistor, 3-phase dq0"
    extends Partials.ImpedYDNonSymBase(final f_nom=0, final dynType=Types.Dynamics.SteadyState);

    parameter SIpu.Resistance r0=100 "small voltage resistance";
    parameter SIpu.Voltage v0=1 "saturation voltage";
    PS.Voltage[3] v_abc;
    PS.Current[3] i_abc(start=zeros(3));
  protected
    final parameter Real V0=(v0*Utilities.Precalculation.baseV(puUnits, V_nom));
    final parameter Real H0=(r0*Utilities.Precalculation.baseR(
          puUnits,
          V_nom,
          S_nom)/V0);

  equation
    i_abc = transpose(Park)*i;
    v_abc = V0*tanh(H0*i_abc);
    v = Park*v_abc;
  end Varistor;

  package Partials "Partial models"
    extends Modelica.Icons.BasesPackage;

    partial model ImpedYDBase "One terminal impedance base, 3-phase dq0"
      extends Ports.YDport_p;
      extends Common.Nominal.NominalAC;

      parameter Types.Dynamics dynType=system.dynType "transient or steady-state model"
      parameter SIpu.Resistance r_n=1 "resistance neutral to grd"
    protected
      final parameter SI.Resistance R_n=r_n*Utilities.Precalculation.baseR(
              puUnits,
              V_nom,
              S_nom);
      SI.AngularFrequency[2] omega;

    equation
      omega = der(term.theta);
      v_n = R_n*i_n "equation neutral to ground (if Y-topology)";
    end ImpedYDBase;

    partial model ImpedYDNonSymBase
      "One terminal impedance base non symmetric, 3-phase dq0"
      extends ImpedYDBase;

    protected
      Real[3,3] Park=Utilities.Transforms.park(term.theta[2]);

    end ImpedYDNonSymBase;

    partial model ImpedYDHeat
      "One terminal impedance base with heat port, 3-phase dq0"
      extends ImpedYDBase;
      extends PowerSystems.Interfaces.AddHeat;

    equation
      Q_flow = v*i;
    end ImpedYDHeat;

    partial model ImpedYDNonSymHeat
      "One terminal impedance base non symmetric with heat port, 3-phase dq0"
      extends ImpedYDNonSymBase;
      extends PowerSystems.Interfaces.AddHeatV(
                                       final m_heat=3);

      PS.Voltage[3] v_abc=Park*top.v_cond;
      PS.Current[3] i_abc=Park*top.i_cond;

    equation
      Q_flow = v_abc.*i_abc;
    end ImpedYDNonSymHeat;

  end Partials;
end ImpedancesYD;


Rectifiers and Inverters

within PowerSystems.AC3ph;
package Inverters "Rectifiers and Inverters"
  extends Modelica.Icons.VariantsPackage;

block Select "Select frequency and voltage-phasor type"
  extends PowerSystems.Icons.Block;

    parameter Types.SourceFrequency fType=PowerSystems.Types.SourceFrequency.System
      "frequency type"
  parameter SI.Frequency f=system.f "frequency if type is parameter"

  parameter Boolean use_vPhasor_in = false
      "= true to enable signal input vPhasor_in"

  parameter Real v0=1 "voltage amplitude pu vDC/2"
  parameter SI.Angle alpha0=0 "phase angle"

  Modelica.Blocks.Interfaces.RealInput[2] vPhasor_in if use_vPhasor_in
      "{abs(v), phase(v)}"
  Modelica.Blocks.Interfaces.RealInput omega_in(final unit="rad/s") if fType
       == PowerSystems.Types.SourceFrequency.Signal        "angular frequency"

  Modelica.Blocks.Interfaces.RealOutput[2] vPhasor_out
      "{abs(u), phase(u)} to inverter"
  Modelica.Blocks.Interfaces.RealOutput theta_out
      "abs angle to inverter, der(theta)=omega"
  outer System system;

  protected
  SI.Angle theta;
  Modelica.Blocks.Interfaces.RealInput omega_internal
      "Needed to connect to conditional connector";
  Modelica.Blocks.Interfaces.RealInput[2] vPhasor_internal
      "Needed to connect to conditional connector";

initial equation
  if fType == Types.SourceFrequency.Signal then
    theta = 0;
  end if;

equation
  connect(omega_in, omega_internal);
  connect(vPhasor_in, vPhasor_internal);
  if fType <> Types.SourceFrequency.Signal then
     omega_internal = 0.0;
  end if;
  if not use_vPhasor_in then
     vPhasor_internal = {v0, alpha0};
  end if;

  if fType == Types.SourceFrequency.System then
    theta = system.theta;
  elseif fType == Types.SourceFrequency.Parameter then
    theta = 2*pi*f*(time - system.initime);
  elseif fType == Types.SourceFrequency.Signal then
    der(theta) = omega_internal;
  end if;
  theta_out = theta;

  vPhasor_out = vPhasor_internal;
end Select;

model Rectifier "Rectifier, 3-phase dq0"
  extends Partials.AC_DC_base(heat(final m=3));

  replaceable model Rectifier = PowerSystems.AC3ph.Inverters.Components.RectifierEquation
    constrainedby PowerSystems.AC3ph.Inverters.Partials.AC_DC_base "rectifier model"
  Rectifier rectifier "rectifier model"

equation
  connect(AC, rectifier.AC)
  connect(rectifier.DC, DC)
  connect(rectifier.heat, heat)
end Rectifier;

model RectifierAverage "Rectifier time-average, 3-phase dq0"
  extends Partials.SwitchEquation(heat(final m=1));

  replaceable record Data = PowerSystems.Semiconductors.Ideal.SCparameter(final Hsw_nom=0)
      "SC parameters"
  final parameter Data par "SC parameters"
  parameter Real sigma=1 "power correction"
  protected
  final parameter Real S_abs=sigma*(2*sqrt(6)/pi);
  final parameter SI.Resistance R_nom=par.V_nom/par.I_nom;
  Real cT;
  Real iAC2;

equation
  cT = if size(par.cT_loss,1)==0 then 1 else loss(T[1]-par.T0_loss, par.cT_loss);
  iAC2 = AC.i*AC.i;

  switch_dq0 = S_abs*AC.i/(sqrt(iAC2) + 1e-5);
  v_dq0 = (vDC1 + cT*par.Vf)*switch_dq0;

  Q_flow = {par.eps[1]*R_nom*iAC2 + (2*sqrt(6)/pi)*par.Vf*sqrt(iAC2)};
end RectifierAverage;

model Inverter "Complete modulator and inverter, 3-phase dq0"
  extends Partials.AC_DC_base(heat(final m=3));

  Modelica.Blocks.Interfaces.RealInput theta "abs angle, der(theta)=omega"
  Modelica.Blocks.Interfaces.RealInput[2] vPhasor "desired {abs(v), phase(v)}"
  replaceable model Modulator = PowerSystems.Control.Modulation.PWMasyn
    constrainedby PowerSystems.Control.Modulation.Partials.ModulatorBase
      "modulator type"
  Modulator modulator
  replaceable model Inverter = PowerSystems.AC3ph.Inverters.Components.InverterSwitch
    constrainedby PowerSystems.AC3ph.Inverters.Partials.AC_DC_base "inverter model"
  Inverter inverter "inverter model"
  protected
  outer System system;

equation
  Connections.potentialRoot(AC.theta);
  if Connections.isRoot(AC.theta) then
    AC.theta = if system.synRef then {0, theta} else {theta, 0};
  end if;

  connect(AC, inverter.AC)
  connect(inverter.DC, DC)
  connect(theta, modulator.theta)
  connect(vPhasor,modulator.vPhasor)
  connect(modulator.gates, inverter.gates)
  connect(inverter.heat, heat)
end Inverter;

model InverterAverage "Inverter time-average, 3-phase dq0"
  extends Partials.SwitchEquation(heat(final m=1));

  replaceable record Data = PowerSystems.Semiconductors.Ideal.SCparameter
      "SC parameters"
  final parameter Data par "SC parameters"
  parameter Integer modulation=1 "equivalent modulation :"
  parameter Boolean syn=false "synchronous, asynchronous"
  parameter Integer m_carr(min=1)=1 "f_carr/f, pulses/period"
  parameter SI.Frequency f_carr=1e3 "carrier frequency"
  parameter Real width0=2/3 "relative width, (0 - 1)"
  Modelica.Blocks.Interfaces.RealInput theta "abs angle, der(theta)=omega"
  Modelica.Blocks.Interfaces.RealInput[2] vPhasor "desired {abs(v), phase(v)}"
  protected
  outer System system;
  final parameter SI.Resistance R_nom=par.V_nom/par.I_nom;
  final parameter Real factor=
    if modulation==1 then sqrt(3/2) else
    if modulation==2 then (4/3)*sqrt(3/2) else
    if modulation==3 then (4/pi)*sin(width0*pi/2)*sqrt(3/2) else 0
  SI.Angle phi;
  PS.Voltage Vloss;
  Real iAC2;
  Real cT;
  Real hsw_nom;

equation
  Connections.potentialRoot(AC.theta);
  if Connections.isRoot(AC.theta) then
    AC.theta = if system.synRef then {0, theta} else {theta, 0};
  end if;

  Vloss = if par.Vf<1e-3 then 0 else tanh(10*iDC1/par.I_nom)*2*par.Vf;
  iAC2 = AC.i*AC.i;
  cT = if size(par.cT_loss,1)==0 then 1 else loss(T[1]-par.T0_loss, par.cT_loss);
  hsw_nom = if syn then (2*par.Hsw_nom*m_carr/(pi*par.V_nom*par.I_nom))*der(theta) else
                        4*par.Hsw_nom*f_carr/(par.V_nom*par.I_nom);

  phi = AC.theta[1] + vPhasor[2] + system.alpha0;
  switch_dq0 = factor*vPhasor[1]*PS.map({cos(phi), sin(phi), 0});
  v_dq0 = (vDC1 - cT*Vloss)*switch_dq0;
// passive mode?

 Q_flow = {par.eps[1]*R_nom*iAC2 +
                     (2*sqrt(6)/pi)*cT*(par.Vf + hsw_nom*abs(vDC1))*sqrt(iAC2)};
end InverterAverage;

  package Components "Equation-based and modular components"
    extends Modelica.Icons.VariantsPackage;

  model RectifierEquation "Rectifier equation, 3-phase dq0"
    extends Partials.SwitchEquation(heat(final m=3));

    replaceable record Data = PowerSystems.Semiconductors.Ideal.SCparameter(final Hsw_nom=0)
        "SC parameters"
    final parameter Data par "SC parameters"
    protected
    PS.Voltage[3] V;
    PS.Voltage[3] v "voltage in inertial abc representation";
    PS.Voltage[3] i_sc
        "current scaled to voltage in inertial abc representation";
    Real[3] s(each start = 0.5) "arc-length on characteristic";
    Real[3] switch "switch function in inertial abc representation";
      Real[3,3] Park=Utilities.Transforms.park(AC.theta[2]);

  equation
    i_sc = transpose(Park)*AC.i*par.V_nom/par.I_nom;

    for k in 1:3 loop
      V[k] = if size(par.cT_loss,1)==0 then  vDC1 + par.Vf else vDC1 + par.Vf*loss(T[k]-par.T0_loss, par.cT_loss);
      if s[k] > V[k] then // vDC+ < vAC
        {v[k],i_sc[k]} = {par.eps[1]*s[k] + (1 - par.eps[1])*V[k], s[k] - (1 - par.eps[2])*V[k]};
      elseif s[k] < -V[k] then  // vAC < vDC-
        {v[k],i_sc[k]} = {par.eps[1]*s[k] - (1 - par.eps[1])*V[k], s[k] + (1 - par.eps[2])*V[k]};
      else // vDC- < vAC < vDC+
        {v[k],i_sc[k]} = {s[k],par.eps[2]*s[k]};
      end if;
      switch[k] = noEvent(sign(s[k]));
    end for;

    v_dq0 = Park*v;
    switch_dq0 = Park*switch;
    Q_flow = (v - switch*vDC1).*i_sc*par.I_nom/par.V_nom;
  end RectifierEquation;

  model RectifierModular "Rectifier modular, 3-phase"
    extends Partials.AC_DC_base(heat(final m=3));

    replaceable record Data = PowerSystems.Semiconductors.Ideal.SCparameter(final Hsw_nom=0)
      "SC parameters"
    final parameter Data par "SC parameters"
    Nodes.ACdq0_a_b_c acdq0_a_b_c
    Common.Thermal.Heat_a_b_c_abc heat_adapt
    Semiconductors.PhaseModules.DiodeModule diodeMod_a(final par=par)
        "diode module AC_a"
    Semiconductors.PhaseModules.DiodeModule diodeMod_b(final par=par)
        "diode module AC_b"
    Semiconductors.PhaseModules.DiodeModule diodeMod_c(final par=par)
        "diode module AC_c"

  equation
    connect(AC, acdq0_a_b_c.term)
    connect(acdq0_a_b_c.term_a, diodeMod_a.AC)
    connect(acdq0_a_b_c.term_b, diodeMod_b.AC)
    connect(acdq0_a_b_c.term_c, diodeMod_c.AC)
    connect(diodeMod_a.DC, DC)
    connect(diodeMod_b.DC, DC)
    connect(diodeMod_c.DC, DC)
    connect(diodeMod_a.heat, heat_adapt.port_a)
    connect(diodeMod_b.heat, heat_adapt.port_b)
    connect(diodeMod_c.heat, heat_adapt.port_c)
    connect(heat_adapt.port_abc, heat)
  end RectifierModular;

  model InverterSwitch "Inverter switch, 3-phase dq0"
    extends Partials.SwitchEquation(heat(final m=3));

    Modelica.Blocks.Interfaces.BooleanInput[6] gates
        "gates pairs {a_p, a_n, b_p, b_n, c_p, c_n}"
    protected
    constant Integer[3] pgt={1,3,5} "positive gates";
    constant Integer[3] ngt={2,4,6} "negative gates";
    PS.Voltage[3] v "voltage in inertial abc representation";
    Real[3] switch "switch function in inertial abc representation";
      Real[3,3] Park=Utilities.Transforms.park(AC.theta[2]);

  equation
    for k in 1:3 loop
      if gates[pgt[k]] then // switched mode DC+ to AC
        switch[k] = 1;
        v[k] = vDC1;
      elseif gates[ngt[k]] then // switched mode DC- to AC
        switch[k] = -1;
        v[k] = -vDC1;
      else
        switch[k] = 0;
        v[k] = 0;
      end if;
    end for;

    v_dq0 = Park*v;
    switch_dq0 = Park*switch;
    Q_flow = zeros(heat.m);
  end InverterSwitch;

  model InverterEquation "Inverter equation, 3-phase dq0"
    extends Partials.SwitchEquation(heat(final m=3));

    replaceable record Data = PowerSystems.Semiconductors.Ideal.SCparameter
        "SC parameters"
    final parameter Data par "SC parameters"
    Modelica.Blocks.Interfaces.BooleanInput[6] gates
        "gates pairs {a_p, a_n, b_p, b_n, c_p, c_n}"
    protected
    constant Integer[3] pgt={1,3,5} "positive gates";
    constant Integer[3] ngt={2,4,6} "negative gates";
    PS.Voltage[3] V_s;
    PS.Voltage[3] V_d;
    PS.Voltage[3] v "voltage in inertial abc representation";
    PS.Voltage[3] i_sc
        "current scaled to voltage in inertial abc representation";
    Real[3] s(each start = 0.5) "arc-length on characteristic";
    Real[3] switch "switch function in inertial abc representation";
      Real[3,3] Park=Utilities.Transforms.park(AC.theta[2]);

  equation
    i_sc = transpose(Park)*AC.i*par.V_nom/par.I_nom;

    if par.Vf<1e-3 then // faster code if forward voltage drop Vf not used (Vf=0).
      for k in 1:3 loop
        V_s[k] = 0;
        V_d[k] = vDC1;
        if gates[pgt[k]] then // switched mode DC+ to AC
          switch[k] = 1;
          {v[k],i_sc[k]} = {par.eps[1]*s[k] + (1 - par.eps[1])*V_d[k],s[k] - (1 - par.eps[2])*V_d[k]};
        elseif gates[ngt[k]] then // switched mode DC- to AC
          switch[k] = -1;
          {v[k],i_sc[k]} = {par.eps[1]*s[k] - (1 - par.eps[1])*V_d[k],s[k] + (1 - par.eps[2])*V_d[k]};
        else // rectifier mode
         if s[k] > V_d[k] then // vDC+ < vAC
            {v[k],i_sc[k]} = {par.eps[1]*s[k] + (1 - par.eps[1])*V_d[k], s[k] - (1 - par.eps[2])*V_d[k]};
          elseif s[k] < -V_d[k] then  // vAC < vDC-
            {v[k],i_sc[k]} = {par.eps[1]*s[k] - (1 - par.eps[1])*V_d[k], s[k] + (1 - par.eps[2])*V_d[k]};
          else // vDC- < vAC < vDC+
            {v[k],i_sc[k]} = {s[k],par.eps[2]*s[k]};
          end if;
          switch[k] = noEvent(sign(s[k]));
        end if;
      end for;
      Q_flow = zeros(heat.m);
    else // slower code if voltage drop used (Vf_s>0 or Vf_d>0).
      for k in 1:3 loop
        {V_s[k], V_d[k]} = if size(par.cT_loss,1)==0 then {vDC1-par.Vf, vDC1+par.Vf} else {vDC1, vDC1} + {-par.Vf, par.Vf}*loss(T[k]-par.T0_loss, par.cT_loss);
        if gates[pgt[k]] then // switched mode DC+ to AC
          switch[k] = 1;
          if s[k] > V_d[k] then
            {v[k],i_sc[k]} = {par.eps[1]*s[k] + (1 - par.eps[1])*V_d[k],s[k] - (1 - par.eps[2])*V_d[k]};
          elseif s[k] < V_s[k] then
            {v[k],i_sc[k]} = {par.eps[1]*s[k] + (1 - par.eps[1])*V_s[k],s[k] - (1 - par.eps[2])*V_s[k]};
          else
            {v[k],i_sc[k]} = {s[k],par.eps[2]*s[k]};
          end if;
        elseif gates[ngt[k]] then // switched mode DC- to AC
          switch[k] = -1;
          if s[k] < -V_d[k] then
            {v[k],i_sc[k]} = {par.eps[1]*s[k] - (1 - par.eps[1])*V_d[k],s[k] + (1 - par.eps[2])*V_d[k]};
          elseif s[k] > -V_s[k] then
            {v[k],i_sc[k]} = {par.eps[1]*s[k] -(1 - par.eps[1])*V_s[k],s[k] + (1 - par.eps[2])*V_s[k]};
          else
            {v[k],i_sc[k]} = {s[k],par.eps[2]*s[k]};
          end if;
        else // rectifier mode
          if s[k] > V_d[k] then // vDC+ < vAC
            {v[k],i_sc[k]} = {par.eps[1]*s[k] + (1 - par.eps[1])*V_d[k], s[k] - (1 - par.eps[2])*V_d[k]};
          elseif s[k] < -V_d[k] then  // vAC < vDC-
            {v[k],i_sc[k]} = {par.eps[1]*s[k] - (1 - par.eps[1])*V_d[k], s[k] + (1 - par.eps[2])*V_d[k]};
          else // vDC- < vAC < vDC+
            {v[k],i_sc[k]} = {s[k],par.eps[2]*s[k]};
          end if;
          switch[k] = noEvent(sign(s[k]));
        end if;
      end for;
      Q_flow = (v - switch*vDC1).*i_sc*par.I_nom/par.V_nom;
    end if;

    v_dq0 = Park*v;
    switch_dq0 = Park*switch;
  end InverterEquation;

  model InverterModular "Inverter modular, 3-phase"
    extends Partials.AC_DC_base(heat(final m=3));

    replaceable model Switch = PowerSystems.Semiconductors.Ideal.SCswitch_Diode "Semiconductor model"
      constrainedby PowerSystems.Semiconductors.Partials.GateInput
    replaceable record Data = PowerSystems.Semiconductors.Ideal.SCparameter "SC parameters"
    final parameter Data par "SC parameters"
    Modelica.Blocks.Interfaces.BooleanInput[6] gates
        "gates pairs {a_p, a_n, b_p, b_n, c_p, c_n}"
    Nodes.ACdq0_a_b_c acdq0_a_b_c
    Common.Thermal.Heat_a_b_c_abc heat_adapt
    Blocks.Multiplex.Gate3demux gate3demux1(final n=2)
    Semiconductors.PhaseModules.SwitchModule switchMod_a(redeclare model Switch=Switch, final par=par)
        "switch + reverse diode module AC_a"
    Semiconductors.PhaseModules.SwitchModule switchMod_b(redeclare model Switch=Switch, final par=par)
        "switch + reverse diode module AC_b"
    Semiconductors.PhaseModules.SwitchModule switchMod_c(redeclare model Switch=Switch, final par=par)
        "switch + reverse diode module AC_c"

  equation
    connect(AC, acdq0_a_b_c.term)
    connect(acdq0_a_b_c.term_a, switchMod_a.AC)
    connect(switchMod_a.DC, DC)
    connect(acdq0_a_b_c.term_b, switchMod_b.AC)
    connect(switchMod_b.DC, DC)
    connect(acdq0_a_b_c.term_c, switchMod_c.AC)
    connect(switchMod_c.DC, DC)
    connect(gates, gate3demux1.gates)
    connect(gate3demux1.gates_a, switchMod_a.gates)
    connect(gate3demux1.gates_b, switchMod_b.gates)
    connect(gate3demux1.gates_c, switchMod_c.gates)
    connect(switchMod_a.heat, heat_adapt.port_a)
    connect(switchMod_b.heat, heat_adapt.port_b)
    connect(switchMod_c.heat, heat_adapt.port_c)
    connect(heat_adapt.port_abc, heat)
  end InverterModular;
  end Components;

package Partials "Partial models"
  extends Modelica.Icons.BasesPackage;

partial model AC_DC_base "AC-DC base, 3-phase dq0"
  extends PowerSystems.Icons.Inverter_dq0;
  extends Ports.PortBase;

  Ports.ACdq0_n AC "AC 3-phase connection"
  AC1ph_DC.Ports.TwoPin_p DC "DC connection"
  Interfaces.ThermalV_n heat(m=3) "vector heat port"
end AC_DC_base;

partial model SwitchEquation "Switch equation, 3-phase dq0"
  extends AC_DC_base;

    protected
  PS.Voltage vDC1=0.5*(DC.v[1] - DC.v[2]);
  PS.Voltage vDC0=0.5*(DC.v[1] + DC.v[2]);
  PS.Current iDC1=(DC.i[1] - DC.i[2]);
  PS.Current iDC0=(DC.i[1] + DC.i[2]);
  Real[PS.n] v_dq0 "switching function voltage in dq0 representation";
  Real[PS.n] switch_dq0 "switching function in dq0 representation";

  SI.Temperature[heat.m] T "component temperature";
  SI.HeatFlowRate[heat.m] Q_flow "component loss-heat flow";
  function loss = Utilities.Math.taylor "temp dependence of losses";
  SI.Conductance C0 = 1 "for dq phase system";

equation
  AC.v = v_dq0 + PS.map({0,0,sqrt(3)*vDC0});
  iDC1 + switch_dq0*AC.i = 0;
  if PS.n > 2 then
    iDC0 + sqrt(3)*AC.i[3] = 0;
  else
    iDC0 = C0*vDC0 "iDC0 = 0, vDC0 = 0";
  end if;
  T = heat.ports.T;
  heat.ports.Q_flow = -Q_flow;
end SwitchEquation;
end Partials;
end Inverters;


Transmission lines 3-phase

within PowerSystems.AC3ph;
package Lines "Transmission lines 3-phase"
  extends Modelica.Icons.VariantsPackage;

  model RXline0 "RX line without length parameter, 3-phase dq0"
    extends Impedances.Partials.ImpedBase;

    parameter SIpu.Resistance r=0.01 "resistance";
    parameter SIpu.Reactance x=0.1 "reactance";
    parameter SIpu.Reactance x0=3*x "reactance zero-comp";
  protected
    final parameter SI.Resistance[2] RL_base=Utilities.Precalculation.baseRL(
          puUnits,
          V_nom,
          S_nom,
          2*pi*f_nom);
    final parameter SI.Resistance R=r*RL_base[1];
    final parameter SI.Inductance L=x*RL_base[2];
    final parameter SI.Inductance L0=x0*RL_base[2];

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(i) = omega[1]*j(i);
    elseif dynType == Types.Dynamics.FixedInitial then
      i = i_start;
    end if;

  equation
    if dynType <> Types.Dynamics.SteadyState then
      PS.map({L,L,L0}).*der(i) + omega[2]*L*j(i) + R*i = v;
    else
      omega[2]*L*j(i) + R*i = v;
    end if;
  end RXline0;

  model RXline "RX transmission line, 3-phase dq0"
    extends Ports.Port_pn;
    extends Partials.RXlineBase(final ne=1);

    PS.Voltage[PS.n] v(start = v_start);
    PS.Current[PS.n] i(start = i_start);
  protected
    SI.AngularFrequency[2] omega;

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(i) = omega[1]*j(i);
    elseif dynType == Types.Dynamics.FixedInitial then
      i = i_start;
    end if;

  equation
    omega = der(term_p.theta);
    v = term_p.v - term_n.v;
    i = term_p.i;

    if dynType <> Types.Dynamics.SteadyState then
      PS.map({L,L,L0}).*der(i) + omega[2]*L*j(i) + R*i = v;
    else
      omega[2]*L*j(i) + R*i = v;
    end if;
  end RXline;

  model PIline "PI transmission line, 3-phase dq0"
    extends Ports.Port_p_n;
    extends Partials.LineBase;

    PS.Voltage[PS.n,ne1] v(start = transpose(fill(v_start, ne1)));
    PS.Current[PS.n,ne] i(start = transpose(fill(i_start, ne)));
  protected
    final parameter Integer ne1=ne + 1;
    SI.AngularFrequency[2] omega;

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(v) = omega[1]*jj(v);
      der(i) = omega[1]*jj(i);
    elseif dynType == Types.Dynamics.FixedInitial then
      v = transpose(fill(v_start, ne1));
      i = transpose(fill(i_start, ne));
    end if;

  equation
    omega = der(term_p.theta);
    v[:, 1] = term_p.v;
    v[:, ne1] = term_n.v;

    if dynType <> Types.Dynamics.SteadyState then
      diagonal(PS.map({C,C,C0}))*der(v) + omega[2]*C*jj(v) + G*v =
       [[2*(term_p.i - i[:, 1])], i[:, 1:ne - 1] - i[:, 2:ne], [2*(i[:, ne] + term_n.i)]];
      diagonal(PS.map({L,L,L0}))*der(i) + omega[2]*L*jj(i) + R*i =
       v[:,1:ne] - v[:,2:ne1];
    else
      omega[2]*C*jj(v) + G*v =
       [[2*(term_p.i - i[:, 1])], i[:, 1:ne - 1] - i[:, 2:ne], [2*(i[:, ne] + term_n.i)]];
      omega[2]*L*jj(i) + R*i =
       v[:,1:ne] - v[:,2:ne1];
    end if;
  end PIline;

  model Tline "T transmission line, 3-phase dq0"
    extends Ports.Port_p_n;
    extends Partials.LineBase;

    PS.Voltage[PS.n,ne] v(start = transpose(fill(v_start, ne)));
    PS.Current[PS.n,ne1] i(start = transpose(fill(i_start, ne1)));
  protected
    final parameter Integer ne1=ne + 1;
    SI.AngularFrequency[2] omega;

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(v) = omega[1]*jj(v);
      der(i) = omega[1]*jj(i);
    elseif dynType == Types.Dynamics.FixedInitial then
      v = transpose(fill(v_start, ne));
      i = transpose(fill(i_start, ne1));
    end if;

  equation
    omega = der(term_p.theta);
    i[:, 1] = term_p.i;
    i[:, ne1] = -term_n.i;

    if dynType <> Types.Dynamics.SteadyState then
      diagonal(PS.map({C,C,C0}))*der(v) + omega[2]*C*jj(v) + G*v =
       i[:,1:ne] - i[:,2:ne1];
      diagonal(PS.map({L,L,L0}))*der(i) + omega[2]*L*jj(i) + R*i =
       [[2*(term_p.v - v[:, 1])], v[:, 1:ne - 1] - v[:, 2:ne], [2*(v[:, ne] - term_n.v)]];
    else
      omega[2]*C*jj(v) + G*v = i[:,1:ne] - i[:,2:ne1];
      omega[2]*L*jj(i) + R*i =
       [[2*(term_p.v - v[:, 1])], v[:, 1:ne - 1] - v[:, 2:ne], [2*(v[:, ne] - term_n.v)]];
    end if;
  end Tline;

  model FaultRXline "Faulted RX transmission line, 3-phase dq0"
    extends Ports.Port_p_n_f;
    parameter Real p(min=0,max=1)=0.5 "rel fault-position (0 < p < 1)";
    extends Partials.RXlineBase(final ne=1);

    PS.Current[PS.n] i1(start = i_start);
    PS.Current[PS.n] i2(start = i_start);
  protected
    SI.AngularFrequency[2] omega;

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(i1) = omega[1]*j(i1);
      der(i2) = omega[1]*j(i2);
    elseif dynType == Types.Dynamics.FixedInitial then
      i1 = i_start;
      i2 = i_start;
    end if;

  equation
    omega = der(term_p.theta);
    term_p.i + term_n.i + term_f.i = zeros(PS.n);
    i1 = term_p.i;
    i2 = -term_n.i;

    if dynType <> Types.Dynamics.SteadyState then
      p*(PS.map({L,L,L0}).*der(i1) + omega[2]*L*j(i1) + R*i1) =
       term_p.v - term_f.v;
      (1 - p)*(PS.map({L,L,L0}).*der(i2) + omega[2]*L*j(i2) + R*i2) =
       term_f.v - term_n.v;
    else
      p*(omega[2]*L*j(i1) + R*i1) = term_p.v - term_f.v;
      (1 - p)*(omega[2]*L*j(i2) + R*i2) = term_f.v - term_n.v;
    end if;
  end FaultRXline;

  model FaultTline "Faulted T transmission line, 3-phase dq0"
    extends Ports.Port_p_n_f;
    parameter Real p(min=0.5/ne,max=1-0.5/ne)=0.5
      "rel fault-pos (1/2ne <= p < 1 - 1/2ne)";
    extends Partials.LineBase;

    parameter PS.Current[PS.n] iF_start = zeros(PS.n) "start value of fault current"

    PS.Voltage[PS.n,ne] v(start = transpose(fill(v_start, ne)));
    PS.Current[PS.n,ne1] i(start = transpose(fill(i_start, ne1)));
    PS.Current[PS.n] iF(start = iF_start);
    PS.Current[PS.n,2] iF_p(each stateSelect=StateSelect.never);
  protected
    final parameter Integer ne1=ne + 1;
    final parameter Integer nF=integer(ne*p + 1.5);
    final parameter Real pe=min(0.9, max(0.1, ne*p + 1.5 - nF))
      "relative fault position within element nF";
    SI.AngularFrequency[2] omega;

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(v) = omega[1]*jj(v);
      der(i) = omega[1]*jj(i);
      der(iF) = omega[1]*j(iF);
    elseif dynType == Types.Dynamics.FixedInitial then
      v = transpose(fill(v_start, ne));
      i = transpose(fill(i_start, ne1));
      iF = iF_start;
    end if;

  equation
    omega = der(term_p.theta);
    i[:, 1] = term_p.i;
    i[:, ne1] = -term_n.i;
    iF = -term_f.i;
    iF_p = [(1-pe)*iF, pe*iF];

    if dynType <> Types.Dynamics.SteadyState then
      diagonal(PS.map({C,C,C0}))*der(v) + omega[2]*C*jj(v) + G*v =
       [i[:,1:nF-2]-i[:, 2:nF-1], i[:,nF-1:nF]-i[:,nF:nF+1]-iF_p, i[:,nF+1:ne]-i[:,nF+2:ne1]];
      diagonal(PS.map({L,L,L0}))*der(i) + omega[2]*L*jj(i) + R*i =
       [[2*(term_p.v - v[:, 1])], v[:, 1:ne - 1] - v[:, 2:ne], [2*(v[:, ne] - term_n.v)]];
      PS.map({L,L,L0}).*der(iF) + omega[2]*L*j(iF) + R*iF =
       (v[:, nF-1] - term_f.v)/pe + (v[:, nF] - term_f.v)/(1-pe);
    else
      omega[2]*C*jj(v) + G*v =
       [i[:,1:nF-2]-i[:, 2:nF-1], i[:,nF-1:nF]-i[:,nF:nF+1]-iF_p, i[:,nF+1:ne]-i[:,nF+2:ne1]];
      omega[2]*L*jj(i) + R*i =
       [[2*(term_p.v - v[:, 1])], v[:, 1:ne - 1] - v[:, 2:ne], [2*(v[:, ne] - term_n.v)]];
      omega[2]*L*j(iF) + R*iF =
       (v[:, nF-1] - term_f.v)/pe + (v[:, nF] - term_f.v)/(1-pe);
    end if;
  end FaultTline;

  package Partials "Partial models"
    extends Modelica.Icons.MaterialPropertiesPackage;

    partial model RXlineBase "RX-line base, 3-phase dq0"
      extends Ports.PortBase;

      parameter Types.Dynamics dynType=system.dynType "transient or steady-state model"
      parameter PS.Voltage[PS.n] v_start = zeros(PS.n) "start value of voltage drop"
      parameter PS.Current[PS.n] i_start = zeros(PS.n) "start value of current"

      parameter SI.Length len=100e3 "line length";
      parameter Integer ne(min=1)=1 "number of line elements";
      replaceable record Data = PowerSystems.AC3ph.Lines.Parameters.RXline
        constrainedby PowerSystems.AC3ph.Lines.Parameters.RXline
        "line parameters"
      final parameter Data par "line parameters"
    protected
      outer System system;
      final parameter SI.Resistance[2] RL_base=Utilities.Precalculation.baseRL(
              par.puUnits,
              par.V_nom,
              par.S_nom,
              2*pi*par.f_nom);
      final parameter Real delta_len_km(final quantity="Length", final unit="km")=len/1e3/ne;
      final parameter SI.Resistance R=par.r*delta_len_km*RL_base[1];
      final parameter SI.Inductance L=par.x*delta_len_km*RL_base[2];
      final parameter SI.Inductance L0=par.x0*delta_len_km*RL_base[2];

    end RXlineBase;

    partial model LineBase "PI- and T-line base, 3-phase dq0"
      extends RXlineBase(ne=3, redeclare replaceable record Data =
          PowerSystems.AC3ph.Lines.Parameters.Line);
    protected
      final parameter Real[2] GC_base=Utilities.Precalculation.baseGC(
              par.puUnits,
              par.V_nom,
              par.S_nom,
              2*pi*par.f_nom);
      final parameter SI.Conductance G=(par.g_pg + 3*par.g_pp)*delta_len_km*GC_base[1];
      final parameter SI.Capacitance C=(par.b_pg + 3*par.b_pp)*delta_len_km*GC_base[2];
      final parameter SI.Capacitance C0=par.b_pg*delta_len_km*GC_base[2];
    end LineBase;

  end Partials;

 package Parameters "Parameter data for interactive use"
  extends Modelica.Icons.BasesPackage;

   record RXline "RX-line parameters, 3-phase"
     extends Common.Nominal.NominalDataAC(
                                      S_nom=100e6);
     SIpu.Resistance_km r=0.1e-3 "resistance/km"
     SIpu.Reactance_km x=1e-3 "reactance/km"
     SIpu.Reactance_km x0=3*x "reactance/km zero-comp"
   end RXline;

   record Line "Line parameters, 3-phase"
     extends RXline;

     SIpu.Conductance_km g_pg=0 "shunt conductance/km ph-grd"
     SIpu.Conductance_km g_pp=0 "shunt conductance/km ph_ph"
     SIpu.Susceptance_km b_pg=0.025e-3 "susceptance/km ph-grd"
     SIpu.Susceptance_km b_pp=0.025e-3 "susceptance/km ph-ph"
   end Line;
 end Parameters;
end Lines;


Loads

within PowerSystems.AC3ph;
package Loads "Loads"
  extends Modelica.Icons.VariantsPackage;

  model PQload "PQ steady-state load"
    extends PowerSystems.AC3ph.Loads.Partials.LoadBase;
  equation
    PS.map({pq[1], pq[2], 0}) = PS.phasePowers_vi(v, i);
  end PQload;

  model Zload "Impedance load, 3-phase dq0"
    extends Partials.IndLoadBase;

  equation
    Z = (pq/(pq*pq))*V2_nom;
  end Zload;

  model PQindLoad "PQ inductive load, 3-phase dq0"
    extends Partials.IndLoadBase;

    parameter SIpu.Current imax(unit="1")=2 "maximum current";
    parameter SI.Time tcst=0.01 "time constant Z";
  protected
    Real v2 = v*v;

  initial equation
    der(Z) = {0, 0};

  equation
  //  der(Z) = ((pq/(pq*pq))*v2 - Z)/tcst;
    der(Z) = ((pq/(pq*pq))*v2*tanh(imax)/tanh((imax/V2_nom)*v2) - Z)/tcst;
  end PQindLoad;

  model Yload "Admittance load, 3-phase dq0"
    extends Partials.CapLoadBase;

  equation
    Y = (pq/(pq*pq))*I2_nom;
  end Yload;

  model PQcapLoad "PQ capacitive load, 3-phase dq0"
    extends Partials.CapLoadBase;

    parameter SIpu.Voltage vmax(unit="1")=2 "maximum voltage";
    parameter SI.Time tcst=0.01 "time constant Y";
  protected
    Real i2 = i*i;

  initial equation
    der(Y) = {0, 0};

  equation
  //  der(Y) = ((pq/(pq*pq))*i2 - Y)/tcst;
    der(Y) = ((pq/(pq*pq))*i2*tanh(vmax)/tanh((vmax/I2_nom)*i2) - Y)/tcst;
  end PQcapLoad;

  model ZIPload "ZIP inductive load, 3-phase dq0"
    extends Partials.IndLoadBase;

    parameter SIpu.Current imax(unit="1")=2 "maximum current";
    parameter Real[2] aZ={1/3,1/3} "weight(power) impedance-dependent";
    parameter Real[2] aI={1/3,1/3} "weight(power) current-dependent";
    parameter Real[2] aP={1,1}-aZ-aI "weight(power) fixed";
    parameter SI.Time tcst=0.01 "time constant Z";
  protected
    SI.Power[2] pq_ZIP(start=pq0);
    Real v2 = v*v;
    Real v2_pu = v2/V2_nom;

  initial equation
    der(Z) = {0, 0};

  equation
    pq_ZIP =  diagonal(aZ*v2_pu + aI*sqrt(v2_pu) + aP)*pq;
  //  der(Z) = ((pq_ZIP/(pq_ZIP*pq_ZIP))*v2 - Z)/tcst;
    der(Z) = ((pq_ZIP/(pq_ZIP*pq_ZIP))*v2*tanh(imax)/tanh(imax*v2_pu) - Z)/tcst;
  end ZIPload;

  model FrequencyLoad "Frequency inductive load, 3-phase dq0"
    extends Partials.IndLoadBase;

    parameter SIpu.Current imax(unit="1")=2 "maximum current";
    parameter Real[2] af={1,1} "frequency sensitivity";
    parameter Real[2] aV={1,1} "voltage sensitivity";
    parameter SI.Time tcst=0.01 "time constant Z";
  protected
    final parameter Real[2] aw=af/(2*pi);
    SI.Power[2] pq_fV(start=pq0);
    Real v2 = v*v;
    Real v2_pu = v2/V2_nom;

  initial equation
    der(Z) = {0, 0};

  equation
    pq_fV = diagonal({1,1} + aV*(sqrt(v2_pu)-1) + aw*(sum(omega) - system.omega_nom))*pq;
  //  der(Z) = ((pq_fV/(pq_fV*pq_fV))*v2 - Z)/tcst;
    der(Z) = ((pq_fV/(pq_fV*pq_fV))*v2*tanh(imax)/tanh(imax*v2_pu) - Z)/tcst;
  end FrequencyLoad;

  model DynamicLoad "Dynamic inductive load, 3-phase dq0"
    extends Partials.IndLoadBase;

    parameter SIpu.Current imax(unit="1")=2 "maximum current";
    parameter Real[2] as={0.5,1} "voltage exponent steady-state power";
    parameter Real[2] at={2,2} "voltage exponent transient power";
    parameter SI.Time[2] t_rec={60,60} "power recovery times";
    parameter SI.Time tcst=0.01 "time constant Z";
  protected
    SI.Power[2] pq_st(start=pq0);
    Real v2 = v*v;
    Real v2_pu = v2/V2_nom;
    Real[2] x;
    Real[2] vs;
    Real[2] vt;
    Real[2] xT;

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(x) = {0,0};
    end if;
    der(Z) = {0,0};

  equation
    vs = {v2_pu^(as[1]/2), v2_pu^(as[2]/2)};
    vt = {v2_pu^(at[1]/2), v2_pu^(at[2]/2)};
    xT = {x[1]/t_rec[1], x[2]/t_rec[2]};
    der(x) = diagonal(vs - vt)*pq - xT;
    pq_st =  diagonal(vt)*pq + xT;
  //  der(Z) = ((pq_st/(pq_st*pq_st))*v2 - Z)/tcst;
    der(Z) = ((pq_st/(pq_st*pq_st))*v2*tanh(imax)/tanh(imax*v2_pu) - Z)/tcst;
  end DynamicLoad;

  package Partials "Partial models"
    extends Modelica.Icons.BasesPackage;

    partial model LoadBase "Load base, 3-phase dq0"
      extends Ports.Yport_p;
      extends Common.Nominal.Nominal;

      parameter Types.Dynamics dynType=system.dynType "transient or steady-state model"

      parameter Boolean use_pq_in = false
        "= true to use input signal pq_in, otherwise use parameter pq0"

      parameter SIpu.Power[2] pq0(each min=0)={sqrt(3),1}/2
        "fixed {active, reactive} power (start value if use_pq_in)"
      parameter SIpu.Resistance r_n=0 "resistance neutral to grd";
      Modelica.Blocks.Interfaces.RealInput[2] pq_in(each min=0) if use_pq_in
        "desired {active, reactive} power"

    protected
      outer System system;
      final parameter Real S_base=Utilities.Precalculation.baseS(puUnits, S_nom);
      final parameter Real R_base=Utilities.Precalculation.baseR(
              puUnits,
              V_nom,
              S_nom);
      final parameter SI.Resistance R_n=r_n*R_base;
      SI.AngularFrequency[2] omega;
      SI.Power[2] pq(start=pq0);
      Modelica.Blocks.Interfaces.RealInput[2] pq_internal
        "Needed to connect to conditional connector";
    equation
      connect(pq_in, pq_internal);

      omega = der(term.theta);
      if not use_pq_in then
        pq_internal = pq0;
      end if;
      pq = pq_internal*S_base;
      v_n = R_n*i_n "equation neutral to ground";
    end LoadBase;

    partial model IndLoadBase "Inductive load base, 3-phase dq0"
      extends LoadBase(v(start={v_start[1],v_start[2],0}), i(start={i_start[1],i_start[2],0}));

      parameter Real cpl(min=-0.5,max=1)=0
        "phase coupling x_m/x_s, (-1/2 < cpl < 1)";
      SI.MagneticFlux[3] psi(each stateSelect=StateSelect.prefer)
        "magnetic flux";
    protected
      final parameter Real c0=(1 + 2*cpl)/(1 - cpl);
      final parameter Real V2_nom=V_nom*V_nom;
      final parameter Real[2] Z_start=(pq0/(pq0*pq0*S_base))*V2_nom;
      final parameter PS.Voltage[2] v_start={cos(system.alpha0), sin(system.alpha0)}*V_nom;
      final parameter PS.Current[2] i_start=[Z_start[1],Z_start[2];-Z_start[2],Z_start[1]]*v_start/(Z_start*Z_start);
      SI.Impedance[2] Z(start=Z_start);

    initial equation
      if dynType == Types.Dynamics.SteadyInitial then
        der(psi) = omega[1]*{-psi[2], psi[1], 0};
      end if;

    equation
      psi = Z[2]*{i[1], i[2], c0*i[3]}/system.omega_nom;
      if dynType <> Types.Dynamics.SteadyState then
        der(psi) + omega[2]*j_dq0(psi) + Z[1]*i = v;
      else
        omega[2]*j_dq0(psi)  + Z[1]*i = v;
      end if;
    end IndLoadBase;

    partial model CapLoadBase "Capacitive load base, 3-phase dq0"
      extends LoadBase(v(start={v_start[1],v_start[2],0}), i(start={i_start[1],i_start[2],0}));

      parameter Real beta(min=0)=0 "ratio b_pp/b_pg, (beta > 0)";
      SI.ElectricCharge[3] q(each stateSelect=StateSelect.prefer)
        "electric charge";
    protected
      final parameter Real c0=1/(1+3*beta);
      final parameter Real I2_nom=(S_nom/V_nom)^2;
      final parameter SI.Admittance[2] Y_start=(pq0/(pq0*pq0*S_base))*I2_nom;
      final parameter PS.Voltage[2] v_start={cos(system.alpha0), sin(system.alpha0)}*V_nom;
      final parameter PS.Current[2] i_start=[Y_start[1],-Y_start[2];Y_start[2],Y_start[1]]*v_start;
      SI.Admittance[2] Y(start=Y_start);

    initial equation
      if dynType == Types.Dynamics.SteadyInitial then
        der(q) = omega[1]*{-q[2], q[1], 0};
      end if;

    equation
      q = Y[2]*{v[1], v[2], c0*v[3]}/system.omega_nom;
      if dynType <> Types.Dynamics.SteadyState then
        der(q) + omega[2]*j_dq0(q) + Y[1]*v = i;
      else
        omega[2]*j_dq0(q) + Y[1]*v = i;
      end if;
    end CapLoadBase;

  end Partials;
end Loads;