Sensors n-phase or DC

within PowerSystems.AC1ph_DC;
package Sensors "Sensors n-phase or DC"
  extends Modelica.Icons.SensorsPackage;

  model VdiffSensor "Voltage difference sensor, 1-phase"
    extends Partials.Sensor1Base(final S_nom=1);

    Modelica.Blocks.Interfaces.RealOutput v
      "difference voltage 'plus' - 'minus'"

  protected
    final parameter PS.Voltage V_base=Utilities.Precalculation.baseV(
      puUnits, V_nom);

  equation
    v = (term.v[1] - term.v[2])/V_base;
  end VdiffSensor;

  model IdiffSensor "Current difference sensor, 1-phase"
    extends Partials.Sensor2Base;

    Modelica.Blocks.Interfaces.RealOutput i
      "current ('plus' - 'minus')/2, term_p to term_n"

  protected
    final parameter PS.Current I_base=Utilities.Precalculation.baseI(
      puUnits, V_nom, S_nom);

  equation
    i = 0.5*(term_p.i[1] - term_p.i[2])/I_base;
  end IdiffSensor;

  model Vsensor "Voltage sensor, 1-phase"
    extends Partials.Sensor1Base(final S_nom=1);

    Modelica.Blocks.Interfaces.RealOutput[2] v
      "voltage 'plus' and 'minus'-to-ground"

  protected
    final parameter PS.Voltage V_base=Utilities.Precalculation.baseV(
      puUnits, V_nom);

  equation
    v = term.v/V_base;
  end Vsensor;

  model Isensor "Current sensor, 1-phase"
    extends Partials.Sensor2Base;

    Modelica.Blocks.Interfaces.RealOutput[2] i
      "current 'plus' and 'minus', term_p to term_n"

  protected
    final parameter PS.Current I_base=Utilities.Precalculation.baseI(
      puUnits, V_nom, S_nom);

  equation
    i = term_p.i/I_base;
  end Isensor;

  model Psensor "Power sensor, 1-phase"
    extends Partials.Sensor2Base;

    Modelica.Blocks.Interfaces.RealOutput p "power, term_p to term_n"

  protected
    final parameter SI.ApparentPower S_base=Utilities.Precalculation.baseS(
      puUnits, S_nom);

  equation
    p = term_p.v*term_p.i/S_base;
  end Psensor;

  model Vmeter "Voltage meter, 1-phase"
    extends Partials.Meter1Base(final S_nom=1);

    output SIpu.Voltage v(stateSelect=StateSelect.never);
    output SIpu.Voltage v0(stateSelect=StateSelect.never);
  protected
    SIpu.Voltage[2] v_ab(each stateSelect=StateSelect.never);
    final parameter PS.Voltage V_base=Utilities.Precalculation.baseV(
      puUnits, V_nom);

  equation
    v_ab = term.v/V_base;

    v = v_ab[1] - v_ab[2];
    v0 = (v_ab[1] + v_ab[2])/2;
  end Vmeter;

  model Imeter "Current meter, 1-phase"
    extends Partials.Meter2Base;

    output SIpu.Current i(stateSelect=StateSelect.never);
    output SIpu.Current i0(stateSelect=StateSelect.never);
  protected
    SIpu.Current[2] i_ab(each stateSelect=StateSelect.never);
    final parameter PS.Current I_base=Utilities.Precalculation.baseI(
      puUnits, V_nom, S_nom);

  equation
    i_ab = term_p.i/I_base;

    i = (i_ab[1] - i_ab[2])/2;
    i0 = (i_ab[1] + i_ab[2]);
  end Imeter;

  model Pmeter "Power meter, 1-phase"

    parameter Boolean av=false "time average power"
    parameter SI.Time tcst(min=1e-9)=1 "average time-constant"
    extends Partials.Meter2Base(final V_nom=1);

    output SIpu.Power p(stateSelect=StateSelect.never);
    output SIpu.Power p_av=pav if av;
  protected
    outer System system;
    final parameter SI.ApparentPower S_base=Utilities.Precalculation.baseS(
      puUnits, S_nom);
    SIpu.Power pav;

  initial equation
    if av then
      pav = p;
    end if;

  equation
    p = (term_p.v*term_p.i)/S_base;
    if av then
      der(pav) = (p - pav)/tcst;
    else
      pav = 0;
    end if;
  end Pmeter;

  model PVImeter "Power-voltage-current meter, 1-phase"

    parameter Boolean av=false "time average power"
    parameter SI.Time tcst(min=1e-9)=1 "average time-constant"
    extends Partials.Meter2Base;
    output SIpu.Power p(stateSelect=StateSelect.never);
    output SIpu.Power p_av=pav if av;
    output SIpu.Voltage v(stateSelect=StateSelect.never);
    output SIpu.Voltage v0(stateSelect=StateSelect.never);
    output SIpu.Current i(stateSelect=StateSelect.never);
    output SIpu.Current i0(stateSelect=StateSelect.never);
  protected
    outer System system;
    final parameter PS.Voltage V_base=Utilities.Precalculation.baseV(
      puUnits, V_nom);
    final parameter PS.Current I_base=Utilities.Precalculation.baseI(
      puUnits, V_nom, S_nom);
    SIpu.Power pav;
    SIpu.Voltage[2] v_ab;
    SIpu.Current[2] i_ab;

  initial equation
    if av then
      pav = p;
    end if;

  equation
    v_ab = term_p.v/V_base;
    i_ab = term_p.i/I_base;
    v = v_ab[1] - v_ab[2];
    v0 = (v_ab[1] + v_ab[2])/2;
    i = (i_ab[1] - i_ab[2])/2;
    i0 = (i_ab[1] + i_ab[2]);
    p = v_ab*i_ab;
    if av then
      der(pav) = (p - pav)/tcst;
    else
      pav = 0;
    end if;
  end PVImeter;

  model Efficiency "Power sensor, 3-phase dq0"
    extends Partials.Sensor2Base;

    Interfaces.ThermalV_p heat(     m=m) "vector heat port"
    parameter Boolean dir_in=true "direction"
    parameter Integer m(final min=1)=1 "dimension of heat port";
    parameter Boolean av=false "time average efficiency"
    parameter SI.Time tcst(min=1e-9)=1 "average time-constant"
    parameter SI.Temperature T_amb=300 "ambient temperature";
    output Real eta "efficiency";
  protected
    SI.Power p "total el power, term_p to term_n";
    SI.HeatFlowRate q "total heat flow 'in'";
    SI.Power pav(start=1);
    SI.HeatFlowRate qav(start=1);

  initial equation
    if av then
      pav = p;
      qav = q;
    end if;

  equation
    heat.ports.T = fill(T_amb, heat.m);
    p = term_p.v*term_p.i;
    q = sum(heat.ports.Q_flow);

    if av then
      der(pav) = (p - pav)/tcst;
      der(qav) = (q - qav)/tcst;
    else
      pav = p;
      qav = q;
    end if;

    if qav < abs(pav) then
      if dir_in then
        eta = if pav > 0 then 100*(pav - qav)/pav else -100*pav/(pav - qav);
      else
        eta = if pav > 0 then 100*pav/(pav + qav) else -100*(pav + qav)/pav;
      end if;
    else
      eta = 0;
    end if;
  end Efficiency;

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

    partial model Sensor1Base "Sensor Base, 1-phase"
      extends Ports.Port_p;
      extends Common.Nominal.Nominal;

    equation
      term.i = zeros(2);
    end Sensor1Base;

    partial model Sensor2Base "Sensor Base, 1-phase"
      extends Ports.Port_pn;
      extends Common.Nominal.Nominal;

    equation
      term_p.v = term_n.v;
    end Sensor2Base;

    partial model Meter1Base "Meter base 1 terminal, 1-phase"
      extends Sensor1Base;
    end Meter1Base;

    partial model Meter2Base "Meter base 2 terminal, 1-phase"
      extends Sensor2Base;
    end Meter2Base;

  end Partials;
