Text book example and variants of it

within PowerSystems.Examples.Generic;
package Network "Text book example and variants of it"
  extends Modelica.Icons.ExamplesPackage;

  model NetworkLoop
    "Simple textbook example for a steady-state power flow calculation"
    extends Modelica.Icons.Example;

    replaceable package PhaseSystem =
        PhaseSystems.ThreePhase_dq "Default phase system"

    PowerSystems.Generic.FixedVoltageSource
      fixedVoltageSource1(V=10e3, redeclare package PhaseSystem=PhaseSystem)
    PowerSystems.Generic.Impedance impedance1(R=2, L=0,
    redeclare package PhaseSystem = PhaseSystem)
    PowerSystems.Generic.Impedance impedance2(R=4, L=0,
    redeclare package PhaseSystem = PhaseSystem)
    PowerSystems.Generic.Impedance impedance3(R=2, L=0,
    redeclare package PhaseSystem = PhaseSystem)
    PowerSystems.Generic.Impedance impedance4(L=0, R=1,
    redeclare package PhaseSystem = PhaseSystem)
    PowerSystems.Generic.Impedance impedance5(L=0, R=3,
    redeclare package PhaseSystem = PhaseSystem)
    PowerSystems.Generic.FixedCurrent fixedCurrent3(I=50,
      redeclare package PhaseSystem = PhaseSystem)
    PowerSystems.Generic.FixedCurrent fixedCurrent1(I=55,
      redeclare package PhaseSystem = PhaseSystem)
    PowerSystems.Generic.FixedCurrent fixedCurrent2(I=45,
      redeclare package PhaseSystem = PhaseSystem)
    PowerSystems.Generic.FixedCurrent fixedCurrent4(I=60,
      redeclare package PhaseSystem = PhaseSystem)
    PowerSystems.Generic.Transformer transformer1(ratio=10/10.4156,
      redeclare package PhaseSystem = PhaseSystem)
    PowerSystems.Generic.Transformer transformer2(ratio=10/10, redeclare
        package PhaseSystem=PhaseSystem)
    inner System system
  equation
    connect(impedance1.terminal_n, impedance2.terminal_p)
    connect(impedance2.terminal_n, impedance3.terminal_p)
    connect(impedance4.terminal_p, impedance5.terminal_n)
    connect(fixedCurrent1.terminal, impedance1.terminal_n)
    connect(fixedCurrent2.terminal, impedance3.terminal_p)
    connect(fixedCurrent4.terminal, impedance5.terminal_n)
    connect(fixedVoltageSource1.terminal, transformer1.terminal_p)
    connect(transformer1.terminal_n, impedance1.terminal_p)
    connect(transformer2.terminal_n, impedance5.terminal_p)
    connect(transformer2.terminal_p, fixedVoltageSource1.terminal)
    connect(impedance3.terminal_n, fixedCurrent3.terminal)
    connect(impedance4.terminal_n, impedance3.terminal_n)
  end NetworkLoop;

  model NetworkLoop_d "NetworkLoop example with phase system ThreePhase_d"
    extends NetworkLoop(
      redeclare replaceable package PhaseSystem =
        PowerSystems.PhaseSystems.ThreePhase_d);
  end NetworkLoop_d;

  model NetworkLoop_dq "NetworkLoop example with phase system ThreePhase_dq"
    extends NetworkLoop(
      redeclare replaceable package PhaseSystem =
        PowerSystems.PhaseSystems.ThreePhase_dq);
  end NetworkLoop_dq;

  model NetworkLoop_dq0 "NetworkLoop example with phase system ThreePhase_dq0"
    extends NetworkLoop(
      redeclare replaceable package PhaseSystem =
        PowerSystems.PhaseSystems.ThreePhase_dq0);
  end NetworkLoop_dq0;

  model NetworkOpened
    "Steady-state power flow calculation with two voltage sources"
    extends Modelica.Icons.Example;

    PowerSystems.Generic.FixedVoltageSource fixedVoltageSource1(V=10e3)
    PowerSystems.Generic.FixedVoltageSource fixedVoltageSource2(V=10e3)
    PowerSystems.Generic.Impedance impedance1(R=2, L=0)
    PowerSystems.Generic.Impedance impedance2(L=0, R=4)
    PowerSystems.Generic.Impedance impedance3(R=2, L=0)
    PowerSystems.Generic.Impedance impedance4(L=0, R=1)
    PowerSystems.Generic.Impedance impedance5(L=0, R=3)
    PowerSystems.Generic.FixedCurrent
                         fixedCurrent3(I=50)
    PowerSystems.Generic.FixedCurrent
                         fixedCurrent1(I=55)
    PowerSystems.Generic.FixedCurrent
                         fixedCurrent2(I=45)
    PowerSystems.Generic.FixedCurrent
                         fixedCurrent4(I=60)
    PowerSystems.Generic.Transformer transformer1(ratio=10/10.4156)
    PowerSystems.Generic.Transformer transformer2(ratio=10/10)
    inner System system
  equation
    connect(impedance1.terminal_n, impedance2.terminal_p)
    connect(impedance2.terminal_n, impedance3.terminal_p)
    connect(impedance3.terminal_n, impedance4.terminal_n)
    connect(impedance4.terminal_p, impedance5.terminal_n)
    connect(impedance3.terminal_n, fixedCurrent3.terminal)
    connect(fixedCurrent1.terminal, impedance1.terminal_n)
    connect(fixedCurrent2.terminal, impedance3.terminal_p)
    connect(fixedCurrent4.terminal, impedance5.terminal_n)
    connect(fixedVoltageSource1.terminal, transformer1.terminal_p)
    connect(transformer1.terminal_n, impedance1.terminal_p)
    connect(fixedVoltageSource2.terminal, transformer2.terminal_p)
    connect(transformer2.terminal_n, impedance5.terminal_p)
  end NetworkOpened;

  model NetworkControlled "Dynamic power flow calculation with two generators"
    extends Modelica.Icons.Example;

    PowerSystems.Generic.Impedance impedance1(R=2, L=0)
    PowerSystems.Generic.Impedance impedance2(L=0, R=4)
    PowerSystems.Generic.Impedance impedance3(R=2, L=0)
    PowerSystems.Generic.Impedance impedance4(L=0, R=1)
    PowerSystems.Generic.Impedance impedance5(L=0, R=3)
    PowerSystems.Generic.FixedCurrent
                         fixedCurrent3(I=50)
    PowerSystems.Generic.FixedCurrent
                         fixedCurrent1(I=55)
    PowerSystems.Generic.FixedCurrent
                         fixedCurrent2(I=45)
    PowerSystems.Generic.FixedCurrent
                         fixedCurrent4(I=60)
    PowerSystems.Generic.Transformer transformer1(ratio=10/10.4156)
    PowerSystems.Generic.Transformer transformer2(ratio=10/10)
    PowerSystems.Generic.Generator generator1
    Modelica.Mechanics.Rotational.Components.Inertia inertia1(
      J=1e3,
      w(start=system.w_nom/generator1.pp),
      a(start=0))
    PowerSystems.Generic.Generator generator2(pp=8)
    Modelica.Mechanics.Rotational.Components.Inertia inertia2(
                                                   J=1e3,
      w(start=system.w_nom/generator2.pp),
      a(start=0))
    Modelica.Mechanics.Rotational.Sources.Torque turbine1(useSupport=false)
    Modelica.Mechanics.Rotational.Sensors.SpeedSensor angularVelocity
    Modelica.Mechanics.Rotational.Sources.Torque turbine2(useSupport=false)
    Modelica.Blocks.Sources.Trapezoid disturbance(
      width=30,
      rising=0,
      falling=0,
      period=60,
      amplitude=2e3,
      offset=2e3)
    Modelica.Blocks.Sources.Constant const(k=system.f_nom)
    Modelica.Blocks.Continuous.LimPID frequencyPowerControl(
      controllerType=Modelica.Blocks.Types.SimpleController.PI,
      Td=0,
      yMax=1e5,
      k=1e6/50,
      Ti=10)
    Modelica.Blocks.Math.Gain frequency(k=1/(2*pi))
    inner System system(fType=PowerSystems.Types.SystemFrequency.Average)
    Interfaces.Sender sender1(H=0.5*inertia1.J*inertia1.w^2/1e6, w=generator1.w)
    Interfaces.Sender sender2(H=0.5*inertia2.J*inertia2.w^2/1e6, w=generator2.w)
  initial equation
    if system.dynType == Types.Dynamics.SteadyInitial then
      inertia1.a = 0;
    else
      inertia1.w = system.omega/generator1.pp;
    end if;
    inertia1.phi = system.theta/generator1.pp;

  equation
    connect(impedance1.terminal_n, impedance2.terminal_p)
    connect(impedance2.terminal_n, impedance3.terminal_p)
    connect(impedance3.terminal_n, impedance4.terminal_n)
    connect(impedance4.terminal_p, impedance5.terminal_n)
    connect(impedance3.terminal_n, fixedCurrent3.terminal)
    connect(fixedCurrent1.terminal, impedance1.terminal_n)
    connect(fixedCurrent2.terminal, impedance3.terminal_p)
    connect(fixedCurrent4.terminal, impedance5.terminal_n)
    connect(transformer1.terminal_n, impedance1.terminal_p)
    connect(transformer2.terminal_n, impedance5.terminal_p)
    connect(inertia1.flange_b, generator1.flange)
    connect(generator1.terminal, transformer1.terminal_p)
    connect(inertia2.flange_b, generator2.flange)
    connect(generator2.terminal, transformer2.terminal_p)
    connect(turbine1.flange, inertia1.flange_a)
    connect(turbine2.flange, inertia2.flange_a)
    connect(disturbance.y, turbine2.tau)
    connect(angularVelocity.flange, inertia1.flange_b)
    connect(frequencyPowerControl.y, turbine1.tau)
    connect(const.y, frequencyPowerControl.u_s)
    connect(angularVelocity.w, frequency.u)
    connect(frequency.y, frequencyPowerControl.u_m)
    connect(system.receiveFreq, sender1.sendFreq)
    connect(system.receiveFreq, sender2.sendFreq)
  end NetworkControlled;
end Network;


Examples for Generic components

within PowerSystems.Examples;
package Generic "Examples for Generic components"
  extends Modelica.Icons.ExamplesPackage;
end Generic;


Small examples with Generic components

within PowerSystems.Examples.Generic;
package Test "Small examples with Generic components"
  extends Modelica.Icons.ExamplesPackage;

  model ImpedanceTest
    extends Modelica.Icons.Example;

    PowerSystems.Generic.FixedVoltageSource source
    PowerSystems.Generic.Impedance
      load(R=30, L=10/314)
    PowerSystems.Generic.Ground ground
    inner PowerSystems.System system
  equation
    connect(source.terminal, load.terminal_p)
    connect(load.terminal_n, ground.terminal)
  end ImpedanceTest;

  model AdmittanceTest
    extends Modelica.Icons.Example;

    PowerSystems.Generic.FixedVoltageSource source
    PowerSystems.Generic.Admittance
      load(G=30/(30*30 + 10*10), C=10/(30*30 + 10*10)/314)
    PowerSystems.Generic.Ground ground
    inner PowerSystems.System system
  equation
    connect(source.terminal, load.terminal_p)
    connect(load.terminal_n, ground.terminal)
  end AdmittanceTest;

  model InductiveLoadTest
    extends Modelica.Icons.Example;

    PowerSystems.Generic.FixedVoltageSource source
    PowerSystems.Generic.Impedance
      line(R=1.2, L=1.6/314)
    PowerSystems.Generic.Impedance
      load(R=30, L=10/314)
    PowerSystems.Generic.Ground ground
    inner PowerSystems.System system
  equation
    connect(source.terminal, line.terminal_p)
    connect(load.terminal_n, ground.terminal)
    connect(line.terminal_n, load.terminal_p)
  end InductiveLoadTest;

  model FixedCurrentTest
    extends Modelica.Icons.Example;

    PowerSystems.Generic.FixedVoltageSource source
    PowerSystems.Generic.Impedance
      line(R=1.2, L=1.6/314)
    PowerSystems.Generic.FixedCurrent load(I=173.448, phi=-0.356)
    inner PowerSystems.System system
  equation
    connect(line.terminal_n, load.terminal)
    connect(source.terminal, line.terminal_p)
  end FixedCurrentTest;

  model FixedLoadTest
    extends Modelica.Icons.Example;

    PowerSystems.Generic.FixedVoltageSource source
    PowerSystems.Generic.Impedance
      line(R=1.2, L=1.6/314)
    PowerSystems.Generic.FixedLoad load(P=2.7076e6, phi=atan(1000/3000))
    inner PowerSystems.System system
  equation
    connect(source.terminal, line.terminal_p)
    connect(line.terminal_n, load.terminal)
  end FixedLoadTest;

  model PMeterTest
    extends Modelica.Icons.Example;

    PowerSystems.Generic.FixedVoltageSource source
    PowerSystems.Generic.Sensors.PMeter pMeter
    PowerSystems.Generic.FixedLoad load(P=2.7076e6, phi=atan(1000/3000))
    inner PowerSystems.System system
  equation
  connect(source.terminal, pMeter.terminal_p)
  connect(pMeter.terminal_n, load.terminal)
  end PMeterTest;

  model GeneratorTest
    extends Modelica.Icons.Example;

    PowerSystems.Generic.Generator generator
    Modelica.Mechanics.Rotational.Components.Inertia inertia(J=1e3,
      phi(start=0, fixed=true),
      w(start=2*pi*50, fixed=true))
    Modelica.Mechanics.Rotational.Sources.ConstantTorque constantTorque(useSupport=false, tau_constant=3e6/50/2/pi)
    PowerSystems.Generic.FixedLoad fixedLoad(P=3e6,phi=0.3)
    inner PowerSystems.System system
  equation
  connect(inertia.flange_b, generator.flange)
    connect(constantTorque.flange, inertia.flange_a)
  connect(generator.terminal, fixedLoad.terminal)
  end GeneratorTest;

  model GeneratorTest2
    extends Modelica.Icons.Example;

    PowerSystems.Generic.Generator generator
    Modelica.Mechanics.Rotational.Components.Inertia inertia(J=1e3,
      phi(start=0, fixed=true),
      w(start=50*2*pi, fixed=true))
    Modelica.Mechanics.Rotational.Sources.ConstantTorque constantTorque(useSupport=false, tau_constant=3e6/50/2/2/pi)
    PowerSystems.Generic.FixedLoad fixedLoad(P=3e6,phi=0.3)
    PowerSystems.Generic.Generator generator1(synchronous=false)
    Modelica.Mechanics.Rotational.Components.Inertia inertia1(J=1e3,
    phi(start=0, fixed=true),
    w(start=50*2*pi, fixed=true))
    Modelica.Mechanics.Rotational.Sources.ConstantTorque constantTorque1(useSupport=false, tau_constant=3e6/50/2/pi)
    PowerSystems.Generic.Impedance impedance
    PowerSystems.Generic.Impedance impedance1
    inner PowerSystems.System system
  equation
    connect(inertia.flange_b, generator.flange)
    connect(constantTorque.flange, inertia.flange_a)
    connect(inertia1.flange_b, generator1.flange)
    connect(constantTorque1.flange, inertia1.flange_a)
    connect(generator.terminal, impedance.terminal_p)
    connect(impedance.terminal_n, fixedLoad.terminal)
    connect(generator1.terminal, impedance1.terminal_p)
    connect(impedance1.terminal_n, fixedLoad.terminal)
  end GeneratorTest2;

