Impedance and admittance two terminal

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

  model Resistor "Resistor, 1-phase"
    extends Partials.ImpedBase(final f_nom=0);

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

  equation
    diagonal(R)*i = v;
  end Resistor;

  model Conductor "Conductor, 1-phase"
    extends Partials.ImpedBase(final f_nom=0);

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

  equation
    diagonal(G)*v = i;
  end Conductor;

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

    parameter SIpu.Resistance[2] r={0,0} "resistance";
    parameter SIpu.Reactance[2,2] x=[1,0;0,1] "reactance matrix";
  protected
    final parameter Real[2] RL_base=Utilities.Precalculation.baseRL(
          puUnits,
          V_nom,
          S_nom,
          2*pi*f_nom);
    final parameter SI.Resistance[2] R=r*RL_base[1];
    final parameter SI.Inductance[2,2] L=x*RL_base[2];

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(i) = zeros(2);
    elseif dynType == Types.Dynamics.FixedInitial then
      i = i_start;
    end if;

  equation
    L*der(i) + diagonal(R)*i = v;
  end Inductor;

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

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

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(v) = zeros(2);
    elseif dynType == Types.Dynamics.FixedInitial then
      v = v_start;
    end if;

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

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

    parameter SIpu.Impedance z_abs=1 "impedance-value";
    parameter Real cos_phi(min=0,max=1)=0.1 "cos-phi of impedance";
    parameter Real cpl(min=-1,max=1)=0 "phase coupling, -1 < cpl < 1";
  protected
    final parameter Real[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[2,2] L=([1,cpl;cpl,1]/(1 - cpl))*z_abs*sin(acos(cos_phi))*RL_base[2];

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(i) = zeros(2);
    elseif dynType == Types.Dynamics.FixedInitial then
      i = i_start;
    end if;

  equation
    L*der(i) + R*i = v;
  end Impedance;

  model Admittance "Admittance (capacitive) with parallel conductor, 1-phase"
    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 Real[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) = zeros(2);
    elseif dynType == Types.Dynamics.FixedInitial then
      v = v_start;
    end if;

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

  model Varistor "Varistor, 1-phase"
    extends Partials.ImpedBase(final f_nom=0);

    parameter SIpu.Resistance r0=100 "small voltage resistance";
    parameter SIpu.Voltage v0=1 "saturation voltage";
  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
    v = V0*tanh(H0*i);
  end Varistor;

  model ResistorSym "Symmetrical capacitor with neutral access"
    extends Partials.ImpedBase0;

    parameter SI.Resistance R=1;
    Interfaces.Electric_n neutral "symmetrical point"
    Nodes.Electric_pn_p_n pn_p_n
    Nodes.Electric_pn_p_n p_n_pn
    ImpedancesSingle.ResistorSym resSym(final R=R)

  equation
    connect(pn_p_n.term_p, resSym.term_p)
    connect(resSym.term_p, p_n_pn.term_p)
    connect(pn_p_n.term_n, resSym.term_n)
    connect(resSym.term_n, p_n_pn.term_n)
    connect(term_p, pn_p_n.term_pn)
    connect(p_n_pn.term_pn, term_n)
    connect(resSym.neutral, neutral)
  end ResistorSym;

  model CapacitorSym "Symmetrical capacitor with neutral access"
    extends Partials.ImpedBase0;

    parameter Types.Dynamics dynType=system.dynType "transient or steady-state model"
    parameter PS.Voltage V_start=0 "start voltage"
    parameter SI.Conductance G=1e-6;
    parameter SI.Capacitance C=1e-6;
    Interfaces.Electric_n neutral "symmetrical point"
    Nodes.Electric_pn_p_n pn_p_n
    Nodes.Electric_pn_p_n p_n_pn
    ImpedancesSingle.CapacitorSym capSym(final G=G, final C=C, final V_start=V_start)
  protected
    outer System system;

  initial equation
    capSym.cap1.v = capSym.cap2.v;
    if dynType == Types.Dynamics.SteadyInitial then
      der(capSym.cap1.v) + der(capSym.cap2.v) = 0;
    end if;

  equation
    connect(pn_p_n.term_p, capSym.term_p)
    connect(capSym.term_p, p_n_pn.term_p)
    connect(pn_p_n.term_n, capSym.term_n)
    connect(capSym.term_n, p_n_pn.term_n)
    connect(term_p, pn_p_n.term_pn)
    connect(p_n_pn.term_pn, term_n)
    connect(capSym.neutral, neutral)
  end CapacitorSym;

  model DClink "DC-link with filter circuit"
    extends Partials.ImpedBase0;

    parameter Types.Dynamics dynType=system.dynType "transient or steady-state model"
    parameter PS.Voltage V_start=0 "start voltage"
    parameter SI.Resistance Rfilter=1e-3;
    parameter SI.Inductance Lfilter=1e-3;
    parameter SI.Capacitance Cfilter=1e-6;
    parameter SI.Capacitance Cdc=1e-6;
    ImpedancesSingle.Resistor res1(final R=Rfilter)
    ImpedancesSingle.Inductor ind1(final L=Lfilter)
    ImpedancesSingle.Capacitor cap1(final C=Cfilter)
    ImpedancesSingle.Capacitor cap(final C=Cdc, final v(start=V_start))
    Interfaces.Electric_n grd "ground"
    Nodes.Electric_pn_p_n pn_p_n
    Nodes.Electric_pn_p_n p_n_pn
  protected
    outer System system;

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(cap.v) = 0;
      der(cap1.v) = 0;
    end if;

  equation
    connect(pn_p_n.term_p, res1.term_p)
    connect(res1.term_n, ind1.term_p)
    connect(ind1.term_n, cap1.term_p)
    connect(cap1.term_n, pn_p_n.term_n)
    connect(p_n_pn.term_p, cap.term_p)
    connect(p_n_pn.term_n, cap.term_n)
    connect(res1.term_p, cap.term_p)
    connect(cap.term_n, cap1.term_n)
    connect(cap.term_n, grd)
    connect(term_p, pn_p_n.term_pn)
    connect(p_n_pn.term_pn, term_n)
  end DClink;

  model DClinkSym "Symmetrical DC-link with filter circuit and neutral access"
    extends Partials.ImpedBase0;

    parameter Types.Dynamics dynType=system.dynType "transient or steady-state model"
    parameter PS.Voltage V_start=0 "start voltage"
    parameter SI.Resistance Rfilter=1e-3;
    parameter SI.Inductance Lfilter=1e-3;
    parameter SI.Capacitance Cfilter=1e-6;
    parameter SI.Capacitance Cdc=1e-6;
    ImpedancesSingle.Resistor res1(final R=Rfilter)
    ImpedancesSingle.Inductor ind1(final L=Lfilter)
    ImpedancesSingle.Capacitor cap1(final C=Cfilter)
    ImpedancesSingle.CapacitorSym capSym(final C=Cdc, final V_start=V_start)
    Interfaces.Electric_n neutral "symmetrical point"
    Nodes.Electric_pn_p_n pn_p_n
    Nodes.Electric_pn_p_n p_n_pn
  protected
    outer System system;

  initial equation
    capSym.cap1.v = capSym.cap2.v;
    if dynType == Types.Dynamics.SteadyInitial then
      der(cap1.v) = 0;
    end if;

  equation
    connect(pn_p_n.term_p, res1.term_p)
    connect(res1.term_n, ind1.term_p)
    connect(ind1.term_n, cap1.term_p)
    connect(cap1.term_n, pn_p_n.term_n)
    connect(p_n_pn.term_p, capSym.term_p)
    connect(p_n_pn.term_n, capSym.term_n)
    connect(res1.term_p, capSym.term_p)
    connect(capSym.term_n, cap1.term_n)
    connect(capSym.neutral, neutral)
    connect(term_p, pn_p_n.term_pn)
    connect(p_n_pn.term_pn, term_n)
  end DClinkSym;

  package Partials "Partial models"
    partial model ImpedBase0 "Impedance base 0, 1-phase"
      extends Ports.PortBase;

      Ports.TwoPin_p term_p "positive terminal"
      Ports.TwoPin_n term_n "negative terminal"
    end ImpedBase0;
    extends Modelica.Icons.BasesPackage;

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

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

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

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

    partial model ImpedBaseHeat "Impedance base with heat port, 1-phase"
      extends ImpedBase;
      extends Interfaces.AddHeat;
    end ImpedBaseHeat;

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

  equation
    Q_flow = v.*i;
  end ImpedNonSymHeat;

  end Partials;
end Impedances;


Impedance and admittance one terminal

within PowerSystems.AC1ph_DC;
package ImpedancesOneTerm "Impedance and admittance one terminal"
  extends Modelica.Icons.VariantsPackage;

  model Resistor "Resistor, 1-phase"
    extends Partials.ImpedBase(final f_nom=0);

    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, 1-phase"
    extends Partials.ImpedBase(final f_nom=0);

    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, 1-phase"
    extends Partials.ImpedBase;

    parameter SIpu.Resistance r=0 "resistance";
    parameter SIpu.Reactance x=1 "reactance matrix";
  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*RL_base[2];

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

  equation
    L*der(i) + R*i = v;
  end Inductor;

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

    parameter SIpu.Conductance g=0 "conductance";
    parameter SIpu.Susceptance b=1 "susceptance";
  protected
    final parameter Real[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) = 0;
    elseif dynType == Types.Dynamics.FixedInitial then
      v = v_start;
    end if;

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

  model Varistor "Varistor, 1-phase"
    extends Partials.ImpedBase(final f_nom=0);

    parameter SIpu.Resistance r0=100 "small voltage resistance";
    parameter SIpu.Voltage v0=1 "saturation voltage";
  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
    v = V0*tanh(H0*i);
  end Varistor;

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

    partial model ImpedBase "One terminal impedance base, 1-phase"
      extends Ports.Port_p;
      extends Common.Nominal.NominalAC;

      parameter Types.Dynamics dynType=system.dynType "transient or steady-state initialization"
      parameter PS.Voltage v_start = 0 "start value of voltage drop"
      parameter PS.Current i_start = 0 "start value of current"

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

    equation
      term.i[1] + term.i[2] = 0;
      v = term.v[1] - term.v[2];
      i = term.i[1];
    end ImpedBase;

    partial model ImpedBaseHeat
      "One terminal impedance base with heat port, 1-phase"
      extends ImpedBase;
      extends Interfaces.AddHeat;
    end ImpedBaseHeat;

  end Partials;
end ImpedancesOneTerm;


within PowerSystems.AC1ph_DC;
package ImpedancesSingle "Simple mpedance and admittance two terminal"
  extends Modelica.Icons.VariantsPackage;

  model Resistor "Resistor, 1-phase"
    extends Partials.ImpedBase;

    parameter SI.Resistance R=1;

  equation
    R*i = v;
  end Resistor;

  model Conductor "Conductor, 1-phase"
    extends Partials.ImpedBase;

    parameter SI.Conductance G=1;

  equation
    G*v = i;
  end Conductor;

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

    parameter SI.Resistance R=0;
    parameter SI.Inductance L=1e-3;

  equation
    L*der(i) + R*i = v;
  end Inductor;

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

    parameter SI.Conductance G=0;
    parameter SI.Capacitance C=1e-6;

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

  model ResistorSym "Symmetrical capacitor with neutral access, 1-phase"
    extends Ports.PortBase;

    parameter SI.Resistance R=1;
    Interfaces.Electric_p term_p
    Interfaces.Electric_n term_n
    Interfaces.Electric_n neutral "symmetrical point"
    Resistor res1(final R=R/2)
    Resistor res2(final R=R/2)

  equation
    connect(term_p, res1.term_p)
    connect(res1.term_n, neutral)
    connect(neutral, res2.term_p)
    connect(res2.term_n, term_n)
  end ResistorSym;

  model CapacitorSym "Symmetrical capacitor with neutral access, 1-phase"
    extends Ports.PortBase;

    parameter SI.Conductance G=0;
    parameter SI.Capacitance C=1e-6;
    parameter PS.Voltage V_start=0 "start voltage";
    Interfaces.Electric_p term_p
    Interfaces.Electric_n term_n
    Interfaces.Electric_n neutral "symmetrical point"
    Capacitor cap1(final G=2*G, final C=2*C, v(start=V_start/2))
    Capacitor cap2(final G=2*G, final C=2*C, v(start=V_start/2))

  equation
    connect(term_p, cap1.term_p)
    connect(cap1.term_n, neutral)
    connect(neutral, cap2.term_p)
    connect(cap2.term_n, term_n)
  end CapacitorSym;

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

    partial model ImpedBase "Impedance base, 1-phase"
      extends Ports.PortBase;

      parameter PS.Voltage v_start = 0 "start value of voltage drop"
      parameter PS.Current i_start = 0 "start value of current"
      PS.Voltage v(start = v_start);
      PS.Current i(start = i_start);
      Interfaces.Electric_p term_p
      Interfaces.Electric_n term_n
    equation
      term_p.i + term_n.i = 0;
      v = term_p.v - term_n.v;
      i = term_p.i;
    end ImpedBase;

  end Partials;
end ImpedancesSingle;


Rectifiers and Inverters

within PowerSystems.AC1ph_DC;
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(u), phase(u)}"
  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, 1-phase"
  extends Partials.AC_DC_base(heat(final m=2));

  replaceable model Rectifier =
    PowerSystems.AC1ph_DC.Inverters.Components.RectifierEquation
      "rectifier model"
  Rectifier rectifier "rectifier model"

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

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

  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.PWMasyn1ph
    constrainedby Control.Modulation.Partials.ModulatorBase "modulator type"
  Modulator modulator "modulator type"

  replaceable model Inverter =
    PowerSystems.AC1ph_DC.Inverters.Components.InverterSwitch "inverter model"
  Inverter inverter "inverter model"
  protected
  outer System system;

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