end Sensors;


within PowerSystems.AC1ph_DC;
package Shunts
  extends Modelica.Icons.VariantsPackage;

  model ReactiveShunt "Shunt reactor with parallel conductor, 1-phase"
    extends Partials.ShuntBase;

    parameter SIpu.Conductance g=0 "conductance (parallel)";
    parameter SIpu.Resistance r=0 "resistance (serial)";
    parameter SIpu.Reactance x_s=1 "self reactance";
    parameter SIpu.Reactance x_m=0 "mutual reactance, -x_s < x_m < x_s";
  protected
    final parameter SI.Resistance[2] RL_base=Utilities.Precalculation.baseRL(
        puUnits,
        V_nom,
        S_nom,
        2*pi*f_nom);
    SI.Conductance G=g/RL_base[1];
    SI.Resistance R=r*RL_base[1];
    SI.Inductance[2,2] L=[x_s,x_m;x_m,x_s]*RL_base[2];
    PS.Current[2] i_x;

  equation
    i_x = i - G*v;
    L*der(i_x) + R*i_x = v;
  end ReactiveShunt;

  model CapacitiveShunt "Shunt capacitor with parallel conductor, 1-phase, pp pg"
    extends Partials.ShuntBase;

    parameter SIpu.Conductance g_pg=0 "conductance ph-grd";
    parameter SIpu.Conductance g_pp=0 "conductance ph_ph";
    parameter SIpu.Susceptance b_pg=0.5 "susceptance ph-grd";
    parameter SIpu.Susceptance b_pp=0.5 "susceptance ph-ph";
  protected
    final parameter SI.Resistance[2] GC_base=Utilities.Precalculation.baseGC(
        puUnits,
        V_nom,
        S_nom,
        2*pi*f_nom);
    SI.Conductance[2,2] G=[g_pg+g_pp,-g_pp;-g_pp,g_pg+g_pp]*GC_base[1];
    SI.Capacitance[2,2] C=[b_pg+b_pp,-b_pp;-b_pp,b_pg+b_pp]*GC_base[2];

  equation
    C*der(v) + G*v = i;
  end CapacitiveShunt;

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

  partial model ShuntBase "Load base, 1-phase"
    extends Ports.Port_p;
    extends Common.Nominal.NominalAC;

    PS.Voltage[2] v "voltage";
    PS.Current[2] i "current";

  equation
    v = term.v;
    i = term.i;
  end ShuntBase;

end Partials;
end Shunts;


DC voltage sources