end Test;


within PowerSystems.Examples;
package PowerWorld "Demonstrate stabilization of wind power in Eurosyslib work package 5.3"
  extends Modelica.Icons.ExamplesPackage;

  model PowerWorld "Interoperation of wind power and thermal power"
    extends Modelica.Icons.Example;

    Components.WindFarm windFarm(redeclare package PhaseSystem =
      PowerSystems.PhaseSystems.DirectCurrent)
    Components.City city
    Components.LoadDispatcher dispatcher
    Components.PowerPlant powerPlant(primaryControlMax=40)
    PowerSystems.Generic.Transformer trafoPlant(ratio=10/380)
    PowerSystems.Generic.Transformer distribution(ratio=380/50)
    PowerSystems.Generic.Inverter HVDC(potentialReference=false)
    Components.HydroPlant hydroPlant(primaryControlMax=200)
    PowerSystems.Generic.Transformer trafoHydro(ratio=380/10)
    PowerSystems.Generic.Impedance linePlant(R=1, L=1/314)
    PowerSystems.Generic.Impedance lineWind(R=1, L=1/314)
    PowerSystems.Generic.Impedance lineHydro(R=1, L=1/314)
    Modelica.Blocks.Sources.RealExpression frequency(y=system.omega/2/pi)
      "Average frequency"
    inner System system(dynType=PowerSystems.Types.Dynamics.FixedInitial,
      fType=PowerSystems.Types.SystemFrequency.Average)
  equation
    connect(powerPlant.terminal, trafoPlant.terminal_p)
    connect(distribution.terminal_n, city.terminal)
    connect(windFarm.terminal, HVDC.terminal_dc)
    connect(dispatcher.plantDispatch, powerPlant.plantDispatch)
    connect(dispatcher.hydroDispatch, hydroPlant.hydroDispatch)
    connect(trafoPlant.terminal_n, linePlant.terminal_p)
    connect(linePlant.terminal_n, distribution.terminal_p)
    connect(HVDC.terminal, lineWind.terminal_p)
    connect(lineWind.terminal_n, distribution.terminal_p)
    connect(lineHydro.terminal_n, distribution.terminal_p)
    connect(frequency.y, dispatcher.frequency)
    connect(hydroPlant.terminal, trafoHydro.terminal_n)
    connect(trafoHydro.terminal_p, lineHydro.terminal_p)
  end PowerWorld;

  package Components "Aggregated components for PowerWorld example"
    extends Modelica.Icons.VariantsPackage;

    model PowerPlant "Thermal Power Plant with primary and secondary control"
      extends PowerSystems.Generic.Ports.PartialSource(
        final potentialReference=true);

      parameter Boolean Modakond = false "Install Modakond for condensate stop"
      parameter Real primaryControlMax(unit="MW") = 40
      "Maximum power for primary frequency control"

      Real P_generator(unit="MW") = -generator.p[1]/1e6;
      Real P_control(unit="MW") = -(P_generator - plantDispatch[1]);

    PowerSystems.Generic.Generator generator(redeclare package PhaseSystem =
          PhaseSystem, definiteReference=definiteReference)
      Modelica.Mechanics.Rotational.Components.Inertia rotor(
                       J=10e6,
      a(start=0),
        w(fixed=false, start=system.w_nom/generator.pp))
      Modelica.Mechanics.Rotational.Sources.Torque turbine
      Modelica.Mechanics.Rotational.Sensors.SpeedSensor angularVelocity
      Modelica.Blocks.Sources.Constant reference(k=system.f_nom)
      Modelica.Blocks.Continuous.LimPID primaryControl(
                                               k=0.05*800/0.2,
        controllerType=Modelica.Blocks.Types.SimpleController.P,
        yMax=primaryControlMax) "UCTE: df of 200 mHz corresponds to 5% of load"
      Modelica.Blocks.Interfaces.RealInput[3] plantDispatch(each unit="MW")
      Modelica.Blocks.Math.Add loadControl(k1=1e6/50/2/pi, k2=1e6/50/2/pi)
      Modelica.Blocks.Continuous.FirstOrder evaporator(T=60, y_start=490,
      initType=Modelica.Blocks.Types.Init.InitialState)
      Modelica.Blocks.Continuous.FirstOrder superheater1(T=60, y_start=490,
      initType=Modelica.Blocks.Types.Init.InitialState)
      Modelica.Blocks.Continuous.FirstOrder superheater2(T=60, y_start=490,
      initType=Modelica.Blocks.Types.Init.InitialState)
      Modelica.Blocks.Math.Add fuel
      Modelica.Blocks.Continuous.TransferFunction transferFunction(b={180,1}, a=
           {60,1},
      initType=Modelica.Blocks.Types.Init.SteadyState)
      "achieve a power ramp of 2% per minute, minus 0.8% tolerance"
      Modelica.Blocks.Math.Add add
      Modelica.Blocks.Continuous.LimIntegrator hotwellLevel(
        k=1,
        outMax=10,
        outMin=0,
        y(unit="m")) "level of hotwell"
      Modelica.Blocks.Math.Max on
      Modelica.Blocks.Math.Sign condStop
      Modelica.Blocks.Math.Min off
      Modelica.Blocks.Math.Add accumulation(k2=1e-2, k1=if Modakond then 5e-4 else
                  0)
      Modelica.Blocks.Sources.Constant zero(k=0)
      Modelica.Blocks.Continuous.FirstOrder throttleDynamics(T=120, k=-300/800,
      initType=Modelica.Blocks.Types.Init.SteadyState)
      Modelica.Blocks.Math.Add pressure(k1=300/800)
      Modelica.Blocks.Math.Min throttling
      Modelica.Blocks.Sources.Constant throttleMin(k=if Modakond then 0 else
            Modelica.Constants.inf)
      Modelica.Blocks.Sources.Constant throttleReserve(k=if Modakond then 0 else
                  5)
      Modelica.Blocks.Math.Add pressureLoss
      Modelica.Blocks.Continuous.Integrator throttleCosts(k=1/365)
      Modelica.Blocks.Math.Gain frequency(k=1/(2*pi))
  protected
      outer System system;

  public
      Interfaces.Sender sender(w=generator.w, H=0.5*rotor.J*rotor.w^2/800e6)
    initial equation
      if Connections.isRoot(generator.terminal.theta) then
        if system.dynType == Types.Dynamics.SteadyInitial then
          rotor.a = 0;
        else
          rotor.w = system.omega/generator.pp;
        end if;
        rotor.phi = system.theta/generator.pp;
      end if;
    equation
      connect(sender.sendFreq, system.receiveFreq);
      connect(rotor.flange_b, angularVelocity.flange)
      connect(primaryControl.y, loadControl.u1)
      connect(evaporator.y, superheater1.u)
      connect(superheater1.y, superheater2.u)
      connect(superheater2.y, loadControl.u2)
      connect(loadControl.y, turbine.tau)
      connect(turbine.flange, rotor.flange_a)
      connect(rotor.flange_b, generator.flange)
      connect(fuel.y, evaporator.u)
      connect(transferFunction.y, fuel.u2)
      connect(add.y, transferFunction.u)
      connect(loadControl.u1, add.u2)
      connect(accumulation.y, hotwellLevel.u)
      connect(loadControl.u1, condStop.u)
      connect(condStop.y, on.u1)
      connect(condStop.y, off.u2)
      connect(zero.y, on.u2)
      connect(zero.y, off.u1)
      connect(on.y, accumulation.u1)
      connect(off.y, accumulation.u2)
      connect(primaryControl.y, throttling.u2)
      connect(throttleMin.y, throttling.u1)
      connect(throttling.y, throttleDynamics.u)
      connect(superheater2.y, pressure.u1)
      connect(throttleDynamics.y, pressureLoss.u2)
      connect(throttleReserve.y, pressureLoss.u1)
      connect(pressureLoss.y, pressure.u2)
      connect(pressureLoss.y, throttleCosts.u)

      connect(plantDispatch[2], add.u1)
      connect(plantDispatch[1], fuel.u1)
      connect(reference.y, primaryControl.u_s)
      connect(angularVelocity.w, frequency.u)
      connect(frequency.y, primaryControl.u_m)
    connect(generator.terminal, terminal)
    end PowerPlant;

    model HydroPlant
      extends PowerSystems.Generic.Ports.PartialSource(
        final potentialReference=true);

      parameter Real primaryControlMax(unit="MW") = 200
      "Maximum power for primary frequency control"

      Real P_generator(unit="MW") = -generator.p[1]/1e6;
      Real P_control(unit="MW") = -(P_generator - hydroDispatch[1]);

      Modelica.Blocks.Interfaces.RealInput[3] hydroDispatch(each unit="MW")
      Modelica.Blocks.Continuous.Integrator reservoirLevel(y_start=10, k=-1/5e4,
        y(unit="m"))
      Modelica.Mechanics.Rotational.Sources.Torque reservoirTurbine
      Modelica.Mechanics.Rotational.Components.Inertia rotor(J=1e6,
      a(start=0),
        w(fixed=false, start=system.w_nom/generator.pp))
    PowerSystems.Generic.Generator generator(redeclare package PhaseSystem =
          PhaseSystem, definiteReference=definiteReference)
      Modelica.Mechanics.Rotational.Sensors.SpeedSensor angularVelocity
      Modelica.Blocks.Sources.Constant reference(k=system.f_nom)
      Modelica.Blocks.Continuous.LimPID primaryControl(
        k=50/0.2,
        controllerType=Modelica.Blocks.Types.SimpleController.P,
        yMax=primaryControlMax) "200 mHz corresponds to 50 MW"
      Modelica.Blocks.Math.Gain powerControl(k=1e6/50/2/pi)
      Modelica.Blocks.Continuous.TransferFunction controlDynamics(a={1,1}, b={1},
        initType=Modelica.Blocks.Types.Init.InitialState)
      Modelica.Blocks.Math.Add add
      Modelica.Blocks.Math.Gain riverControl(k=1e6/50/2/pi)
      Modelica.Mechanics.Rotational.Sources.Torque riverTurbine
      Modelica.Mechanics.Rotational.Components.Inertia rotorRiver(
                       J=0.5e6,
      a(start=0),
        w(fixed=false, start=system.w_nom/generator.pp))
      Modelica.Blocks.Math.Gain frequency(k=1/(2*pi))
  protected
      outer System system;

  public
      Interfaces.Sender sender(w=generator.w, H=0.5*rotor.J*rotor.w^2/200e6)
    initial equation
      if Connections.isRoot(generator.terminal.theta) then
        if system.dynType == Types.Dynamics.SteadyInitial then
          rotor.a = 0;
        else
          rotor.w = system.omega/generator.pp;
        end if;
        rotor.phi = system.theta/generator.pp;
      end if;
    equation
      connect(sender.sendFreq, system.receiveFreq);
      connect(rotor.flange_b, angularVelocity.flange)

      connect(reservoirTurbine.flange, rotor.flange_a)
      connect(rotor.flange_b, generator.flange)
      connect(powerControl.y, reservoirTurbine.tau)
      connect(controlDynamics.y, reservoirLevel.u)
      connect(controlDynamics.y, powerControl.u)
      connect(add.y, controlDynamics.u)
      connect(hydroDispatch[2], add.u2)

      connect(hydroDispatch[1], riverControl.u)
      connect(riverControl.y, riverTurbine.tau)
      connect(reference.y, primaryControl.u_s)
      connect(primaryControl.y, add.u1)
      connect(riverTurbine.flange, rotorRiver.flange_a)
      connect(rotorRiver.flange_b, generator.flange)
      connect(angularVelocity.w, frequency.u)
      connect(frequency.y, primaryControl.u_m)
    connect(generator.terminal, terminal)
    end HydroPlant;

    model WindFarm
      extends PowerSystems.Generic.Ports.PartialSource(
        final potentialReference=false, final definiteReference=false);
      parameter Boolean cut_out = false
      "stop producing energy as wind exceeds cut-out speed of 20-25 m/s"

      Modelica.Blocks.Sources.CombiTimeTable wind(
        tableName="tab",
        fileName=PowerWorldResources + "LoadData.txt",
        tableOnFile=true,
        table=fill(
                0.0,
                0,
                10))
      PowerSystems.Generic.PrescribedPowerSource mills(
        redeclare package PhaseSystem = PhaseSystem,
        definiteReference = definiteReference)
      Modelica.Blocks.Sources.Trapezoid disturbance(
        rising=120,
        period=86400,
        offset=1,
        width=1800,
        falling=1800,
        startTime=20040,
        amplitude=if cut_out then -1 else 0)
      Modelica.Blocks.Math.Product product
    Modelica.Blocks.Math.Gain MW2W(k=1e6)
    equation

      connect(wind.y[4], product.u2)

      connect(disturbance.y, product.u1)
    connect(mills.terminal, terminal)
    connect(product.y, MW2W.u)
    connect(MW2W.y, mills.P)
    end WindFarm;

    model LoadDispatcher

      Modelica.Blocks.Sources.CombiTimeTable data(
        tableName="tab",
        fileName=PowerWorldResources + "LoadData.txt",
        tableOnFile=true,
        table=fill(
            0.0,
            0,
            10))
      Modelica.Blocks.Interfaces.RealOutput[3] plantDispatch(each unit="MW")
      Modelica.Blocks.Interfaces.RealOutput loadForcast(unit="MW")
      Modelica.Blocks.Interfaces.RealOutput windForcast(unit="MW")
      Modelica.Blocks.Sources.Constant hydroBase(k=25)
      Modelica.Blocks.Sources.Constant primaryControl(k=40)
      Modelica.Blocks.Interfaces.RealOutput[3] hydroDispatch(each unit="MW")
      Modelica.Blocks.Sources.Constant controlHydro(k=200)
      Modelica.Blocks.Interfaces.RealInput frequency(unit="Hz")
      Modelica.Blocks.Continuous.LimPID secondaryControl(   k=60/0.4,
        controllerType=Modelica.Blocks.Types.SimpleController.PI,
        Ti=600,
        yMax=60) "400 mHz corresponds to 60 MW"
      Modelica.Blocks.Sources.Constant reference(k=system.f_nom)
      Modelica.Blocks.Math.Add3 plantSchedule(k2=-1, k3=-1,
        y(unit="MW"))
      Modelica.Blocks.Sources.Trapezoid hydroDaily(
        rising=86400/4,
        width=86400/4,
        falling=86400/4,
        period=86400,
        startTime=86400/8,
        amplitude=50,
        offset=-25,
        y(unit="MW"))
      Modelica.Blocks.Math.Add add
      Modelica.Blocks.Math.Gain distributionLoss(k=1)
  protected
      outer System system;
    equation
      connect(primaryControl.y, plantDispatch[3])
      connect(hydroBase.y, hydroDispatch[1])
      connect(controlHydro.y, hydroDispatch[3])
      connect(data.y[3], windForcast)
      connect(secondaryControl.y, plantDispatch[2])
      connect(windForcast, plantSchedule.u2)
      connect(plantSchedule.y, plantDispatch[1])
      connect(hydroDaily.y, hydroDispatch[2])
      connect(hydroDaily.y, add.u1)
      connect(hydroBase.y, add.u2)
      connect(add.y, plantSchedule.u3)
      connect(frequency, secondaryControl.u_m)
      connect(reference.y, secondaryControl.u_s)
      connect(data.y[1], loadForcast)
      connect(loadForcast, distributionLoss.u)
      connect(distributionLoss.y, plantSchedule.u1)
    end LoadDispatcher;

    model City
      extends PowerSystems.Generic.Ports.PartialLoad;
      Modelica.Blocks.Sources.CombiTimeTable data(
        tableName="tab",
        fileName=PowerWorldResources + "LoadData.txt",
        tableOnFile=true,
        table=fill(
                0.0,
                0,
                10))
      PowerSystems.Generic.PrescribedPowerLoad load(phi=0.34906585039887)
    Modelica.Blocks.Math.Gain MW2W(k=1e6)
    equation
    connect(terminal, load.terminal)
    connect(data.y[2], MW2W.u)
    connect(MW2W.y, load.P)
    end City;

  end Components;

  package Test "Component tests for PowerWorld example"
    extends Modelica.Icons.ExamplesPackage;

    model PowerPlantTest1 "Test primary control"
      extends Modelica.Icons.Example;
      Components.PowerPlant powerPlant
      Modelica.Blocks.Sources.Constant schedule(k=450)
      PowerSystems.Generic.PrescribedPowerLoad prescribedLoad(phi=
                                                              0.34906585039887)
      Modelica.Blocks.Sources.Step step(startTime=10,
                                        height=-40,
                                        offset=490)
      Modelica.Blocks.Sources.Constant secondary(k=40)
      Modelica.Blocks.Sources.Constant primary(k=40)
    Modelica.Blocks.Math.Gain MW2W(k=1e6)
    inner PowerSystems.System system
    equation
      connect(powerPlant.terminal, prescribedLoad.terminal)
      connect(secondary.y, powerPlant.plantDispatch[2])
      connect(schedule.y, powerPlant.plantDispatch[1])
      connect(primary.y, powerPlant.plantDispatch[3])
    connect(step.y, MW2W.u)
    connect(MW2W.y, prescribedLoad.P)
    end PowerPlantTest1;

    model PowerPlantTest2 "Test secondary control"
      extends Modelica.Icons.Example;
      Components.PowerPlant powerPlant
      Modelica.Blocks.Sources.Constant schedule(k=490)
      PowerSystems.Generic.PrescribedPowerLoad prescribedLoad(phi=
                                                              0.34906585039887)
      Modelica.Blocks.Sources.Ramp ramp(offset=490,
                                        height=48,
                                        duration=180,
                                        startTime=100)
      Modelica.Blocks.Sources.Step secondary(height=48, startTime=100)
      Modelica.Blocks.Sources.Constant primary(k=40)
    Modelica.Blocks.Math.Gain MW2W(k=1e6)
    inner PowerSystems.System system
    equation
      connect(powerPlant.terminal, prescribedLoad.terminal)
      connect(schedule.y, powerPlant.plantDispatch[1])
      connect(secondary.y, powerPlant.plantDispatch[2])
      connect(primary.y, powerPlant.plantDispatch[3])
    connect(ramp.y, MW2W.u)
    connect(MW2W.y, prescribedLoad.P)
    end PowerPlantTest2;

    model PowerPlantTest3 "Test connection to a large net"
      extends Modelica.Icons.Example;
      Components.PowerPlant powerPlant
      Modelica.Blocks.Sources.Constant schedule(k=490)
      PowerSystems.Generic.FixedVoltageSource largeGrid
      Modelica.Blocks.Sources.Ramp secondary(startTime=100,
                                             height=300,
                                             duration=0)
      PowerSystems.Generic.Impedance
        line(R=1, L=1/314)
      Modelica.Blocks.Sources.Constant primary(k=40)
    inner PowerSystems.System system
    equation
      connect(schedule.y, powerPlant.plantDispatch[1])
      connect(secondary.y, powerPlant.plantDispatch[2])
      connect(powerPlant.terminal, line.terminal_p)
    connect(line.terminal_n, largeGrid.terminal)
      connect(primary.y, powerPlant.plantDispatch[3])
    end PowerPlantTest3;

    model HydroPlantTest1 "Test primary control"
      extends Modelica.Icons.Example;
      Components.HydroPlant hydroPlant(primaryControlMax=310)
      Modelica.Blocks.Sources.Constant schedule(k=50)
      PowerSystems.Generic.PrescribedPowerLoad prescribedLoad
      Modelica.Blocks.Sources.Trapezoid trapezoid(startTime=100,
                                                  offset=50,
                                                  amplitude=300,
                                                  width=300,
                                                  falling=300,
                                                  nperiod=1,
                                                  rising=60,
                                                  period=900)
      Modelica.Blocks.Sources.Constant primary(k=400)
      Modelica.Blocks.Sources.Constant secondary(k=0)
    Modelica.Blocks.Math.Gain MW2W(k=1e6)
    inner PowerSystems.System system
    equation
      connect(schedule.y, hydroPlant.hydroDispatch[1])
      connect(hydroPlant.terminal, prescribedLoad.terminal)
      connect(primary.y, hydroPlant.hydroDispatch[3])
      connect(secondary.y, hydroPlant.hydroDispatch[2])
    connect(trapezoid.y, MW2W.u)
    connect(MW2W.y, prescribedLoad.P)
    end HydroPlantTest1;

    model HydroPlantTest2 "Test secondary control"
      extends Modelica.Icons.Example;
      Components.HydroPlant hydroPlant
      Modelica.Blocks.Sources.Constant schedule(k=50)
      Modelica.Blocks.Sources.Constant primary(k=400)
      Modelica.Blocks.Sources.Trapezoid secondary(amplitude=100,
                                                  offset=-50,
                                                  rising=86400/4,
                                                  width=86400/4,
                                                  falling=86400/4,
                                                  period=86400,
                                                  startTime=86400/8)
      PowerSystems.Generic.FixedVoltageSource largeGrid
      PowerSystems.Generic.Impedance
        line(R=1, L=1/314)
    inner PowerSystems.System system
    equation
      connect(schedule.y, hydroPlant.hydroDispatch[1])
      connect(primary.y, hydroPlant.hydroDispatch[3])
      connect(secondary.y, hydroPlant.hydroDispatch[2])
      connect(line.terminal_n, largeGrid.terminal)
      connect(hydroPlant.terminal, line.terminal_p)
    end HydroPlantTest2;

    model WindFarmGridTest "WindFarm connected to a large net"
      extends Modelica.Icons.Example;
      Components.WindFarm windFarm
      PowerSystems.Generic.FixedVoltageSource largeGrid
    inner PowerSystems.System system
    equation
    connect(windFarm.terminal, largeGrid.terminal)
    end WindFarmGridTest;

    model WindFarmHVDCTest "WindFarm connected to a large net via HVDC"
      extends Modelica.Icons.Example;
      Components.WindFarm windFarm(redeclare package PhaseSystem =
            PowerSystems.PhaseSystems.DirectCurrent)

      PowerSystems.Generic.FixedVoltageSource largeGrid
      PowerSystems.Generic.Inverter
        inverter
      inner PowerSystems.System system
    equation
      connect(windFarm.terminal, inverter.terminal_dc)
    connect(inverter.terminal, largeGrid.terminal)
    end WindFarmHVDCTest;

    model CityTest
      extends Modelica.Icons.Example;
      PowerSystems.Generic.FixedVoltageSource largeGrid
      Components.City city
      inner PowerSystems.System system
    equation
    connect(largeGrid.terminal, city.terminal)
    end CityTest;

    model LoadDispatcherTest
      extends Modelica.Icons.Example;
      Components.LoadDispatcher loadDispatcher
      Modelica.Blocks.Sources.Trapezoid frequency(amplitude=2,
                                                  rising=15,
                                                  falling=15,
                                                  period=60,
                                                  offset=49,
                                                  width=15)
      inner System system
    equation
      connect(frequency.y, loadDispatcher.frequency)
    end LoadDispatcherTest;
  end Test;

  constant String PowerWorldResources = Modelica.Utilities.Files.loadResource("modelica://PowerSystems.Examples.PowerWorld/Resources/");