model InverterAverage "Inverter time-average, 1-phase"
  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 1 else
    if modulation==3 then (4/pi)*sin(width0*pi/2) else 0
  SI.Angle phi;
  PS.Voltage Vloss;
  Real cT;
  Real hsw_nom;

equation
  Vloss = if par.Vf<1e-3 then 0 else tanh(10*iDC1/par.I_nom)*2*par.Vf;
  cT = if size(par.cT_loss,1)>0 then loss(T[1]-par.T0_loss, par.cT_loss) else 1;
  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 = theta +vPhasor [2] + system.alpha0;
  switch[1] = factor*vPhasor[1]*cos(phi);
  switch[2] = -switch[1];
  v = (vDC1 - cT*Vloss)*switch;
// passive mode?

  Q_flow = {par.eps[1]*R_nom*AC.i*AC.i+
                       cT*(par.Vf + hsw_nom*abs(vDC1))*(abs(AC.i[1])+abs(AC.i[2]))};
end InverterAverage;

model Chopper "DC-DC converter"
  extends Partials.DC_DC_base(heat(final m=2));

  Modelica.Blocks.Interfaces.RealInput vDC "desired vDC"
  replaceable model Modulator = PowerSystems.Control.Modulation.ChopperPWM
    constrainedby PowerSystems.Icons.BlockS       "modulator type"
  Modulator modulator "modulator type"

  replaceable model Chopper =
    PowerSystems.AC1ph_DC.Inverters.Components.ChopperModular "chopper model"
  Chopper chopper "chopper model"