within PowerSystems.AC1ph_DC;
package Sources "DC voltage sources"
  extends Modelica.Icons.SourcesPackage;

  model ACvoltage "Ideal AC voltage, 1-phase"
    extends Partials.ACvoltageBase;

    parameter SIpu.Voltage v0eff=1 "fixed effective voltage"
    parameter SI.Angle alpha0=0 "fixed phase angle"
  protected
    PS.Voltage V;
    SI.Angle alpha;
    SI.Angle phi;

  equation
    if not use_vPhasor_in then
      vPhasor_internal = {v0eff, alpha0};
    end if;
    V = vPhasor_internal[1]*sqrt(2)*V_base;
    alpha = vPhasor_internal[2];

    phi = theta + alpha + system.alpha0;
    term.v[1] - term.v[2] = V*cos(phi);
  end ACvoltage;

  model Vspectrum "Ideal voltage spectrum, 1-phase"
    extends Partials.ACvoltageBase;

    parameter Integer[:] h={1,3,5} "[1,.. ], which harmonics?";
    parameter SIpu.Voltage[N] v0eff={1,0.3,0.1} "effective voltages";
    parameter SI.Angle[N] alpha0=zeros(N) "phase angles";
  protected
    final parameter Integer N=size(h, 1) "nb of harmonics";
    PS.Voltage V;
    SI.Angle alpha;
    SI.Angle[N] phi;

  equation
    if not use_vPhasor_in then
      vPhasor_internal = {1, 0};
    end if;
    V = vPhasor_internal[1]*sqrt(2)*V_base;
    alpha = vPhasor_internal[2];

    phi = h*(theta + alpha + system.alpha0) + h.*alpha0;
    term.v[1] - term.v[2] = V*v0eff*cos(phi);
  end Vspectrum;

  model DCvoltage "Ideal DC voltage"
    extends Partials.DCvoltageBase(pol=-1);

    parameter SIpu.Voltage v0=1 "fixed DC voltage"
  protected
    PS.Voltage v;

  equation
    if not use_vDC_in then
      vDC_internal = v0;
    end if;
    v = vDC_internal*V_base;
    term.v[1] - term.v[2] = v;
  end DCvoltage;

  model Battery "Battery"
    extends Ports.Port_n;
    extends Common.Nominal.Nominal;

    parameter SIpu.Voltage v0=1 "battery voltage";
  protected
    final parameter Real V_base=Utilities.Precalculation.baseV(puUnits, V_nom);
    PS.Voltage v;
    PS.Current i;

  equation
    v = v0*V_base;
    term.v[2] = 0;
    term.v[1] - term.v[2] = v;
    term.i[1] = -i;
  end Battery;

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

    partial model VoltageBase "Voltage base"
      extends Ports.Port_n;
      extends Common.Nominal.Nominal(
                                 final S_nom=1);

      parameter Integer pol(min=-1,max=1)=-1 "grounding scheme"

      Interfaces.Electric_p neutral "(use for grounding)"
    protected
      final parameter Real V_base=Utilities.Precalculation.baseV(puUnits, V_nom);

    equation
      if pol==1 then
        term.v[1] = neutral.v;
      elseif pol==-1 then
        term.v[2] = neutral.v;
      else
        term.v[1] + term.v[2] = neutral.v;
      end if;

      sum(term.i) + neutral.i = 0;
    end VoltageBase;

    partial model ACvoltageBase "AC voltage base"
      extends VoltageBase;

      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 use input signal vPhasor_in, otherwise use fixed values"
      Modelica.Blocks.Interfaces.RealInput[2] vPhasor_in if use_vPhasor_in
        "{abs(voltage), phase(voltage)}"
      Modelica.Blocks.Interfaces.RealInput omega_in(final unit="rad/s") if fType
         == PowerSystems.Types.SourceFrequency.Signal
        "Angular frequency of source"

    protected
      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";

      outer System system;
      SI.Angle theta(stateSelect=StateSelect.prefer);

    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 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;
    end ACvoltageBase;

    partial model DCvoltageBase "DC voltage base"
      extends VoltageBase;

      parameter Integer pol(min=-1,max=1)=-1 "grounding scheme"

      parameter Boolean use_vDC_in = false
        "= true to use input signal vDC_in, otherwise use fixed value"
      Modelica.Blocks.Interfaces.RealInput vDC_in if
                                                  use_vDC_in "DC voltage"
    protected
      Modelica.Blocks.Interfaces.RealInput vDC_internal
        "Needed to connect to conditional connector";
    equation
      connect(vDC_in, vDC_internal);
    end DCvoltageBase;

  end Partials;
end Sources;


Transformers 1-phase