end PowerWorld;


Different wind turbine concepts

within PowerSystems.Examples;
package Wind "Different wind turbine concepts"
  extends Modelica.Icons.ExamplesPackage;

  model WindTurbine_IG
  "Wind turbine with Induction Generator (asynchronous) -- fixed speed"
    extends Modelica.Icons.Example;
    PowerSystems.AC3ph.Machines.Asynchron generator(redeclare record Data =
        Data.Machines.Asynchron400V_30kVA (
        V_nom=690,
        S_nom=3e6,
        pp=4))
    PowerSystems.Common.Thermal.BdCondV bdCond(m=2)
    inner System system
    PowerSystems.AC3ph.Nodes.BusBar busbar
    PowerSystems.AC3ph.Sensors.PVImeter meter(
      V_nom(displayUnit="kV") = 1000,
      S_nom(displayUnit="MVA") = 1000000)
    PowerSystems.AC3ph.Lines.PIline line(len=1000, redeclare record Data =
        PowerSystems.AC3ph.Lines.Parameters.Line (V_nom=15e3, S_nom=3e6))
    PowerSystems.AC3ph.Sources.InfBus infBus(V_nom=15e3)
    PowerSystems.AC3ph.Nodes.GroundOne grd
    Modelica.Blocks.Sources.Ramp windSpeed(
      duration=80,
      startTime=10,
    offset=3,
    height=12)
    Components.Rotor rotor(R=40)
    PowerSystems.Mechanics.Rotational.Rotor inertia(
      J=300, w_start=314/generator.par.pp)
    Modelica.Mechanics.Rotational.Components.IdealGear gear(ratio=generator.par.pp
          /200)
    PowerSystems.AC3ph.Transformers.TrafoIdeal trafo(redeclare record Data =
        PowerSystems.AC3ph.Transformers.Parameters.TrafoIdeal (V_nom={690,15e3}, S_nom=3e6))
  equation
    connect(generator.heat,bdCond. heat)
    connect(busbar.term, meter.term_p)
    connect(line.term_n,infBus. term)
    connect(infBus.neutral,grd. term)
    connect(generator.term, busbar.term)
    connect(windSpeed.y, rotor.v)
    connect(rotor.flange, gear.flange_a)
    connect(gear.flange_b,inertia.flange_a)
    connect(inertia.flange_b, generator.airgap)
    connect(meter.term_n, trafo.term_p)
    connect(trafo.term_n, line.term_p)
  end WindTurbine_IG;

  model WindTurbine_DFIG
  "Wind turbine with Doubly Fed Induction Generator (asynchronous) -- variable speed"
     extends Modelica.Icons.Example;
  PowerSystems.AC3ph.Machines.Asynchron_dfig generator(redeclare record Data =
        Data.Machines.Asynchron400V_30kVA (
        V_nom=690,
        S_nom=3e6,
        pp=4))
    PowerSystems.Common.Thermal.BdCondV bdCond(m=2)
    inner System system
    PowerSystems.AC3ph.Nodes.BusBar busbar
    PowerSystems.AC3ph.Sensors.PVImeter meter(
      V_nom(displayUnit="kV") = 1000,
      S_nom(displayUnit="MVA") = 1000000)
    PowerSystems.AC3ph.Lines.PIline line(len=1000, redeclare record Data =
        PowerSystems.AC3ph.Lines.Parameters.Line (V_nom=15e3, S_nom=3e6))
    PowerSystems.AC3ph.Sources.InfBus infBus(V_nom=15e3)
    PowerSystems.AC3ph.Nodes.GroundOne grd
    Modelica.Blocks.Sources.Ramp windSpeed(
      duration=80,
      startTime=10,
    height=12,
    offset=3)
    Components.Rotor rotor(R=40)
    PowerSystems.Mechanics.Rotational.Rotor inertia(J=300, w_start=314/generator.par.pp)
    Modelica.Mechanics.Rotational.Components.IdealGear gear(ratio=generator.par.pp
        /200)
    PowerSystems.AC3ph.Inverters.InverterAverage inverter1
    PowerSystems.Common.Thermal.BdCondV bdCond1(m=1)
    PowerSystems.AC1ph_DC.Sensors.PVImeter meterDC(av=true, tcst=0.1)
    PowerSystems.AC3ph.Inverters.InverterAverage inverter2
    PowerSystems.AC3ph.Inverters.Select select2
    PowerSystems.Common.Thermal.BdCondV bdCond2(m=1)
    Modelica.Blocks.Sources.RealExpression vPhasor_set[2](y={0.5 - min(
        windSpeed.y, 15)/20,0.25*windSpeed.y/15})
    PowerSystems.AC3ph.Transformers.TrafoIdeal trafo(redeclare record Data =
        PowerSystems.AC3ph.Transformers.Parameters.TrafoIdeal (V_nom={690,15e3}, S_nom=3e6))
  equation
    connect(generator.heat,bdCond. heat)
    connect(busbar.term, meter.term_p)
    connect(line.term_n,infBus. term)
    connect(infBus.neutral,grd. term)
    connect(generator.term, busbar.term)
    connect(windSpeed.y, rotor.v)
    connect(rotor.flange, gear.flange_a)
    connect(gear.flange_b, inertia.flange_a)
    connect(inertia.flange_b, generator.airgap)
    connect(inverter1.heat, bdCond1.heat)
    connect(inverter1.AC, generator.term_r)
    connect(generator.phiRotor, inverter1.theta)
    connect(bdCond2.heat,inverter2. heat)
    connect(select2.vPhasor_out,inverter2. vPhasor)
    connect(select2.theta_out,inverter2. theta)
    connect(inverter2.AC, busbar.term)
    connect(inverter1.DC, meterDC.term_p)
    connect(meterDC.term_n, inverter2.DC)
    connect(meter.term_n, trafo.term_p)
    connect(trafo.term_n, line.term_p)
    connect(vPhasor_set.y, inverter1.vPhasor)
  end WindTurbine_DFIG;

  model WindTurbine_PSGR
  "Wind turbine with Permanent magnet Synchronous Generator and generator side Rectifier"
    extends Modelica.Icons.Example;
    Modelica.Blocks.Sources.Ramp windSpeed(
      duration=80,
      startTime=10,
    height=12,
    offset=3)
    Components.Rotor rotor(R=40)
    inner System system
  PowerSystems.Mechanics.Rotational.Rotor inertia(J=300, w_start=314/generator.par.pp)
    Modelica.Mechanics.Rotational.Components.IdealGear gear(ratio=generator.par.pp
        /200)
    PowerSystems.AC3ph.Machines.Synchron_pm generator(redeclare record Data =
        Data.Machines.Synchron_pm400V_30kVA (
        V_nom=690,
        S_nom=3e6,
        pp=4))
    PowerSystems.Common.Thermal.BdCondV bdCond(m=2)
    PowerSystems.AC3ph.Inverters.RectifierAverage rectifier1(redeclare record Data =
          Semiconductors.Ideal.SCparameter)
    PowerSystems.Common.Thermal.BdCondV bdCond1(m=1)
    PowerSystems.AC1ph_DC.Sensors.PVImeter meterDC(av=true, tcst=0.1)
    PowerSystems.AC3ph.Inverters.InverterAverage inverter2
    PowerSystems.AC3ph.Inverters.Select select2
    PowerSystems.Common.Thermal.BdCondV bdCond2(m=1)
    PowerSystems.AC3ph.Sensors.PVImeter meter(
      V_nom(displayUnit="kV") = 1000,
      S_nom(displayUnit="MVA") = 1000000)
    PowerSystems.AC3ph.Lines.PIline line(len=1000, redeclare record Data =
          PowerSystems.AC3ph.Lines.Parameters.Line (V_nom=15e3, S_nom=3e6))
    PowerSystems.AC3ph.Sources.InfBus infBus(V_nom=15e3)
    PowerSystems.AC3ph.Nodes.GroundOne grd
    PowerSystems.AC3ph.Nodes.BusBar busbar
    PowerSystems.AC3ph.Transformers.TrafoIdeal trafo(redeclare record Data =
        PowerSystems.AC3ph.Transformers.Parameters.TrafoIdeal(V_nom={690,15e3}, S_nom=3e6))
    PowerSystems.AC3ph.Nodes.DefReference reference
  equation
    connect(windSpeed.y, rotor.v)
    connect(rotor.flange, gear.flange_a)
    connect(gear.flange_b,inertia.flange_a)
    connect(generator.heat,bdCond.heat)
    connect(rectifier1.heat, bdCond1.heat)
    connect(inertia.flange_b, generator.airgap)
    connect(rectifier1.DC, meterDC.term_p)
    connect(meterDC.term_n, inverter2.DC)
    connect(bdCond2.heat, inverter2.heat)
    connect(select2.vPhasor_out, inverter2.vPhasor)
    connect(select2.theta_out, inverter2.theta)
    connect(line.term_n,infBus. term)
    connect(infBus.neutral,grd. term)
    connect(busbar.term, meter.term_p)
    connect(inverter2.AC, busbar.term)
    connect(meter.term_n, trafo.term_p)
    connect(trafo.term_n, line.term_p)
    connect(generator.term, reference.term)
    connect(reference.term, rectifier1.AC)
    connect(generator.phiRotor, reference.theta)
  end WindTurbine_PSGR;

  model WindTurbine_PSGI
    "Wind turbine with Permanent magnet Synchronous Generator and generator side Inverter"
    extends Modelica.Icons.Example;
    Modelica.Blocks.Sources.Ramp windSpeed(
      duration=80,
      startTime=10,
    height=12,
    offset=3)
    Components.Rotor rotor(R=40)
    inner System system
    PowerSystems.Mechanics.Rotational.Rotor inertia(J=300, w_start=314/generator.par.pp)
    Modelica.Mechanics.Rotational.Components.IdealGear gear(ratio=generator.par.pp
        /200)
    PowerSystems.AC1ph_DC.Sensors.PVImeter meterDC(av=true, tcst=0.1)
    PowerSystems.AC3ph.Machines.Synchron_pm_ctrl generator(redeclare record Data =
        Data.Machines.Synchron_pm400V_30kVA (
        V_nom=690,
        S_nom=3e6,
        pp=4))
    PowerSystems.Common.Thermal.BdCondV bdCond(m=2)
    PowerSystems.AC3ph.Inverters.InverterAverage inverter1
    PowerSystems.Common.Thermal.BdCondV bdCond1(m=1)
    PowerSystems.AC3ph.Inverters.InverterAverage inverter2
    PowerSystems.AC3ph.Inverters.Select select2
    PowerSystems.Common.Thermal.BdCondV bdCond2(m=1)
    PowerSystems.AC3ph.Sensors.PVImeter meter(
      V_nom(displayUnit="kV") = 1000,
      S_nom(displayUnit="MVA") = 1000000)
    PowerSystems.AC3ph.Lines.PIline line(len=1000, redeclare record Data =
        PowerSystems.AC3ph.Lines.Parameters.Line (V_nom=15e3, S_nom=3e6))
    PowerSystems.AC3ph.Sources.InfBus infBus(V_nom=15e3)
    PowerSystems.AC3ph.Nodes.GroundOne grd
    PowerSystems.AC3ph.Nodes.BusBar busbar
    PowerSystems.AC3ph.Transformers.TrafoIdeal trafo(redeclare record Data =
        PowerSystems.AC3ph.Transformers.Parameters.TrafoIdeal(V_nom={690,15e3}, S_nom=3e6))
    Modelica.Blocks.Continuous.PI PI(T=0.5, initType=Modelica.Blocks.Types.Init.SteadyState)
    Modelica.Blocks.Sources.RealExpression i_q_err(y=(0.75 + min(windSpeed.y,
        15)/12) - inertia.w*generator.par.pp/200)
    Modelica.Blocks.Sources.RealExpression i_d_set(y=0)
  equation
    connect(windSpeed.y, rotor.v)
    connect(rotor.flange, gear.flange_a)
    connect(gear.flange_b, inertia.flange_a)
    connect(generator.heat,bdCond.heat)
    connect(generator.term, inverter1.AC)
    connect(inverter1.heat, bdCond1.heat)
    connect(inverter1.DC, meterDC.term_p)
    connect(inertia.flange_b, generator.airgap)
    connect(bdCond2.heat,inverter2. heat)
    connect(select2.vPhasor_out,inverter2. vPhasor)
    connect(select2.theta_out,inverter2. theta)
    connect(line.term_n,infBus. term)
    connect(infBus.neutral,grd. term)
    connect(meterDC.term_n,inverter2. DC)
    connect(busbar.term, meter.term_p)
    connect(inverter2.AC, busbar.term)
    connect(meter.term_n, trafo.term_p)
    connect(trafo.term_n, line.term_p)
    connect(generator.vPhasor, inverter1.vPhasor)
    connect(generator.phiRotor, inverter1.theta)
    connect(PI.y, generator.i_act[2])
    connect(i_d_set.y, generator.i_act[1])
  connect(i_q_err.y, PI.u)
  end WindTurbine_PSGI;

  model WindFarm "Multiple wind turbines connected together"
    extends Modelica.Icons.Example;
    inner System system
    PowerSystems.AC3ph.Lines.PIline line(len=500, redeclare record Data =
        PowerSystems.AC3ph.Lines.Parameters.Line (V_nom=15e3, S_nom=15e6))
    PowerSystems.AC3ph.Sources.InfBus infBus(V_nom=15e3)
    PowerSystems.AC3ph.Nodes.GroundOne grd
    Modelica.Blocks.Sources.Ramp windSpeed(
      duration=80,
      startTime=10,
    height=12,
    offset=3)
    Components.WindTurbine wt1
    Components.WindTurbine wt2
    Components.WindTurbine wt3
    PowerSystems.AC3ph.Sensors.PVImeter meter(
      V_nom(displayUnit="kV") = 1000,
      S_nom(displayUnit="MVA") = 1000000)
    PowerSystems.AC3ph.Nodes.BusBar busbar
    PowerSystems.AC3ph.Lines.PIline line1(
    ne=1,
    len=100,
    redeclare record Data = PowerSystems.AC3ph.Lines.Parameters.Line (V_nom=15e3, S_nom=3e6))
    PowerSystems.AC3ph.Lines.PIline line2(
    ne=1,
    len=100,
    redeclare record Data = PowerSystems.AC3ph.Lines.Parameters.Line (V_nom=15e3, S_nom=3e6))
    PowerSystems.AC3ph.Lines.PIline line3(
    ne=1,
    len=100,
    redeclare record Data = PowerSystems.AC3ph.Lines.Parameters.Line (V_nom=15e3, S_nom=3e6))
    Components.WindTurbine wt4
    PowerSystems.AC3ph.Lines.PIline line4(
    ne=1,
    len=100,
    redeclare record Data = PowerSystems.AC3ph.Lines.Parameters.Line (V_nom=15e3, S_nom=3e6))
    Components.WindTurbine wt5
    PowerSystems.AC3ph.Lines.PIline line5(
    ne=1,
    len=100,
    redeclare record Data = PowerSystems.AC3ph.Lines.Parameters.Line (V_nom=15e3, S_nom=3e6))
  equation
    connect(line.term_n,infBus. term)
    connect(infBus.neutral,grd. term)
  connect(windSpeed.y, wt1.windSpeed)
  connect(windSpeed.y, wt2.windSpeed)
  connect(windSpeed.y, wt3.windSpeed)
    connect(busbar.term, meter.term_p)
    connect(meter.term_n, line.term_p)
  connect(wt2.term, line2.term_p)
    connect(line2.term_n, busbar.term)
    connect(line1.term_n, busbar.term)
    connect(line3.term_n, busbar.term)
    connect(wt3.term, line3.term_p)
    connect(wt1.term, line1.term_p)
    connect(wt4.term, line4.term_p)
    connect(wt5.term, line5.term_p)
    connect(windSpeed.y, wt4.windSpeed)
    connect(windSpeed.y, wt5.windSpeed)
    connect(line4.term_n, busbar.term)
    connect(line5.term_n, busbar.term)
  end WindFarm;

  package Components
    extends Modelica.Icons.VariantsPackage;

    model Rotor "Transformation of wind to mechanical power. See S. Heier, Grid Integration of Wind Energy Conversion Systems, John Wiley & Sons Ltd.,