equation
  connect(vDC,modulator.vDC)
  connect(DCin, chopper.DCin)
  connect(chopper.DCout, DCout)
  connect(modulator.gate, chopper.gate)
  connect(chopper.heat, heat)
end Chopper;

model ChopperAverage "DC-DC converter time-average"
  extends Partials.DC_DC_base(heat(final m=1));

  replaceable record Data = PowerSystems.Semiconductors.Ideal.SCparameter
      "SC parameters"
  final parameter Data par "SC parameters"
  parameter SI.Frequency f_carr=1e3 "carrier frequency"
  Modelica.Blocks.Interfaces.RealInput uDC "desired uDC"
  protected
  PS.Voltage vDCin=DCin.v[1] - DCin.v[2];
  PS.Voltage vDCout=DCout.v[1] - DCout.v[2];
  final parameter SI.Resistance R_nom=par.V_nom/par.I_nom;
  Real hsw_nom;
  Real cT;

  SI.Temperature[heat.m] T = heat.ports.T "component temperature";
  SI.HeatFlowRate[heat.m] Q_flow = -heat.ports.Q_flow
      "component loss-heat flow";
  function lossT = Utilities.Math.taylor
                                     "spec loss function of temperature";

equation
  DCin.v[2] = DCout.v[2];
  DCin.i + DCout.i = {0, 0};
  vDCout = uDC*max(vDCin - cT*par.Vf, 0);

  hsw_nom = 4*par.Hsw_nom*f_carr/(par.V_nom*par.I_nom);
  cT = if size(par.cT_loss,1)==0 then 1 else lossT(T[1]-par.T0_loss, par.cT_loss);
  Q_flow = {par.eps[1]*R_nom*DCin.i[1]*DCin.i[1] +
                     cT*(par.Vf + hsw_nom*abs(vDCin))*abs(DCin.i[1])};
end ChopperAverage;

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

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

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

equation
  i_sc = AC.i*par.V_nom/par.I_nom;

  for k in 1:2 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;

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

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

  package SCpackage = PowerSystems.Semiconductors.Ideal "SC package";
  replaceable record Data = SCpackage.SCparameter(final Hsw_nom=0)
        "SC parameters"
  final parameter Data par "SC parameters"
  AC1ph_DC.Nodes.Electric_pn_p_n pn_p_n
  Common.Thermal.Heat_a_b_ab heat_adapt
  Semiconductors.PhaseModules.DiodeModule diodeMod_a1(par=par)
        "diode module AC_a1"
  Semiconductors.PhaseModules.DiodeModule diodeMod_a2(par=par)
        "diode module AC_a2"

equation
  connect(AC, pn_p_n.term_pn)
  connect(pn_p_n.term_p, diodeMod_a1.AC)
  connect(diodeMod_a1.DC, DC)
  connect(pn_p_n.term_n, diodeMod_a2.AC)
  connect(diodeMod_a2.DC, DC)
  connect(diodeMod_a1.heat, heat_adapt.port_a)
  connect(diodeMod_a2.heat, heat_adapt.port_b)
  connect(heat_adapt.port_ab, heat)
end RectifierModular;