within PowerSystems.AC1ph_DC;
package Transformers "Transformers 1-phase "
  extends Modelica.Icons.VariantsPackage;

  model TrafoIdeal "Ideal transformer, 1-phase"
    extends Partials.TrafoIdealBase;

  equation
    i1 + i2 = 0;
    v1 = v2;
  end TrafoIdeal;

  model TrafoStray "Ideal magnetic coupling transformer, 1-phase"
    extends Partials.TrafoStrayBase;

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(i1) = 0;
    elseif dynType == Types.Dynamics.FixedInitial then
      i1 = i1_start;
    end if;

  equation
    i1 + i2 = 0;
    sum(L)*der(i1) + sum(R)*i1 = v1 - v2;
  end TrafoStray;

  model TrafoMag "Magnetic coupling transformer, 1-phase"
    extends Partials.TrafoMagBase;

    PS.Voltage v0;
    PS.Current imag;
    PS.Current iedc;
  Real psi0 "unsaturated flux";

  equation
    i1 + i2 = imag + iedc;
    Redc*iedc = v0;
  psi0 = Lm*imag;
    L[1]*der(i1) + R[1]*i1 = v1 - v0;
    L[2]*der(i2) + R[2]*i2 = v2 - v0;
    Lm*der(imag) = v0;
  end TrafoMag;

  model TrafoSat "Saturation transformer, 1-phase"
    extends Partials.TrafoSatBase;

    PS.Voltage v0;
    PS.Current imag;
    PS.Current iedc;
  protected
    Real psi0 "unsaturated flux";
    Real g;
    function der_sat = Common.IronSaturation.der_saturationAnalytic;

  equation
    i1 + i2 = imag + iedc;
    Redc*iedc = v0;
    psi0 = Lm*imag;
    g = scalar(der_sat({psi0}/psi_nom, c_sat));

    L[1]*der(i1) + R[1]*i1 = v1 - v0;
    L[2]*der(i2) + R[2]*i2 = v2 - v0;
    g*der(psi0) = v0;
  end TrafoSat;

  model Trafo3Stray "Ideal magnetic coupling transformer, 1-phase"
    extends Partials.Trafo3StrayBase;

  equation
    i1 + i2a + i2b = 0;
    L[1]*der(i1) + R[1]*i1 = v1 - v0;
    L[2]*der(i2a) + R[2]*i2a = v2a - v0;
    L[3]*der(i2b) + R[3]*i2b = v2b - v0;
  end Trafo3Stray;

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

    partial model TrafoIdealBase "Base for ideal transformer, 1-phase"

      extends Ports.PortTrafo_p_n(i1(start = i1_start), i2(start = i2_start));

      parameter Types.Dynamics dynType=system.dynType "transient or steady-state model"
      parameter PS.Current i1_start = 0 "start value of primary current"
      parameter PS.Current i2_start = i1_start
        "start value of secondary current"

      parameter Boolean use_tap_1_in = false "= true to enable input tap_1_in"
      parameter Integer tap_1 = par.tap_neutral[1] "fixed tap_1 position"
      parameter Boolean use_tap_2_in = false "= true to enable input tap_2_in"
      parameter Integer tap_2 = par.tap_neutral[2] "fixed tap_2 position"
      parameter Boolean dynTC=false "enable dynamic tap-changing"

      Modelica.Blocks.Interfaces.IntegerInput tap_1_in if use_tap_1_in
        "1: index of voltage level"
      Modelica.Blocks.Interfaces.IntegerInput tap_2_in if use_tap_2_in
        "2: index of voltage level"

      replaceable record Data =
        PowerSystems.AC1ph_DC.Transformers.Parameters.TrafoIdeal1ph
        "trafo parameters"
      final parameter Data par "trafo parameter record"
    protected
      Modelica.Blocks.Interfaces.IntegerInput tap_1_internal
        "Needed to connect to conditional connector";
      Modelica.Blocks.Interfaces.IntegerInput tap_2_internal
        "Needed to connect to conditional connector";

      outer System system;
      constant Real tc=0.01 "time constant tap-chg switching";
      final parameter PS.Voltage[2] V_base=Utilities.Precalculation.baseTrafoV(
                                                                           par.puUnits, par.V_nom);
      final parameter Real[2,2] RL_base=Utilities.Precalculation.baseTrafoRL(
              par.puUnits,
              par.V_nom,
              par.S_nom,
              2*pi*par.f_nom);
      Real w_nom = par.V_nom[2]/par.V_nom[1] "nominal turns ratio";
      Real[2] dv_tap_pu = par.dv_tap .* V_base ./ par.V_nom;
      Real w1_set = (1 + (tap_1_internal - par.tap_neutral[1]) * dv_tap_pu[1])
        "1: set voltage ratio to nominal primary";
      Real w2_set = (1 + (tap_2_internal - par.tap_neutral[2]) * dv_tap_pu[2]) * w_nom
        "2: set voltage ratio to nominal primary";

    initial equation
      if dynTC then
        w1 = w1_set;
        w2 = w2_set;
      end if;

    equation
      connect(tap_1_in, tap_1_internal);
      connect(tap_2_in, tap_2_internal);
      if not use_tap_1_in then
         tap_1_internal = tap_1;
      end if;
      if not use_tap_2_in then
         tap_2_internal = tap_2;
      end if;

      if dynTC then
        der(w1) + (w1 - w1_set)/tc = 0;
        der(w2) + (w2 - w2_set)/tc = 0;
      else
        w1 = w1_set;
        w2 = w2_set;
      end if;
    end TrafoIdealBase;

    partial model TrafoStrayBase
      "Base for ideal magnetic coupling transformer, 1-phase"
      extends TrafoIdealBase(redeclare replaceable record Data =
          PowerSystems.AC1ph_DC.Transformers.Parameters.TrafoStray1ph);
    protected
      SI.Resistance[2] R=par.r.*RL_base[:, 1];
      SI.Inductance[2] L=par.x.*RL_base[:, 2];
    end TrafoStrayBase;

    partial model TrafoMagBase
      "Base for magnetic coupling transformer, 1-phase"
      extends TrafoStrayBase(redeclare replaceable record Data =
          PowerSystems.AC1ph_DC.Transformers.Parameters.TrafoMag1ph);
    protected
      final parameter SI.Resistance[2] RL12_base = sqrt((RL_base[1,:].*RL_base[2,:]));
      SI.Resistance Redc=par.redc*RL12_base[1];
      SI.Inductance Lm=par.xm*RL12_base[2];
    end TrafoMagBase;

    partial model TrafoSatBase "Base for saturation transformer, 1-phase"
      extends TrafoMagBase(redeclare replaceable record Data =
          PowerSystems.AC1ph_DC.Transformers.Parameters.TrafoSat1ph);
    protected
      Real xratio=par.xm_sat/par.xm;
      Real[3] c_sat={1-xratio,(1-xratio)/(par.psi_sat-xratio),xratio};
      final parameter SI.MagneticFlux psi_nom=sqrt(2)*par.V_nom[1]/(2*pi*par.f_nom)
        "amplitude!";

    end TrafoSatBase;

    partial model Trafo3IdealBase "Base for ideal transformer, 1-phase"

      extends Ports.PortTrafo_p_n_n;

      parameter Boolean use_tap_1_in = false "= true to enable input tap_1_in"
      parameter Integer tap_1 = par.tap_neutral[1] "fixed tap_1 position"
      parameter Boolean use_tap_2_in = false "= true to enable input tap_2_in"
      parameter Integer[2] tap_2 = par.tap_neutral[2:3] "fixed tap_2 position"
      parameter Boolean dynTC=false "enable dynamic tap-changing"

      Modelica.Blocks.Interfaces.IntegerInput tap_1_in if use_tap_1_in
        "1: index of voltage level"
      Modelica.Blocks.Interfaces.IntegerInput[2] tap_2_in if use_tap_2_in
        "2: indices of voltage levels"

      replaceable record Data =
        PowerSystems.AC1ph_DC.Transformers.Parameters.Trafo3Ideal1ph
        "trafo parameters"
      final parameter Data par "trafo parameter"
    protected
      Modelica.Blocks.Interfaces.IntegerInput tap_1_internal
        "Needed to connect to conditional connector";
      Modelica.Blocks.Interfaces.IntegerInput[2] tap_2_internal
        "Needed to connect to conditional connector";

      outer System system;
      constant Real tc=0.01 "time constant tap-chg switching";
      final parameter PS.Voltage[3] V_base=Utilities.Precalculation.baseTrafoV(
                                                                           par.puUnits, par.V_nom);
      final parameter Real[3,2] RL_base=Utilities.Precalculation.baseTrafoRL(
              par.puUnits,
              par.V_nom,
              par.S_nom,
              2*pi*par.f_nom);
      Real wa_nom = par.V_nom[2]/par.V_nom[1] "nominal turns ratio";
      Real wb_nom = par.V_nom[3]/par.V_nom[1] "nominal turns ratio";
      Real[3] dv_tap_pu = par.dv_tap .* V_base ./ par.V_nom;
      Real w1_set = (1 + (tap_1_internal - par.tap_neutral[1]) * dv_tap_pu[1])
        "1: set voltage ratio to nominal primary";
      Real w2a_set = (1 + (tap_2_internal[1] - par.tap_neutral[2]) * dv_tap_pu[2]) * wa_nom
        "2a: set voltage ratio to nominal primary";
      Real w2b_set = (1 + (tap_2_internal[2] - par.tap_neutral[3]) * dv_tap_pu[3]) * wb_nom
        "2b: set voltage ratio to nominal primary";

    initial equation
      if dynTC then
        w1 = w1_set;
        w2a = w2a_set;
        w2b = w2b_set;
      end if;

    equation
      connect(tap_1_in, tap_1_internal);
      connect(tap_2_in, tap_2_internal);
      if not use_tap_1_in then
         tap_1_internal = tap_1;
      end if;
      if not use_tap_2_in then
         tap_2_internal = tap_2;
      end if;

      if dynTC then
        der(w1) + (w1 - w1_set)/tc = 0;
        der(w2a) + (w2a - w2a_set)/tc = 0;
        der(w2b) + (w2b - w2b_set)/tc = 0;
      else
        w1 = w1_set;
        w2a = w2a_set;
        w2b = w2b_set;
      end if;
    end Trafo3IdealBase;

    partial model Trafo3StrayBase
      "Base for ideal magnetic coupling transformer, 1-phase"
      extends Trafo3IdealBase(redeclare replaceable record Data =
          PowerSystems.AC1ph_DC.Transformers.Parameters.Trafo3Stray1ph);
    protected
      SI.Resistance[3] R=par.r.*RL_base[:, 1];
      SI.Inductance[3] L=par.x.*RL_base[:, 2];
    end Trafo3StrayBase;

  end Partials;

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