1998"
      parameter Real c1=0.5176;
      parameter Real c2=116;
      parameter Real c3=0.4;
      parameter Real c4=5;
      parameter Real c5=21;
      parameter Real c6=0.0068;
      parameter SI.Angle beta = 0 "Pitch angle of blades (0..20deg)";
      parameter SI.Density rho = 1.29 "Density of air";
      parameter SI.Radius R = 17 "Rotor length (radius)";
      parameter SI.Power P_nom = 1e6 "Nominal power"
      SI.Area A = pi*R^2 "Area swept by rotor";
      Real Cp "power coefficient";
      Real lambda "tip speed ratio";
      Real lambdai;
      SI.AngularVelocity w = der(flange.phi);
      SIpu.Power P(start = 1);

      Modelica.Mechanics.Rotational.Interfaces.Flange_b flange(tau(start=-P_nom/10))
      Modelica.Blocks.Interfaces.RealInput v(unit="m/s") "wind speed"
    equation
      0 = P*P_nom + w*flange.tau;
      P*P_nom = 0.5*rho*A*v^3*Cp;
      Cp=c1*(c2*lambdai-c3*beta-c4)*exp(-c5*lambdai)+c6*lambda;
      lambdai = 1/(lambda+0.08*beta) - 0.035/(beta^3 + 1);
      lambda = w*R/v;
    end Rotor;

    model WindTurbine
      inner outer System system;

      Modelica.Blocks.Interfaces.RealInput windSpeed
    PowerSystems.AC3ph.Machines.Asynchron_dfig generator(redeclare record Data =
          Data.Machines.Asynchron400V_30kVA (
          V_nom=690,
          S_nom=3e6,
          pp=4))
      PowerSystems.Common.Thermal.BdCondV bdCond(m=2)
      PowerSystems.AC3ph.Nodes.BusBar busbar
      PowerSystems.AC3ph.Sensors.Psensor sensor
      Rotor rotor(R=40)
      PowerSystems.Mechanics.Rotational.Rotor inertia(J=300, w_start=314/generator.par.pp)
      Modelica.Mechanics.Rotational.Components.IdealGear gear(ratio=generator.par.pp
          /200)
      PowerSystems.AC3ph.Inverters.InverterAverage inverter1
      PowerSystems.Common.Thermal.BdCondV bdCond1(m=1)
      PowerSystems.AC1ph_DC.Sensors.PVImeter meterDC(av=true, tcst=0.1)
      PowerSystems.AC3ph.Inverters.InverterAverage inverter2
      PowerSystems.AC3ph.Inverters.Select select2
      PowerSystems.Common.Thermal.BdCondV bdCond2(m=1)
      PowerSystems.AC3ph.Transformers.TrafoIdeal trafo(redeclare record Data =
          PowerSystems.AC3ph.Transformers.Parameters.TrafoIdeal(V_nom={690,15e3}, S_nom=3e6))
      PowerSystems.AC3ph.Ports.ACdq0_p term
      Modelica.Blocks.Sources.RealExpression vPhasor_set[2](y={0.5 - min(
          windSpeed, 15)/20,0.25*windSpeed/15})
    equation
      connect(generator.heat,bdCond.heat)
      connect(busbar.term,sensor.term_p)
      connect(generator.term,busbar.term)
      connect(rotor.flange,gear.flange_a)
      connect(gear.flange_b,inertia.flange_a)
      connect(inertia.flange_b,generator.airgap)
      connect(inverter1.heat,bdCond1.heat)
      connect(inverter1.AC,generator.term_r)
      connect(generator.phiRotor,inverter1.theta)
      connect(bdCond2.heat,inverter2.heat)
      connect(select2.vPhasor_out,inverter2.vPhasor)
      connect(select2.theta_out,inverter2.theta)
      connect(inverter2.AC,busbar.term)
      connect(inverter1.DC,meterDC.term_p)
      connect(meterDC.term_n,inverter2.DC)
      connect(sensor.term_n,trafo.term_p)
      connect(windSpeed, rotor.v)
      connect(trafo.term_n, term)
      connect(vPhasor_set.y, inverter1.vPhasor)
    end WindTurbine;

  end Components;

  package Test
    extends Modelica.Icons.ExamplesPackage;
    model RotorTest
      extends Modelica.Icons.Example;
      Components.Rotor rotor(R=17)
      Modelica.Blocks.Sources.Ramp ramp(
        duration=80,
        startTime=10,
        height=15,
        offset=10)
      Modelica.Mechanics.Rotational.Sources.ConstantSpeed constantSpeed(w_fixed(
            displayUnit="rpm") = 6.2831853071796, phi(start=0, fixed=true))
    equation
      connect(ramp.y, rotor.v)
      connect(rotor.flange, constantSpeed.flange)
    end RotorTest;

  end Test;
