Static excitation system - IEEE type ST4B .

within PowerGrids.Electrical.Controls.ExcitationSystems;

model IEEE_ST4B "Static excitation system - IEEE type ST4B "
  parameter SI.PerUnit kpr = 10.75 "Voltage regulator proportional gain";
  parameter Real kir(unit = "1/s") = 10.75 "Voltage regulator integral gain";
  parameter SI.Time Ta = 0.02 "Voltage regulator time constant";
  parameter SI.PerUnit vrmax = 1 "Maximum voltage regulator output";
  parameter SI.PerUnit vrmin = -0.87 "Minimum voltage regulator output";
  parameter SI.PerUnit kpm = 1 "Voltage regulator proportional gain output";
  parameter Real kim(unit = "1/s") = 0 "Voltage regulator integral gain output";
  parameter SI.PerUnit vmmax = 99 "Maximum inner loop output";
  parameter SI.PerUnit vmmin = -99 "Minimum inner loop output";
  parameter SI.PerUnit kg = 0 "Feedbak gain of the inner loop field regulator";
  parameter SI.PerUnit kc = 0.113 "Rectifier loading factor proportional to commutating reactance";
  parameter SI.PerUnit vbmax = 11.63 "Maximum excitation voltage";
  Modelica.Blocks.Interfaces.RealInput VsPu "PSS output p.u"
  Modelica.Blocks.Interfaces.RealInput VcPu "Machine terminal voltage p.u."
  Modelica.Blocks.Interfaces.RealInput VePu "Exciter voltage back of commutating reactance p.u."
  Modelica.Blocks.Interfaces.RealInput IfdPu "Machine field current p.u."
  Modelica.Blocks.Interfaces.RealInput VrefPu "Voltage reference p.u."
  Modelica.Blocks.Interfaces.RealInput VuelPu "Underexcitation limit p.u."
  Modelica.Blocks.Interfaces.RealInput VoelPu "Overexcitation limit p.u."
  Modelica.Blocks.Interfaces.RealOutput EfdPu "Exciter output voltage p.u."
  Modelica.Blocks.Math.MultiSum sum1(k = {+1, +1, -1, +1}, nu = 4)
  PowerGrids.Controls.PIWithNonWindupLimiter voltageRegulatorPI(Ki = kir, Kp = kpr, initType = Modelica.Blocks.Types.Init.SteadyState, yMax = vrmax, yMin = vrmin, yStart = 1)
  PowerGrids.Controls.FirstOrder voltageRegulatorTa(T = Ta, initType = Modelica.Blocks.Types.Init.SteadyState, y_start = 1)
  Modelica.Blocks.Math.Feedback feedback
  PowerGrids.Controls.PIWithNonWindupLimiter voltageRegulatorOutput(Ki = kim, Kp = kpm, initType = Modelica.Blocks.Types.Init.SteadyState, yMax = vmmax, yMin = vmmin, yStart = 1)
  Modelica.Blocks.Math.Min lvGate
  Modelica.Blocks.Math.Gain gainKg(k = kg)
  Modelica.Blocks.Math.Product prod1
  Modelica.Blocks.Math.Division div1
  Modelica.Blocks.Math.Gain gainKc(k = kc)
  BaseClasses.ExciterRectifierRegulationCharacteristicEquationsIEEE exciterRectifierRegulationCharacteristicEquationsIEEE
  Modelica.Blocks.Math.Product prod2
  Modelica.Blocks.Nonlinear.Limiter limiterVbmax(limitsAtInit = true, uMax = vbmax, uMin = -Modelica.Constants.inf)
equation
  connect(limiterVbmax.y, prod1.u2)
  connect(prod2.y, limiterVbmax.u)
  connect(VePu, prod2.u2)
  connect(exciterRectifierRegulationCharacteristicEquationsIEEE.y, prod2.u1)
  connect(gainKc.y, exciterRectifierRegulationCharacteristicEquationsIEEE.u)
  connect(div1.y, gainKc.u)
  connect(VePu, div1.u2)
  connect(IfdPu, div1.u1)
  connect(gainKg.y, feedback.u2)
  connect(prod1.y, gainKg.u)
  connect(prod1.y, EfdPu)
  connect(lvGate.y, prod1.u1)
  connect(lvGate.u1, VoelPu)
  connect(voltageRegulatorOutput.y, lvGate.u2)
  connect(feedback.y, voltageRegulatorOutput.u)
  connect(voltageRegulatorTa.y, feedback.u1)
  connect(voltageRegulatorPI.y, voltageRegulatorTa.u)
  connect(sum1.y, voltageRegulatorPI.u)
  connect(VrefPu, sum1.u[4])
  connect(VcPu, sum1.u[3])
  connect(VuelPu, sum1.u[2])
  connect(VsPu, sum1.u[1])
end IEEE_ST4B;


Overall equivalent gain.

within PowerGrids.Electrical.Controls.ExcitationSystems;
block VRProportional
  extends Controls.BaseClasses.BaseControllerFramework;

  parameter SI.PerUnit Ka(min = 0) "Overall equivalent gain";
  parameter SI.PerUnit VrMax "Output voltage max limit in p.u.";
  parameter SI.PerUnit VrMin "Output voltage min limit in p.u.";
  parameter Types.Time LagMax = 0 "Time lag before taking action when u going above uMax";
  parameter Types.Time LagMin = 0 "Time lag before taking action when u going below uMin";
  parameter PowerGrids.Controls.LimiterWithLag.State stateStart = PowerGrids.Controls.LimiterWithLag.State.notSat "Saturation initial state"
  parameter SI.PerUnit VcPuStart = 1 "Required start value of VcPu when fixInitialControlledVariable = true"
  parameter SI.PerUnit oversaturationPu = 0.1 "abs(u-usat)/(Vmax-Vmin) in case of saturated initial condition"
  final parameter Real delta = (limiterWithLag.uMax-limiterWithLag.uMin)*oversaturationPu "Actuator saturation margin";

  outer PowerGrids.Electrical.System systemPowerGrids "Reference to system object";

  Modelica.Blocks.Interfaces.RealInput VcPu "Machine terminal voltage p.u."
  Modelica.Blocks.Interfaces.RealInput VrefPu "Voltage reference p.u."
  Modelica.Blocks.Interfaces.RealOutput efdPu "Exciter output voltage p.u."
  Modelica.Blocks.Math.Feedback Verr
  PowerGrids.Controls.LimiterWithLag limiterWithLag(LagMax = LagMax, LagMin = LagMin, stateStart = stateStart,uMax = VrMax, uMin = VrMin)
  Modelica.Blocks.Math.Gain gain(k = Ka)
initial equation
  /* The following equation could be written as

     if fixInitialControlledVariable then
       if limiterWithLag.u > limiterWithLag.uMax then
         limiterWithLag.u = limiterWithLag.uMax + delta;
       elseif limiterWithLag.u < limiterWithLag.uMin then
         limiterWithLag.u = limiterWithLag.uMin - delta;
       else
         VcPu = VcPuStart;
       end if;
     end if;

     However, we need to use homotopy with a simplified linear model, to
     avoid the need of explicitly initializing all the internal controller
     variables. This is only possible by writing those equations in implicit form
  */
  if fixInitialControlledVariable then
    0 = homotopy(
      actual = if limiterWithLag.u > limiterWithLag.uMax then limiterWithLag.u - (limiterWithLag.uMax + delta)
               else if limiterWithLag.u < limiterWithLag.uMin then limiterWithLag.u - (limiterWithLag.uMin - delta)
               else VcPu - VcPuStart,
      simplified = VcPu - VcPuStart);
  end if;
equation
  connect(VrefPu, Verr.u1)
  connect(VcPu, Verr.u2)
  connect(limiterWithLag.y, efdPu)
  connect(Verr.y, gain.u)
  connect(gain.y, limiterWithLag.u)
end VRProportional;


Exciter rectifier regulation characteristic IEEE.

within PowerGrids.Electrical.Controls.ExcitationSystems.BaseClasses;
model ExciterRectifierRegulationCharacteristicEquationsIEEE "Exciter rectifier regulation characteristic IEEE"
  extends Modelica.Blocks.Interfaces.SISO;

algorithm
  if u < 0.433 then
    y := 1 - 0.577*u;
  elseif u < 0.75 then
    y := sqrt(0.75 - u^2);
  elseif u < 1 then
    y := 1.732*(1-u);
  else
    y := 0;
  end if;
end ExciterRectifierRegulationCharacteristicEquationsIEEE;


Power System Stabilizer IEEE type PSS2B.

within PowerGrids.Electrical.Controls.PowerSystemStabilizers;
model IEEE_PSS2A "Power System Stabilizer IEEE type PSS2B"
  parameter SI.Time Tw1 = 2 "First washout on frequency signal time constant";
  parameter SI.Time Tw2 = 2 "Second washout on frequency signal time constant";
  parameter SI.Time Tw3 = 2 "First washout on power signal time constant";
  parameter SI.Time Tw4 = 2 "Second washout on power signal time constant";
  parameter SI.Time T1 = 0.12  "Lead time constant - leadlag1";
  parameter SI.Time T2 = 0.02 "Lag time constant - leadlag1";
  parameter SI.Time T3 = 0.3 "Lead time constant - leadlag2";
  parameter SI.Time T4 = 0.02 "Lag time constant - leadlag2";
  parameter SI.Time T6 = 0 "Time constant on frequency signal";
  parameter SI.Time T7 = 2 "Time constant on power signal";
  parameter SI.Time T8 = 0.2 "Lead of ramp tracking filter";
  parameter SI.Time T9 = 0.1 "Lag of ramp tracking filter";
  parameter SI.PerUnit Ks1 = 12 "Stabilizer gain";
  parameter SI.PerUnit Ks2 = 0.2 "Gain on power signal";
  parameter SI.PerUnit Ks3 = 1 "Gain on power signal before ramp-tracking filter";
  parameter Integer N = 1 "Order of ramp tracking filter";
  parameter Integer M = 5 "Denominator order of ramp tracking filter";
  parameter SI.PerUnit VstMax = 0.1 "Stabilizer output max limit in p.u.";
  parameter SI.PerUnit VstMin = -0.1 "Stabilizer output min limit in p.u.";
  Modelica.Blocks.Interfaces.RealInput Vsi1Pu "Frequency input p.u."
  Modelica.Blocks.Interfaces.RealInput Vsi2Pu "Power input p.u."
  Modelica.Blocks.Interfaces.RealOutput VstPu "Stabilizer output"
  PowerGrids.Controls.DerivativeLag firstWashoutVsi1( T1 = Tw1,Td = Tw1, initType = Modelica.Blocks.Types.Init.SteadyState, yStart = 0)
  PowerGrids.Controls.DerivativeLag secondWashoutVsi1( T1 = Tw2,Td = Tw2, initType = Modelica.Blocks.Types.Init.SteadyState, yStart = 0)
  PowerGrids.Controls.DerivativeLag firstWashoutVsi2( T1 = Tw3,Td = Tw3, initType = Modelica.Blocks.Types.Init.SteadyState, yStart = 0)
  PowerGrids.Controls.DerivativeLag secondWashoutVsi2( T1 = Tw4,Td = Tw4, initType = Modelica.Blocks.Types.Init.SteadyState, yStart = 0)
  Modelica.Blocks.Math.Add add1
  PowerGrids.Controls.RampTrackingFilter rampTrackingFilter(M = M, N = N, T1 = T8, T2 = T9, initType = Modelica.Blocks.Types.Init.SteadyState, k = 1, yStart = 0)
  PowerGrids.Controls.FirstOrder firstOrderVsi1(T = T6, initType = Modelica.Blocks.Types.Init.SteadyState, k = 1, y_start = 0)
  Modelica.Blocks.Math.Add add2(k2 = -1)
  PowerGrids.Controls.LeadLag leadLag1(T1 = T1, T2 = T2, initType = Modelica.Blocks.Types.Init.SteadyState, k = 1, yStart = 0)
  PowerGrids.Controls.LeadLag leadLag2(T1 = T3, T2 = T4, initType = Modelica.Blocks.Types.Init.SteadyState, k = 1, yStart = 0)
  Modelica.Blocks.Nonlinear.Limiter limiterVst(limitsAtInit = true, uMax = VstMax, uMin = VstMin)
  PowerGrids.Controls.FirstOrder firstOrderVsi2(T = T7, initType = Modelica.Blocks.Types.Init.SteadyState, k = Ks2, y_start = 0)
  Modelica.Blocks.Math.Gain gainKs1(k = Ks1)
  Modelica.Blocks.Math.Gain gainKs3(k = Ks3)
  Modelica.Blocks.Math.Feedback deltaPu
  Modelica.Blocks.Sources.Constant refPu(k = 1)
equation
  connect(refPu.y, deltaPu.u2)
  connect(deltaPu.y, firstWashoutVsi1.u)
  connect(Vsi1Pu, deltaPu.u1)
  connect(firstOrderVsi2.y, add2.u2)
  connect(rampTrackingFilter.y, add2.u1)
  connect(add2.y, gainKs1.u)
  connect(Vsi2Pu, firstWashoutVsi2.u)
  connect(limiterVst.y, VstPu)
  connect(leadLag2.y, limiterVst.u)
  connect(leadLag1.y, leadLag2.u)
  connect(gainKs1.y, leadLag1.u)
  connect(add1.y, rampTrackingFilter.u)
  connect(firstOrderVsi1.y, add1.u1)
  connect(secondWashoutVsi1.y, firstOrderVsi1.u)
  connect(firstWashoutVsi1.y, secondWashoutVsi1.u)
  connect(gainKs3.y, add1.u2)
  connect(firstOrderVsi2.y, gainKs3.u)
  connect(secondWashoutVsi2.y, firstOrderVsi2.u)
  connect(firstWashoutVsi2.y, secondWashoutVsi2.u)
end IEEE_PSS2A;