record TrafoIdeal1ph "Parameters for ideal transformer, 1-phase"
  extends Common.Nominal.NominalDataTrafo;
  Integer[2] tap_neutral={0, 0} "{1,2}: neutral tap position"
  SIpu.Voltage[2] dv_tap={0, 0} "{1,2}: delta-v per tap change"
end TrafoIdeal1ph;

record TrafoStray1ph
      "Parameters for ideal magnetic coupling transformer, 1-phase"
  extends TrafoIdeal1ph;
  SIpu.Resistance[2] r={0.05,0.05} "{1,2}: resistance"
  SIpu.Reactance[2] x={0.05,0.05} "{1,2}: stray reactance"
end TrafoStray1ph;

record TrafoMag1ph "Parameters for magnetic coupling transformer, 1-phase"
  extends TrafoStray1ph;
  SIpu.Resistance redc=500 "resistance eddy current"
  SIpu.Reactance xm=500 "mutual reactance"
end TrafoMag1ph;

record TrafoSat1ph "Parameters for saturation transformer, 1-phase"
  extends TrafoMag1ph;
  Real psi_sat(unit="1")=1.5 "saturation flux"
  SIpu.Reactance xm_sat=1 "mutual reactance saturated"
end TrafoSat1ph;

record Trafo3Ideal1ph "Parameters for ideal transformer, 1-phase"
  Integer[3] tap_neutral={0, 0, 0} "{1,2a,2b}: neutral tap position"
  SIpu.Voltage[3] dv_tap={0, 0, 0} "{1,2a,2b}: delta-v per tap change"
  extends Common.Nominal.NominalDataTrafo(V_nom={1,1,1}
    "{prim,sec_a,sec_b} nom Voltage (= base if pu)");