end Wind;


Mechanical components

within PowerSystems;
package Mechanics "Mechanical components"
  extends Modelica.Icons.Package;
end Mechanics;


Rotating parts

within PowerSystems.Mechanics;
package Rotational "Rotating parts "
  extends Modelica.Icons.VariantsPackage;

  model Speed "Rotation with given angular velocity"
    extends Ports.Flange_b;

    parameter SI.Time tcst(min=1e-9)=0.1 "time-constant";

    parameter Boolean use_w_in = false
      "= true if speed defined by input w_in, otherwise by parameter w0"

    parameter SI.AngularVelocity w0=1 "angular velocity"
    Modelica.Blocks.Interfaces.RealInput w_in(final unit="rad/s") if use_w_in
      "(signal ang-velocity)"
  protected
    SI.AngularVelocity phi_dot;
    Modelica.Blocks.Interfaces.RealInput w_internal
      "Needed to connect to conditional connector";

  equation
    connect(w_in, w_internal);
    if not use_w_in then
       w_internal = w0;
    end if;

    der(flange.phi) = phi_dot;
    der(phi_dot) = (w_internal - phi_dot)/tcst;
  end Speed;

  model Torque "Driving torque"
    extends Ports.Flange_b;

    parameter Boolean use_tau_in = false
      "= true if torque defined by input tau_in, otherwise by parameter tau0"

     parameter SI.Torque tau0=1 "torque"
    Modelica.Blocks.Interfaces.RealInput tau_in(final unit="N.m") if use_tau_in
      "(signal torque)"
  protected
    Modelica.Blocks.Interfaces.RealInput tau_internal
      "Needed to connect to conditional connector";

  equation
    connect(tau_in, tau_internal);
    if not use_tau_in then
       tau_internal = tau0;
    end if;

    flange.tau = -tau_internal;
  end Torque;

model TabTimeTorque "Torque using table (time... torque)"
  extends Partials.TabTorque;

  parameter SI.Time t_unit=1 "unit of 'time' in tab";
  parameter SI.Torque tau_unit=1 "unit of 'torque' in tab";
  parameter Real[2] t_bd(unit="s")={0,1} "{first, last} time in tab";
  parameter Integer drive_load=1 "driving or load"
  parameter Integer direction(min=-1,max=1)=1 "forward or backward in time"
  parameter Boolean scale=false "scale time and torque";
  parameter SI.Time T=1 "scale duration to T"
  parameter SI.Percent tau_scale = 1 "scale tab torque to tau_scale"
  protected
  SI.Time t;
  final parameter SI.Time t_factor=if scale then T/abs(t_bd[2]-t_bd[1]) else t_unit;
  final parameter SI.Torque tau_factor=if scale then drive_load*tau_scale*tau_unit else drive_load*tau_unit;

equation
  if direction == 1 then
    t = t_factor*t_bd[1] + time;
  elseif direction == -1 then
    t = t_factor*t_bd[2] - time;
  else
    t = 0;
  end if;
  table.u = t/t_factor;
  tau = tau_factor*table.y[1];

  when t > t_factor*t_bd[2] or t < t_factor*t_bd[1] then
    terminate("BOUNDARY TIME REACHED!");
  end when;
end TabTimeTorque;

model TabPosSlopeTorque "Torque using table (position... slope)"
  extends Partials.TabTorque;

  constant SI.Force g_n=Modelica.Constants.g_n;
  parameter SI.Distance s_unit=1 "unit of 'position' in tab";
  parameter Real[2] s_bd(each unit="m")={0,1} "{first, last} position in tab";
  parameter Integer dirTrack(min=-1,max=1)=+1 "forward or backward track"
  parameter Integer dirVehicle(min=-1,max=1)=+1
      "vehicle forward or backward driving"
  parameter Boolean scale=false "scale position and slope";
  parameter SI.Distance D=1 "scale distance to D"
  parameter SI.Percent slope_scale=1 "scale slope to slope_scale"
  parameter SI.Mass mass=1 "mass";
  parameter Real[2] cFrict(each min=0)={0,0}
      "friction cst {lin, quadr} (translation) in {[N.s/m], [N.s2/m2]}";
  parameter SI.Radius r=1 "radius wheel";
  parameter Real gRatio=1 "gear-ratio";
  SI.Distance s;
  SI.Velocity vVehicle(start=0) "vehicle horizontal velocity";
  protected
  final parameter Real s_factor=if scale then D/abs(s_bd[2]-s_bd[1]) else s_unit;
  final parameter Real slope_factor=if scale then slope_scale else 1;
  final parameter Integer sig=dirTrack*dirVehicle;
  Real slope;
  Real sin_gam;
  SI.Angle phi;
  SI.Force f;
  constant Real cFrictUnit1(unit="N.s/m") = 1
  constant Real cFrictUnit2(unit="N.s2/m2") = 1

initial equation
  s = if dirTrack == 1 then s_factor*s_bd[1] else s_factor*s_bd[2];

equation
  phi =flange_a.phi;
  gRatio*vVehicle = r*der(phi);
  r*f = gRatio*tau;
  table.u = s/s_factor;
  slope = slope_factor*table.y[1];
  sin_gam = slope/sqrt(1 + slope*slope); // = sin(atan(slope))
  der(s) = sig*vVehicle;
  mass*der(vVehicle) = -(f + sig*mass*g_n*sin_gam +
         (cFrict[1]*cFrictUnit1 + cFrict[2]*cFrictUnit2*abs(vVehicle))*vVehicle);

  when s > s_factor*s_bd[2] or s < s_factor*s_bd[1] then
    terminate("BOUNDARY POSITION REACHED!");
  end when;
end TabPosSlopeTorque;

  model FrictionTorque "Friction torque"
    extends Ports.Flange_a;

     parameter Real[2] cFrict(each min=0)={0,0}
      "friction cst {lin, quadr} in {[N.s/m], [N.s2/m2]}";
    SI.Angle phi;
    SI.AngularVelocity w;

  protected
    constant Real cFrictUnit1(unit="N.s/m") = 1
    constant Real cFrictUnit2(unit="N.s2/m2") = 1
  equation
    phi = flange.phi;
    w = der(phi);
    flange.tau = (cFrict[1]*cFrictUnit1 + cFrict[2]*cFrictUnit2*noEvent(abs(w)))*w;
  end FrictionTorque;

model FixedAngle "Flange at fixed angular position"
  parameter SI.Angle phi0=0 "angle";

   Interfaces.Rotation_p flange

equation
  flange.phi = phi0;
end FixedAngle;

model Rotor "Rigid rotating mass"
  extends Partials.RigidRotorBase;

equation
  J*a =flange_a.tau  +flange_b.tau;
end Rotor;

  model ThermalTurbineRotor "Thermal turbine rotor"
    extends Partials.RigidRotorCase;

  end ThermalTurbineRotor;

  model HydroTurbineRotor "Hydro turbine rotor"
    extends Partials.RigidRotorCase;
  end HydroTurbineRotor;

  model DieselRotor "Diesel rotor"
    extends Partials.RigidRotorCase;
  end DieselRotor;

  model WindTurbineRotor "Wind turbine rotor"
    extends Partials.RigidRotorCase;
  end WindTurbineRotor;

  model ElectricRotor "Electric generator/motor rotor, mechanical"
    extends Partials.RigidRotorCase;
  end ElectricRotor;

model ShaftNoMass "Elastic massless shaft"
  extends Ports.Compliant;

  parameter SI.TorsionStiffness stiff=1e6 "torsion stiffness";

equation
    flange_a.tau
               +flange_b.tau  = 0;
  d_tau = stiff*d_phi;
end ShaftNoMass;

model Shaft "Elastic massive shaft"
  extends Ports.Compliant;

  parameter SI.Inertia J=1 "inertia";
  parameter SI.TorsionStiffness stiff=1e6 "torsion stiffness";
  SI.Angle phi(stateSelect=StateSelect.prefer) "rotation angle center";
  SI.AngularVelocity w(stateSelect=StateSelect.prefer);
  SI.AngularAcceleration a;

equation
    flange_a.phi
               +flange_b.phi  = 2*phi;
  w = der(phi);
  a = der(w);
  J*a =flange_a.tau  +flange_b.tau;
  d_tau = stiff*d_phi;
end Shaft;

model GearNoMass "Massless gear"
  extends Ports.Flange_a_b;

  parameter Real[:] ratio={1,1}
      "gear-ratio {p, .., n}, (speeds in arbitrary units)";
  protected
  final parameter Real ratio_pn=ratio[1]/ratio[end];

equation
    flange_a.phi
               = ratio_pn*flange_b.phi;
  ratio_pn*flange_a.tau +flange_b.tau  = 0;
end GearNoMass;

model Gear "Massive gear"
  extends Ports.Flange_a_b;

  parameter Real[:] ratio={1,1}
      "gear-ratio {p, .., n}, (speeds in arbitrary units)";
  parameter SI.Inertia[:] J={1,1} "inertias {p, .., n}, (not reduced)";
  SI.Angle phi(stateSelect=StateSelect.prefer);
  SI.AngularVelocity w(stateSelect=StateSelect.prefer);
  SI.AngularAcceleration a;
  protected
  final parameter Real ratio_pn=ratio[1]/ratio[end];
  final parameter Real[size(ratio,1)] ratio2=diagonal(ratio)*ratio/(ratio[end]*ratio[end]);

equation
    flange_a.phi
               = ratio_pn*flange_b.phi;
  phi =flange_b.phi;
  w = der(phi);
  a = der(w);
  (ratio2*J)*a = ratio_pn*flange_a.tau +flange_b.tau;
end Gear;

model NoGear "Placeholder for gear"
  extends Ports.Flange_a_b;

equation
    flange_a.phi = flange_b.phi;
    flange_a.tau + flange_b.tau  = 0;
end NoGear;

model AngleSensor "Angle and angular velocity sensor (mechanical)"
  extends Ports.Flange_a;

  Modelica.Blocks.Interfaces.RealOutput phi "angle"
  Modelica.Blocks.Interfaces.RealOutput w "angular velocity"

equation
  flange.tau = 0;
  phi = flange.phi;
  w = der(flange.phi);
end AngleSensor;

model PowerSensor "Power and torque sensor (mechanical)"
  extends Ports.Rigid;

  Modelica.Blocks.Interfaces.RealOutput p "power, flange_a to flange_b"
  Modelica.Blocks.Interfaces.RealOutput tau "torque, flange_a to flange_b"

equation
  flange_a.tau + flange_b.tau = 0;
  tau = flange_a.tau;
  p = der(flange_a.phi)*flange_a.tau;