model InverterSwitch "Inverter equation, 1-phase"
  extends Partials.SwitchEquation(heat(final m=2));

  Modelica.Blocks.Interfaces.BooleanInput[4] gates
        "gates pairs {a1_p, a1_n, a2_p, a2_n}"
    protected
  constant Integer[2] pgt={1,3} "positive gates";
  constant Integer[2] ngt={2,4} "negative gates";

equation
  for k in 1:2 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;

  Q_flow = zeros(heat.m);
end InverterSwitch;

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

  replaceable record Data = PowerSystems.Semiconductors.Ideal.SCparameter
        "SC parameters"
  final parameter Data par "SC parameters"
  Modelica.Blocks.Interfaces.BooleanInput[4] gates
        "gates pairs {a1_p, a1_n, a2_p, a2_n}"
    protected
  constant Integer[2] pgt={1,3} "positive gates";
  constant Integer[2] ngt={2,4} "negative gates";
  PS.Voltage[2] V_s;
  PS.Voltage[2] V_d;
  PS.Voltage[2] i_sc "current scaled to voltage in inertial abc representation";
  Real[2] s(each start = 0.5) "arc-length on characteristic";

equation
  i_sc = AC.i*par.V_nom/par.I_nom;

  if par.Vf<1e-3 then // faster code if forward voltage drop Vf not used (Vf_s=0 and Vf_d=0).
    for k in 1:2 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:2 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;
end InverterEquation;

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

  package SCpackage = PowerSystems.Semiconductors.Ideal "SC package";
  replaceable record Data = SCpackage.SCparameter "SC parameters"
  final parameter Data par "SC parameters"
  Modelica.Blocks.Interfaces.BooleanInput[4] gates
        "gates pairs {a1_p, a1_n, a2_p, a2_n}"
  Nodes.Electric_pn_p_n pn_p_n
  Common.Thermal.Heat_a_b_ab heat_adapt
  Blocks.Multiplex.Gate2demux gate2demux1(final n=2)
  Semiconductors.PhaseModules.SwitchModule switchMod_a1(par=par)
        "switch + reverse diode module AC_a1"
  Semiconductors.PhaseModules.SwitchModule switchMod_a2(par=par)
        "switch + reverse diode module AC_a2"

equation
  connect(gate2demux1.gates_1, switchMod_a1.gates)
  connect(gate2demux1.gates_2, switchMod_a2.gates)
  connect(gates, gate2demux1.gates)
  connect(AC, pn_p_n.term_pn)
  connect(pn_p_n.term_p, switchMod_a1.AC)
  connect(switchMod_a1.DC, DC)
  connect(pn_p_n.term_n, switchMod_a2.AC)
  connect(switchMod_a2.DC, DC)
  connect(switchMod_a1.heat, heat_adapt.port_a)
  connect(switchMod_a2.heat, heat_adapt.port_b)
  connect(heat_adapt.port_ab, heat)
end InverterModular;

model ChopperModular "DC_DC converter modular"
  extends Partials.DC_DC_base(heat(final m=2));

  package SCpackage = PowerSystems.Semiconductors.Ideal "SC package";
  replaceable record Data = SCpackage.SCparameter "SC parameters"
  final parameter Data par "SC parameters"
  Modelica.Blocks.Interfaces.BooleanInput gate "gate"
  AC1ph_DC.Nodes.Electric_pn_p_n pn_p_n
  AC1ph_DC.Nodes.Electric_pn_p_n p_n_pn
  SCpackage.SCswitch_Diode switch_D(par=par) "switch + reverse diode"
  SCpackage.Diode diode(par=par) "diode"

      Common.Thermal.Heat_a_b_ab heat_adapt
equation
  connect(gate, switch_D.gate)
  connect(DCin, pn_p_n.term_pn)
  connect(pn_p_n.term_p, switch_D.term_p)
  connect(switch_D.term_n, p_n_pn.term_p)
  connect(pn_p_n.term_n, p_n_pn.term_n)
  connect(p_n_pn.term_n, diode.term_p)
  connect(diode.term_n, p_n_pn.term_p)
  connect(p_n_pn.term_pn, DCout)
  connect(switch_D.heat, heat_adapt.port_a)
  connect(diode.heat, heat_adapt.port_b)
  connect(heat_adapt.port_ab, heat)
end ChopperModular;
end Components;

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

partial model AC_DC_base "AC-DC base, 1-phase"
  extends Icons.Inverter;
  extends Ports.PortBase;

  Ports.TwoPin_n AC "AC connection"
  Ports.TwoPin_p DC "DC connection"
  Interfaces.ThermalV_n heat(     m=2) "vector heat port"

end AC_DC_base;

partial model DC_DC_base "DC-DC base"
  extends Icons.Inverter;
  extends Ports.PortBase;

  Ports.TwoPin_p DCin "DC in connection"
  Ports.TwoPin_n DCout "DC out connection"
  Interfaces.ThermalV_n heat(     m=2) "vector heat port"

end DC_DC_base;

partial model SwitchEquation "Switch equation, 1-phase"
  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[2] v "switching function voltage";
  Real[2] switch "switching function";

  SI.Temperature[heat.m] T "component temperature";
  SI.HeatFlowRate[heat.m] Q_flow "component loss-heat flow";
  function loss = Utilities.Math.taylor
                                    "spec loss function of temperature";

equation
  AC.v = v + {vDC0,vDC0};
  iDC1 + switch*AC.i = 0;
  iDC0 + sum(AC.i) = 0;

  T = heat.ports.T;
  heat.ports.Q_flow = -Q_flow;
end SwitchEquation;

end Partials;
end Inverters;


Transmission lines 1-phase