end Trafo3Ideal1ph;

record Trafo3Stray1ph
      "Parameters for ideal magnetic coupling transformer, 1-phase"
  extends Trafo3Ideal1ph;
  SIpu.Resistance[3] r={0.05,0.05,0.05} "{1,2a,2b}: resistance"
  SIpu.Reactance[3] x={0.05,0.05,0.05} "{1,2a,2b}: stray reactance"
end Trafo3Stray1ph;
end Parameters;
end Transformers;


Switches and Breakers 3-phase

within PowerSystems.AC3ph;
package Breakers "Switches and Breakers 3-phase"
  extends Modelica.Icons.VariantsPackage;

  model ForcedSwitch "Forced switch, 3-phase dq0"
    extends Partials.SwitchBase(final n=1);

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

    parameter SI.Time t_relax=10e-3 "switch relaxation time";
    parameter Integer p_relax(min=2)=4 "power of relaxation exponent";
  protected
    outer System system;
    SI.Time t0(start=-Modelica.Constants.inf);
    Real[2] r(start={0,1});
    Real[PS.n] s;
  /*
  Boolean open(start=not control[1])=not control[1];
  Boolean closed(start=control[1])=control[1];

  Start values not correct, since no parameter expressions.
  Removed start values and initalized the pre(..) values in the
  initial equation section.
*/
    Boolean open=not control[1];
    Boolean closed=control[1];

    function relaxation=PowerSystems.Utilities.Math.relaxation;

  initial equation
    pre(open) = not control[1];
    pre(closed) = control[1];
    if dynType <> Types.Dynamics.SteadyState then
      t0 = -Modelica.Constants.inf;
    end if;
  equation
    if dynType <> Types.Dynamics.SteadyState then
      when edge(open) or edge(closed) then
        t0 = time;
      end when;
      r = relaxation(time - t0, t_relax, p_relax);
      {v,i} = if closed then {(r[1]+r[2]*epsR)*s,(r[1]*epsG+r[2])*s} else {(r[1]*epsR+r[2])*s,(r[1]+r[2]*epsG)*s};
    else
      t0 = 0;
      r = {1,0};
      {v,i} = if closed then {epsR*s,s} else {s,epsG*s};
    end if;
  end ForcedSwitch;

  model ForcedCommSwitch "Forced commuting switch, 3-phase dq0"
    extends Ports.PortBase;
    extends PowerSystems.Common.Nominal.NominalVI;

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

    parameter Real[2] eps(final min={0,0}, each unit="1")={1e-4,1e-4}
      "{resistance 'closed', conductance 'open'}";
    parameter SI.Time t_relax=10e-3 "switch relaxation time";
    parameter Integer p_relax(min=2)=4 "power of relaxation exponent";
    PS.Voltage[PS.n] v_t;
    PS.Voltage[PS.n] v_f;
    PS.Current[PS.n] i_t;
    PS.Current[PS.n] i_f;

    Ports.ACdq0_p term_p "positive terminal"
    Ports.ACdq0_n term_nt "negative terminal 'true'"
    Ports.ACdq0_n term_nf "negative terminal 'false'"
    Modelica.Blocks.Interfaces.BooleanInput control
      "true: p - nt closed, false: p - nf closed"
  protected
    outer System system;
    final parameter SI.Resistance epsR=eps[1]*V_nom/I_nom;
    final parameter SI.Conductance epsG=eps[2]*I_nom/V_nom;
    SI.Time t0(start=-Modelica.Constants.inf);
    Real[2] r(start={0,1});
    Real[PS.n] s_t;
    Real[PS.n] s_f;
  /*
  Boolean open_t(start=not control)=not control;
  Boolean closed_t(start=control)=control;

  Start values not correct, since no parameter expressions.
  Removed start values and initalized the pre(..) values in the
  initial equation section.
*/
    Boolean open_t = not control;
    Boolean closed_t = control;

    function relaxation=PowerSystems.Utilities.Math.relaxation;
  initial equation
    pre(open_t) = not control;
    pre(closed_t) = control;
    if dynType <> Types.Dynamics.SteadyState then
      t0 = -Modelica.Constants.inf;
    end if;
  equation
    Connections.branch(term_p.theta, term_nt.theta);
    Connections.branch(term_p.theta, term_nf.theta);
    term_nt.theta = term_p.theta;
    term_nf.theta = term_p.theta;

    v_t = term_p.v - term_nt.v;
    v_f = term_p.v - term_nf.v;
    term_nt.i = -i_t;
    term_nf.i = -i_f;
    term_p.i + term_nt.i + term_nf.i = zeros(PS.n);

    if dynType <> Types.Dynamics.SteadyState then
      when edge(open_t) or edge(closed_t) then
        t0 = time;
      end when;
      r = relaxation(time - t0, t_relax, p_relax);
      {v_t,i_t} = if closed_t then {(r[1]+r[2]*epsR)*s_t,(r[1]*epsG+r[2])*s_t} else {(r[1]*epsR+r[2])*s_t,(r[1]+r[2]*epsG)*s_t};
      {v_f,i_f} = if open_t then {(r[1]+r[2]*epsR)*s_f,(r[1]*epsG+r[2])*s_f} else {(r[1]*epsR+r[2])*s_f,(r[1]+r[2]*epsG)*s_f};
    else
      t0 = 0;
      r = {1,0};
      {v_t,i_t} = if control then {epsR*s_t,s_t} else {s_t,epsG*s_t};
      {v_f,i_f} = if not control then {epsR*s_f,s_f} else {s_f,epsG*s_f};
    end if;
  end ForcedCommSwitch;

  model Switch "Ideal switch, 3-phase dq0"
    extends Partials.SwitchSinglePhaseBase;

  protected
    Common.Switching.Switch switch_a(
      epsR=epsR,
      epsG=epsG)
    Common.Switching.Switch switch_b(
      epsR=epsR,
      epsG=epsG)
    Common.Switching.Switch switch_c(
      epsR=epsR,
      epsG=epsG)

  equation
    switch_a.v=v_abc[1];
    switch_a.i=i_abc[1];
    switch_b.v=v_abc[2];
    switch_b.i=i_abc[2];
    switch_c.v=v_abc[3];
    switch_c.i=i_abc[3];

    connect(control[1], switch_a.closed)
    connect(control[2], switch_b.closed)
    connect(control[3], switch_c.closed)
  end Switch;

  model Breaker "Breaker, 3-phase dq0"
    extends Partials.SwitchSinglePhaseBase;

    replaceable parameter Parameters.BreakerArc par "breaker parameter"
  protected
    replaceable Common.Switching.Breaker breaker_a(
      D=par.D,
      t_opening=par.t_opening,
      Earc=par.Earc,
      R0=par.R0,
      epsR=epsR,
      epsG=epsG)
    replaceable Common.Switching.Breaker breaker_b(
      D=par.D,
      t_opening=par.t_opening,
      Earc=par.Earc,
      R0=par.R0,
      epsR=epsR,
      epsG=epsG)
    replaceable Common.Switching.Breaker breaker_c(
      D=par.D,
      t_opening=par.t_opening,
      Earc=par.Earc,
      R0=par.R0,
      epsR=epsR,
      epsG=epsG)

  equation
    breaker_a.v=v_abc[1];
    breaker_a.i=i_abc[1];
    breaker_b.v=v_abc[2];
    breaker_b.i=i_abc[2];
    breaker_c.v=v_abc[3];
    breaker_c.i=i_abc[3];

    connect(control[1], breaker_a.closed)
    connect(control[2], breaker_b.closed)
    connect(control[3], breaker_c.closed)
  end Breaker;

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

    partial model SwitchBase "Switch base, 3-phase dq0"
      extends Ports.Port_pn;
      extends PowerSystems.Common.Nominal.NominalVI;

      parameter Integer n=3 "number of independent switches";
      parameter Real[2] eps(final min={0,0}, each unit="1")={1e-4,1e-4}
        "{resistance 'closed', conductance 'open'}";
      PS.Voltage[PS.n] v;
      PS.Current[PS.n] i;
      Modelica.Blocks.Interfaces.BooleanInput[n] control
        "true:closed, false:open"
    protected
      final parameter SI.Resistance epsR=eps[1]*V_nom/I_nom;
      final parameter SI.Conductance epsG=eps[2]*I_nom/V_nom;

    equation
      v = term_p.v - term_n.v;
      term_p.i = i;
    end SwitchBase;

    partial model SwitchSinglePhaseBase
      "Switch base, additional abc-variables for single-phase switching"
      extends SwitchBase(final n=3);

      PS.Voltage[3] v_abc(each stateSelect=StateSelect.never)
        "voltage switch a, b, c";
      PS.Current[3] i_abc(each stateSelect=StateSelect.never)
        "current switch a, b, c";
    protected
      Real[3,3] Park=PowerSystems.Utilities.Transforms.park(term_p.theta[2]);

    equation
      v = Park*v_abc;
      i_abc = transpose(Park)*i;
    /*
  Loop not solvable for this version:
  static = not (switch_a.arc or switch_b.arc or switch_c.arc); //Switch
  static = not (breaker_a.arc or breaker_b.arc or breaker_c.arc); //Breaker
  if static then
    v_abc = {0,0,0} "v_abc not needed";
    i_abc = {0,0,0} "i_abc not needed)";
  else
    v = Park*v_abc;
    i_abc = transpose(Park)*i;
  end if;
*/
    /*
  Initial equation needed, if the equation
  der(i_abc) = transpose(Park)*(der(i) + omega[2]*j_dq0(i));
  is used:
  initial equation
  i_abc = transpose(Park)*i;
*/
    end SwitchSinglePhaseBase;

  end Partials;

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