end PowerSensor;

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

    partial model TabTorque "Table data to torque"
      extends Ports.Flange_a_b;

      parameter String tableName="" "table name in file";
      parameter String fileName=TableDir + "" "name of file containing table";
      parameter Integer colData=2 "column # used data";
      SI.Torque tau;

    Modelica.Blocks.Tables.CombiTable1Ds table(
      final tableName=tableName,
      final fileName=fileName,
      final columns={colData},
      tableOnFile=true) "{time t .. force f ..}"

    equation
      flange_a.phi =flange_b.phi;
      flange_a.tau +flange_b.tau  + tau = 0;
    end TabTorque;

    partial model RigidRotorBase "Rigid rotor base"
      extends Ports.Rigid;

      parameter Types.Dynamics dynType=system.dynType "transient or steady-state model"
      parameter SI.Inertia J=1 "inertia";
      parameter SI.AngularVelocity w_start = 0
        "start value of angular velocity"
      SI.Angle phi "rotation angle absolute";
      SI.AngularVelocity w(start = w_start);
      SI.AngularAcceleration a;

    protected
      outer System system;

    initial equation
      if dynType == Types.Dynamics.SteadyInitial then
        der(w) = 0;
      else
        w = w_start;
      end if;

    equation
      phi =flange_a.phi;
      w = der(phi);
      a = der(w);
    end RigidRotorBase;

    partial model RigidRotorCase "Rigid rotor with case"
      extends RigidRotorBase;

      Interfaces.Rotation_p rotor
        "connector to turbine (mech) or airgap (el) torque"
      Interfaces.Rotation_p stator "access for stator reaction moment"
      Interfaces.Rotation_n friction "access for friction model"

    equation
      if cardinality(stator) == 0 then
        stator.phi = 0;
      else
        rotor.tau + stator.tau + friction.tau = 0;
      end if;
      rotor.phi = phi - stator.phi;
      friction.phi = rotor.phi;
      J*a = rotor.tau +flange_a.tau  +flange_b.tau  + friction.tau;
    end RigidRotorCase;

  end Partials;

  package Ports "One- and two-flange base for rotating mechanical components."
  extends Modelica.Icons.InterfacesPackage;

  partial model Flange_a "One flange, side a"

    Interfaces.Rotation_p flange "positive flange"
  end Flange_a;

  partial model Flange_b "One flange, side b"

    Interfaces.Rotation_n flange "negative flange"
  end Flange_b;

  partial model Flange_a_b "Two flange"

    Interfaces.Rotation_p flange_a "flange side a"
    Interfaces.Rotation_n flange_b "flange side b"
  end Flange_a_b;

  partial model Rigid "Rigid two-flange"
    extends Flange_a_b;

  equation
      flange_a.phi
                 =flange_b.phi;
  end Rigid;

  partial model Compliant "Compliant two-flange"
    extends Flange_a_b;

    SI.Angle d_phi "difference angle (twist)";
    SI.Torque d_tau "twisting torque";

  equation
      flange_b.phi
                 -flange_a.phi  = d_phi;
      flange_b.tau
                 -flange_a.tau  = 2*d_tau;
  end Compliant;
  end Ports;
end Rotational;


Turbines including generator-rotor

within PowerSystems.Mechanics;
package TurboGroups "Turbines including generator-rotor"
  extends Modelica.Icons.VariantsPackage;

  model FixedSpeedTG "Fixed speed turbo-generator rotor"

    parameter Types.Dynamics dynType=system.dynType "transient or steady-state model"
    parameter SI.AngularVelocity w_start=0 "initial rotor angular velocity"
    parameter SI.AngularVelocity w_nom=1 "nominal angular velocity"
    Interfaces.Rotation_n airgap "to airgap electric machine"
    Modelica.Blocks.Interfaces.RealInput power(
                     final unit="1") "turbine power pu"
    Modelica.Blocks.Interfaces.RealOutput speed(
                               final unit="1") "turbine speed pu"
  protected
    outer System system;
    SI.Angle phi(stateSelect=StateSelect.prefer);
    SI.AngularVelocity w(start=w_start, stateSelect=StateSelect.prefer);

  initial equation
    if dynType <> Types.Dynamics.SteadyInitial then
      w = w_start;
    end if;

  equation
    phi = airgap.phi;
    w = der(phi);
    0 = der(w);
    speed = w/w_nom;
  end FixedSpeedTG;

  model SingleMassTG "Single mass turbo-generator rotor"

    parameter Types.Dynamics dynType=system.dynType "transient or steady-state model"
    parameter SIpu.AngularVelocity speed_thr(unit="1")=0.5
      "threshold: torque ctrl \\ power ctrl";
    parameter SI.Time H=1 "inertia constant turbine + generator";
    parameter SI.AngularVelocity w_start=0 "initial rotor angular velocity"
    parameter SI.AngularVelocity w_nom=1 "nominal angular velocity"
    parameter SI.Power P_nom=1 "nominal power turbine"
    Interfaces.Rotation_n airgap "to airgap electric machine"
    Modelica.Blocks.Interfaces.RealInput power(
                     final unit="1") "turbine power pu"
    Modelica.Blocks.Interfaces.RealOutput speed(
                               final unit="1") "turbine speed pu"
  protected
    outer System system;
    final parameter SI.Inertia J=2*H*P_nom/(w_nom*w_nom)
      "inertia turbine + generator";
    final parameter SI.Torque tau_nom=P_nom/w_nom;
    SI.Angle phi(stateSelect=StateSelect.prefer);
    SI.AngularVelocity w(start=w_start, stateSelect=StateSelect.prefer);
    SI.AngularAcceleration a(start=0);
    Real tau_pu(unit="1");

  initial equation
    if dynType == Types.Dynamics.SteadyInitial then
      der(w) = 0;
    else
      w = w_start;
    end if;

  equation
    max(speed_thr, speed)*tau_pu = power;
    phi = airgap.phi;
    w = der(phi);
    a = der(w);
    J*a = tau_pu*tau_nom + airgap.tau;
    speed = w/w_nom;
  end SingleMassTG;

  model SteamTurboGroup "Steam turbo-group with generator-rotor"
    extends Partials.TurboBase1(final n=size(par.P_nom,1));

    replaceable record Data =
      PowerSystems.Mechanics.TurboGroups.Parameters.SteamTurboGroup
      "turbo-group par"
    final parameter Data par "turbo-group par"
    Rotational.ElectricRotor genRotor(
      J=par.J_gen,
      w(start=w_start),
      a(start=0))
    SI.Angle[n] delta "difference angles";
  protected
    Rotational.Rotor aux1(J=par.J_aux[1])
    Rotational.ShaftNoMass shaft1(stiff=par.stiff[1])
    Rotational.ThermalTurbineRotor turbine1(J=par.J_turb[1])
    Rotational.ShaftNoMass shaft2(stiff=par.stiff[2])
    Rotational.ThermalTurbineRotor turbine2(J=par.J_turb[2])
    Rotational.ShaftNoMass shaft3(stiff=par.stiff[3])
    Rotational.ThermalTurbineRotor turbine3(J=par.J_turb[3])
    Rotational.ShaftNoMass shaft4(stiff=par.stiff[4])
    Rotational.ThermalTurbineRotor turbine4(J=par.J_turb[4])
    Rotational.ShaftNoMass shaft5(stiff=par.stiff[5])
    Rotational.ShaftNoMass shaft6(stiff=par.stiff[6])
    Rotational.Rotor aux2(J=par.J_aux[2])

  initial equation
    aux1.w = turbine1.w;
    aux1.a = turbine1.a;
    turbine1.w = turbine2.w;
    turbine1.a = turbine2.a;
    turbine2.w = turbine3.w;
    turbine2.a = turbine3.a;
    turbine3.w = turbine4.w;
    turbine3.a = turbine4.a;
    turbine4.w = genRotor.w;
    turbine4.a = genRotor.a;
    genRotor.w = aux2.w;
    genRotor.a = aux2.a;

  equation
    delta = {turbine2.flange_a.phi-turbine1.flange_b.phi,turbine3.flange_a.phi -turbine2.flange_b.phi,
      turbine4.flange_a.phi-turbine3.flange_b.phi,genRotor.flange_a.phi -turbine4.flange_b.phi};

    connect(aux1.flange_b,shaft1.flange_a)
    connect(shaft1.flange_b,turbine1.flange_a)
    connect(turbine1.flange_b,shaft2.flange_a)
    connect(shaft2.flange_b,turbine2.flange_a)
    connect(turbine2.flange_b,shaft3.flange_a)
    connect(shaft3.flange_b,turbine3.flange_a)
    connect(turbine3.flange_b,shaft4.flange_a)
    connect(shaft4.flange_b,turbine4.flange_a)
    connect(turbine4.flange_b,shaft5.flange_a)
    connect(shaft5.flange_b,genRotor.flange_a)
    connect(genRotor.flange_b,shaft6.flange_a)
    connect(shaft6.flange_b,aux2.flange_a)
    connect(blades[1], turbine1.rotor)
    connect(blades[2], turbine2.rotor)
    connect(blades[3], turbine3.rotor)
    connect(blades[4], turbine4.rotor)
    connect(airgap, genRotor.rotor)
  end SteamTurboGroup;

  model GasTurbineGear "Gas turbine with gear and generator-rotor"
    extends Partials.TurboBase1(final n=size(par.P_nom,1));

    replaceable record Data =
      PowerSystems.Mechanics.TurboGroups.Parameters.GasTurbineGear
      "turbo-group par"
    final parameter Data par "turbo-group par"
    Rotational.ElectricRotor genRotor(
      J=par.J_gen,
      w(start=w_start*par.ratio[end]/par.ratio[1]),
      a(start=0))
  protected
    Rotational.ThermalTurbineRotor turbine(J=par.J_turb)
    Rotational.ShaftNoMass shaft1(stiff=par.stiff_sh[1])
    Rotational.ThermalTurbineRotor compressor(J=par.J_comp)
    Rotational.ShaftNoMass shaft2(stiff=par.stiff_sh[2])
    Rotational.Gear gear1(ratio=par.ratio[1:2], J=par.J_gear1)
    Rotational.ShaftNoMass shaft3(stiff=par.stiff_sh[3])
    Rotational.Gear gear2(ratio=par.ratio[2:3], J=par.J_gear2)
    Rotational.ShaftNoMass shaft4(stiff=par.stiff_sh[4])
    Rotational.Rotor accessory(J=par.J_acc)
    Rotational.ShaftNoMass shaft5(stiff=par.stiff_sh[5])
    Rotational.Shaft coupling(J=par.J_cpl, stiff=par.stiff_cpl)
    Rotational.ShaftNoMass shaft6(stiff=par.stiff_sh[6])

  initial equation
    turbine.w = compressor.w;
    turbine.a = compressor.a;
    compressor.w = (par.ratio[1]/par.ratio[2])*gear1.w;
    compressor.a = (par.ratio[1]/par.ratio[2])*gear1.a;
    gear1.w = (par.ratio[2]/par.ratio[3])*gear2.w;
    gear1.a = (par.ratio[2]/par.ratio[3])*gear2.a;
    gear2.w = accessory.w;
    gear2.a = accessory.a;
    accessory.w = coupling.w;
    accessory.a = coupling.a;
    coupling.w = genRotor.w;
    coupling.a = genRotor.a;

  equation
    connect(turbine.flange_b,shaft1.flange_a)
    connect(compressor.flange_b,shaft1.flange_b)
    connect(compressor.flange_a,shaft2.flange_a)
    connect(shaft2.flange_b,gear1.flange_a)
    connect(gear1.flange_b,shaft3.flange_a)
    connect(shaft3.flange_b,gear2.flange_a)
    connect(gear2.flange_b,shaft4.flange_a)
    connect(shaft4.flange_b,accessory.flange_a)
    connect(accessory.flange_b,shaft5.flange_a)
    connect(shaft5.flange_b,coupling.flange_a)
    connect(coupling.flange_b,shaft6.flange_a)
    connect(shaft6.flange_b,genRotor.flange_a)
    connect(blades[1], turbine.rotor)
    connect(blades[2], compressor.rotor)
    connect(airgap, genRotor.rotor)
  end GasTurbineGear;

  model HydroTurbine "Hydro turbine with generator-rotor"
    extends Partials.TurboBase2(final n=1);

    replaceable record Data =
      PowerSystems.Mechanics.TurboGroups.Parameters.HydroTurbine
      "hydro-turbine par"
    final parameter Data par "hydro-turbine par"
    Rotational.ElectricRotor genRotor(
      J=par.J_gen,
      w(start=w_start),
      a(start=0))
  protected
    Rotational.HydroTurbineRotor turbine(J=par.J_turb)
    Rotational.Shaft shaft(J=par.J_shaft, stiff=par.stiff)

  initial equation
    turbine.w = shaft.w;
    der(turbine.w) = der(shaft.w);
    shaft.w = genRotor.w;
    der(shaft.w) = der(genRotor.w);

  equation
    connect(turbine.flange_b,shaft.flange_a)
    connect(shaft.flange_b,genRotor.flange_a)
    connect(blades[1], turbine.rotor)
    connect(airgap, genRotor.rotor)
  end HydroTurbine;

  model Diesel "Diesel with generator-rotor"
    extends Partials.TurboBase3(final n=1);                                                                                // annotation 0;

    replaceable record Data =
      PowerSystems.Mechanics.TurboGroups.Parameters.Diesel "Diesel par"
    final parameter Data par "Diesel par"
    Rotational.ElectricRotor genRotor(
      J=par.J_gen,
      w(start=w_start),
      a(start=0))
  protected
    Rotational.DieselRotor diesel(J=par.J_turb)
    Rotational.ShaftNoMass shaft(stiff=par.stiff)

  initial equation
    diesel.w = genRotor.w;
    der(diesel.w) = der(genRotor.w);

  equation
    connect(diesel.flange_b,shaft.flange_a)
    connect(shaft.flange_b,genRotor.flange_a)
    connect(blades[1], diesel.rotor)
    connect(airgap, genRotor.rotor)
  end Diesel;

  model WindTurbineGear "Wind turbine with gear and generator-rotor"
    extends Partials.TurboBase4(final n=1);

    replaceable record Data =
      PowerSystems.Mechanics.TurboGroups.Parameters.WindTurbineGear
      "turbine par"
    final parameter Data par "turbine par"
    Rotational.ElectricRotor genRotor(
      J=par.J_gen,
      w(start=w_start*par.ratio[end]/par.ratio[1]),
      a(start=0))
  protected
    final parameter Real[3] gr2=diagonal(par.ratio)*par.ratio/par.ratio[end]^2;
    final parameter SI.Inertia J_red=par.J_turb*gr2[1] + par.J_gear*gr2 + par.J_gen
      "gear reduced inertia";
    Rotational.WindTurbineRotor turbine(J=par.J_turb)
    Rotational.ShaftNoMass shaft1(stiff=par.stiff_sh[1])
    Rotational.Gear gear(J=par.J_gear, ratio=par.ratio)
    Rotational.ShaftNoMass shaft2(stiff=par.stiff_sh[2])

  initial equation
    turbine.w = (par.ratio[1]/par.ratio[end])*gear.w;
    der(turbine.w) = (par.ratio[1]/par.ratio[end])*der(gear.w);
    gear.w = genRotor.w;
    der(gear.w) = der(genRotor.w);

  equation
    connect(turbine.flange_b,shaft1.flange_a)
    connect(shaft1.flange_b,gear.flange_a)
    connect(gear.flange_b,shaft2.flange_a)
    connect(airgap, genRotor.rotor)
    connect(blades[1], turbine.rotor)
    connect(shaft2.flange_b,genRotor.flange_a)
  end WindTurbineGear;

  model PcontrolTorque "Turbine torque from power control"

    parameter SI.AngularVelocity w_nom = 314.159265358979323846
      "nom r.p.m. turbine"
    parameter SI.Power[:] P_nom={1} "nom power turbines"

    parameter SIpu.AngularVelocity speed_thr(unit="1")=0.5
      "threshold torque ctrl \\ power ctrl";
    SI.Angle phi;
    SIpu.Torque tau_pu(unit="1");
    Modelica.Blocks.Interfaces.RealInput power(
                    final unit="1") "power pu"
    Modelica.Blocks.Interfaces.RealOutput speed(
                                 final unit="1") "angular velocity pu"
    Interfaces.Rotation_n[     n] blades "to turbine model"
  protected
    final parameter Integer n=size(P_nom,1) "number of turbines"
    final parameter SI.Torque[n] tau_nom=P_nom/w_nom "nom torque"

  equation
    max(speed_thr, speed)*tau_pu = power;
    phi=blades[end].phi;
    for k in 1:n loop
      blades[k].tau = -tau_pu*tau_nom[k];
    end for;
    speed = der(phi)/w_nom;
  end PcontrolTorque;

  model WindTabTorque "Turbine torque, table {speed, torque pu}"

    parameter SI.AngularVelocity w_nom = 314.159265358979323846
      "nom r.p.m. turbine"
    parameter SI.Power P_nom=1 "nom power turbine"

    parameter String tableName="torque" "table name in file";
    parameter String fileName=TableDir+"WindTorque.tab"
      "name of file containing table";

    Modelica.Blocks.Tables.CombiTable1Ds table(table=[0,0,1; 0,1,1],
      final tableName=tableName,
      final fileName=fileName,
      columns={2},
      final tableOnFile=true) "{wind speed m/s, torque pu}"
    Interfaces.Rotation_n blades "to turbine model"
    Modelica.Blocks.Interfaces.RealInput windSpeed "wind speed"
  protected
    final parameter SI.Torque tau_nom=P_nom/w_nom "nom torque"

  equation
    blades.tau = -table.y[1]*tau_nom;

    connect(windSpeed, table.u)
  end WindTabTorque;

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