within PowerSystems.AC1ph_DC;
package Lines "Transmission lines 1-phase"
  extends Modelica.Icons.VariantsPackage;

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

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

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(i) = zeros(2);
    elseif dynType == Types.Dynamics.FixedInitial then
      i = i_start;
    end if;

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

    L*der(i) + diagonal(R)*i = v;
  end RXline;

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

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

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(v) = zeros(2,ne1);
      der(i) = zeros(2,ne);
    elseif dynType == Types.Dynamics.FixedInitial then
      v = transpose(fill(v_start, ne1));
      i = transpose(fill(i_start, ne));
    end if;

  equation
    v[:, 1] = term_p.v;
    v[:, ne1] = term_n.v;

    C*der(v) + G*v =
     [[2*(term_p.i - i[:, 1])], i[:, 1:ne - 1] - i[:, 2:ne], [2*(i[:, ne] + term_n.i)]];
    L*der(i) + diagonal(R)*i =
     v[:, 1:ne] - v[:, 2:ne1];
  end PIline;

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

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

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(v) = zeros(2,ne);
      der(i) = zeros(2,ne1);
    elseif dynType == Types.Dynamics.FixedInitial then
      v = transpose(fill(v_start, ne));
      i = transpose(fill(i_start, ne1));
    end if;

  equation
    i[:, 1] = term_p.i;
    i[:, ne1] = -term_n.i;

    C*der(v) + G*v = i[:, 1:ne] - i[:, 2:ne1];
    L*der(i) + diagonal(R)*i = [[2*(term_p.v - v[:, 1])], v[:, 1:ne - 1] - v[:, 2:ne], [2*(v[:, ne] - term_n.v)]];
  end Tline;

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

  PS.Current[2] i1(start = i_start);
  PS.Current[2] i2(start = i_start);

initial equation
  if dynType == Types.Dynamics.SteadyInitial then
    der(i1) = zeros(2);
    der(i2) = zeros(2);
  elseif dynType == Types.Dynamics.FixedInitial then
    i1 = i_start;
    i2 = i_start;
  end if;

equation
  term_p.i + term_n.i + term_f.i = {0,0};
  i1 = term_p.i;
  i2 = -term_n.i;

  p*(L*der(i1) + diagonal(R)*i1) = term_p.v - term_f.v;
  (1 - p)*(L*der(i2) + diagonal(R)*i2) = term_f.v - term_n.v;
end FaultRXline;

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

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

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

initial equation
  if dynType == Types.Dynamics.SteadyInitial then
    der(v) = zeros(2,ne);
    der(i) = zeros(2,ne1);
    der(iF) = zeros(2);
  elseif dynType == Types.Dynamics.FixedInitial then
    v = transpose(fill(v_start, ne));
    i = transpose(fill(i_start, ne1));
    iF = iF_start;
  end if;

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

  C*der(v) + G*v = [i[:,1:nF-2]-i[:, 2:nF-1], i[:,nF-1:nF]-i[:,nF:nF+1]-iF_p, i[:,nF+1:ne]-i[:,nF+2:ne1]];
  L*der(i) + diagonal(R)*i = [[2*(term_p.v - v[:, 1])], v[:, 1:ne - 1] - v[:, 2:ne], [2*(v[:, ne] - term_n.v)]];
  L*der(iF) + diagonal(R)*iF = (v[:, nF-1] - term_f.v)/pe + (v[:, nF] - term_f.v)/(1-pe);
end FaultTline;

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

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

      parameter SI.Length len=100e3 "line length";
      parameter Integer ne(min=1)=1 "number of line elements";
      replaceable record Data = PowerSystems.AC1ph_DC.Lines.Parameters.RXline
        "line parameters"
      final parameter Data par "line parameters"

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

    protected
      outer System system;
      final parameter Real[2] RL_base=Utilities.Precalculation.baseRL(
              par.puUnits,
              par.V_nom,
              par.S_nom,
              2*pi*par.f_nom);
      final parameter Real delta_len_km(final quantity="Length", final unit="km")=len/1e3/ne;
      final parameter SI.Resistance[2] R=par.r*delta_len_km*RL_base[1];
      final parameter SI.Inductance[2,2] L=([(par.x + par.x0),(par.x0 - par.x);(par.x0 - par.x),(par.x + par.x0)]/2)*delta_len_km*RL_base[2];
    end RXlineBase;

    partial model LineBase "PI- and T-line base, 1-phase"
      extends RXlineBase(ne=3, redeclare replaceable record Data =
          PowerSystems.AC1ph_DC.Lines.Parameters.Line);

    protected
      final parameter Real[2] GC_base=Utilities.Precalculation.baseGC(
              par.puUnits,
              par.V_nom,
              par.S_nom,
              2*pi*par.f_nom);
      final parameter SI.Conductance[2,2] G=[par.g_pg+par.g_pp,-par.g_pp;-par.g_pp,par.g_pg+par.g_pp]*delta_len_km*GC_base[1];
      final parameter SI.Capacitance[2,2] C=[par.b_pg+par.b_pp,-par.b_pp;-par.b_pp,par.b_pg+par.b_pp]*delta_len_km*GC_base[2];
    end LineBase;

  end Partials;

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

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

  record Line "Line parameters, 1-phase"
    extends RXline;
    SIpu.Conductance g_pg=0 "shunt conductance/km ph-grd"
    SIpu.Conductance g_pp=0 "shunt conductance/km ph_ph"
    SIpu.Susceptance_km b_pg=0.025e-3 "susceptance/km ph-grd"
    SIpu.Susceptance_km b_pp=0.025e-3 "susceptance/km ph-ph"
  end Line;
end Parameters;
end Lines;


Loads