record BreakerArc "Breaker parameters, 3-phase"
  extends Modelica.Icons.Record;

  SI.Distance D=50e-3 "contact distance open"
  SI.Time t_opening=30e-3 "opening duration"
  SI.ElectricFieldStrength Earc=50e3 "electric field arc"
  Real R0=1 "small signal resistance arc"
end BreakerArc;
end Parameters;
end Breakers;


AC-drives dq0

within PowerSystems.AC3ph;
package Drives "AC-drives dq0"
  extends Modelica.Icons.VariantsPackage;

  model ASM "Asynchronous machine with cage rotor"

    extends Partials.DriveBase(rotor(w(start=w_start)));
    replaceable model Motor = PowerSystems.AC3ph.Machines.Asynchron
      "asyn motor"
    Motor motor "asyn motor"

  equation
    connect(motor.heat, heat)
    connect(motor.airgap, rotor.rotor)
    connect(term, motor.term)
  end ASM;

  model ASM_Y_D "Asynchronous machine with cage rotor, Y-Delta switcheable"

    extends Partials.DriveBase;
    replaceable model Motor = PowerSystems.AC3ph.Machines.AsynchronY_D
      "asyn motor Y-Delta switcheable"
    Motor motor "asyn motor Y-Delta switcheable"
    input Modelica.Blocks.Interfaces.BooleanInput YDcontrol
      "true:Y, false:Delta"

  equation
    connect(YDcontrol, motor.YDcontrol)
    connect(motor.heat, heat)
    connect(motor.airgap, rotor.rotor)
    connect(term, motor.term)
  end ASM_Y_D;

  model ASM_ctrl "Asynchronous machine, current-control"
    extends Partials.DriveBase_ctrl(heat_adapt(final m={2,inverter.heat.m}));

    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)"

    replaceable model Motor = PowerSystems.AC3ph.Machines.Asynchron_ctrl
      "asyn motor, current controlled"
    Motor motor "asyn motor, current controlled"

  equation
    connect(motor.airgap, rotor.rotor)
    connect(term, inverter.DC)
    connect(inverter.AC, motor.term)
    connect(motor.heat, heat_adapt.port_a)
    connect(inverter.heat, heat_adapt.port_b)
    connect(motor.vPhasor,inverter.vPhasor)
    connect(motor.i_meas, i_meas)
    connect(i_act, motor.i_act)
    connect(motor.phiRotorflux, inverter.theta)
  end ASM_ctrl;

  model SM_el "Synchronous machine, electric excitation"

    extends Partials.DriveBase;

    replaceable model Excitation =
        PowerSystems.AC3ph.Machines.Control.Excitation "excitation model"
    Excitation excitation "excitation model"

    replaceable model Motor = PowerSystems.AC3ph.Machines.Synchron3rd_ee
      "syn motor"
    Motor motor "syn motor"

    Modelica.Blocks.Interfaces.RealInput fieldVoltage(final unit="1")
      "field voltage pu from exciter control"
    Modelica.Blocks.Interfaces.RealOutput[3] termVoltage(final unit="1")
      "terminal voltage pu to exciter control"

  equation
    connect(fieldVoltage, excitation.fieldVoltage)
    connect(excitation.term, motor.term)
    connect(excitation.field, motor.field)
    connect(term, motor.term)
    connect(motor.airgap, rotor.rotor)
    connect(motor.heat, heat)
    connect(excitation.termVoltage, termVoltage)
  end SM_el;

  model SM_ctrl "Synchronous machine, current-control"
    extends Partials.DriveBase_ctrl(heat_adapt(final m={2,inverter.heat.m}));
    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)"

    replaceable model Motor = PowerSystems.AC3ph.Machines.Synchron3rd_pm_ctrl
      "syn motor, current controlled"
    Motor motor "syn motor, current controlled"

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

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

  partial model DriveBase0 "AC drives base mechanical"

    parameter SI.AngularVelocity w_start=0
      "initial rpm (start-value if steady init)"
    Interfaces.Rotation_n flange "mechanical flange"
    replaceable model Rotor = PowerSystems.Mechanics.Rotational.ElectricRotor
        "machine rotor"
    Rotor rotor(w_start=w_start) "machine rotor"
    replaceable model Gear = PowerSystems.Mechanics.Rotational.NoGear
        "type of gear"
    Gear gear "type of gear"
    Interfaces.ThermalV_n heat(m=2)
        "heat source port {stator, rotor}"
    protected
    outer System system;

  equation
    connect(rotor.flange_b,gear.flange_a)
    connect(gear.flange_b, flange)
  end DriveBase0;

  partial model DriveBase "AC drives base"
    extends DriveBase0;

    AC3ph.Ports.ACdq0_p term "electric terminal"
  end DriveBase;

  partial model DriveBase_ctrl "AC drives base control"

    extends DriveBase0(heat(final m=sum(heat_adapt.m)));

    AC1ph_DC.Ports.TwoPin_p term "electric terminal DC"
    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"
    protected
    Common.Thermal.HeatV_a_b_ab heat_adapt

  equation
    connect(heat_adapt.port_ab, heat)
  end DriveBase_ctrl;

  end Partials;
end Drives;


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;