within PowerGrids.Electrical.Controls.PowerSystemStabilizers;
model IEEE_PSS2B "Power System Stabilizer IEEE type PSS2B"
  parameter SI.PerUnit Vsi1Max = 2 "Input frequency signal max limit in p.u.";
  parameter SI.PerUnit Vsi1Min = -2 "Input frequency signal min limit in p.u.";
  parameter SI.Time Tw1 = 2 "First washout on frequency signal time constant";
  parameter SI.Time Tw2 = 2 "Second washout on frequency signal time constant";
  parameter SI.PerUnit Vsi2Max = 2 "Input power signal max limit in p.u.";
  parameter SI.PerUnit Vsi2Min = -2 "Input power signal min limit in p.u.";
  parameter SI.Time Tw3 = 2 "First washout on power signal time constant";
  parameter SI.Time Tw4 = 2 "Second washout on power signal time constant";
  parameter SI.Time T1 = 0.12  "Lead time constant - leadlag1";
  parameter SI.Time T2 = 0.02 "Lag time constant - leadlag1";
  parameter SI.Time T3 = 0.3 "Lead time constant - leadlag2";
  parameter SI.Time T4 = 0.02 "Lag time constant - leadlag2";
  parameter SI.Time T6 = 0 "Time constant on frequency signal";
  parameter SI.Time T7 = 2 "Time constant on power signal";
  parameter SI.Time T8 = 0.2 "Lead of ramp tracking filter";
  parameter SI.Time T9 = 0.1 "Lag of ramp tracking filter";
  parameter SI.Time T10 = 0 "Lead time constant";
  parameter SI.Time T11 = 0 "Lag time constant";
  parameter SI.PerUnit Ks1 = 12 "Stabilizer gain";
  parameter SI.PerUnit Ks2 = 0.2 "Gain on power signal";
  parameter SI.PerUnit Ks3 = 1 "Gain on power signal before ramp-tracking filter";
  parameter Integer N = 1 "Order of ramp tracking filter";
  parameter Integer M = 5 "Denominator order of ramp tracking filter";
  parameter SI.PerUnit VstMax = 0.1 "Stabilizer output max limit in p.u.";
  parameter SI.PerUnit VstMin = -0.1 "Stabilozer output min limit in p.u.";
  Modelica.Blocks.Interfaces.RealInput Vsi1Pu
  Modelica.Blocks.Interfaces.RealInput Vsi2Pu
  Modelica.Blocks.Interfaces.RealOutput VstPu
  Modelica.Blocks.Nonlinear.Limiter limiterVsi1(limitsAtInit = true, uMax = Vsi1Max, uMin = Vsi1Min)
  Modelica.Blocks.Nonlinear.Limiter limiterVsi2(limitsAtInit = true, uMax = Vsi2Max, uMin = Vsi2Min)
  PowerGrids.Controls.DerivativeLag firstWashoutVsi1( T1 = Tw1,Td = Tw1, initType = Modelica.Blocks.Types.Init.SteadyState, yStart = 0)
  PowerGrids.Controls.DerivativeLag secondWashoutVsi1( T1 = Tw2,Td = Tw2, initType = Modelica.Blocks.Types.Init.SteadyState, yStart = 0)
  PowerGrids.Controls.DerivativeLag firstWashoutVsi2( T1 = Tw3,Td = Tw3, initType = Modelica.Blocks.Types.Init.SteadyState, yStart = 0)
  PowerGrids.Controls.DerivativeLag secondWashoutVsi2( T1 = Tw4,Td = Tw4, initType = Modelica.Blocks.Types.Init.SteadyState, yStart = 0)
  Modelica.Blocks.Math.Add add1
  PowerGrids.Controls.RampTrackingFilter rampTrackingFilter(M = M, N = N, T1 = T8, T2 = T9, initType = Modelica.Blocks.Types.Init.SteadyState, k = 1, yStart = 0)
  PowerGrids.Controls.FirstOrder firstOrderVsi1(T = T6, initType = Modelica.Blocks.Types.Init.SteadyState, k = 1, y_start = 0)
  Modelica.Blocks.Math.Add add2(k2 = -1)
  PowerGrids.Controls.LeadLag leadLag1(T1 = T1, T2 = T2, initType = Modelica.Blocks.Types.Init.SteadyState, k = 1, yStart = 0)
  PowerGrids.Controls.LeadLag leadLag2(T1 = T3, T2 = T4, initType = Modelica.Blocks.Types.Init.SteadyState, k = 1, yStart = 0)
  PowerGrids.Controls.LeadLag leadLag3(T1 = T10, T2 = T11, initType = Modelica.Blocks.Types.Init.SteadyState, k = 1, yStart = 0)
  Modelica.Blocks.Nonlinear.Limiter limiterVst(limitsAtInit = true, uMax = VstMax, uMin = VstMin)
  PowerGrids.Controls.FirstOrder firstOrderVsi2(T = T7, initType = Modelica.Blocks.Types.Init.SteadyState, k = Ks2, y_start = 0)
  Modelica.Blocks.Math.Gain gainKs1(k = Ks1)
  Modelica.Blocks.Math.Gain gainKs3(k = Ks3)
  Modelica.Blocks.Math.Feedback deltaPu
  Modelica.Blocks.Sources.Constant refPu(k = 1)
equation
  connect(deltaPu.u2, refPu.y)
  connect(Vsi1Pu, deltaPu.u1)
  connect(deltaPu.y, limiterVsi1.u)
  connect(limiterVst.y, VstPu)
  connect(leadLag3.y, limiterVst.u)
  connect(leadLag2.y, leadLag3.u)
  connect(leadLag1.y, leadLag2.u)
  connect(gainKs1.y, leadLag1.u)
  connect(add2.y, gainKs1.u)
  connect(rampTrackingFilter.y, add2.u1)
  connect(add1.y, rampTrackingFilter.u)
  connect(firstOrderVsi1.y, add1.u1)
  connect(secondWashoutVsi1.y, firstOrderVsi1.u)
  connect(firstWashoutVsi1.y, secondWashoutVsi1.u)
  connect(limiterVsi1.y, firstWashoutVsi1.u)
  connect(gainKs3.y, add1.u2)
  connect(firstOrderVsi2.y, add2.u2)
  connect(firstOrderVsi2.y, gainKs3.u)
  connect(secondWashoutVsi2.y, firstOrderVsi2.u)
  connect(firstWashoutVsi2.y, secondWashoutVsi2.u)
  connect(limiterVsi2.y, firstWashoutVsi2.u)
  connect(Vsi2Pu, limiterVsi2.u)
end IEEE_PSS2B;


Simple proportional governor.

within PowerGrids.Electrical.Controls.TurbineGovernors;

block GoverProportional "Simple proportional governor"
  extends Controls.BaseClasses.BaseControllerFramework;

  parameter SI.PerUnit KGover "Mechanical power sensitivity to frequency";
  parameter SI.PerUnit PMaxPu = 1 "Maximum mechanical power p.u.";
  parameter SI.PerUnit PMinPu = 0 "Minimum mechanical power p.u.";
  parameter SI.PerUnit PPuStart = 1 "Required start value of PPu when fixInitialControlledVariable = true"
  parameter SI.PerUnit oversaturationPu = 0.1 "abs(u-usat)/(Vmax-Vmin) in case of saturated initial condition"
  final parameter Real delta = (limiter.uMax-limiter.uMin)*oversaturationPu "Actuator saturation margin";

  outer PowerGrids.Electrical.System systemPowerGrids "Reference to system object";

  Modelica.Blocks.Interfaces.RealInput PmRefPu "Reference frequency/load input [pu]"
  Modelica.Blocks.Interfaces.RealInput omegaPu "Frequency [pu]"
  Modelica.Blocks.Interfaces.RealOutput PMechPu "Mechanical turbine power [pu]"

  Modelica.Blocks.Math.Feedback errPu
  Modelica.Blocks.Math.Feedback deltaOmegaPu
  Modelica.Blocks.Sources.Constant omegaRefPu(k = 1)
  Modelica.Blocks.Math.Gain gain(k = KGover)
  Modelica.Blocks.Nonlinear.Limiter limiter(limitsAtInit = true, uMax = PMaxPu, uMin = PMinPu)
  Modelica.Blocks.Interfaces.RealInput PPu "Generator Active Power p.u."
initial equation
  /* The following equation could be written as

     if fixInitialControlledVariable then
       if limiter.u > limiter.uMax then
         limiter.u = limiter.uMax + delta;
       elseif limiter.u < limiter.uMin then
         limiter.u = limiter.uMin - delta;
       else
         PPu = PPuStart;
      end if;

      However, we need to use homotopy with a simplified linear model, to
      avoid the need of explicitly initializing all the internal controller
      variables. This is only possible by writing those equations in implicit form
  */
  if fixInitialControlledVariable then
    0 = homotopy(
      actual = if limiter.u > limiter.uMax then limiter.u - (limiter.uMax + delta)
               else if limiter.u < limiter.uMin then limiter.u - (limiter.uMin - delta)
               else PPu - PPuStart,
      simplified = PPu - PPuStart);
  end if;
equation
  connect(omegaRefPu.y, deltaOmegaPu.u2)
  connect(PmRefPu, errPu.u1)
  connect(omegaPu, deltaOmegaPu.u1)
  connect(deltaOmegaPu.y, gain.u)
  connect(gain.y, errPu.u2)
  connect(errPu.y, limiter.u)
  connect(limiter.y, PMechPu)
end GoverProportional;


Simple general-purpose governor for hydraulic turbines.

within PowerGrids.Electrical.Controls.TurbineGovernors;
model GovHydro4GeneralPurpose "Simple general-purpose governor for hydraulic turbines"
  extends BaseClasses.GovHydro4Base;
equation
  connect(deadBandDb2.y, div1.u1)
end GovHydro4GeneralPurpose;


Pelton.

within PowerGrids.Electrical.Controls.TurbineGovernors;

model GovHydro4Kaplan
  extends BaseClasses.GovHydro4Base;
  Modelica.Blocks.Tables.CombiTable1Ds tableGvPgv(smoothness = Modelica.Blocks.Types.Smoothness.MonotoneContinuousDerivative1, table = [0.1, 0; 0.4, 0.35; 0.5, 0.468; 0.7, 0.796; 0.8, 0.917; 0.9, 0.99; 1, 1])
equation
  connect(deadBandDb2.y, tableGvPgv.u)
  connect(div1.u1, tableGvPgv.y[1])
end GovHydro4Kaplan;


Pelton.

within PowerGrids.Electrical.Controls.TurbineGovernors;

model GovHydro4PeltonFrancis
  extends BaseClasses.GovHydro4Base;
  Modelica.Blocks.Tables.CombiTable1Ds tableGvPgv(smoothness = Modelica.Blocks.Types.Smoothness.MonotoneContinuousDerivative1, table = [0.1, 0; 0.4, 0.42; 0.5, 0.56; 0.7, 0.8; 0.8, 0.9; 0.9, 0.97; 1, 1])
equation
  connect(deadBandDb2.y, tableGvPgv.u)
  connect(div1.u1, tableGvPgv.y[1])
end GovHydro4PeltonFrancis;


Simple Steam Turbine Governor - IEEE type TGOV1.

within PowerGrids.Electrical.Controls.TurbineGovernors;
block IEEE_TGOV1 "Simple Steam Turbine Governor - IEEE type TGOV1"
  extends Controls.BaseClasses.BaseControllerFramework;

  parameter SI.PerUnit VMax = 1 "Maximum gate limit in p.u.";
  parameter SI.PerUnit VMin = 0 "Minimum gate limit in p.u.";
  parameter SI.PerUnit R = 0.05 "Controller Droop";
  parameter SI.PerUnit Dt = 0 "Frictional losses factor";
  parameter SI.Time T1 = 0.5 "Governor time constant";
  parameter SI.Time T2 = 3 "Turbine derivative time constant";
  parameter SI.Time T3 = 10 "Turbine delay time constant";
  parameter SI.PerUnit PMechPuStart = 1 "Required start value of PmechPu when fixInitialControlledVariable = true"
  parameter SI.PerUnit oversaturationPu = 0.1 "abs(u-usat)/(Vmax-Vmin) in case of saturated initial condition"
  final parameter Real delta = (firstOrderLim.yMax - firstOrderLim.yMin)*oversaturationPu "Actuator saturation margin";

  Modelica.Blocks.Interfaces.RealInput RefLPu "Reference frequency/load input [pu]"
  Modelica.Blocks.Interfaces.RealInput omegaPu "Frequency [pu]"
  Modelica.Blocks.Interfaces.RealOutput PMechPu "Mechanical turbine power [pu]"
  Modelica.Blocks.Math.Feedback errPu
  Modelica.Blocks.Math.Feedback deltaOmegaPu
  Modelica.Blocks.Sources.Constant omegaRefPu(k = 1)
  Modelica.Blocks.Math.Gain gainDt(k = Dt)
  Modelica.Blocks.Math.Gain gainDivR(k = 1 / R)
  PowerGrids.Controls.FirstOrderWithNonWindupLimiter firstOrderLim(T = T1, initType = Modelica.Blocks.Types.Init.SteadyState, k = 1, yMax = VMax, yMin = VMin)
  PowerGrids.Controls.LeadLag leadLag(T1 = T2, T2 = T3, initType = Modelica.Blocks.Types.Init.SteadyState, k = 1)
  Modelica.Blocks.Math.Feedback sumPMechPu
initial equation
  /* The following equation could be written as

    if fixInitialControlledVariable then
      if firstOrderLim.u > firstOrderLim.yMax then
        firstOrderLim.u = firstOrderLim.yMax + delta;
      elseif firstOrderLim.u < firstOrderLim.yMin then
        firstOrderLim.u = firstOrderLim.yMin - delta;
      else
        PMechPu = PMechPuStart;
      end if;
    end if;

      However, we need to use homotopy with a simplified linear model, to
      avoid the need of explicitly initializing all the internal controller
      variables. This is only possible by writing those equations in implicit form
  */
  if fixInitialControlledVariable then
    0 = homotopy(
      actual = if firstOrderLim.u > firstOrderLim.yMax then firstOrderLim.u - (firstOrderLim.yMax + delta)
               else if firstOrderLim.u < firstOrderLim.yMin then firstOrderLim.u - (firstOrderLim.yMin - delta)
               else PMechPu - PMechPuStart,
      simplified = PMechPu - PMechPuStart);
  end if;
equation
  connect(omegaRefPu.y, deltaOmegaPu.u2)
  connect(gainDt.y, sumPMechPu.u2)
  connect(deltaOmegaPu.y, gainDt.u)
  connect(deltaOmegaPu.y, errPu.u2)
  connect(sumPMechPu.y, PMechPu)
  connect(leadLag.y, sumPMechPu.u1)
  connect(firstOrderLim.y, leadLag.u)
  connect(gainDivR.y, firstOrderLim.u)
  connect(errPu.y, gainDivR.u)
  connect(RefLPu, errPu.u1)
  connect(omegaPu, deltaOmegaPu.u1)
end IEEE_TGOV1;


Base class for Governors of hydraulic turbines.

within PowerGrids.Electrical.Controls.TurbineGovernors.BaseClasses;