record SteamTurboGroup "Steam turbo-group parameters"
  extends Modelica.Icons.Record;

  parameter SI.AngularVelocity w_nom = 314.159265358979323846
        "nom r.p.m. turbines"
  parameter SI.Power[:] P_nom={500e6,250e6,250e6,250e6} "nom power turbines"
  parameter SI.Inertia[size(P_nom,1)] J_turb={20000,200000,200000,200000}
        "inertia turbines";
  parameter SI.Inertia J_gen=70000 "inertia generator";
  parameter SI.Inertia[:] J_aux={500,1000} "inertia auxiliaries";
  parameter SI.Stiffness[size(J_turb,1)+size(J_aux,1)] stiff={250,350,750,750,750,250}*1e6
        "stiffness shafts";
end SteamTurboGroup;

record GasTurbineGear "Turbo-group parameters"
  extends Modelica.Icons.Record;

  parameter SI.AngularVelocity w_nom = 1576.7653528367 "nom r.p.m. turbine"
  parameter SI.Power[:] P_nom={12, -2}*1e6 "nom power {turbine, compressor}"
  parameter SI.Inertia J_turb=40 "inertia turbine";
  parameter SI.Inertia J_comp=50 "inertia compressor";
  parameter SI.Inertia[2] J_gear1={0.6,12} "inertias gear1";
  parameter SI.Inertia[2] J_gear2={5,200} "inertias gear2";
  parameter SI.Inertia J_acc=6 "inertia accessory";
  parameter SI.Inertia J_cpl=40 "inertia coupling";
  parameter SI.Inertia J_gen=2500 "inertia generator";
  parameter Real[3] ratio={15057,5067,1500} "gear ratio";
  parameter SI.Stiffness[6] stiff_sh={3,5.5,100,2500,250,200}*1e6
        "stiffness shafts";
  parameter SI.TorsionStiffness stiff_cpl=130*1e6 "stiffness coupling";
end GasTurbineGear;

record HydroTurbine "Turbo-group parameters"
  extends Modelica.Icons.Record;

  parameter SI.AngularVelocity w_nom = 314.159265358979323846
        "nom r.p.m. turbine"
  parameter SI.Power P_nom=20e6 "nom power turbine"
  parameter SI.Inertia J_turb=1000 "inertia turbines";
  parameter SI.Inertia J_shaft=5 "inertia shaft";
  parameter SI.Inertia J_gen=500 "inertia generator";
  parameter SI.TorsionStiffness stiff=300e6 "stiffness shaft";
end HydroTurbine;

record Diesel "Turbo-group parameters"
  extends Modelica.Icons.Record;

  parameter SI.AngularVelocity w_nom = 157.07963267949 "nom r.p.m. Diesel"
  parameter SI.Power P_nom=100e3 "nom power diesel"
  parameter SI.Inertia J_turb=20 "inertia diesel";
  parameter SI.Inertia J_gen=20 "inertia generator";
  parameter SI.TorsionStiffness stiff=1e6 "stiffness shaft";
end Diesel;

record WindTurbineGear "Turbo-group parameters"
  extends Modelica.Icons.Record;

  parameter SI.AngularVelocity w_nom=1.0471975511966 "nom r.p.m. turbine"
  parameter SI.Power P_nom=1e6 "nom power turbine"
  parameter SI.Inertia J_turb=30 "inertia turbine";
  parameter SI.Inertia[3] J_gear={30,2,0.1} "inertias gear";
  parameter SI.Inertia J_gen=450 "inertia generator";
  parameter Real ratio[3]={10,100,1000} "gear ratio";
  parameter SI.TorsionStiffness[2] stiff_sh={16,1}*1e6 "stiffness shafts";
end WindTurbineGear;
end Parameters;

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

    partial model TurboBase "Turbine-generator rotor base "

      parameter SI.AngularVelocity w_start=0 "initial rotor angular velocity";
      parameter Integer n=1 "number of turbines";
      Interfaces.Rotation_p[     n] blades "to turbine torque model"
      Interfaces.Rotation_n airgap "to airgap electric machine"
    protected
      outer System system;
    end TurboBase;

    partial model TurboBase1 "Turbine-generator rotor base "
      extends Partials.TurboBase;
    end TurboBase1;

    partial model TurboBase2 "Turbine-generator rotor base "
      extends Partials.TurboBase;
    end TurboBase2;

    partial model TurboBase3 "Turbine-generator rotor base "
      extends Partials.TurboBase;
    end TurboBase3;

    partial model TurboBase4 "Turbine-generator rotor base "
      extends Partials.TurboBase;
    end TurboBase4;

  end Partials;
end TurboGroups;


Custom models

within PowerSystems.Semiconductors;
package Custom "Custom models"
  extends Modelica.Icons.VariantsPackage;

record SCparameter "Custom semiconductor parameters"
  extends Common.Nominal.NominalDataVI;
end SCparameter;

model Diode "Diode"
  extends Partials.ComponentBase;

  parameter SCparameter par "parameters"

  protected
  constant Real unitAmperePerVolt(unit="A/V") = 1

equation
  i = v*unitAmperePerVolt; // replace!
end Diode;

model SCswitch "IGBT"
  extends Partials.ComponentBase;

  parameter SCparameter par "parameters"
  Modelica.Blocks.Interfaces.BooleanInput gate "true:on, false: off"

  protected
  constant Real unitAmperePerVolt(unit="A/V") = 1
equation
  i = v*unitAmperePerVolt; // replace!
end SCswitch;

model Thyristor "Thyristor"
  extends Partials.ComponentBase;

  parameter SCparameter par "parameters"
  Modelica.Blocks.Interfaces.BooleanInput gate "true:on, false: off"

  protected
  constant Real unitAmperePerVolt(unit="A/V") = 1
equation
  i = v*unitAmperePerVolt; // replace!
end Thyristor;
end Custom;


Custom models

within PowerSystems.Semiconductors;
package Ideal "Custom models"
  extends Modelica.Icons.VariantsPackage;

record SCparameter "Ideal semiconductor parameters"
  extends Common.Nominal.NominalDataVI;

  parameter Real[2] eps(final min={0,0}, each final unit="1")={1e-4,1e-4}
      "{resistance 'on', conductance 'off'}";
  parameter SI.Voltage Vf(final min=0)=0 "forward threshold-voltage"
  parameter SI.Heat Hsw_nom=0 "switching loss at V_nom, I_nom (av on off)"
  parameter Real[:] cT_loss=fill(0,0) "{cT1,cT2,...} T-coef thermal losses"
  parameter SI.Temperature T0_loss=300 "reference T for cT_loss expansion"
end SCparameter;

partial model IdealCharacteristic "Ideal diode characteristic"
  extends Partials.ComponentBase;

  parameter Ideal.SCparameter par "ideal with forward Vf"
  protected
  constant Real unitAmperePerVolt(unit="A/V") = 1

  Boolean on(start = false);
  Real s(start = 0.5) "auxiliary variable";
  SI.Voltage V "forward threshold voltage";
  SI.Current i_sc = i*par.V_nom/par.I_nom*unitAmperePerVolt
      "current scaled to voltage";
  function loss = Utilities.Math.taylor
                                    "spec loss function of temperature";

equation
  V = if size(par.cT_loss,1)==0 then par.Vf else par.Vf*loss(T - par.T0_loss, par.cT_loss);
  {v,i_sc} = if on then {par.eps[1]*s + (1 - par.eps[1])*V,s - (1 - par.eps[2])*V} else {s,par.eps[2]*s};
end IdealCharacteristic;

model Diode "Diode"
  extends IdealCharacteristic;

equation
  on = s > V;
end Diode;

model Thyristor "Thyristor"
  extends IdealCharacteristic;
  extends Partials.GateInput;

equation
  on = s > V and (pre(on) or gate);
end Thyristor;

model SCswitch "Semiconductor switch"
  extends IdealCharacteristic;
  extends Partials.GateInput;

equation
  on = s > V and gate;
end SCswitch;

model SCswitch_Diode "Semiconductor switch with reverse Diode"
  extends Partials.ComponentBase;
  extends Partials.GateInput;

  parameter SCparameter par "ideal with forward Vf"

protected
  constant Real unitAmperePerVolt(unit="A/V") = 1

  Real s(start = 0.5) "auxiliary variable";
  SI.Voltage V "forward threshold voltage";
  SI.Current i_sc = i*par.V_nom/par.I_nom*unitAmperePerVolt
      "current scaled to voltage";

  function loss = Utilities.Math.taylor
                                    "spec loss function of temperature";

equation
  V = if size(par.cT_loss,1)>0 then par.Vf*loss(T -par.T0_loss, par.cT_loss) else par.Vf;
  if gate then
    if s > V then
      {v, i_sc} = {par.eps[1]*s + (1 - par.eps[1])*V,s - (1 - par.eps[2])*V};
    elseif s < -V then
      {v, i_sc} = {par.eps[1]*s - (1 - par.eps[1])*V,s + (1 - par.eps[2])*V};
    else
      {v, i_sc} = {s,par.eps[2]*s};
    end if;
  else
    {v, i_sc} = if s < - V then {par.eps[1]*s - (1 - par.eps[1])*V, s + (1 - par.eps[2])*V} else {s,par.eps[2]*s};
  end if;
end SCswitch_Diode;
end Ideal;


Semiconductors

within PowerSystems;
package Semiconductors "Semiconductors"
  extends Modelica.Icons.Package;
end Semiconductors;


Partial models

within PowerSystems.Semiconductors;
package Partials "Partial models"
  extends Modelica.Icons.BasesPackage;

  partial model ComponentBase "Semiconductor component base"

    SI.Voltage v "voltage";
    SI.Current i "current";
    Interfaces.Electric_p term_p "positive terminal"
    Interfaces.Electric_n term_n "negative terminal"
    Interfaces.Thermal_n heat "source dissipated heat power"
  protected
    SI.Temperature T "component temperature";

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

    T = heat.T;
    heat.Q_flow = -v*i;
  end ComponentBase;

  partial model GateInput "Provide gate input for active components"

    Modelica.Blocks.Interfaces.BooleanInput gate "true:on, false: off"
  end GateInput;

  partial model AC1ph_DC_base "AC(scalar)-DC base"
    extends PowerSystems.Icons.Inverter;

    Interfaces.Electric_n AC "AC scalar connection"
    AC1ph_DC.Ports.TwoPin_p DC "DC connection"
    Interfaces.Thermal_n heat

  end AC1ph_DC_base;

end Partials;


Phase modules

within PowerSystems.Semiconductors;
package PhaseModules "Phase modules"
  extends Modelica.Icons.VariantsPackage;

model DiodeModule "Diode module"
  extends Partials.AC1ph_DC_base;

/*replaceable package SCpackage=Semiconductors.Ideal "SC package"*/
  parameter Semiconductors.Ideal/*SCpackage*/.SCparameter par "SC parameters"
  PowerSystems.AC1ph_DC.Nodes.Electric_pn_p_n pn_p_n
  Semiconductors.Ideal/*SCpackage*/.Diode diode1(final par=par) "diode DC_p"
  Semiconductors.Ideal/*SCpackage*/.Diode diode2(final par=par) "diode DC_n"

equation
  connect(AC,diode1. term_p)
  connect(diode1.term_n, pn_p_n.term_p)
  connect(pn_p_n.term_n,diode2. term_p)
  connect(diode2.term_n, AC)
  connect(pn_p_n.term_pn, DC)
  connect(diode1.heat, heat)
  connect(diode2.heat, heat)
end DiodeModule;

model SwitchModule "Switch module"
  extends Partials.AC1ph_DC_base;