within PowerSystems.AC1ph_DC;
package Loads "Loads"
  model Rload "Resistance load, 1-phase"
    extends Partials.ResLoadBase;

  equation
    R = V2_nom/p;
  end Rload;
  extends Modelica.Icons.VariantsPackage;

  model ZloadAC "Impedance load AC, 1-phase"
    extends Partials.IndLoadBaseAC;

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

  model YloadAC "Admittance load AC, 1-phase"
    extends Partials.CapLoadBaseAC;

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

  model ZloadDC "Impedance load DC"
    extends Partials.IndLoadBaseDC;

  equation
    R = V2_nom/p;
    L = t_RL*R;
  end ZloadDC;

  model PindLoadDC "Inductive load DC"
    extends Partials.IndLoadBaseDC;

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

  initial equation
    der(R) = 0;

  equation
  //  der(R) = (v2/p - R)/tcst;
    der(R) = ((v2/p)*tanh(imax)/tanh(imax*v2/V2_nom) - R)/tcst;
    L = t_RL*R;
  end PindLoadDC;

  model PresLoadDC "P resistive load"
    extends Partials.ResLoadBase;

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

  initial equation
    der(R) = 0;

  equation
  //  der(R) = (v2/p - R)/tcst;
    der(R) = ((v2/p)*tanh(imax)/tanh(imax*v2/V2_nom) - R)/tcst;
  end PresLoadDC;

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

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

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

      PS.Voltage v;
      PS.Current i;

    protected
      outer System system;
      final parameter Real S_base=Utilities.Precalculation.baseS(puUnits, S_nom);

    equation
      term.i[1] + term.i[2] = 0;
      v = term.v[1] - term.v[2];
      i = term.i[1];
    end LoadBase;

    partial model ResLoadBase "Resistive load base, 1-phase"
      extends LoadBase(v(start=V_nom), i(start=V_nom/R_start));

      parameter Boolean use_p_in = false
        "= true to use input signal p_in, otherwise use parameter p0"
      parameter SIpu.Power p0(min=0)=1 "fixed power (start value if signal input)"
      Modelica.Blocks.Interfaces.RealInput p_in(min=0) if  use_p_in
        "desired power"

    protected
      Modelica.Blocks.Interfaces.RealInput p_internal
        "Needed to connect to conditional connector";

      final parameter Real V2_nom(unit="V2")=V_nom*V_nom;
      final parameter Real R_start=V2_nom/(p0*S_base);
      SI.Power p;
      SI.Resistance R(start=R_start);
    equation
      connect(p_in, p_internal);

      if not use_p_in then
        p_internal = p0;
      end if;
      p = p_internal*S_base;
      R*i = v;
    end ResLoadBase;

    partial model LoadBaseAC "Load base AC, 1-phase"
      extends LoadBase;

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

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

    protected
      Modelica.Blocks.Interfaces.RealInput[2] pq_internal
        "Needed to connect to conditional connector";
      SI.Power[2] pq;

    equation
      connect(pq_in, pq_internal);

      if not use_pq_in then
        pq_internal = pq0;
      end if;
      pq = pq_internal*S_base;
    end LoadBaseAC;

                 partial model IndLoadBaseAC "Inductive load base AC, 1-phase"
                   extends LoadBaseAC(v(start=v_start), i(start=i_start));

                   parameter SI.MagneticFlux psi_start=0 "start value for magnetic flux"
                   SI.MagneticFlux psi(start=psi_start, stateSelect=StateSelect.prefer)
                     "magnetic flux";
    protected
                   final parameter Real V2_nom=V_nom*V_nom;
                   final parameter Real[2] Z_start=(pq0/(pq0*pq0*S_base))*V2_nom;
                   final parameter PS.Voltage v_start=cos(system.alpha0)*V_nom;
                   final parameter PS.Current i_start=cos(system.alpha0-atan(Z_start[2]/Z_start[1]))*V_nom/sqrt(Z_start*Z_start);
                   SI.Impedance[2] Z(start=Z_start);
                   function atan=Modelica.Math.atan;

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

                 equation
                   psi = Z[2]*i/system.omega_nom;
                   if dynType <> Types.Dynamics.SteadyState then
                     der(psi) + Z[1]*i = v;
                   else
                     Z[1]*i = v;
                   end if;
                 end IndLoadBaseAC;

                 partial model CapLoadBaseAC "Capacitive load base AC, 1-phase"
                   extends LoadBaseAC(v(start=v_start), i(start=i_start));

                   parameter SI.ElectricCharge q_start=0 "start value for electric charge"
                   SI.ElectricCharge q(start=q_start, stateSelect=StateSelect.prefer)
                     "electric charge";
    protected
                   final parameter Real I2_nom=(S_nom/V_nom)^2;
                   final parameter SI.Admittance[2] Y_start=(pq0/(pq0*pq0*S_base))*I2_nom;
                   final parameter PS.Voltage v_start=cos(system.alpha0)*V_nom;
                   final parameter PS.Current i_start=cos(system.alpha0+atan(Y_start[2]/Y_start[1]))*V_nom*sqrt(Y_start*Y_start);
                   SI.Admittance[2] Y(start=Y_start);
                   function atan=Modelica.Math.atan;

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

                 equation
                   q = Y[2]*v/system.omega_nom;
                   if dynType <> Types.Dynamics.SteadyState then
                     der(q) + Y[1]*v = i;
                   else
                     Y[1]*v = i;
                   end if;
                 end CapLoadBaseAC;

    partial model LoadBaseDC "Inductive load base DC"
      extends LoadBase;

      parameter Boolean use_p_in = false
        "= true to use input signal p_in, otherwise use parameter p0"
      parameter SIpu.Power p0(min=0)=1 "fixed power (start value if use_p_in)"
      Modelica.Blocks.Interfaces.RealInput p_in(min=0) if  use_p_in
        "desired power"

    protected
      Modelica.Blocks.Interfaces.RealInput p_internal
        "Needed to connect to conditional connector";
      SI.Power p;

    equation
      connect(p_in, p_internal);

      if not use_p_in then
        p_internal = p0;
      end if;
      p = p_internal*S_base;
    end LoadBaseDC;

    partial model IndLoadBaseDC "Inductive load base DC"
      extends LoadBaseDC;

      parameter SI.Time t_RL=0.1 "R-L time constant";
      parameter PS.Current i_start = 0
        "start value of current"

    protected
      final parameter Real V2_nom(unit="V2")=V_nom*V_nom;
      final parameter Real R_start=V2_nom/(p0*S_base);
      SI.Resistance R(start=R_start);
      SI.Inductance L(start=t_RL*R_start);

    initial equation
      if dynType == Types.Dynamics.SteadyInitial then
        der(L*i) = 0;
      elseif dynType == Types.Dynamics.FixedInitial then
        i = i_start;
      end if;

    equation
      der(L*i) + R*i = v;
    end IndLoadBaseDC;

  end Partials;
end Loads;


DC-machines, electric part