partial model GovHydro4Base "Base class for Governors of hydraulic turbines"
  parameter Modelica.SIunits.PerUnit db1 = 0 "Intentional dead-band width"
  parameter Modelica.SIunits.PerUnit db2 = 0 "Unintentional dead-band width"
  parameter Modelica.SIunits.Time Tp = 0.1 "Pilot servo time constant"
  parameter Modelica.SIunits.Time Tg = 0.5 "Gate servo time constant"
  parameter Modelica.SIunits.Time Tr = 5 "Dashpot time constant"
  parameter Modelica.SIunits.PerUnit uo = 0.2 "Max gate opening velocity"
  parameter Modelica.SIunits.PerUnit uc = -0.2 "Max gate closing velocity"
  parameter Modelica.SIunits.PerUnit gMax = 1 "Maximum gate opening"
  parameter Modelica.SIunits.PerUnit gMin = 0 "Minimum gate opening"
  parameter Modelica.SIunits.PerUnit rPerm = 0.05 "Permanent droop"
  parameter Modelica.SIunits.PerUnit rTemp = 0.3 "Temporary droop"
  parameter Real GvPgvTable[:, :] = [0, 0; 1, 1] "Points to define the curve Pgv = f(Gv)"
  parameter Modelica.Blocks.Types.Smoothness GvPgvSmoothness = Modelica.Blocks.Types.Smoothness.LinearSegments "Smoothness of curve Pgv = f(Gv)"
  parameter Modelica.SIunits.PerUnit at = 1.2 "Turbine gain"
  parameter Modelica.SIunits.PerUnit qnl = 0.08 "No-load flow at nominal head"
  parameter Modelica.SIunits.Time Tw = 1 "Water inertia time constant"
  parameter Modelica.SIunits.PerUnit hDam = 1 "Head available at dam"
  parameter Modelica.SIunits.PerUnit dTurb = 0.5 "Turbine damping factor"
  parameter Modelica.SIunits.PerUnit qStart "Turbine flow Start value"
  Modelica.Blocks.Interfaces.RealInput deltaOmegaPu
  Modelica.Blocks.Interfaces.RealInput PrefPu
  Modelica.Blocks.Interfaces.RealOutput PmPu
  PowerGrids.Controls.DiscontinuousDeadBand deadbandDb1(uMax = db1 / 2)
  Modelica.Blocks.Math.Add3 add1(k2 = -1, k3 = -1)
  PowerGrids.Controls.FirstOrder lagTp(T = Tp, initType = Modelica.Blocks.Types.Init.SteadyState, y_start = 1)
  Modelica.Blocks.Nonlinear.Limiter limU(limitsAtInit = true, uMax = uo, uMin = uc)
  PowerGrids.Controls.IntegratorWithNonWindupLimiter limIntG(initType = Modelica.Blocks.Types.Init.SteadyState, yMax = gMax, yMin = gMin, yStart = 1)
  Modelica.Blocks.Math.Add add2
  Modelica.Blocks.Math.Gain gainRperm(k = rPerm)
  PowerGrids.Controls.DerivativeLag derlagTrRtemp(Td = Tr*rTemp, T1 = Tr, initType = Modelica.Blocks.Types.Init.SteadyState, yStart = 1)
  Modelica.Blocks.Math.Division div1
  Modelica.Blocks.Math.Product square1
  Modelica.Blocks.Sources.Constant constHdam(k = hDam)
  Modelica.Blocks.Sources.Constant constQnl(k = qnl)
  Modelica.Blocks.Math.Product prod1
  Modelica.Blocks.Math.Gain gainAt(k = at)
  Modelica.Blocks.Math.Add add3(k1 = -1)
  Modelica.Blocks.Math.Add add4(k2 = -1)
  Modelica.Blocks.Math.Add add5(k1 = -1)
  Modelica.Blocks.Math.Gain gainDturb(k = dTurb)
  Modelica.Blocks.Math.Product product1
  Modelica.Blocks.Math.Gain gainTg(k = 1 / Tg)
  Modelica.Blocks.Math.Gain gainRtemp(k = rTemp)
  Modelica.Blocks.Continuous.Integrator intTw(initType = Modelica.Blocks.Types.Init.InitialOutput, k = 1 / Tw, y_start = qStart)
  PowerGrids.Controls.DeadBand deadBandDb2(uMax = db2 / 2)
equation
  connect(add5.y, PmPu)
  connect(intTw.y, div1.u2)
  connect(deadBandDb2.y, gainRtemp.u)
  connect(deadBandDb2.y, gainRperm.u)
  connect(deadBandDb2.y, product1.u2)
  connect(limIntG.y, deadBandDb2.u)
  connect(derlagTrRtemp.y, add2.u2)
  connect(constQnl.y, add4.u2)
  connect(gainDturb.y, add5.u1)
  connect(product1.y, gainDturb.u)
  connect(gainRperm.y, add2.u1)
  connect(intTw.y, add4.u1)
  connect(add4.y, prod1.u2)
  connect(add3.y, intTw.u)
  connect(gainRtemp.y, derlagTrRtemp.u)
  connect(gainTg.y, limU.u)
  connect(lagTp.y, gainTg.u)
  connect(deltaOmegaPu, product1.u1)
  connect(constHdam.y, add3.u2)
  connect(deltaOmegaPu, deadbandDb1.u)
  connect(gainAt.y, add5.u2)
  connect(prod1.y, gainAt.u)
  connect(square1.y, prod1.u1)
  connect(square1.y, add3.u1)
  connect(div1.y, square1.u2)
  connect(div1.y, square1.u1)
  connect(PrefPu, add1.u1)
  connect(add2.y, add1.u3)
  connect(limU.y, limIntG.u)
  connect(add1.y, lagTp.u)
  connect(deadbandDb1.y, add1.u2)
end GovHydro4Base;


Load model with impedance specified by PRef and QRef.

within PowerGrids.Electrical.Loads;

model LoadImpedancePQ "Load model with impedance specified by PRef and QRef"
  extends PowerGrids.Electrical.Buses.BaseClasses.BusBase(
    e = Complex(0),
    Z = 1/ComplexMath.conj(Complex(PRef,QRef)/URef^2),
    PStart = PRefConst,
    QStart = QRefConst);
  extends Icons.Load;
  import Modelica.ComplexMath;
  parameter Types.ActivePower PRefConst = 0 "Active power consumption at reference voltage";
  parameter Types.ReactivePower QRefConst = 0 "Reactive power consumption at reference voltage";
  parameter Types.Voltage URef = UNom "Reference value of phase-to-phase voltage";
  Types.ActivePower PRef(nominal = SNom) = PRefConst "Active power consumption at reference voltage, the default binding can be changed when instantiating";
  Types.ActivePower QRef(nominal = SNom) = QRefConst "Reactive power consumption at reference voltage, the default binding can be changed when instantiating";
end LoadImpedancePQ;


Load model with impedance specified by PRefIn and QRefIn inputs.

within PowerGrids.Electrical.Loads;

model LoadImpedancePQInputs "Load model with impedance specified by PRefIn and QRefIn inputs"
  extends LoadImpedancePQ(
    final PRef = PRefIn,
    final QRef = QRefIn,
    final PRefConst = 0,
    final QRefConst = 0);
  Modelica.Blocks.Interfaces.RealInput PRefIn(unit="W", displayUnit="MW") "Active reference power at VPu = 1, W"
  Modelica.Blocks.Interfaces.RealInput QRefIn(unit="var", displayUnit = "MVA") "Reactive reference power at VPu = 1, var"
end LoadImpedancePQInputs;


Load model with voltage dependent P and Q.

within PowerGrids.Electrical.Loads;

model LoadPQVoltageDependence "Load model with voltage dependent P and Q"
  extends PowerGrids.Electrical.BaseClasses.OnePortAC(
    final portVariablesPu=true,
    PStart = PRefConst,
    QStart = QRefConst);
  extends Icons.Load;

  parameter Types.PerUnit alpha = 0 "Exponential of voltage ratio for actual P calculation";
  parameter Types.PerUnit beta = 0 "Exponential of voltage ratio for actual Q calculation";

  parameter Types.ActivePower PRefConst = 0 "Constant active power entering the load at reference voltage";
  parameter Types.ReactivePower QRefConst = 0 "Constant reactive power entering the load at reference voltage";
  parameter Types.Voltage URef = UNom "Reference value of phase-to-phase voltage";

  Types.ActivePower PRef(nominal = SNom) =  PRefConst "Active power at reference voltage, the default binding can be changed when instantiating";
  Types.ActivePower QRef(nominal = SNom) =  QRefConst "Reactive power at reference voltage, the default binding can be changed when instantiating";
    Types.PerUnit U_URef(start = UStart/UNom) "Ratio between voltage and reference voltage";
equation
  U_URef = port.U / URef;
  port.P = PRef*U_URef^alpha;
  port.Q = QRef*U_URef^ beta;

in which case, the constant reference value PRefConst is ignored. Alternatively, one can use the LoadPQVoltageDependenceInputs model that has input connectors for PRef and QRef.

By default alpha = beta = 0 so there is no voltage dependence.

"));
end LoadPQVoltageDependence;


Load model with voltage dependent P and Q specified by inputs.

within PowerGrids.Electrical.Loads;

model LoadPQVoltageDependenceInputs "Load model with voltage dependent P and Q specified by inputs"
  extends LoadPQVoltageDependence(
    final PRef = PRefIn,
    final QRef = QRefIn,
    final PRefConst = 0,
    final QRefConst = 0,
    PStart = 0,
    QStart = 0);
  Modelica.Blocks.Interfaces.RealInput PRefIn(unit="W", displayUnit="MW") "Active reference power at VPu = 1, W"
  Modelica.Blocks.Interfaces.RealInput QRefIn(unit="var", displayUnit = "MVA") "Reactive reference power at VPu = 1, var"
end LoadPQVoltageDependenceInputs;


Load models

within PowerGrids.Electrical;
package Loads "Load models"
  extends Modelica.Icons.Package;
end Loads;


Synchronous machine models

within PowerGrids.Electrical;

package Machines "Synchronous machine models"
  extends Modelica.Icons.Package;
end Machines;


Synchronous machine with four windings - external parameters.

within PowerGrids.Electrical.Machines;

model SynchronousMachine4Windings "Synchronous machine with four windings - external parameters"
  // General-purpose start values are provided, to avoid division by zero errors.
  // These values don't need to be modified for specific machine instancces
  extends SynchronousMachine4WindingsInternalParameters(
    final LdPu(fixed = false, min = 1e-3, start = 0.1),
    final MdPu(fixed = false, min = 1e-3, start = 1),
    final rfPu(fixed = false, min = 1e-5, start = 0.001),
    final rDPu(fixed = false, min = 1e-4, start = 0.01),
    final LfPu(fixed = false, min = 1e-3, start = 0.1),
    final LDPu(fixed = false, min = 1e-3, start = 0.2),
    final mrcPu(fixed = false),
    final LqPu(fixed = false,  min = 1e-3, start = 0.1),
    final MqPu(fixed = false,  min = 1e-3, start = 1),
    final rQ1Pu(fixed = false, min = 1e-5, start = 0.01),
    final rQ2Pu(fixed = false, min = 1e-5, start = 0.001),
    final LQ1Pu(fixed = false, min = 1e-3, start = 0.5),
    final LQ2Pu(fixed = false, min = 1e-3, start = 0.1),
    final thetaStart =
      UPhaseStart +
      atan2(xqPu*IStartPu*cosPhiStart - raPu*IStartPu*sinPhiStart,
            VStartPu + raPu*IStartPu*cosPhiStart + xqPu*IStartPu*sinPhiStart));
  // External parameters
  parameter Types.PerUnit xlPu "Stator leakage in p.u.";
  parameter Types.PerUnit xdPu "Direct axis reactance in p.u.";
  parameter Types.PerUnit xpdPu "Direct axis transient reactance in p.u.";
  parameter Types.PerUnit xppdPu "Direct axis sub-transient reactance p.u.";
  parameter Types.Time Tpd0 "Direct axis, open circuit transient time constant";
  parameter Types.Time Tppd0 "Direct axis, open circuit sub-transient time constant";
  parameter Types.PerUnit xqPu "Quadrature axis reactance in p.u.";
  parameter Types.PerUnit xpqPu "Quadrature axis transient reactance in p.u.";
  parameter Types.PerUnit xppqPu "Quadrature axis sub-transient reactance in p.u.";
  parameter Types.Time Tpq0 "Open circuit quadrature axis transient time constant";
  parameter Types.Time Tppq0 "Open circuit quadrature axis sub-transient time constant";
  parameter Types.Choices.TimeConstantsApproximation timeConstApprox =
    PowerGrids.Types.Choices.TimeConstantsApproximation.classicalDefinition
    "Approximation of time constants for internal parameter computation";

  // Auxiliary parameters, direct and quadrature axis
  // Start values are good enough to achieve convergence for all realistic
  // values of the constants
  final parameter Types.PerUnit T1dPu(fixed = false, min = 0, start = 1000);
  final parameter Types.PerUnit T2dPu(fixed = false, min = 0, start = 100);
  final parameter Types.PerUnit T3dPu(fixed = false, min = 0, start = 10);
  final parameter Types.PerUnit T4dPu(fixed = false, min = 0, start = 1000);
  final parameter Types.PerUnit T5dPu(fixed = false, min = 0, start = 100);
  final parameter Types.PerUnit T6dPu(fixed = false, min = 0, start = 10);

  final parameter Types.PerUnit T1qPu(fixed = false, min = 0, start = 1000);
  final parameter Types.PerUnit T2qPu(fixed = false, min = 0, start = 100);
  final parameter Types.PerUnit T3qPu(fixed = false, min = 0, start = 10);
  final parameter Types.PerUnit T4qPu(fixed = false, min = 0, start = 100);
  final parameter Types.PerUnit T5qPu(fixed = false, min = 0, start = 100);
  final parameter Types.PerUnit T6qPu(fixed = false, min = 0, start = 10);

  final parameter Types.Time Tpd(fixed = false, min = 0, start = 10);
  final parameter Types.Time Tppd(fixed = false, min = 0,start = 0.1);
  final parameter Types.Time Tpq(fixed = false, min = 0, start = 1);
  final parameter Types.Time Tppq(fixed = false, min = 0, start = 0.1);

  // Start values
  final parameter Types.PerUnit cosPhiStart = abs(PStart)/sqrt(PStart^2+QStart^2+1e-9*SNom)
    "Start value of power factor cos(phi)";
  final parameter Types.PerUnit sinPhiStart = sqrt(1 - cosPhiStart^2)
    "Start value of sin(phi)";
  final parameter Types.PerUnit VStartPu = port.VStart/port.VBase "Start value of voltage modulus in p.u.";
  final parameter Types.PerUnit IStartPu = port.IStart/port.IBase "Start value of current modulus in p.u.";