/*replaceable package SCpackage=Semiconductors.Ideal "SC package"*/
  replaceable model Switch = PowerSystems.Semiconductors.Ideal/*SCpackage*/.SCswitch_Diode
    constrainedby PowerSystems.Semiconductors.Partials.GateInput
  parameter Semiconductors.Ideal/*SCpackage*/.SCparameter par "SC parameters"
  Modelica.Blocks.Interfaces.BooleanInput[2] gates "gate-pair p and n"
  Blocks.Multiplex.Gate2demux gate2demux(final n=1)
  PowerSystems.AC1ph_DC.Nodes.Electric_pn_p_n pn_p_n
  Switch switch1(final par=par) "switch DC_p"
  Switch switch2(final par=par) "switch DC_n"

equation
  connect(AC, switch1.term_n)
  connect(switch1.term_p, pn_p_n.term_p)
  connect(AC, switch2.term_p)
  connect(switch2.term_n, pn_p_n.term_n)
  connect(gates, gate2demux.gates)
  connect(gate2demux.gates_1[1], switch1.gate)
  connect(gate2demux.gates_2[1], switch2.gate)
  connect(pn_p_n.term_pn, DC)
  connect(switch1.heat, heat)
  connect(switch2.heat, heat)
end SwitchModule;
end PhaseModules;


Parameter f

within PowerSystems;
package Types
  extends Modelica.Icons.TypesPackage;

  type SourceFrequency = enumeration(
    Parameter   "Parameter f",
    Signal   "Signal omega_in",
    System   "System defined") "Options for specification of frequency"

  type SystemFrequency = enumeration(
    Parameter   "Parameter f",
    Signal   "Signal omega_in",
    Average   "Average generators")
    "Options for specification of frequency in system object"

  type ReferenceFrame = enumeration(
    Synchron   "Synchronously rotating",
    Inertial   "Inertial (signals oscillate)")
    "Options for specification of reference frame"

  type Dynamics = enumeration(
    FreeInitial   "Free initial conditions",
    FixedInitial   "Fixed initial conditions",
    SteadyInitial   "Steady-state initial conditions",
    SteadyState   "Steady-state (quasi-stationary)") "Options for specification of simulation"

  type Init = enumeration(
    v_alpha   "v, alpha: voltage and phase angle, 'slack' (steady init)",
    v_p   "v, p: voltage and active power (steady init)",
    v_q   "v, q: voltage and reactive power (steady init)",
    p_q   "p, q: active and reactive power (steady init)",
    phi_w_el   "phi_el, w_el: machine angle and angular velocity electric",
    none   "none: no initial condition") "Initialization type"

  type ReferenceAngle "Reference angle"
    extends SI.Angle;

    function equalityConstraint
      input ReferenceAngle theta1[:];
      input ReferenceAngle theta2[:];
      output Real[0] residue "No constraints";
    algorithm
      for i in 1:size(theta1, 1) loop
        assert(abs(theta1[i] - theta2[i]) < Modelica.Constants.eps, "angles theta1 and theta2 not equal over connection!");
      end for;
    end equalityConstraint;
  end ReferenceAngle;

  type Color = Integer[3] (each min=0, each max=255) "RGB color"

end Types;


within PowerSystems.Types;
package SI "SI types with custom attributes, like display units"
  extends Modelica.Icons.Package;
  import MSI = Modelica.Units.SI;

  type Time = MSI.Time;
  type Frequency = MSI.Frequency;

  type Length = MSI.Length(displayUnit = "km");
  type Distance = MSI.Distance;
  type Radius = MSI.Radius;
  type Area = MSI.Area;
  type Velocity = MSI.Velocity;
  type Angle = MSI.Angle;
  type AngularVelocity = MSI.AngularVelocity(displayUnit = "rpm");
  type AngularAcceleration = MSI.AngularAcceleration;
  type AngularFrequency = MSI.AngularFrequency;

  type Force = MSI.Force;
  type Mass = MSI.Mass;
  type Density = MSI.Density;
  type Inertia = MSI.Inertia;
  type Torque = MSI.Torque;
  type Stiffness = Real (
    final quantity = "Stiffness",
    final unit = "N",
    final min=0);
  type TorsionStiffness = Real (
    final quantity="TorsionStiffness",
    final unit="N.m/rad",
    final min=0);

  type Voltage = MSI.Voltage(displayUnit = "kV");
  type Current = MSI.Current;
  type Resistance = MSI.Resistance;
  type Conductance = MSI.Conductance;
  type Inductance = MSI.Inductance;
  type Capacitance = MSI.Capacitance;
  type Admittance = MSI.Admittance;
  type Reactance = MSI.Reactance;
  type Impedance = MSI.Impedance;
  type Power = MSI.Power(displayUnit = "MW");
  type ActivePower = MSI.ActivePower(displayUnit = "MW");
  type ApparentPower = MSI.ApparentPower(displayUnit = "MVA");
  type ReactivePower = MSI.ReactivePower(displayUnit = "Mvar");
  type ElectricFieldStrength = MSI.ElectricFieldStrength;
  type MagneticFlux = MSI.MagneticFlux;
  type ElectricCharge = MSI.ElectricCharge;

  type Temperature = MSI.Temperature;
  type Heat = MSI.Heat;
  type HeatFlowRate = MSI.HeatFlowRate;
  type HeatCapacity = MSI.HeatCapacity;
  type ThermalConductance = MSI.ThermalConductance;

  type Percent = Real (
    final quantity="Percent",
    final unit="1",
    final displayUnit="1/100");
end SI;


Additional types for power systems

within PowerSystems.Types;
package SIpu "Additional types for power systems"
  extends Modelica.Icons.Package;

  type AngularVelocity = Real(final quantity="AngularVelocity", unit="rad.s/(rad.s)");
  type Voltage = Real (final quantity="ElectricPotential", unit="V/V");
  type Current = Real (final quantity="ElectricCurrent", unit="A/A");
  type Power = Real (final quantity="Power", unit="W/W");
  type ActivePower = Real (final quantity="Power", unit="W/W");
  type ApparentPower = Real (final quantity="ApparentPower", unit="VA/VA");
  type ReactivePower = Real (final quantity="ReactivePower", unit="var/var");
  type Resistance = Real (
    final quantity="Resistance",
    unit="Ohm/(V.V/VA)",
    final min=0);
  type Reactance = Real (final quantity="Reactance", unit="Ohm/Ohm");
  type Impedance = Real (final quantity="Impedance", unit="Ohm/Ohm");
  type Inductance = Real (final quantity="Inductance", unit="H/H");
  type Conductance = Real (
    final quantity="Conductance",
    unit="S/S",
    final min=0);
  type Susceptance = Real (
    final quantity="Susceptance",
    unit="S/S");
  type Admittance = Real (
    final quantity="Admittance",
    unit="S/S",
    min=0);
  type Resistance_km = Real (
    final quantity="Resistance",
    unit="Ohm/(Ohm.km)",
    min=0);
  type Reactance_km = Real (final quantity="Reactance_per_km",
    unit="Ohm/(Ohm.km)",
    min=0);
  type Conductance_km = Real (
    final quantity="Conductance",
    unit="S/(S.km)",
    min=0);
  type Susceptance_km = Real (
    final quantity="Susceptance",
    unit="S/(S.km)",
    min=0);
  type MagneticFlux = Real (final quantity="MagneticFlux", unit="Wb/Wb");

  type Energy = Real (final quantity="Energy", unit="J/J");
  type Torque = Real (final quantity="Torque", unit="N.m/(N.m)");
end SIpu;


within PowerSystems.Utilities;
package Complex "Complex functions (auxiliary sub-package)"
  extends Modelica.Icons.Package;

  type ComplexType = Real[2, 2] "matrix representation of complex number";

  constant ComplexType re = [1,0;0,1] "matrix representation of real unit";
  constant ComplexType im = [0,-1;1,0]
    "matrix representation of imaginary unit";

  function conjC "Conjugate value of complex number"
    extends Modelica.Icons.Function;

    input ComplexType z "complex argument";
    output ComplexType conj_z "conjugate value of z";

  algorithm
    conj_z := transpose(z);
  end conjC;

  function absC "Absolute value of complex number"
    extends Modelica.Icons.Function;

    input ComplexType z "complex argument";
    output Real abs_z "absolute value of z";

  algorithm
    abs_z := sqrt(detC(z));
  end absC;

  function detC "Determinant of complex number matrix"
    extends Modelica.Icons.Function;

    input ComplexType z "complex argument";
    output Real det_z "determinant of z";

  algorithm
    det_z := z[1,1]*z[2,2] - z[1,2]*z[2,1];
  end detC;

  function invC "Inverse of complex number"
    extends Modelica.Icons.Function;

    input ComplexType z "complex argument";
    output ComplexType inv_z "inverse of z";

  algorithm
    inv_z := transpose(z)/detC(z);
  end invC;

  function sumC "Sum of complex numbers"
    extends Modelica.Icons.Function;

    input ComplexType[          :] z "complex vector";
    output ComplexType s "sum of components of z";

  algorithm
    s := z[1, :, :];
    for k in 2:size(z,1) loop
      s := s + z[k,:,:];
    end for;
  end sumC;

  function prodC "Product of complex numbers"
    extends Modelica.Icons.Function;

    input ComplexType[          :] z "complex vector";
    output ComplexType p "product of components of z";

  algorithm
    p := z[1, :, :];
    for k in 2:size(z,1) loop
      p := p*z[k,:,:];
    end for;
  end prodC;

  function expI "Exponential of imaginary number"
    extends Modelica.Icons.Function;

    input Real phi "real argument";
    output ComplexType exp_jphi "exponential of j*phi";
  protected
    Real c;
    Real s;

  algorithm
    c := cos(phi);
    s := sin(phi);
    exp_jphi := [c, -s; s, c];
  end expI;

  function expC "Exponential of complex number"
    extends Modelica.Icons.Function;

    input ComplexType z "complex argument";
    output ComplexType exp_z "exponential of z";

  algorithm
    exp_z := exp(z[1,1])*expI(z[2,1]);
  end expC;

  function powerC "Power of complex number"
    extends Modelica.Icons.Function;

    input ComplexType z "complex argument";
    input Real alpha "exponent";
    output ComplexType pow_z "power of z";
  protected
    function atan2=Modelica.Math.atan2;

  algorithm
    pow_z := detC(z)^(0.5*alpha)*expI(alpha*atan2(z[2,1], z[1,1]));
  end powerC;

  function sqrtC "Square-root of complex number"
    extends Modelica.Icons.Function;

    input ComplexType z "complex argument";
    output ComplexType sqrt_z "square-root of z";
  protected
    function atan2=Modelica.Math.atan2;

  algorithm
    sqrt_z := sqrt(absC(z))*expI(0.5*atan2(z[2,1], z[1,1]));
  end sqrtC;

  function logC "Logarithm of complex number"
    extends Modelica.Icons.Function;

    input ComplexType z "complex argument";
    output ComplexType log_z "logarithm of z";
  protected
    Real re;
    Real im;
    function atan2=Modelica.Math.atan2;
    function log=Modelica.Math.log;

  algorithm
    re := 0.5*log(detC(z));
    im := atan2(z[2,1], z[1,1]);
    log_z := [re, -im; im, re];
  end logC;

  function cosC "Cosine of complex number"
    extends Modelica.Icons.Function;

    input ComplexType z "complex argument";
    output ComplexType cos_z "cosine of z";
  protected
    Real re;
    Real im;

  algorithm
    re := cos(z[1,1])*cosh(z[2,1]);
    im := -sin(z[1,1])*sinh(z[2,1]);
    cos_z := [re, -im; im, re];
  end cosC;

  function sinC "Sine of complex number"
    extends Modelica.Icons.Function;

    input ComplexType z "complex argument";
    output ComplexType sin_z "sine of z";
  protected
    Real re;
    Real im;

  algorithm
    re := sin(z[1,1])*cosh(z[2,1]);
    im := cos(z[1,1])*sinh(z[2,1]);
    sin_z := [re, -im; im, re];
  end sinC;

  function tanC "Tangens of complex number"
    extends Modelica.Icons.Function;

    input ComplexType z "complex argument";
    output ComplexType tan_z "tangens of z";

  algorithm
    tan_z := sinC(z)*invC(cosC(z));
  end tanC;

  function atanC "Arc-tangens of complex number"
    extends Modelica.Icons.Function;

    input ComplexType z "complex argument";
    output ComplexType atan_z "arc-tangens of z";
  protected
    Real a;

  algorithm
    a := 0.5*(1 - detC(z));
    atan_z := 0.5*logC([a, -z[1,1]; z[1,1], a]/(1 - a + z[2,1]));
    atan_z := [atan_z[2,1], atan_z[2,2]; -atan_z[1,1], -atan_z[1,2]];
  end atanC;

  function coshC "Hyperbolic cosine of complex number"
    extends Modelica.Icons.Function;

    input ComplexType z "complex argument";
    output ComplexType cosh_z "hyp cosine of z";
  protected
    Real re;
    Real im;

  algorithm
    re := cosh(z[1,1])*cos(z[2,1]);
    im := sinh(z[1,1])*sin(z[2,1]);
    cosh_z := [re, -im; im, re];
  end coshC;

  function sinhC "Hyperbolic sine of complex number"
    extends Modelica.Icons.Function;

    input ComplexType z "complex argument";
    output ComplexType sinh_z "hyp sine of z";
  protected
    Real re;
    Real im;

  algorithm
    re := sinh(z[1,1])*cos(z[2,1]);
    im := cosh(z[1,1])*sin(z[2,1]);
    sinh_z := [re, -im; im, re];
  end sinhC;

  function tanhC "Hyperbolic tangens of complex number"
    extends Modelica.Icons.Function;

    input ComplexType z "complex argument";
    output ComplexType tanh_z "hyp tangens of z";

  algorithm
    tanh_z := sinhC(z)*invC(coshC(z));
  end tanhC;

  function atanhC "Area-tangens-hyp of complex number"
    extends Modelica.Icons.Function;

    input ComplexType z "complex argument";
    output ComplexType atan_z "area-tangens-hyp of z";
  protected
    Real a;

  algorithm
    a := 0.5*(1 - detC(z));
    atan_z := 0.5*logC([a, -z[2,1]; z[2,1], a]/(1 - a - z[1,1]));
  end atanhC;
end Complex;