within PowerSystems.AC1ph_DC;
package Machines "DC-machines, electric part"
  extends Modelica.Icons.VariantsPackage;

  model EMF "Electro motoric force"
    extends Ports.Port_p;

    parameter Real k(final unit="N.m/A") = 1 "transformation coefficient";

    SI.AngularVelocity w "ang velocity rotor";
    Interfaces.Rotation_n airgap "electro-mechanical connection"

  equation
    sum(term.i) = 0;

    w = der(airgap.phi);
    k*w = term.v[1] - term.v[2];
    airgap.tau = -k*term.i[1];
  end EMF;

  model DCser "DC machine series excited"
    extends Partials.DCserBase;

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

  equation
    if dynType <> Types.Dynamics.SteadyState then
      c.L*der(i) + (w_el*c.L_md + sum(c.R))*i = v;
    else
      (w_el*c.L_md + sum(c.R))*i = v;
    end if;

    tau_el = i*(c.L_md*i);
    heat.ports.Q_flow = -c.R*i*i;
  end DCser;

  model DCpar "DC machine parallel excited"
    extends Partials.DCparBase;

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der({i_f, i}) = {0,0};
    elseif dynType == Types.Dynamics.FixedInitial then
      i = i_start;
    end if;

  equation
    if dynType <> Types.Dynamics.SteadyState then
      diagonal(c.L)*der({i_f, i}) + {0, w_el*c.L_md*i_f} + diagonal(c.R)*{i_f, i} = {v_f, v};
    else
      {0, w_el*c.L_md*i_f} + diagonal(c.R)*{i_f, i} = {v_f, v};
    end if;

    tau_el = i*(c.L_md*i_f);
    heat.ports.Q_flow = -{c.R[1]*i_f*i_f, c.R[2]*i*i};
  end DCpar;

  model DCpm "DC machine permanent magnet excited"
    extends Partials.DCpmBase;

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

  equation
    if dynType <> Types.Dynamics.SteadyState then
      c.L*der(i) + c.R*i = v - w_el*c.Psi_pm;
    else
      c.R*i = v - w_el*c.Psi_pm;
    end if;

    tau_el = i*c.Psi_pm;
    heat.ports.Q_flow = -{0, c.R*i*i};
  end DCpm;

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

    partial model DCBase "Base DC machine"
      extends Ports.Port_p;

      parameter Types.Dynamics dynType=system.dynType "transient or steady-state model"
      parameter PS.Voltage v_start = 0 "start value of voltage drop"
      parameter PS.Current i_start = 0 "start value of current"
      parameter Integer pp=2 "pole-pair number";
      parameter SI.Angle phi_el_start=0 "initial rotor angle electric"
      SI.Angle phi_el(start=phi_el_start, stateSelect=StateSelect.prefer)
        "rotor angle electric";
      SI.AngularVelocity w_el "rotor angular velocity el";
      SI.Torque tau_el "electromagnetic torque";
      PS.Voltage v(start = v_start) "voltage";
      PS.Current i(start = i_start) "current";

      Interfaces.Rotation_n airgap "electro-mechanical connection"
      Interfaces.ThermalV_n heat(m=2) "heat source port {stator, rotor}"
    protected
      outer System system;

    initial equation
      phi_el = phi_el_start;

    equation
      sum(term.i) = 0;
      v = term.v[1] - term.v[2];
      i = term.i[1];

      pp*airgap.phi = phi_el;
      airgap.tau = -pp*tau_el;
      w_el = der(phi_el);
    end DCBase;

    partial model DCserBase "DC machine series excited, parameter"
      extends DCBase(final pp=par.pp);

      replaceable record Data = PowerSystems.AC1ph_DC.Machines.Parameters.DCser
        "machine parameters"
      final parameter Data par "machine parameters"
    protected
      final parameter Coefficients.DCser c = Utilities.Precalculation.machineDCser(
                                                                               par);
    end DCserBase;

    partial model DCparBase "DC machine parallel excited, parameter"
      extends DCBase(final pp=par.pp);

      replaceable record Data = PowerSystems.AC1ph_DC.Machines.Parameters.DCpar
        "machine parameters"
      final parameter Data par "machine parameters"
      PS.Voltage v_f;
      PS.Current i_f;
      Ports.TwoPin_p field
    protected
      final parameter Coefficients.DCpar c = Utilities.Precalculation.machineDCpar(
                                                                               par);
    equation
      sum(field.i) = 0;
      v_f = field.v[1] - field.v[2];
      i_f = field.i[1];
    end DCparBase;

    partial model DCpmBase "DC machine permanent magnet excited, parameter"
      extends DCBase(final pp=par.pp);

      replaceable record Data = PowerSystems.AC1ph_DC.Machines.Parameters.DCpm
        "machine parameters"
      final parameter Data par "machine parameters"
    protected
      final parameter Coefficients.DCpm c = Utilities.Precalculation.machineDCpm(
                                                                             par);

    end DCpmBase;

  end Partials;

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

record DCser "DC machine parameters series excited"
  extends Common.Nominal.NominalDataDC(
                                      w_nom=157.079632679489661923);

  Integer pp=2 "pole-pair nb"
  SIpu.Inductance l_fd=0.15 "inductance field (d-axis)"
  SIpu.Resistance r_fd=0.01 "resistance field (d-axis)"
  SIpu.Inductance l_q=0.5 "inductance armature+ (q-axis)"
  SIpu.Resistance r_q=0.05 "resistance armature+ (q-axis)"
end DCser;

record DCpar "DC machine parameters parallel excited"
  extends Common.Nominal.NominalDataDC(
                                      w_nom=157.079632679489661923);

  SI.Voltage Vf_nom=1 "nom field voltage"
  Integer pp=2 "pole-pair nb"
  SIpu.Inductance l_fd=100*pi "inductance field (d-axis)"
  SIpu.Resistance r_fd=100 "resistance field (d-axis)"
  SIpu.Inductance l_q=0.5 "inductance armature+ (q-axis)"
  SIpu.Resistance r_q=0.05 "resistance armature+ (q-axis)"
end DCpar;

record DCpm "DC machine parameters permanent magnet excited"
  extends Common.Nominal.NominalDataDC(
                                      w_nom=157.079632679489661923);

  Integer pp=2 "pole-pair nb"
  SIpu.Inductance l_aq=0.5 "inductance armature (q-axis)"
  SIpu.Resistance r_aq=0.05 "resistance armature (q-axis)"
end DCpm;
end Parameters;

package Coefficients "Coefficient matrices of machine equations"
  extends Modelica.Icons.MaterialPropertiesPackage;

record DCser "Coefficients of DC machine series excited"
  extends Modelica.Icons.Record;

  SI.Inductance L "series inductance";
  SI.Resistance[2] R "resistance {d (field), q (armature)} axis";
  SI.Inductance L_md "mutual inductance";
end DCser;

record DCpar "Coefficients of DC machine parallel excited"
  extends Modelica.Icons.Record;

  SI.Inductance[2] L "inductance {d (field), q (armature)} axis";
  SI.Resistance[2] R "resistance {d (field), q (armature)} axis";
  SI.Inductance L_md "mutual inductance";