initial equation
  // Initial equations to determine the internal parameters as a function
  // of the external ones
  //
  // These equations, found in the Kundur textbook, would allow to compute the external parameters
  // explicitly, given the internal parameters. The Modelica tool figures out automatically
  // how to solve them backwards, using symbolic and numerical techniques

  // Modelling assumption taken by Kundur
  LqPu = xlPu;
  LdPu = xlPu;

  // Direct axis
  MdPu + LdPu = xdPu;
  T1dPu = (MdPu + LfPu)/rfPu;
  T2dPu = (MdPu + LDPu)/rDPu;
  T3dPu = (LDPu + MdPu * LfPu / (MdPu + LfPu)) / rDPu;
  T4dPu = (LfPu + MdPu * LdPu / (MdPu + LdPu)) / rfPu;
  T5dPu = (LDPu + MdPu * LdPu / (MdPu + LdPu)) / rDPu;
  T6dPu = (LDPu + MdPu * LdPu * LfPu / (MdPu * LdPu + MdPu * LfPu + LdPu * LfPu)) / rDPu;

  // For the accurate and exact case, the equations are first solved by the Modelica tool
  // using the approximate values, which are given by the second argument of the
  // homotopy() operator. Then, the solution to the accurate or exact equations is
  // computed by a continuation method, whereby the approximated expression is smoothly
  // transformed into the actual one
  if timeConstApprox == Types.Choices.TimeConstantsApproximation.classicalDefinition then
    Tpd0  * omegaBase = T1dPu;
    Tppd0 * omegaBase = T3dPu;
    Tpd   * omegaBase = T4dPu;
    Tppd  * omegaBase = T6dPu;
  elseif timeConstApprox == Types.Choices.TimeConstantsApproximation.accurateEstimation then
    Tpd0  * omegaBase = homotopy(T1dPu + T2dPu,               T1dPu);
    Tppd0 * omegaBase = homotopy(T1dPu*T3dPu/(T1dPu + T2dPu), T3dPu);
    Tpd   * omegaBase = homotopy(T4dPu + T5dPu,               T4dPu);
    Tppd  * omegaBase = homotopy(T4dPu*T6dPu/(T4dPu + T5dPu), T6dPu);
  else
    Tpd0  * omegaBase = homotopy( Functions.largerTimeConstant(T1dPu + T2dPu, T1dPu*T3dPu), T1dPu);
    Tppd0 * omegaBase = homotopy(Functions.smallerTimeConstant(T1dPu + T2dPu, T1dPu*T3dPu), T3dPu);
    Tpd   * omegaBase = homotopy( Functions.largerTimeConstant(T4dPu + T5dPu, T4dPu*T6dPu), T4dPu);
    Tppd  * omegaBase = homotopy(Functions.smallerTimeConstant(T4dPu + T5dPu, T4dPu*T6dPu), T6dPu);
  end if;
  xpdPu   = xdPu *Tpd /Tpd0;
  xppdPu  = xpdPu*Tppd/Tppd0;

  // Quadrature axis
  MqPu + LqPu = xqPu;
  T1qPu = (MqPu + LQ1Pu)/rQ1Pu;
  T2qPu = (MqPu + LQ2Pu)/rQ2Pu;
  T3qPu = (LQ2Pu + MqPu * LQ1Pu / (MqPu + LQ1Pu))/ rQ2Pu;
  T4qPu = (LQ1Pu + MqPu * LqPu  / (MqPu + LqPu)) / rQ1Pu;
  T5qPu = (LQ2Pu + MqPu * LqPu  / (MqPu + LqPu)) / rQ2Pu;
  T6qPu = (LQ2Pu + MqPu * LqPu * LQ1Pu / (MqPu * LqPu + MqPu * LQ1Pu + LqPu * LQ1Pu)) / rQ2Pu;
  if timeConstApprox == Types.Choices.TimeConstantsApproximation.classicalDefinition then
    Tpq0 *omegaBase = T1qPu;
    Tpq  *omegaBase = T4qPu;
    Tppq0*omegaBase = T3qPu;
    Tppq *omegaBase = T6qPu;
  elseif timeConstApprox == Types.Choices.TimeConstantsApproximation.accurateEstimation then
    Tpq0  * omegaBase = homotopy(T1qPu + T2qPu,               T1qPu);
    Tppq0 * omegaBase = homotopy(T1qPu*T3qPu/(T1qPu + T2qPu), T3qPu);
    Tpq   * omegaBase = homotopy(T4qPu + T5qPu,               T4qPu);
    Tppq  * omegaBase = homotopy(T4qPu*T6qPu/(T4qPu + T5qPu), T6qPu);
  else
    Tpq0  * omegaBase = homotopy( Functions.largerTimeConstant(T1qPu + T2qPu, T1qPu*T3qPu), T1qPu);
    Tppq0 * omegaBase = homotopy(Functions.smallerTimeConstant(T1qPu + T2qPu, T1qPu*T3qPu), T3qPu);
    Tpq   * omegaBase = homotopy( Functions.largerTimeConstant(T4qPu + T5qPu, T4qPu*T6qPu), T4qPu);
    Tppq  * omegaBase = homotopy(Functions.smallerTimeConstant(T4qPu + T5qPu, T4qPu*T6qPu), T6qPu);
  end if;
  xpqPu   = xqPu *Tpq /Tpq0;
  xppqPu  = xpqPu*Tppq/Tppq0;

  mrcPu = 0;
end SynchronousMachine4Windings;


Synchronous machine with 4 windings - internal parameters.

within PowerGrids.Electrical.Machines;

model SynchronousMachine4WindingsInternalParameters "Synchronous machine with 4 windings - internal parameters"
  extends BaseClasses.OnePortACdqPU(
    final generatorConvention = true,
    localInit = if initOpt == InitializationOption.localSteadyStateFixedPowerFlow
                then LocalInitializationOption.PV
                else LocalInitializationOption.none);
  extends Icons.Machine;
  import PowerGrids.Types.Choices.InitializationOption;
  import PowerGrids.Types.Choices.LocalInitializationOption;

  parameter Types.ActivePower PNom = SNom "Nominal active (turbine) power";
  parameter Types.PerUnit raPu "Armature resistance in p.u.";
  parameter Types.PerUnit LdPu "Direct axis stator leakage in p.u.";
  parameter Types.PerUnit MdPu "Direct axis mutual inductance in p.u.";
  parameter Types.PerUnit mrcPu "Canay's mutual inductance in p.u.";
  parameter Types.PerUnit LDPu "Direct axis damper leakage in p.u.";
  parameter Types.PerUnit rDPu "Resistance of the direct axis damper in p.u.";
  parameter Types.PerUnit LfPu "Excitation winding leakage in p.u.";
  parameter Types.PerUnit rfPu "Resistance of the excitation windings in p.u.";
  parameter Types.PerUnit LqPu "Quadrature axis stator leakage in p.u.";
  parameter Types.PerUnit MqPu "Quadrature axis mutual inductance in p.u.";
  parameter Types.PerUnit LQ1Pu "Quadrature axis 1st damper leakage in p.u.";
  parameter Types.PerUnit rQ1Pu "Quadrature axis 2nd damper leakage in p.u.";
  parameter Types.PerUnit LQ2Pu "Leakage of quadrature axis 2nd damper in p.u.";
  parameter Types.PerUnit rQ2Pu "Resistance of quadrature axis 2nd damper in p.u.";
  parameter Types.PerUnit DPu = 0 "Damping coefficient of the swing equation in p.u.";
  parameter Modelica.SIunits.Time H "Kinetic constant = kinetic energy / rated power";
  parameter Types.Choices.ExcitationPuType excitationPuType =
    PowerGrids.Types.Choices.ExcitationPuType.nominalStatorVoltageNoLoad "Choice of excitation base voltage";
  parameter Boolean neglectTransformerTerms = true "Neglect the transformer terms in the Park equations";
  parameter Boolean referenceGenerator = false "True if reference generator in an isolated synchronous system";
  parameter Types.Choices.InitializationOption initOpt = systemPowerGrids.initOpt "Initialization option";
  final parameter SI.AngularVelocity omegaBase = systemPowerGrids.omegaNom "Base angular frequency value";
  final parameter Types.PerUnit kuf(fixed = false) "Scaling factor for excitation p.u. voltage";
  constant Types.PerUnit omegaNomPu = 1 "Nominal frequency in p.u.";

  final parameter Types.PerUnit lambdadPuStart(fixed = false) "Start value of lambdadPu";
  final parameter Types.PerUnit lambdaqPuStart(fixed = false) "Start value of lambdaqPu";
  final parameter Types.PerUnit ufPuStart(fixed = false) "Start value of exciter voltage in p.u. (Kundur base)";
  final parameter Types.PerUnit ufPuInStart(fixed = false) "Start value of input exciter voltage in p.u. (user-selcted base";
  final parameter Types.PerUnit ifPuStart(fixed = false) "Start value of ifPu";
  // Input variables
  Modelica.Blocks.Interfaces.RealInput PmPu(unit = "1") "Input mechanical power in p.u. (base PNom)"
  Modelica.Blocks.Interfaces.RealInput ufPuIn(unit = "1", start = ufPuInStart) "Input voltage of exciter winding in p.u. (user-selected base voltage)"
  // Output variables
  Modelica.Blocks.Interfaces.RealOutput omega(unit = "rad/s") "Angular frequency in rad/s for system object"
// Other per-unit variables
  Modelica.Blocks.Interfaces.RealOutput omegaPu(start = 1) "Angular frequency in p.u."
  Types.PerUnit iDPu(start = 0) "Current of direct axis damper in p.u";
  Types.PerUnit ifPu(start = ifPuStart) "Current of excitation winding in p.u.";
  Types.PerUnit iQ1Pu(start = 0) "Current of quadrature axis 1st damper in p.u.";
  Types.PerUnit iQ2Pu(start = 0) "Current of quadrature axis 2nd damper in p.u.";
  Types.PerUnit ufPu(start = ufPuStart) "Voltage of exciter winding in p.u. (base voltage as per Kundur)";
  Types.PerUnit lambdadPu(start = lambdadPuStart) "Flux of direct axis in p.u.";
  Types.PerUnit lambdaqPu(start = lambdaqPuStart) "Flux of quadrature axis in p.u.";
  Types.PerUnit lambdaDPu "Flux of direct axis damper in p.u";
  Types.PerUnit lambdafPu "Flux of excitation winding in p.u.";
  Types.PerUnit lambdaQ1Pu "Flux of quadrature axis 1st damper in p.u.";
  Types.PerUnit lambdaQ2Pu "Flux of quadrature axis 1st damper in p.u.";
  Types.PerUnit omegaRefPu = systemPowerGrids.omegaRef/systemPowerGrids.omegaNom "Reference frequency in p.u.";
  Types.PerUnit CmPu(start = -PStart/SNom) "Mechanical torque in p.u. (base PNom/omegaBase)";
  Types.PerUnit CePu(start = -PStart/SNom) "Electrical torque in p.u. (base SNom/omegaBase)";
  Types.PerUnit PePu(start = -PStart/SNom) "Electrical power in p.u. (base SNom)";
  Types.PerUnit PePuPNom = PePu*SNom/PNom "Electrical active power in p.u. (base PNom)";

  // SI-unit variables
  Types.Frequency f = systemPowerGrids.fNom*omegaPu "Frequency of rotation of d-q axes";
  Modelica.Blocks.Interfaces.RealOutput VPu "Port voltage magnitude [pu]"
  Modelica.Blocks.Interfaces.RealOutput PPu "Active Power Production [pu base PNom]"
initial equation
  // Scaling factor for excitation p.u. voltage
  if excitationPuType == Types.Choices.ExcitationPuType.Kundur then
    kuf = 1 "Choice of per-unit as per Kundur textbook";
  else
    kuf = rfPu / MdPu "Base voltage gives 1 p.u. air-gap stator voltage at no load";
  end if;
  // Equations to compute start values
  // these equations are the same that involve the actual variables in the equation section
  // except that they involve the start values instead, and they do not contain terms which
  // are zero at steady state (e.g., all the damping winding currents)
  // the Modelica tool figures out automatically how to solve them for the unknown parameters
  udPuStart = raPu*idPuStart - omegaNomPu*lambdaqPuStart;
  uqPuStart = raPu*iqPuStart + omegaNomPu*lambdadPuStart;
  lambdadPuStart = (MdPu + LdPu)*idPuStart + MdPu*ifPuStart;
  ufPuStart =  rfPu*ifPuStart;
  ufPuInStart = ufPuStart/kuf;

  // Equations to determine the initial state values
  if initOpt == InitializationOption.noInit then
    // No initial equations
  else
    omegaPu = omegaNomPu;
    der(omegaPu) = 0;
    if not neglectTransformerTerms then
      der(lambdadPu) = 0;
      der(lambdaqPu) = 0;
    end if;
    der(lambdafPu) = 0;
    der(lambdaDPu) = 0;
    der(lambdaQ1Pu) = 0;
    der(lambdaQ2Pu) = 0;
  end if;
equation
  // Flux linkages
  lambdadPu = (MdPu + LdPu) * idPu + MdPu * ifPu + MdPu * iDPu;
  lambdafPu =     MdPu      *idPu + (MdPu + LfPu + mrcPu)*ifPu +    (MdPu + mrcPu)    *iDPu;
  lambdaDPu =     MdPu      *idPu +     (MdPu + mrcPu)   *ifPu + (MdPu + LDPu + mrcPu)*iDPu;
  lambdaqPu = (MqPu + LqPu) *iqPu +         MqPu         *iQ1Pu +        MqPu         *iQ2Pu;
  lambdaQ1Pu =     MqPu     *iqPu +     (MqPu + LQ1Pu )  *iQ1Pu +        MqPu         *iQ2Pu;
  lambdaQ2Pu =     MqPu     *iqPu +         MqPu         *iQ1Pu +    (MqPu + LQ2Pu)   *iQ2Pu;

  // Equivalent circuit equations in Park's coordinates
  if neglectTransformerTerms then
    udPu = raPu * idPu - omegaPu * lambdaqPu;
    uqPu = raPu * iqPu + omegaPu * lambdadPu;
  else
    udPu = raPu * idPu - omegaPu * lambdaqPu + der(lambdadPu) / omegaBase;
    uqPu = raPu * iqPu + omegaPu * lambdadPu + der(lambdaqPu) / omegaBase;
  end if;
  ufPu =  rfPu *ifPu  + der(lambdafPu)/omegaBase;
  0    =  rDPu *iDPu  + der(lambdaDPu)/omegaBase;
  0    =  rQ1Pu*iQ1Pu + der(lambdaQ1Pu)/omegaBase;
  0    =  rQ2Pu*iQ2Pu + der(lambdaQ2Pu)/omegaBase;

  // Mechanical equations
  der(theta) = (omegaPu - omegaRefPu) * omegaBase;
  2*H*der(omegaPu) = (CmPu*PNom/SNom - CePu) - DPu*(omegaPu - omegaRefPu);
  CePu = lambdaqPu*idPu - lambdadPu*iqPu;
  PePu = CePu*omegaPu;
  PmPu = CmPu*omegaPu;
  omega = omegaPu*omegaBase;

  // Excitation voltage p.u. conversion
  ufPu = ufPuIn * kuf;

  // Output signal equations
  VPu = port.VPu;
  PPu = -port.P/PNom;
end SynchronousMachine4WindingsInternalParameters;


Components for power flow calculations

within PowerGrids.Electrical;

package PowerFlow "Components for power flow calculations"
  extends Modelica.Icons.Package;
end PowerFlow;


PQ bus.

within PowerGrids.Electrical.PowerFlow;

model PQBus "PQ bus"
  extends BaseClasses.OnePortAC(portVariablesPhases = true);
  extends Icons.Load;
  parameter Types.ActivePower P = SNom "Active power entering the bus";
  parameter Types.ReactivePower Q = 0 "Reactive power entering the bus";
equation
  port.P = P;
  port.Q = Q;

end PQBus;


PV bus.

within PowerGrids.Electrical.PowerFlow;

model PVBus "PV bus"
  extends BaseClasses.OnePortAC(portVariablesPhases = true);
  extends Icons.Machine;
  parameter Types.ActivePower P = SNom "Active power entering the bus";
  parameter Types.Voltage U = UNom "Absolute value of phase-to-phase voltage";
equation
  port.P = P;
  port.U = U;

end PVBus;


Slack Bus.

within PowerGrids.Electrical.PowerFlow;

model SlackBus "Slack Bus"
  extends BaseClasses.OnePortAC;
  extends Icons.Bus;
  parameter Types.Voltage U = UNom "Voltage magnitude, phase-to-phase";
  parameter Types.Angle theta = 0 "Phase of voltage phasor";
equation
  port.u = CM.fromPolar(U, theta) "Voltage of ideal generator, phase-to-ground";

end SlackBus;


Load with constant impedance.

within PowerGrids.Electrical.PowerFlow;

model ZLoad "Load with constant impedance"
  extends BaseClasses.OnePortAC;
  extends Icons.Load;
  parameter Types.ActivePower PNom = SNom "Nominal active power";
  parameter Types.ActivePower QNom = 0 "Nominal reactive power";

  parameter Types.ComplexImpedance Z = UNom^2/Complex(PNom, -QNom) "Constant impedance of the load";
equation
  port.v = Z*port.i;
end ZLoad;


Simple test case with one slack bus connected to a PQ bus..

within PowerGrids.Electrical.PowerFlow.Test;

model OneSlackOneLoad
  extends Modelica.Icons.Example;
  inner PowerGrids.Electrical.System systemPowerGrids
  PowerGrids.Electrical.PowerFlow.SlackBus slack(SNom = 1e+08, UNom = 400000)
  PowerGrids.Electrical.PowerFlow.PQBus load(P = 3e+07, Q = 0, SNom = 3e+07, UNom = 400000)
equation
  connect(load.terminal, slack.terminal)end OneSlackOneLoad;


Simple test case with one slack bus and one PQ bus connected through a <a href=\.

within PowerGrids.Electrical.PowerFlow.Test;

model OneSlackOneLoadWithOneLine
  extends Modelica.Icons.Example;
  inner PowerGrids.Electrical.System systemPowerGrids
  PowerGrids.Electrical.PowerFlow.SlackBus slack(SNom = 1e+08, UNom = 400000)
  PowerGrids.Electrical.PowerFlow.PQBus load(P = 3e+07, Q = 0, SNom = 3e+07, UNom = 400000)
  PowerGrids.Electrical.Branches.LineConstantImpedance line(R = 200, SNom = 3e+07, UNom = 400000, X = 2000)
equation
  connect(line.terminalB, load.terminal)
  connect(line.terminalA, slack.terminal)end OneSlackOneLoadWithOneLine;


Simple test case, similar to <a href=\.

within PowerGrids.Electrical.PowerFlow.Test;

model OneSlackOnePVWithOneLine
  extends Modelica.Icons.Example;
  inner PowerGrids.Electrical.System systemPowerGrids
  PowerGrids.Electrical.PowerFlow.SlackBus slack(SNom = 1e+08, UNom = 400000)
  PowerGrids.Electrical.Branches.LineConstantImpedance line(R = 200, SNom = 3e+07, UNom = 400000, X = 2000)
  PowerGrids.Electrical.PowerFlow.PVBus node1(P = 3e+07, SNom = 3e+07, UNom = 400000)
equation
  connect(line.terminalB, node1.terminal)
  connect(slack.terminal, line.terminalA)
end OneSlackOnePVWithOneLine;


Simple test system with one slack node and one <a href=\.

within PowerGrids.Electrical.PowerFlow.Test;
model OneSlackOneZLoad
  extends Modelica.Icons.Example;
  inner PowerGrids.Electrical.System systemPowerGrids
  PowerGrids.Electrical.PowerFlow.SlackBus slack(SNom = 1e+08, UNom = 400000)
  PowerGrids.Electrical.PowerFlow.ZLoad load(PNom = 2e+07, QNom = 1e+07, SNom = 3e+07, UNom = 400000)
equation
  connect(load.terminal, slack.terminal)end OneSlackOneZLoad;


Small system with a few PQ buses, one PV bus and one slack bus connected through constant impedant lines..

within PowerGrids.Electrical.PowerFlow.Test;

model SmallSystem
  extends Modelica.Icons.Example;
  inner PowerGrids.Electrical.System systemPowerGrids
  PowerGrids.Electrical.PowerFlow.PVBus bus2(P = -1e+08,SNom = 1e+08, UNom = 400000, portVariablesPu = true)
  PowerGrids.Electrical.Branches.LineConstantImpedance line1(R = 100, SNom = 1e+08, UNom = 400000, X = 1000, portVariablesPu = true)
  PowerGrids.Electrical.Branches.LineConstantImpedance line2(R = 100, SNom = 1e+08, UNom = 400000, X = 1000, portVariablesPu = true)
  PowerGrids.Electrical.Branches.LineConstantImpedance line3(R = 100, SNom = 1e+08, UNom = 400000, X = 1000, portVariablesPu = true)
  PowerGrids.Electrical.PowerFlow.PQBus load1(P = 3e+07, SNom = 3e+07, UNom = 400000, portVariablesPu = true)
  PowerGrids.Electrical.PowerFlow.PQBus load2(P = 2e+07, SNom = 4e+07, UNom = 400000, portVariablesPu = true)
  PowerGrids.Electrical.PowerFlow.PQBus load3(P = 2e+07, SNom = 2e+07, UNom = 400000, portVariablesPu = true)
  PowerGrids.Electrical.PowerFlow.PQBus load4(P = 3e+07, SNom = 3e+07, UNom = 400000, portVariablesPu = true)
  PowerGrids.Electrical.PowerFlow.SlackBus slack(SNom = 1e+08, UNom = 400000, portVariablesPu = true)
  Buses.Bus bus(SNom = 2e+07, UNom = 400000)
equation
  connect(load1.terminal, line1.terminalA)
  connect(line3.terminalB, load4.terminal)
  connect(line2.terminalB, load2.terminal)
  connect(load1.terminal, slack.terminal)
  connect(line2.terminalB, bus2.terminal)
  connect(line1.terminalB, bus.terminal)
  connect(line2.terminalA, bus.terminal)
  connect(line3.terminalA, bus.terminal)
  connect(load3.terminal, bus.terminal)end SmallSystem;


info

within PowerGrids.Electrical.Test;

package Info
  extends Modelica.Icons.Info;
end Info;


Test case for LoadImpedancePQ.

within PowerGrids.Electrical.Test;

model LoadImpedancePQ "Test case for LoadImpedancePQ"
  extends Modelica.Icons.Example;
  inner System systemPowerGrids
  PowerGrids.Electrical.Loads.LoadImpedancePQ load1(PRef = 8e+07, PRefConst = 40e6, QRef = 4e+07, QRefConst = 20e6, SNom = 1e+08, UNom = 380000, URef = 400000, portVariablesPhases = true, portVariablesPu = true)
  PowerGrids.Electrical.Loads.LoadImpedancePQ load2(PRef = 8e+07 + (if time >= 1 then 1e7 else 0), PRefConst = 4e+07, QRef = 4e+7 + (if time >= 2 then 5e6 else 0), QRefConst = 2e+07, SNom = 1e+08, UNom = 380000, URef = 400000, portVariablesPhases = true, portVariablesPu = true)
  PowerGrids.Electrical.Loads.LoadImpedancePQInputs load3(SNom = 5e+08, UNom = 380000, URef = 400000, portVariablesPhases = true, portVariablesPu = true)
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBus1(SNom = 1e+08, UNom = 380000, URef = 400000, portVariablesPhases = true, portVariablesPu = true)
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBus2(SNom = 1e+08, UNom = 380000, URef = 400000, portVariablesPhases = true, portVariablesPu = true)
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBus3(SNom = 1e+08, UNom = 380000, URef = 400000, portVariablesPhases = true, portVariablesPu = true)
  Modelica.Blocks.Sources.Step PRef(height = 10e6, offset = 80e6, startTime = 1)
  Modelica.Blocks.Sources.Step QRef(height = 10e6, offset = 40e6, startTime = 2)
equation
  connect(QRef.y, load3.QRefIn)
  connect(PRef.y, load3.PRefIn)
  connect(infiniteBus3.terminal, load3.terminal)
  connect(infiniteBus2.terminal, load2.terminal)
  connect(infiniteBus1.terminal, load1.terminal)
end LoadImpedancePQ;


This model is similar to <a href=\.

within PowerGrids.Electrical.Test;

model OneBusImpedanceOneLoad
  extends OneBusOneLoad(infiniteBus.R = 0.3, infiniteBus.X = 1.5, infiniteBus.portVariablesPhases = true, infiniteBus.portVariablesPu = true, infiniteBus.generatorConvention = true);
end OneBusImpedanceOneLoad;


This model demonstrates both ways of implementing a time-varying load.

The model is similar to <a href=\.

within PowerGrids.Electrical.Test;

model OneBusImpedanceOneVariableLoad
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBus bus1(PStart = -1e+07,R = 0.04,SNom = 1e+08, UNom = 10000, X = 0.4, generatorConvention = true, portVariablesPhases = true, portVariablesPu = true)
  PowerGrids.Electrical.Loads.LoadPQVoltageDependence load1(
    PRef = if time < 1 then 10e6 else 20e6, PStart = 1e+07,
    QRef = if time < 2 then 0 else 30e6, QStart = 0, SNom = 1e+08, UNom = 10000, portVariablesPhases = true)
  inner System systemPowerGrids
  PowerGrids.Electrical.Buses.InfiniteBus bus2(PStart = -1e+07,R = 0.04, SNom = 1e+08, UNom = 10000, X = 0.4, generatorConvention = true, portVariablesPhases = true, portVariablesPu = true)
  PowerGrids.Electrical.Loads.LoadPQVoltageDependenceInputs load2(PStart = 1e+07, SNom = 1e+08, UNom = 10000, portVariablesPhases = true)
  Modelica.Blocks.Sources.Step PSignal(height = 10e6, offset = 10e6, startTime = 1)
  Modelica.Blocks.Sources.Step QSignal(height = 30e6, startTime = 2)
equation
  connect(PSignal.y, load2.PRefIn)
  connect(QSignal.y, load2.QRefIn)
  connect(bus2.terminal, load2.terminal)
  connect(bus1.terminal, load1.terminal)
end OneBusImpedanceOneVariableLoad;


This model demonstrates the usage of a variable-voltage infinite bus.

The model is similar to <a href=\.

within PowerGrids.Electrical.Test;

model OneBusImpedanceVariableVoltageOneLoad
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBusVariableVoltage bus1(PStart = -1e+07, R = 0.04, SNom = 1e+08, UNom = 10000, X = 0.4, generatorConvention = true, portVariablesPhases = true, portVariablesPu = true, useThetaIn = true, useUIn = true)
  PowerGrids.Electrical.Loads.LoadPQVoltageDependence load1(PRefConst = 1e+07,PStart = 1e+07, QRefConst = 0, QStart = 0, SNom = 1e+08, UNom = 10000, portVariablesPhases = true)
  inner System systemPowerGrids
  Modelica.Blocks.Sources.Step UMod(height = -2e3, offset = 10e3, startTime = 1)
  Modelica.Blocks.Sources.Step UPhase(height = 30 / 180 * Modelica.Constants.pi, startTime = 2)
equation
  connect(UPhase.y, bus1.thetaIn)
  connect(UMod.y, bus1.UIn)
  connect(bus1.terminal, load1.terminal)
end OneBusImpedanceVariableVoltageOneLoad;


An infinite bus with zero impedance, U_abs = 10 kV, theta = 30 deg, is connected to a PQ load with P = 10 MW and Q = 0 MW.

As the nominal power is set to 10 MW and the nominal voltage to 10 kV on both components, all p.u. absolute values are one. Since the load is purely resistive, all phasors are rotated by 30 deg.

For simplicity, the Start values are set assuming theta = 0; the nonlinear solver is able to converge on the correct solution from this initial guess.

This model demonstrates the correct behaviour of the <a href=\.

within PowerGrids.Electrical.Test;

model OneBusOneLoad
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBus(SNom = 1e+07, UNom = 10000, portVariablesPu = true, theta = 0.523599)
  PowerGrids.Electrical.Loads.LoadPQVoltageDependence loadPQ(PRefConst = 1e+07, QRefConst = 0, SNom = 1e+07, UNom = 10000, portVariablesPhases = true)
  inner PowerGrids.Electrical.System systemPowerGrids
equation
  connect(infiniteBus.terminal, loadPQ.terminal)
end OneBusOneLoad;


Same behaviour as <a href=\.

within PowerGrids.Electrical.Test;

model OneBusTransmissionLineOneLoad
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBus(SNom = 1e+07, UNom = 10000, portVariablesPu = true, theta = 0.523599)
  PowerGrids.Electrical.Loads.LoadPQVoltageDependence loadPQ(PRefConst = 1e+07, QRefConst = 0, SNom = 1e+07, UNom = 10000, alpha = 0, beta = 0, portVariablesPhases = true)
  inner PowerGrids.Electrical.System systemPowerGrids
  PowerGrids.Electrical.Branches.LineConstantImpedance transmissionLine(R = 0.3, SNom = 1e+07, UNom = 10000, X = 1.5, portVariablesPu = true)
equation
  connect(infiniteBus.terminal, transmissionLine.terminalA)
  connect(transmissionLine.terminalB, loadPQ.terminal)
end OneBusTransmissionLineOneLoad;


This model is similar to<a href=\.

within PowerGrids.Electrical.Test;

model OneBusTransmissionLineShuntOneLoad
  extends OneBusTransmissionLineOneLoad(transmissionLine.B = 0.02, transmissionLine.G = 0.01, transmissionLine.portVariablesPu = true);
end OneBusTransmissionLineShuntOneLoad;


Component test models

within PowerGrids.Electrical;
package Test "Component test models"
  extends Modelica.Icons.ExamplesPackage;
end Test;


Test case for the conversion of external parameter to internal parameters taken from Kundur, Power System Stability and Control, example 4.1. Note that the system frequency for this example is 60 Hz.

The machine is directly connected to an ideal bus with UNom = 24 kV and phase = 0 and initialized in steady-state with PmPu = 0.9, ufPu = 0.000939, using the Kundur base excitation voltage.

 Parameter	Meaning	Value	Unit

 SNom	Rated power	550	MVA

 UNom	Rated phase-to-phase voltage	24	kV

 xlPu	Stator Leakage	0.15	pu

 xdPu	Direct axis reactance	1.81	pu

 xpdPu	Direct axis transient reactance	0.3	pu

 xppdPu	Direct axis sub-transient reactance	0.23	pu

 Tpd0	Direct axis open circuit transient time constant	8	s

 Tppd0	Direct axis open circuit sub-transient time constant	0.03	s

 xqPu	Quadrature axis reactance	1.76	pu

 xpqPu	Quadrature axis transient reactance	0.65	pu

 xppqPu	Quadrature axis sub-transient reactance	0.25	pu

 Tpq0	Quadrature axis open circuit transient time constant	1	s

 Tppq0	Quadrature axis open circuit sub-transient time constant	0.07	s

 raPu	Armature resistance	0.003	pu

 mrcPu	Canay's mutual inductance	0	pu

The following internal parameter values are reported from Kundur and match the ones computed by the model with timeConstantApproximation=classicalDefinitions.

 PowerGrids	Kundur	Meaning	Value	Unit

LdPu	Ll	Direct axis stator leakage	0.15	pu

 MdPu	Lad	Direct axis mutual inductance	1.66	pu

 LDPu	L1d	Direct axis damper leakage	0.1713	pu

 rDPu	R1d	Direct axis damper resistance	0.0284	pu

 LfPu	Lfd	Excitation winding leakage	0.165	pu

 rfPu	Rfd	Excitation windings resistance	0.000605	pu

 LqPu	Ll	Quadrature axis stator leakage 	0.15	pu

 MqPu	Laq	Quadrature axis mutual inductance	1.61	pu

 LQ1Pu	L1q	Quadrature axis 1st damper leakage	0.7252	pu

 rQ1Pu	R1q	Quadrature axis 1st damper resistance	0.0062	pu

 LQ2Pu	L2q	Quadrature axis 2nd damper leakage	0.125	pu

 rQ2Pu	R2q	Quadrature axis 2nd damper resistance	0.02368	pu