end DCpar;

record DCpm "Coefficients of DC machine permanent magnet excited"
  extends Modelica.Icons.Record;

  SI.Resistance R "resistance";
  SI.Inductance L "inductance";
  SI.MagneticFlux Psi_pm "flux permanent magnet";
end DCpm;
end Coefficients;
end Machines;


Nodes

within PowerSystems.AC1ph_DC;
package Nodes "Nodes "
  extends Modelica.Icons.VariantsPackage;

  model Ground "Ground, 1-phase"
    extends Ports.Port_p;

  equation
    term.v = zeros(2);
  end Ground;

  model PolarityGround "Polarity grounding, 1-phase"
    extends Ports.Port_p;

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

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

  model GroundOne "Ground, one conductor"

    Interfaces.Electric_p term

  equation
    term.v = 0;
  end GroundOne;

  model BusBar "Busbar, 1-phase"
    extends Ports.PortBase;

    output PS.Voltage v(stateSelect=StateSelect.never);
    Ports.TwoPin_p term

  equation
    term.i = zeros(2);
    v = term.v[1] - term.v[2];
  end BusBar;

  model Electric_pn_p_n "Adaptor ElectricV[2] (vector) to Electric (scalar)."

    Ports.TwoPin_p term_pn "vector pin {p,n}"
    Interfaces.Electric_p term_p "scalar p"
    Interfaces.Electric_n term_n "scalar n"

  equation
    term_pn.v = {term_p.v, term_n.v};
    term_pn.i + {term_p.i, term_n.i} = zeros(2);
  end Electric_pn_p_n;

/*
  model Electric_abc_a_b_c "Adaptor ElectricV[3] (vector) to Electric (scalar)"

    Basic.Interfaces.ElectricV_p term_abc(
                                         final m=3) "vector {a,b,c}"
    Interfaces.Electric_n term_a "scalar a"
    Interfaces.Electric_n term_b "scalar b"
    Interfaces.Electric_n term_c "scalar c"

  equation
    {term_a.v,term_b.v,term_c.v} = term_abc.v;
    term_abc.i + {term_a.i,term_b.i,term_c.i} = zeros(3);
  end Electric_abc_a_b_c;
*/
end Nodes;


within PowerSystems;
package AC1ph_DC "AC 1-phase and DC components from Spot AC1ph_DC"
  extends Modelica.Icons.VariantsPackage;
end AC1ph_DC;


Strandard electric ports

within PowerSystems.AC1ph_DC;
package Ports "Strandard electric ports"
  extends Modelica.Icons.InterfacesPackage;

  partial model PortBase "base model defining PhaseSystem"
    package PS = PhaseSystems.TwoConductor;
  end PortBase;

  connector TwoPin_p "AC1/DC terminal ('positive')"
    extends Interfaces.TerminalDC(redeclare package PhaseSystem =
          PhaseSystems.TwoConductor);
  end TwoPin_p;

  connector TwoPin_n "AC1/DC terminal ('negative')"
    extends Interfaces.TerminalDC(redeclare package PhaseSystem =
          PhaseSystems.TwoConductor);
  end TwoPin_n;

  partial model Port_p "One port, 'positive'"
    extends PortBase;

    Ports.TwoPin_p term "positive terminal"
  end Port_p;

  partial model Port_n "One port, 'negative'"
    extends PortBase;

    Ports.TwoPin_n term "negative terminal"
  end Port_n;

  partial model Port_f "One port, 'fault'"
    extends PortBase;

    Ports.TwoPin_p term "fault terminal"
  end Port_f;

  partial model Port_p_n "Two port"
    extends PortBase;

    Ports.TwoPin_p term_p "positive terminal"
    Ports.TwoPin_n term_n "negative terminal"
  end Port_p_n;

  partial model Port_pn "Two port, 'current_in = current_out'"
    extends Port_p_n;

  equation
    term_p.i + term_n.i = zeros(2);
  end Port_pn;

  partial model Port_p_n_f "Three port"
    extends Port_p_n;

    Ports.TwoPin_n term_f "fault terminal"
  end Port_p_n_f;

  partial model PortTrafo_p_n "Two port for transformers"
    extends Port_p_n;

    PS.Voltage v1 "voltage 1";
    PS.Current i1 "current 1";

    PS.Voltage v2 "voltage 2";
    PS.Current i2 "current 2";
  protected
    Real w1 "1: voltage ratio to nominal";
    Real w2 "2: voltage ratio to nominal";

  equation
    term_p.i[1] + term_p.i[2] = 0;
    term_n.i[1] + term_n.i[2] = 0;

    v1 = (term_p.v[1] - term_p.v[2])/w1;
    term_p.i[1] = i1/w1;
    v2 = (term_n.v[1] - term_n.v[2])/w2;
    term_n.i[1] = i2/w2;
  end PortTrafo_p_n;

  partial model PortTrafo_p_n_n "Three port for 3-winding transformers"
    extends PortBase;

    Ports.TwoPin_p term_p "positive terminal"
    Ports.TwoPin_n term_na "negative terminal a"
    Ports.TwoPin_n term_nb "negative terminal b"

    PS.Voltage v1 "voltage 1";
    PS.Current i1 "current 1";

    PS.Voltage v2a "voltage 2a";
    PS.Current i2a "current 2a";

    PS.Voltage v2b "voltage 2b";
    PS.Current i2b "current 2b";

    PS.Voltage v0;
  protected
    Real w1 "1: voltage ratio to nominal";
    Real w2a "2a: voltage ratio to nominal";
    Real w2b "2b: voltage ratio to nominal";

  equation
    term_p.i[1] + term_p.i[2] = 0;
    term_na.i[1] + term_na.i[2] = 0;
    term_nb.i[1] + term_nb.i[2] = 0;

    v1 = (term_p.v[1] - term_p.v[2])/w1;
    term_p.i[1] = i1/w1;
    v2a = (term_na.v[1] - term_na.v[2])/w2a;
    term_na.i[1] = i2a/w2a;
    v2b = (term_nb.v[1] - term_nb.v[2])/w2b;
    term_nb.i[1] = i2b/w2b;
  end PortTrafo_p_n_n;
end Ports;


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;