The following table reports the steady-state solution computed by Kundur in Example 3.2 and by the PowerGrids model. Note that the Kundur example unfortunately includes a the effect of an 83.5% magnetic saturation, which is not accounted for in the PowerGrids model, so the two sets of values do not match exactly, particularly as regards the reactive power and the quadrature current. However, the difference is compatible with the effect of the reduced inductances. Also note that the sign convention for id, iq is opposite to Kundur's.

 Variable	Name	Value Kundur	Value PowerGrids	Unit

 PGenPu	Generated active power	0.9	0.89667	pu

 QGenPu	Generated reactive power	0.436	0.55206	pu

 theta	Machine angle	39.1	38.61	deg

 udPu	Direct axis voltage	0.631	0.6240	pu

 uqPu	Quadrature axis voltage	0.776	0.7814	pu

 idPu	Direct axis current	0.906	-0.9909	pu

 iqPu	Quadrature axis current	0.423	-0.3562	pu

.

within PowerGrids.Electrical.Test;

model SynchronousMachine4Windings
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBus bus(SNom = 5.5e+08, UNom = 24000, UStart = 24000, X = 0, portVariablesPhases = true, portVariablesPu = true, theta = 0)
  PowerGrids.Electrical.Machines.SynchronousMachine4Windings machine(H = 6, PStart = -5.52e+08, QStart = -2.52e+08, SNom = 5.5e+08, Tpd0 = 8, Tppd0 = 0.03, Tppq0 = 0.07, Tpq0 = 1, UNom = 24000, UStart = 24000, excitationPuType = PowerGrids.Types.Choices.ExcitationPuType.Kundur, portVariablesPhases = true, raPu = 0.003, timeConstApprox = PowerGrids.Types.Choices.TimeConstantsApproximation.classicalDefinition, xdPu = 1.81, xlPu = 0.15, xpdPu = 0.3, xppdPu = 0.23, xppqPu = 0.25, xpqPu = 0.65, xqPu = 1.76)
  inner PowerGrids.Electrical.System systemPowerGrids(fNom = 60)
  Modelica.Blocks.Sources.Step PmPu(height = 0.0, offset = 0.9, startTime = 50)
  Modelica.Blocks.Sources.Step ufPu(height = 0, offset = 0.000939)
equation
  connect(bus.terminal, machine.terminal)
  connect(ufPu.y, machine.ufPuIn)
  connect(PmPu.y, machine.PmPu)
end SynchronousMachine4Windings;


within PowerGrids.Electrical.Test;

model SynchronousMachine4WindingsAccurate
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBus bus(SNom = 5.5e+08, UNom = 24000, UStart = 24000, X = 0, portVariablesPhases = true, portVariablesPu = true, theta = 0)
  PowerGrids.Electrical.Machines.SynchronousMachine4Windings machine(H = 6, PStart = -5.52e+08, QStart = -2.52e+08, SNom = 5.5e+08, Tpd0 = 8, Tppd0 = 0.03, Tppq0 = 0.07, Tpq0 = 1, UNom = 24000, UStart = 24000, excitationPuType = PowerGrids.Types.Choices.ExcitationPuType.Kundur, portVariablesPhases = true, raPu = 0.003, timeConstApprox = PowerGrids.Types.Choices.TimeConstantsApproximation.accurateEstimation, xdPu = 1.81, xlPu = 0.15, xpdPu = 0.3, xppdPu = 0.23, xppqPu = 0.25, xpqPu = 0.65, xqPu = 1.76)
  inner PowerGrids.Electrical.System systemPowerGrids(fNom = 60)
  Modelica.Blocks.Sources.Step PmPu(height = 0.0, offset = 0.9, startTime = 50)
  Modelica.Blocks.Sources.Step ufPu(height = 0, offset = 0.000939)
equation
  connect(bus.terminal, machine.terminal)
  connect(ufPu.y, machine.ufPuIn)
  connect(PmPu.y, machine.PmPu)
end SynchronousMachine4WindingsAccurate;


within PowerGrids.Electrical.Test;

model SynchronousMachine4WindingsExact
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBus bus(SNom = 5.5e+08, UNom = 24000, UStart = 24000, X = 0, portVariablesPhases = true, portVariablesPu = true, theta = 0)
  PowerGrids.Electrical.Machines.SynchronousMachine4Windings machine(H = 6, PStart = -5.52e+08, QStart = -2.52e+08, SNom = 5.5e+08, Tpd0 = 8, Tppd0 = 0.03, Tppq0 = 0.07, Tpq0 = 1, UNom = 24000, UStart = 24000, excitationPuType = PowerGrids.Types.Choices.ExcitationPuType.Kundur, portVariablesPhases = true, raPu = 0.003, timeConstApprox = PowerGrids.Types.Choices.TimeConstantsApproximation.exactComputation, xdPu = 1.81, xlPu = 0.15, xpdPu = 0.3, xppdPu = 0.23, xppqPu = 0.25, xpqPu = 0.65, xqPu = 1.76)
  inner PowerGrids.Electrical.System systemPowerGrids(fNom = 60)
  Modelica.Blocks.Sources.Step PmPu(height = 0.0, offset = 0.9, startTime = 50)
  Modelica.Blocks.Sources.Step ufPu(height = 0, offset = 0.000939)
equation
  connect(bus.terminal, machine.terminal)
  connect(ufPu.y, machine.ufPuIn)
  connect(PmPu.y, machine.PmPu)
end SynchronousMachine4WindingsExact;


This test case validates the NoLoad choice of base excitation voltage of the SynchronousMachine4Windings model.

By setting ufPuIn = 1 and PmPu = 0, one obtains machine.port.VPu = 1 and machine.port.IPu = 0, as  required by the base voltage definition.

The extermal machine parameters are the same as in the  <a href=\.

within PowerGrids.Electrical.Test;

model SynchronousMachine4WindingsNoLoad
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBus bus(PStart = 0,SNom = 5.5e+08, UNom = 24000, UStart = 24000, X = 0, portVariablesPhases = true, portVariablesPu = true, theta = 0)
  PowerGrids.Electrical.Machines.SynchronousMachine4Windings machine(H = 6, PStart = 0, QStart = 0, SNom = 5.5e+08, Tpd0 = 8, Tppd0 = 0.03, Tppq0 = 0.07, Tpq0 = 1, UNom = 24000, UStart = 24000, excitationPuType = PowerGrids.Types.Choices.ExcitationPuType.nominalStatorVoltageNoLoad, portVariablesPhases = true, raPu = 0.003, timeConstApprox = PowerGrids.Types.Choices.TimeConstantsApproximation.classicalDefinition, xdPu = 1.81, xlPu = 0.15, xpdPu = 0.3, xppdPu = 0.23, xppqPu = 0.25, xpqPu = 0.65, xqPu = 1.76)
  inner PowerGrids.Electrical.System systemPowerGrids(fNom = 50)
  Modelica.Blocks.Sources.Step PmPu(height = 0.0, offset = 0.0, startTime = 50)
  Modelica.Blocks.Sources.Step ufPu(height = 0, offset = 1)
equation
  connect(bus.terminal, machine.terminal)
  connect(ufPu.y, machine.ufPuIn)
  connect(PmPu.y, machine.PmPu)
end SynchronousMachine4WindingsNoLoad;


within PowerGrids.Electrical.Test;

model SynchronousMachine4WindingsNoLoadAccurate
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBus bus(PStart = 0, SNom = 5.5e+08, UNom = 24000, UStart = 24000, X = 0, portVariablesPhases = true, portVariablesPu = true, theta = 0)
  PowerGrids.Electrical.Machines.SynchronousMachine4Windings machine(H = 6, PStart = 0, QStart = 0, SNom = 5.5e+08, Tpd0 = 8, Tppd0 = 0.03, Tppq0 = 0.07, Tpq0 = 1, UNom = 24000, UStart = 24000, excitationPuType = PowerGrids.Types.Choices.ExcitationPuType.nominalStatorVoltageNoLoad, portVariablesPhases = true, raPu = 0.003, timeConstApprox = PowerGrids.Types.Choices.TimeConstantsApproximation.accurateEstimation, xdPu = 1.81, xlPu = 0.15, xpdPu = 0.3, xppdPu = 0.23, xppqPu = 0.25, xpqPu = 0.65, xqPu = 1.76)
  inner PowerGrids.Electrical.System systemPowerGrids(fNom = 50)
  Modelica.Blocks.Sources.Step PmPu(height = 0.0, offset = 0.0, startTime = 50)
  Modelica.Blocks.Sources.Step ufPu(height = 0, offset = 1)
equation
  connect(bus.terminal, machine.terminal)
  connect(ufPu.y, machine.ufPuIn)
  connect(PmPu.y, machine.PmPu)
end SynchronousMachine4WindingsNoLoadAccurate;


within PowerGrids.Electrical.Test;

model SynchronousMachine4WindingsNoLoadExact
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBus bus(PStart = 0, SNom = 5.5e+08, UNom = 24000, UStart = 24000, X = 0, portVariablesPhases = true, portVariablesPu = true, theta = 0)
  PowerGrids.Electrical.Machines.SynchronousMachine4Windings machine(H = 6, PStart = 0, QStart = 0, SNom = 5.5e+08, Tpd0 = 8, Tppd0 = 0.03, Tppq0 = 0.07, Tpq0 = 1, UNom = 24000, UStart = 24000, excitationPuType = PowerGrids.Types.Choices.ExcitationPuType.nominalStatorVoltageNoLoad, portVariablesPhases = true, raPu = 0.003, timeConstApprox = PowerGrids.Types.Choices.TimeConstantsApproximation.exactComputation, xdPu = 1.81, xlPu = 0.15, xpdPu = 0.3, xppdPu = 0.23, xppqPu = 0.25, xpqPu = 0.65, xqPu = 1.76)
  inner PowerGrids.Electrical.System systemPowerGrids(fNom = 50)
  Modelica.Blocks.Sources.Step PmPu(height = 0.0, offset = 0.0, startTime = 50)
  Modelica.Blocks.Sources.Step ufPu(height = 0, offset = 1)
equation
  connect(bus.terminal, machine.terminal)
  connect(ufPu.y, machine.ufPuIn)
  connect(PmPu.y, machine.PmPu)
end SynchronousMachine4WindingsNoLoadExact;


--daeMode -d=initialization,evaluateAllParameters.

within PowerGrids.Electrical.Test;

model SynchronousMachine4WindingsPowerSwing
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBus bus(SNom = 5.5e+08, UNom = 24000, UStart = 24000, X = 0, portVariablesPhases = true, portVariablesPu = true, theta = 0)
  PowerGrids.Electrical.Machines.SynchronousMachine4Windings machine(H = 6, PStart = -4.95e+08, QStart = -2.5e+08, SNom = 5.5e+08, Tpd0 = 8, Tppd0 = 0.03, Tppq0 = 0.07, Tpq0 = 1, UNom = 24000, UStart = 24000, excitationPuType = PowerGrids.Types.Choices.ExcitationPuType.nominalStatorVoltageNoLoad, portVariablesPhases = true, raPu = 0, timeConstApprox = PowerGrids.Types.Choices.TimeConstantsApproximation.exactComputation, xdPu = 1.81, xlPu = 0.15, xpdPu = 0.3, xppdPu = 0.23, xppqPu = 0.25, xpqPu = 0.65, xqPu = 1.76)
  inner PowerGrids.Electrical.System systemPowerGrids
  Modelica.Blocks.Sources.Step PmPu(height = 0.0, offset = 0.9, startTime = 0)
  Modelica.Blocks.Sources.Step ufPu(height = 0, offset = machine.ufPuInStart)
  PowerGrids.Electrical.Branches.LineConstantImpedance line(PStartA = 0, PStartB = 0, R = 0, SNom = 1e+08, UNom = 24000, X = 1, portVariablesPhases = true, portVariablesPu = true)
  PowerGrids.Electrical.Loads.LoadPQVoltageDependenceInputs load(PStart = 4.95e+08, QStart = 2.5e+08, SNom = 5.5e+08, UNom = 24000, UPhaseStart = 0.680678, portVariablesPhases = true)
  Modelica.Blocks.Sources.Step P(height = -10e6, offset = 495e6, startTime = 1)
  Modelica.Blocks.Sources.Step Q(height = 0, offset = 250e6)
equation
  connect(ufPu.y, machine.ufPuIn)
  connect(machine.terminal, line.terminalA)
  connect(line.terminalB, bus.terminal)
  connect(Q.y, load.QRefIn)
  connect(PmPu.y, machine.PmPu)
  connect(load.terminal, machine.terminal)
  connect(P.y, load.PRefIn)
end SynchronousMachine4WindingsPowerSwing;


Test case EquivalentGrid model.

within PowerGrids.Electrical.Test;

model TestEquivalentGrid "Test case EquivalentGrid model"
  extends Modelica.Icons.Example;
  import Modelica.ComplexMath;
  inner PowerGrids.Electrical.System systemPowerGrids
  PowerGrids.Electrical.Buses.InfiniteBus voltageSource( SNom = 5e+08, UNom = 380000, URef = 380000, portVariablesPhases = true, portVariablesPu = true)
  PowerGrids.Electrical.Branches.LineConstantImpedance equivalentLine(R = 6.32207, SNom = 5e+08, UNom = 380000, X = 63.2207, portVariablesPhases = true, portVariablesPu = true)
  Buses.EquivalentGrid equivalentGrid(R_X = 1 / 10, SNom = 5e+08, SSC = 2.5e+09, UNom = 380000, URef = 1.050 * 380e3, c = 1.1, portVariablesPhases = true, portVariablesPu = true)
  Buses.Ground ground
  Loads.LoadPQVoltageDependence load(PRefConst = 1e+07, QRefConst = 2e+07, SNom = 5e+08, UNom = 380000, portVariablesPhases = true)
  Modelica.Blocks.Sources.RealExpression shortCircuitCapacity(y = ComplexMath.'abs'(equivalentLine.portB.S) * equivalentGrid.c)
equation
  connect(load.terminal, equivalentGrid.terminal)
  connect(ground.terminal, equivalentLine.terminalA)
  connect(equivalentLine.terminalB, voltageSource.terminal)
end TestEquivalentGrid;


within PowerGrids.Electrical.Test;
model TestExciterRectifierRegulationCharacteristicIEEE
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Controls.ExcitationSystems.BaseClasses.ExciterRectifierRegulationCharacteristicEquationsIEEE exciterRectifierRegulationCharacteristicIEEE
  Modelica.Blocks.Sources.RealExpression realExpression(y = time)
equation
  connect(realExpression.y, exciterRectifierRegulationCharacteristicIEEE.u)
end TestExciterRectifierRegulationCharacteristicIEEE;


within PowerGrids.Electrical.Test;

model TestExciterVoltageTransducerIEEE
  extends Modelica.Icons.Example;
  Modelica.ComplexBlocks.Sources.ComplexConstant V(k.re = -1, k.im = 1)
  Modelica.ComplexBlocks.Sources.ComplexConstant I(k.re = 1, k.im = 1)
  PowerGrids.Electrical.VoltageTransducers.ExciterVoltageTransducerIEEE exciterVoltageTransducerIEEE(ki = 1,kp = sqrt(2), thetap = 0.785398, xl = 1)
equation
  connect(I.y, exciterVoltageTransducerIEEE.It)
  connect(V.y, exciterVoltageTransducerIEEE.Vt)
end TestExciterVoltageTransducerIEEE;


Same behaviour as <a href=\.

within PowerGrids.Electrical.Test;
model TestOneBusTransmissionLineWithBreakersOneLoad
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBus(SNom = 1e+07, UNom = 10000, portVariablesPu = true, theta = 0.523599)
  PowerGrids.Electrical.Loads.LoadPQVoltageDependence loadPQ(PRefConst = 1e+07, QRefConst = 0, SNom = 1e+07, UNom = 10000, alpha = 0, beta = 0, portVariablesPhases = true)
  inner PowerGrids.Electrical.System systemPowerGrids
  PowerGrids.Electrical.Branches.LineConstantImpedanceWithBreakers transmissionLine(B = 0.02, G = 0.01,R = 0.3, SNom = 1e+07, UNom = 10000, X = 1.5, portVariablesPu = true)
equation
  connect(infiniteBus.terminal, transmissionLine.terminalA)
  connect(transmissionLine.terminalB, loadPQ.terminal)

end TestOneBusTransmissionLineWithBreakersOneLoad;


Time lag before changing the first tap.

within PowerGrids.Electrical.Test;

model TestTapChangerLogicInterval
  extends Modelica.Icons.Example;
  extends PowerGrids.Electrical.Branches.BaseClasses.TapChangerPhaseShifterLogicInterval
    (t1st = 3 "Time lag before changing the first tap",
    tNext = 2 "Time lag before changing subsequent taps",
    tapMin = 1 "Minimum tap",
    tapMax = 20 "Maximum tap",
    Ntap = 20 "Number of taps",
    actionSel = ActionType.direct "Tap direct or reverse action selector",
    lockedStart = false "Wether the tap-changer/phase-shifter is initially locked",
    runningStart = true "Wether the tap-changer/phase-shifter is initially running",
    tapStart = 10 "Initial tap",
    stateStart = State.standard "Initial state",
    tToStandardState = 2 "Time lag before transition to standard state, in order to avoid chattering");
    Real U = sin(2*Modelica.Constants.pi*time/40) "Monitored Value";
    Real Umin = -0.5;
    Real Umax = 0.5;
equation
  locked = time < 20;
  running = true;
  valueAboveMax = U > Umax;
  valueUnderMin = U < Umin;
end TestTapChangerLogicInterval;


Time lag before changing the first tap.

within PowerGrids.Electrical.Test;
model TestTapChangerLogicMax
  extends Modelica.Icons.Example;
  extends PowerGrids.Electrical.Branches.BaseClasses.TapChangerPhaseShifterLogicMax(
    t1st = 3 "Time lag before changing the first tap",
    tNext = 1 "Time lag before changing subsequent taps",
    Ntap = 10 "Number of taps",
    actionSel = ActionType.direct "Tap direct or reverse action selector",
    lockedStart = false "Wether the tap-changer/phase-shifter is initially locked",
    runningStart = true "Wether the tap-changer/phase-shifter is initially running",
    tapStart = 10 "Initial tap",
    stateStart = State.standard "Initial state");
equation
  locked = time >= 5 and time < 8;
  running = true;
  valueUnderStop = time >= 15.5;
  valueAboveMax = time >= 1 and time < 10;
end TestTapChangerLogicMax;


within PowerGrids.Electrical.Test;

model TestTerminalVoltageTransducerIEEE
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.VoltageTransducers.TerminalVoltageTransducerIEEE terminalVoltageTransducer(Rc = 1, Xc = 1, Tr = 1, initType = Modelica.Blocks.Types.Init.InitialOutput)
  Modelica.ComplexBlocks.Sources.ComplexConstant V(k.re = -1, k.im = 1)
  Modelica.ComplexBlocks.Sources.ComplexConstant I(k.re = 1, k.im = 1)
equation
  connect(I.y, terminalVoltageTransducer.It)
  connect(V.y, terminalVoltageTransducer.Vt)
end TestTerminalVoltageTransducerIEEE;


Similar to <a href=\.

within PowerGrids.Electrical.Test;

model TestTransformerFixedRatio
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBus(SNom = 1e+07, UNom = 5000, portVariablesPu = true, theta = 0.523599)
  PowerGrids.Electrical.Loads.LoadPQVoltageDependence loadPQ(PRefConst = 1e+07, QRefConst = 0, SNom = 1e+07, UNom = 10000, alpha = 0, beta = 0, portVariablesPhases = true)
  inner PowerGrids.Electrical.System systemPowerGrids
  PowerGrids.Electrical.Branches.TransformerFixedRatio transformer(R = 0.3, SNom = 1e+07, UNomA = 5000, UNomB = 10000, X = 1.5, portVariablesPu = true, rFixed = 2)
equation
  connect(infiniteBus.terminal, transformer.terminalA)
  connect(transformer.terminalB, loadPQ.terminal)
end TestTransformerFixedRatio;


Similar to <a href=\.

within PowerGrids.Electrical.Test;

model TestTransformerFixedRatioWithBreaker
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBus1(SNom = 1e+07, UNom = 5000, portVariablesPu = true, theta = 0.523599)
  PowerGrids.Electrical.Loads.LoadPQVoltageDependence loadPQ(PRefConst = 1e+07, QRefConst = 0, SNom = 1e+07, UNom = 10000, alpha = 0, beta = 0, portVariablesPhases = true)
  inner PowerGrids.Electrical.System systemPowerGrids
  PowerGrids.Electrical.Branches.TransformerFixedRatioWithBreaker transformer(B = 1e-6, G = 1e-6,R = 0.3, SNom = 1e+07, UNomA = 5000, UNomB = 10000, X = 1.5, portVariablesPu = true, rFixed = 2, useBreaker = true)
  Modelica.Blocks.Sources.BooleanExpression breakerState(y = time < 2)
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBus2(SNom = 1e+07, UNom = 10000, portVariablesPu = true, theta = 0.523599)
  Branches.LineConstantImpedance line(R = 0.06, SNom = 1e+7, UNom = 10000, X = 1.5)
equation
  connect(infiniteBus1.terminal, transformer.terminalA)
  connect(transformer.terminalB, loadPQ.terminal)
  connect(breakerState.y, transformer.breakerStatusIn)
  connect(loadPQ.terminal, line.terminalA)
  connect(line.terminalB, infiniteBus2.terminal)
end TestTransformerFixedRatioWithBreaker;


within PowerGrids.Electrical.Test;

model TestTransformerWithTapChangerInterval
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBusVariableVoltage infiniteBus(R = 0, SNom = 1e+06, UNom = 1000, X = 0, useUIn = true)
  PowerGrids.Electrical.Branches.TransformerWithTapChangerInterval trafo(B = 0, G = 0, K = {2, 3, 4, 5, 6}, Ntap = 5, R = 1, SNom = 1e+06, UMax = 4000, UMin = 2000, UNomA = 1000, UNomB = 1000, X = 1, actionSel = PowerGrids.Electrical.Branches.TransformerWithTapChangerInterval.ActionType.direct, portVariablesPu = true, t1st = 1, tNext = 0.1, tapStart = 2)
  PowerGrids.Electrical.Buses.InfiniteBus busLoad(R = 1000, SNom = 1e+06, UNom = 1000, X = 0, theta = 0)
  Modelica.Blocks.Sources.RealExpression Uset(y = 500 * (sin(6.28 * time / 40) + 2))
  inner PowerGrids.Electrical.System systemPowerGrids
equation
  connect(Uset.y, infiniteBus.UIn)
  connect(trafo.terminalB, busLoad.terminal)
  connect(infiniteBus.terminal, trafo.terminalA)
end TestTransformerWithTapChangerInterval;


within PowerGrids.Electrical.Test;

model TestTransformerWithTapChangerMax
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBusVariableVoltage infiniteBus(R = 0, SNom = 1e+06, UNom = 1000, X = 0, portVariablesPu = true, useUIn = true)
  PowerGrids.Electrical.Branches.TransformerWithTapChangerMax trafo(B = 0, G = 0, K = {1, 2, 3, 4, 5}, Ntap = 5, R = 1, SNom = 1e+06, UMax = 4500, UNomA = 1000, UNomB = 1000, UStop = 2600, X = 1, actionSel = PowerGrids.Electrical.Branches.TransformerWithTapChangerInterval.ActionType.direct, portVariablesPu = true, t1st = 1, tNext = 2, tapStart = 5)
  PowerGrids.Electrical.Buses.InfiniteBus busLoad(R = 1000, SNom = 1e+06, UNom = 1000, X = 0, portVariablesPu = true, theta = 0)
  Modelica.Blocks.Sources.RealExpression Uset(y = 500 * (sin(6.28 * time / 40) + 1))
  inner PowerGrids.Electrical.System systemPowerGrids
equation
  connect(Uset.y, infiniteBus.UIn)
  connect(trafo.terminalB, busLoad.terminal)
  connect(infiniteBus.terminal, trafo.terminalA)
end TestTransformerWithTapChangerMax;


<span style=\.

within PowerGrids.Electrical.Test;
model TestTwoBusesTwoLinesOneLoadOneBreakerOpenClosePortA
  extends TestTwoBusesTwoTransmLinesWithBreakersOneLoad(transmissionLine2.useBreakerA = true);
  Modelica.Blocks.Sources.BooleanExpression BreakerStatus(y = time < 1 or time >= 10)
equation
  connect(BreakerStatus.y, transmissionLine2.breakerStatusA)

end TestTwoBusesTwoLinesOneLoadOneBreakerOpenClosePortA;


<p style=\.

within PowerGrids.Electrical.Test;
model TestTwoBusesTwoLinesOneLoadOneBreakerOpenClosePortB
  extends TestTwoBusesTwoTransmLinesWithBreakersOneLoad(transmissionLine1.useBreakerB = true);
  Modelica.Blocks.Sources.BooleanExpression BreakerStatus(y = time < 1 or time >= 10)
equation
  connect(transmissionLine1.breakerStatusB, BreakerStatus.y)

end TestTwoBusesTwoLinesOneLoadOneBreakerOpenClosePortB;


<p style=\.

within PowerGrids.Electrical.Test;
model TestTwoBusesTwoLinesOneLoadOneBreakerOpenClosePortsAB
  extends TestTwoBusesTwoTransmLinesWithBreakersOneLoad(transmissionLine1.useBreakerB = true, transmissionLine1.portVariablesPu = true, transmissionLine1.useBreakerA = true, transmissionLine2.portVariablesPu = true, transmissionLine2.useBreakerA = true, transmissionLine2.useBreakerB = true);
  Modelica.Blocks.Sources.BooleanExpression BreakerStatusLine1AB(y = time < 1 or time >= 2)
  Modelica.Blocks.Sources.BooleanExpression BreakerStatusLine2A(y = time < 3 or time >= 5)
  Modelica.Blocks.Sources.BooleanExpression BreakerStatusLine2B(y = time < 4 or time >= 5)
equation
  connect(BreakerStatusLine2B.y, transmissionLine2.breakerStatusB)
  connect(BreakerStatusLine2A.y, transmissionLine2.breakerStatusA)
  connect(BreakerStatusLine1AB.y, transmissionLine1.breakerStatusB)
  connect(BreakerStatusLine1AB.y, transmissionLine1.breakerStatusA)

end TestTwoBusesTwoLinesOneLoadOneBreakerOpenClosePortsAB;


<span style=\.

within PowerGrids.Electrical.Test;
model TestTwoBusesTwoTransmLinesWithBreakersOneLoad
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBus1(SNom = 1e+07, UNom = 10000, portVariablesPu = true, theta = 0.523599)
  PowerGrids.Electrical.Loads.LoadPQVoltageDependence loadPQ(PRefConst = 1e+07, QRefConst = 0, SNom = 1e+07, UNom = 10000, alpha = 0, beta = 0, portVariablesPhases = true)
  inner PowerGrids.Electrical.System systemPowerGrids
  PowerGrids.Electrical.Branches.LineConstantImpedanceWithBreakers transmissionLine1(B = 0.02, G = 0.01,R = 0.3, SNom = 1e+07, UNom = 10000, X = 1.5, portVariablesPu = true)
  PowerGrids.Electrical.Branches.LineConstantImpedanceWithBreakers transmissionLine2(B = 0.02, G = 0.01,R = 0.3, SNom = 1e+07, UNom = 10000, X = 1.5, portVariablesPu = true)
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBus2(SNom = 1e+07, UNom = 10000, portVariablesPu = true, theta = 0.523599)
equation
  connect(transmissionLine2.terminalB, infiniteBus2.terminal)
  connect(loadPQ.terminal, transmissionLine2.terminalA)
  connect(transmissionLine1.terminalB, loadPQ.terminal)
  connect(infiniteBus1.terminal, transmissionLine1.terminalA)

end TestTwoBusesTwoTransmLinesWithBreakersOneLoad;


This model demonstrates the dissipation of reactive power of a purely inductive transmission line, connected to two infinite buses, one with a phase-to-phase voltage U = 10 kV, one with a phase-to-phase voltage U = 9 kV, both with a 30 deg phase. The reactance of each conductor is 1 Ohm.

As a consequence, the current flowing in each conductor is

I = (VA - VB)/X = ((UA-UB)/sqrt3)/X = 577.35 A.

The active power flow in the line is zero. The reactive power entering the line from portA is

3*VA*I' = UA*(UA - UB)*X = 10 MW

while the reactive power dissipated by the transmission line is

portA.P + portB.P = 3*(VA - VB)*I = (UA - UB)^2/R = 1 MW

By choosing a base power of 10 MW and a base voltage of 10 kV, the current flowing through the line is 1 p.u., the active power entering portA of the line is 1 p.u. and the active power leaving portB of the line is 0.9 p.u. All currents and voltages have 30 deg phase.

.

within PowerGrids.Electrical.Test;

model TwoBusesInductiveTransmissionLine
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBusA(SNom = 1e+07, UNom = 10000, portVariablesPu = true, theta = 0.523599)
  inner PowerGrids.Electrical.System systemPowerGrids
  PowerGrids.Electrical.Branches.LineConstantImpedance transmissionLine(R = 0, SNom = 1e+07, UNom = 10000, X = 1, portVariablesPhases = true, portVariablesPu = true)
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBusB(SNom = 1e+07, UNom = 9000, portVariablesPu = true, theta = 0.523599)
equation
  connect(infiniteBusA.terminal, transmissionLine.terminalA)
  connect(transmissionLine.terminalB, infiniteBusB.terminal)
end TwoBusesInductiveTransmissionLine;


This model demonstrates the transmission of active power through a purely inductive transmission line, connected to two infinite buses with a phase-to-phase voltage of 10 kV. The generator at portA of the line has 30 deg phase, the other one has 0 deg phase. The reactance of each conductor is 1 Ohm.

The active power flow from portA to portB is

P = 3(VA*VB)/X*sin(delta)= UA*UB/X*sin(delta) = 50 MW.

By choosing a base power of 100 MW and a base voltage of 10 kV, the active power flow from portA to portB is 0.5 p.u.

.

within PowerGrids.Electrical.Test;

model TwoBusesPowerTransferTransmissionLine
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBusA(SNom = 1e+08, UNom = 10000, portVariablesPhases = true, portVariablesPu = true, theta = 0.523599)
  inner PowerGrids.Electrical.System systemPowerGrids
  PowerGrids.Electrical.Branches.LineConstantImpedance transmissionLine(R = 0, SNom = 1e+08, UNom = 10000, X = 1, portVariablesPhases = true, portVariablesPu = true)
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBusB(SNom = 1e+08, UNom = 10000, portVariablesPhases = true, portVariablesPu = true, theta = 0)
equation
  connect(infiniteBusA.terminal, transmissionLine.terminalA)
  connect(transmissionLine.terminalB, infiniteBusB.terminal)
end TwoBusesPowerTransferTransmissionLine;


This model demonstrates the dissipation of active power of a purely resistive transmission line, connected to two infinite buses, one with a phase-to-phase voltage U = 10 kV, one with a phase-to-phase voltage U = 9 kV, both with a 30 deg phase. The resistance of each conductor is 1 Ohm.

As a consequence, the current flowing in each conductor is

I = (VA - VB)/R = ((UA-UB)/sqrt3)/R = 577.35 A.

The reactive power flow in the line is zero. The active power entering the line from portA is

3*VA*I = UA*(UA - UB)/R = 10 MW

while the active power dissipated by the transmission line is

portA.P + portB.P = 3*(VA - VB)*I = (UA - UB)^2/R = 1 kW

By choosing a base power of 10 MW and a base voltage of 10 kV, the current flowing through the line is 1 p.u., the active power entering portA of the line is 1 p.u. and the active power leaving portB of the line is 0.9 p.u. All currents and voltages have 30 deg phase.

.

within PowerGrids.Electrical.Test;

model TwoBusesResistiveTransmissionLine
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBusA(SNom = 1e+07, UNom = 10000, portVariablesPu = true, theta = 0.523599)
  inner PowerGrids.Electrical.System systemPowerGrids
  PowerGrids.Electrical.Branches.LineConstantImpedance transmissionLine(R = 1, SNom = 1e+07, UNom = 10000, X = 0, portVariablesPhases = true, portVariablesPu = true)
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBusB(SNom = 1e+07, UNom = 9000, portVariablesPu = true, theta = 0.523599)
equation
  connect(infiniteBusA.terminal, transmissionLine.terminalA)
  connect(transmissionLine.terminalB, infiniteBusB.terminal)
end TwoBusesResistiveTransmissionLine;


This model demonstrates the behaviour of a purely resistive transmission line with a purely resistive intermediate fault.

At the beginning of the transient, a current flows from bus A (phase to phase voltage 10 kV) to bus B (phase-to-phase voltage 9 kV) through a resistance of 1 Ohm.

As a consequence, the current flowing in each conductor is

I = (VA - VB)/R = ((UA-UB)/sqrt3)/R = 577.35 A.

When the fault is activated, the analytical computation of the current flowing into the fault yields a current of 10.5215 kA, which corresponds to the simulation result.

At time = 0.6 the fault is cleared and the current through the line returns to the original value.

.

within PowerGrids.Electrical.Test;

model TwoBusesResistiveTransmissionLineFault
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBusA(SNom = 1e+07, UNom = 10000, portVariablesPu = true, theta = 0.523599)
  inner PowerGrids.Electrical.System systemPowerGrids
  PowerGrids.Electrical.Branches.LineConstantImpedanceFault transmissionLine(R = 1, RFault = 0.3, SNom = 1e+07, UNom = 10000, X = 0, XFault = 0, faultLocationPu = 0.7, portVariablesPhases = true, portVariablesPu = true, startTime = 0.4, stopTime = 0.6)
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBusB(SNom = 1e+07, UNom = 9000, portVariablesPu = true, theta = 0.523599)
equation
  connect(infiniteBusA.terminal, transmissionLine.terminalA)
  connect(transmissionLine.terminalB, infiniteBusB.terminal)
end TwoBusesResistiveTransmissionLineFault;


This model demonstrates the effect of the shunt admittance of the transmission line, connected to two infinite buses, with phase-to-phase voltage U = 10 kV and 30 deg phase. The line resistance is very high, so there is practically no current flowing through. The shunt admittance and susceptance are both 0.01 Ohm.

As a consequence, the two currents flowing into the line from each port are rotated by 45 deg with respect to the 30 deg voltage angle. The active power on each side is 0.5 MW and the reactive power is -0.5 MVA, which correspond to 0.05 and -0.05 pu with the chosen base quantities.

.

within PowerGrids.Electrical.Test;

model TwoBusesShuntTransmissionLine
  extends Modelica.Icons.Example;
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBusA(SNom = 1e+07, UNom = 10000, portVariablesPu = true, theta = 0.523599)
  inner PowerGrids.Electrical.System systemPowerGrids
  PowerGrids.Electrical.Branches.LineConstantImpedance transmissionLine(B = 0.01, G = 0.01, R = 1e8, SNom = 1e+07, UNom = 10000, X = 0, portVariablesPhases = true, portVariablesPu = true)
  PowerGrids.Electrical.Buses.InfiniteBus infiniteBusB(SNom = 1e+07, UNom = 10000, portVariablesPu = true, theta = 0.523599)
equation
  connect(infiniteBusA.terminal, transmissionLine.terminalA)
  connect(transmissionLine.terminalB, infiniteBusB.terminal)
end TwoBusesShuntTransmissionLine;


Exciter voltage transducer.

within PowerGrids.Electrical.VoltageTransducers;
model ExciterVoltageTransducerIEEE "Exciter voltage transducer"
  parameter SI.PerUnit kp = 9.3"First potential circuit gain";
  parameter SI.Angle thetap = 0 "Potential circuit phase angle Thetap";
  parameter SI.PerUnit ki = 0 "Second potential circuit gain coefficient";
  parameter SI.PerUnit xl = 0.124 "Reactance associated with potential source";
  Modelica.ComplexBlocks.Interfaces.ComplexInput Vt
  Modelica.ComplexBlocks.Interfaces.ComplexInput It
  Modelica.Blocks.Interfaces.RealOutput Ve
  Modelica.Blocks.Sources.Constant constKp(k = kp)
  Modelica.Blocks.Sources.Constant constThetap(k = thetap)
  Modelica.ComplexBlocks.ComplexMath.Add add1
  Modelica.ComplexBlocks.ComplexMath.ComplexToPolar complexToPolar
  Modelica.ComplexBlocks.ComplexMath.PolarToComplex complexKp
  Modelica.ComplexBlocks.ComplexMath.Gain gainXl(k.re = 0, k.im = xl)
  Modelica.ComplexBlocks.ComplexMath.Gain J(k.re = 0, k.im = 1)
  Modelica.ComplexBlocks.ComplexMath.Product prod1
  Modelica.ComplexBlocks.ComplexMath.Add add2
  Modelica.ComplexBlocks.ComplexMath.Product prod2
  Modelica.ComplexBlocks.Sources.ComplexConstant constKi(k.re = ki, k.im = 0)
equation
  connect(constKi.y, add1.u2)
  connect(Vt, prod2.u1)
  connect(complexToPolar.len, Ve)
  connect(add2.y, complexToPolar.u)
  connect(prod1.y, add2.u2)
  connect(prod2.y, add2.u1)
  connect(complexKp.y, prod2.u2)
  connect(It, prod1.u2)
  connect(J.y, prod1.u1)
  connect(add1.y, J.u)
  connect(gainXl.y, add1.u1)
  connect(complexKp.y, gainXl.u)
  connect(constThetap.y, complexKp.phi)
  connect(constKp.y, complexKp.len)
end ExciterVoltageTransducerIEEE;


Voltage transducer models

within PowerGrids.Electrical;
package VoltageTransducers "Voltage transducer models"
  extends Modelica.Icons.Package;
end VoltageTransducers;


Terminal voltage transducer IEEE.

within PowerGrids.Electrical.VoltageTransducers;
model TerminalVoltageTransducerIEEE "Terminal voltage transducer IEEE"
  parameter Modelica.SIunits.Time Tr = 0 "Transducer time constant";
  parameter Modelica.SIunits.PerUnit Rc = 0 "Load compensation resistance";
  parameter Modelica.SIunits.PerUnit Xc = 0 "Load compensation reactance";
  parameter Modelica.Blocks.Types.Init initType=Modelica.Blocks.Types.Init.NoInit "Type of initialization (1: no init, 2: steady state, 3/4: initial output)"
  parameter Real yStart=0 "Initial or guess value of output (= state)"
  Modelica.ComplexBlocks.Interfaces.ComplexInput Vt
  Modelica.ComplexBlocks.Interfaces.ComplexInput It
  Modelica.Blocks.Interfaces.RealOutput Vc
  Modelica.ComplexBlocks.ComplexMath.RealToComplex constZc
  Modelica.Blocks.Sources.Constant constRc(k = Rc)
  Modelica.Blocks.Sources.Constant constXc(k = Xc)
  Modelica.ComplexBlocks.ComplexMath.Add add1
  Modelica.ComplexBlocks.ComplexMath.Product prod1
  Modelica.ComplexBlocks.ComplexMath.ComplexToPolar complexToPolar
  Modelica.Blocks.Continuous.FirstOrder firstOrder(T = Tr, initType = initType, y_start = yStart)
equation
  connect(firstOrder.y, Vc)
  connect(complexToPolar.len, firstOrder.u)
  connect(add1.y, complexToPolar.u)
  connect(Vt, add1.u1)
  connect(prod1.y, add1.u2)
  connect(It, prod1.u1)
  connect(constZc.y, prod1.u2)
  connect(constXc.y, constZc.im)
  connect(constRc.y, constZc.re)
end TerminalVoltageTransducerIEEE;


info

within PowerGrids.Examples;

package Overview
  extends Modelica.Icons.Information;
end Overview;


Information

within PowerGrids.Examples.ENTSOE;

package Info "Information"
  extends Modelica.Icons.Information;
end Info;


Simple example from ENTSO-E document

within PowerGrids.Examples;

package ENTSOE "Simple example from ENTSO-E document"
  extends Modelica.Icons.ExamplesPackage;
end ENTSOE;


Reproduces the basic static power flow, see fig. 3-1 of the report.

within PowerGrids.Examples.ENTSOE;

model SteadyState "Reproduces the basic static power flow, see fig. 3-1 of the report"
  extends Modelica.Icons.Example;
  inner PowerGrids.Electrical.System systemPowerGrids
  PowerGrids.Electrical.Machines.SynchronousMachine4Windings GEN(H = 4, PStart = -4.75e+08, QStart = -1.56e+08, SNom = 5e+08, Tpd0 = 5.143, Tppd0 = 0.042, Tppq0 = 0.083, Tpq0 = 2.16, UNom = 21000, UPhaseStart = 0.161146, UStart = 21e3 * 0.992, portVariablesPhases = true, raPu = 0, xdPu = 2, xlPu = 0.15, xpdPu = 0.35, xppdPu = 0.25, xppqPu = 0.3, xpqPu = 0.5, xqPu = 1.8)
  PowerGrids.Electrical.Buses.Bus NTLV(SNom = 5e+08, UNom = 21000, portVariablesPhases = true, portVariablesPu = true)
  PowerGrids.Electrical.Buses.Bus NTHV(SNom = 5e+08, UNom = 380000, UPhaseStart = 0, UStart = 1.050 * 380e3,portVariablesPhases = true, portVariablesPu = true)
  PowerGrids.Electrical.Branches.TransformerFixedRatio TGEN(PStartA = 4.75e+08, PStartB = -4.75e+08, QStartA = 1.56e+08, QStartB = -7.6e+07, R = 0.15e-2 * 419 ^ 2 / 500, SNom = 5e+08, UNomA = 21000, UNomB = 419000, UPhaseStartA = 0.161146, UPhaseStartB = 0, UStartA = 0.992 * 21e3, UStartB = 1.050 * 380e3, X = 16e-2 * 419 ^ 2 / 500, portVariablesPhases = true, portVariablesPu = true, rFixed = 419 / 21)
  PowerGrids.Electrical.Controls.TurbineGovernors.IEEE_TGOV1 TGOV(R = 0.05, T1 = 0.5, T2 = 3, T3 = 10, VMax = 1)
  PowerGrids.Electrical.Controls.ExcitationSystems.IEEE_AC4A AVR(Ka = 200, Ta = 0.05, Tb = 10, Tc = 3, VrMax = 4)
  PowerGrids.Electrical.Controls.PowerSystemStabilizers.IEEE_PSS2A PSS(Ks1 = 10, Ks2 = 0.1564, M = 0, N = 0, T1 = 0.25, T2 = 0.03, T3 = 0.15, T4 = 0.015, T7 = 2, T8 = 0.5, T9 = 0.1, Tw1 = 2, Tw2 = 2, Tw3 = 2, Tw4 = 0, VstMax = 0.1, VstMin = -0.1)
  Modelica.Blocks.Sources.RealExpression zero
  Modelica.Blocks.Sources.RealExpression VrefPu(y = 1.004552)
  Modelica.Blocks.Sources.RealExpression RefLPu(y = 475 / 500 * 0.05)
  PowerGrids.Electrical.Loads.LoadImpedancePQ GRIDL(PRefConst = 4.75e+08, PStart(displayUnit = "W"), QRefConst = 7.6e+07, SNom = 5e+08, UNom = 380000, URef(displayUnit = "V") = 1.05 * 380e3, UStart(displayUnit = "V"), portVariablesPhases = true, portVariablesPu = true)

  Types.PerUnit       AA_01_NGEN_U = GEN.VPu;
  Types.PerUnit       AA_02_NGRID_U = GRID.port.VPu;
  Types.Angle         AA_03_NGRID_delta = GRID.port.UPhase;
  Types.Angle         AA_04_NGEN_delta = GEN.port.UPhase;
  Types.ActivePower   AA_05_PG = GEN.port.PGen;
  Types.ReactivePower AA_06_QG = GEN.port.QGen;
  Types.ActivePower   AA_07_PGRID = -GRID.port.P;
  Types.ReactivePower AA_08_QGRID = -GRID.port.Q;
  Types.ActivePower   AA_09_PGRIDL = GRIDL.port.P;
  Types.ReactivePower AA_10_QGRIDL = GRIDL.port.Q;
  Electrical.Buses.EquivalentGrid GRID(R_X = 1 / 10, SNom = 5e+08, SSC = 2.5e+09, UNom = 380000, URef = 1.05 * 380e3, c = 1.1, portVariablesPhases = true, portVariablesPu = true)
equation
  connect(VrefPu.y, AVR.VrefPu)
  connect(GRID.terminal, NTHV.terminal)
  connect(TGEN.terminalB, NTHV.terminal)
  connect(NTHV.terminal, GRIDL.terminal)
  connect(GEN.PPu, PSS.Vsi2Pu)
  connect(GEN.VPu, AVR.VcPu)
  connect(RefLPu.y, TGOV.RefLPu)
  connect(zero.y, AVR.VuelPu)
  connect(GEN.omegaPu, PSS.Vsi1Pu)
  connect(PSS.VstPu, AVR.VsPu)
  connect(AVR.efdPu, GEN.ufPuIn)
  connect(GEN.omegaPu, TGOV.omegaPu)
  connect(TGOV.PMechPu, GEN.PmPu)
  connect(NTLV.terminal, TGEN.terminalA)
  connect(GEN.terminal, NTLV.terminal)
end SteadyState;