Base package of all phase systems

within Buildings.Electrical.PhaseSystems;
package PartialPhaseSystem "Base package of all phase systems"
  extends Modelica.Icons.Package;
  constant String phaseSystemName = "UnspecifiedPhaseSystem"
    "Name of the phase system represented by the package";
  constant Integer n "Number of independent voltage and current components";
  constant Integer m "Number of reference angles";

  type Current = Real(unit = "A", quantity = "Current." + phaseSystemName)
    "Current for connector"

  type Voltage = Real(unit = "V", quantity = "Voltage." + phaseSystemName)
    "Voltage for connector"

  type ReferenceAngle "Reference angle for connector"
    extends Modelica.Units.SI.Angle;

    function equalityConstraint "Assert that angles are equal"
      extends Modelica.Icons.Function;
      input ReferenceAngle theta1[:];
      input ReferenceAngle theta2[:];
      output Real residue[0];
    algorithm
      for i in 1:size(theta1, 1) loop
        assert(abs(theta1[i] - theta2[i]) < Modelica.Constants.eps,
          "Angles theta1 and theta2 are not equal over the connection.");
      end for;
    end equalityConstraint;
  end ReferenceAngle;

  replaceable partial function j "Return vector rotated by 90 degrees"
    extends Modelica.Icons.Function;
    input Real x[n];
    output Real y[n];
  end j;

  replaceable partial function jj "Vectorized version of j"
    extends Modelica.Icons.Function;
    input Real[:,:] xx "array of voltage or current vectors";
    output Real[size(xx,1),size(xx,2)] yy "array of rotated vectors";
  algorithm
    //yy := {j(xx[:,k]) for k in 1:size(xx,2)};
    // Note: Dymola 2013 fails to expand
    for k in 1:size(xx,2) loop
      yy[:,k] := j(xx[:,k]);
    end for;
  end jj;

  replaceable partial function rotate
    "Rotate a vector of an angle theta (anti-counterclock)"
    extends Modelica.Icons.Function;
    input Real x[n];
    input Modelica.Units.SI.Angle theta;
    output Real y[n];
  end rotate;

  replaceable partial function product "Multiply two vectors"
      extends Modelica.Icons.Function;
      input Real x[n];
      input Real y[n];
      output Real z[n];
  end product;

  replaceable partial function divide "Divide two vectors"
      extends Modelica.Icons.Function;
      input Real x[n];
      input Real y[n];
      output Real z[n];
  end divide;

  replaceable partial function thetaRel
    "Return absolute angle of rotating system as offset to thetaRef"
    extends Modelica.Icons.Function;
    input Modelica.Units.SI.Angle theta[m];
    output Modelica.Units.SI.Angle thetaRel;
  end thetaRel;

  replaceable partial function thetaRef
    "Return absolute angle of rotating reference system"
    extends Modelica.Icons.Function;
    input Modelica.Units.SI.Angle theta[m];
    output Modelica.Units.SI.Angle thetaRef;
  end thetaRef;

  replaceable partial function phase "Return phase"
    extends Modelica.Icons.Function;
    input Real x[n];
    output Modelica.Units.SI.Angle phase;
  end phase;

  replaceable partial function phaseVoltages "Return phase to neutral voltages"
    extends Modelica.Icons.Function;
    input Modelica.Units.SI.Voltage V "system voltage";
    input Modelica.Units.SI.Angle phi=0 "phase angle";
    output Modelica.Units.SI.Voltage v[n] "phase to neutral voltages";
  end phaseVoltages;

  replaceable partial function phaseCurrents "Return phase currents"
    extends Modelica.Icons.Function;
    input Modelica.Units.SI.Current I "system current";
    input Modelica.Units.SI.Angle phi=0 "phase angle";
    output Modelica.Units.SI.Current i[n] "phase currents";
  end phaseCurrents;

  replaceable partial function phasePowers "Return phase powers"
    extends Modelica.Icons.Function;
    input Modelica.Units.SI.ActivePower P "active system power";
    input Modelica.Units.SI.Angle phi=0 "phase angle";
    output Modelica.Units.SI.Power p[n] "phase powers";
  end phasePowers;

  replaceable partial function phasePowers_vi "Return phase powers"
    extends Modelica.Icons.Function;
    input Modelica.Units.SI.Voltage v[n] "phase voltages";
    input Modelica.Units.SI.Current i[n] "phase currents";
    output Modelica.Units.SI.Power p[n] "phase powers";
  end phasePowers_vi;

  replaceable partial function systemVoltage
    "Return system voltage as function of phase voltages"
    extends Modelica.Icons.Function;
    input Modelica.Units.SI.Voltage v[n];
    output Modelica.Units.SI.Voltage V;
  end systemVoltage;

  replaceable partial function systemCurrent
    "Return system current as function of phase currents"
    extends Modelica.Icons.Function;
    input Modelica.Units.SI.Current i[n];
    output Modelica.Units.SI.Current I;
  end systemCurrent;

  replaceable partial function activePower
    "Return total power as function of phase powers"
    extends Modelica.Icons.Function;
    input Modelica.Units.SI.Voltage v[n] "phase voltages";
    input Modelica.Units.SI.Current i[n] "phase currents";
    output Modelica.Units.SI.ActivePower P "active system power";
  end activePower;
end PartialPhaseSystem;


within Buildings.Electrical.PhaseSystems;
package ThreePhase_d "AC system covering only resistive loads with three symmetric phases"
  extends DirectCurrent(phaseSystemName="ThreePhase_d");

  redeclare function phaseVoltages "Return phase to neutral voltages"
    extends Modelica.Icons.Function;
    input SI.Voltage V "system voltage";
    input SI.Angle phi = 0 "phase angle";
    output SI.Voltage v[n] "phase to neutral voltages";
  algorithm
    v := {V}/sqrt(3);
  end phaseVoltages;

  redeclare function systemVoltage
  "Return system voltage as function of phase voltages"
    extends Modelica.Icons.Function;
    input SI.Voltage v[n];
    output SI.Voltage V;
  algorithm
    V := sqrt(3)*v[1];
  end systemVoltage;
end ThreePhase_d;


within Buildings.Electrical.PhaseSystems;
package ThreePhase_dq "AC system, symmetrically loaded three-phase"
  extends PartialPhaseSystem(phaseSystemName="ThreePhase_dq", n=2, m=1);

  redeclare function extends j "Return vector rotated by 90 degrees"
  algorithm
    y := {-x[2], x[1]};
  end j;

  redeclare function extends thetaRel
  "Return absolute angle of rotating system as offset to thetaRef"
  algorithm
    thetaRel := 0;
  end thetaRel;

  redeclare function extends thetaRef
  "Return absolute angle of rotating reference system"
  algorithm
    thetaRef := theta[1];
  end thetaRef;

  redeclare function extends phase "Return phase"
  algorithm
    phase := atan2(x[2], x[1]);
  end phase;

  redeclare function extends phaseVoltages "Return phase to neutral voltages"
  algorithm
    v := {V*cos(phi), V*sin(phi)}/sqrt(3);
  end phaseVoltages;

  redeclare function extends phaseCurrents "Return phase currents"
  algorithm
    i := {I*cos(phi), I*sin(phi)};
  end phaseCurrents;

  redeclare function extends phasePowers "Return phase powers"
  algorithm
    p := {P, P*tan(phi)};
  end phasePowers;

  redeclare function extends phasePowers_vi "Return phase powers"
  algorithm
    p := {v*i, -j(v)*i};
  end phasePowers_vi;

  redeclare function extends systemVoltage
  "Return system voltage as function of phase voltages"
  algorithm
    V := Modelica.Fluid.Utilities.regRoot(3*v*v, delta = 1e-5);
  end systemVoltage;

  redeclare function extends systemCurrent
  "Return system current as function of phase currents"
  algorithm
    I := Modelica.Fluid.Utilities.regRoot(i*i, delta = 1e-5);
  end systemCurrent;

  redeclare function extends activePower
  "Return total power as function of phase powers"
  algorithm
    P := v[1]*i[1];
  end activePower;
end ThreePhase_dq;


AC system in dqo representation

within Buildings.Electrical.PhaseSystems;
package ThreePhase_dq0 "AC system in dqo representation"
  extends PartialPhaseSystem(phaseSystemName="ThreePhase_dqo", n=3, m=2);

  redeclare function extends j
  "Rotation(pi/2) of vector around {0,0,1} and projection on North plane"
  algorithm
    y := cat(1, {-x[2], x[1]}, zeros(size(x,1)-2));
  end j;

  redeclare function extends rotate
  "Rotate a vector of an angle theta (anti-counterclock)"
  algorithm
    y[1] := cos(theta)*x[1] - sin(theta)*x[2];
    y[2] := sin(theta)*x[1] + cos(theta)*x[2];
    y[3] := x[3];
  end rotate;

  redeclare function jj "Vectorized version of j"
  extends Modelica.Icons.Function;
    input Real[:,:] xx "array of voltage or current vectors";
    output Real[size(xx,1),size(xx,2)] yy "array of rotated vectors";
  algorithm
    yy := cat(1, {-xx[2,:], xx[1,:]}, zeros(size(xx,1)-2, size(xx,2)));
  end jj;

  redeclare function extends thetaRel
  "Return absolute angle of rotating system as offset to thetaRef"
  algorithm
    thetaRel := theta[1];
  end thetaRel;

  redeclare function extends thetaRef
  "Return absolute angle of rotating reference system"
  algorithm
    thetaRef := theta[2];
  end thetaRef;

  redeclare function extends phase "Return phase"
  algorithm
    phase := atan2(x[2], x[1]);
  end phase;

  redeclare function extends phaseVoltages "Return phase to neutral voltages"
  protected
    Voltage neutral_v = 0;
  algorithm
    v := {V*cos(phi), V*sin(phi), sqrt(3)*neutral_v}/sqrt(3);
  end phaseVoltages;

  redeclare function extends phaseCurrents "Return phase currents"
  algorithm
    i := {I*cos(phi), I*sin(phi), 0};
  end phaseCurrents;

  redeclare function extends phasePowers "Return phase powers"
  algorithm
    p := {P, P*tan(phi), 0};
  end phasePowers;

  redeclare function extends phasePowers_vi "Return phase powers"
  algorithm
    p := {v[1:2]*i[1:2], -j(v[1:2])*i[1:2], v[3]*i[3]};
  end phasePowers_vi;

  redeclare function extends systemVoltage
  "Return system voltage as function of phase voltages"
  algorithm
    V := Modelica.Fluid.Utilities.regRoot(v*v, delta = 1e-5);
  end systemVoltage;

  redeclare function extends systemCurrent
  "Return system current as function of phase currents"
  algorithm
    I := Modelica.Fluid.Utilities.regRoot(i*i, delta = 1e-5);
  end systemCurrent;

  redeclare function extends activePower
  "Return total power as function of phase powers"
  algorithm
    P := v[1]*i[1];
  end activePower;
end ThreePhase_dq0;


Two conductors for DC components

within Buildings.Electrical.PhaseSystems;
package TwoConductor "Two conductors for DC components"
  extends PartialPhaseSystem(phaseSystemName="TwoConductor", n=2, m=0);

  redeclare function extends j "Direct current has no complex component"
  algorithm
    y := zeros(n);
  end j;

  redeclare function extends rotate
  "Rotate a vector of an angle theta (anti-counterclock)"
  algorithm
    y[n] := x[n];
  end rotate;

  redeclare function extends thetaRel
  "Return absolute angle of rotating system as offset to thetaRef"
  algorithm
    thetaRel := 0;
  end thetaRel;

  redeclare function extends thetaRef
  "Return absolute angle of rotating reference system"
  algorithm
    thetaRef := 0;
  end thetaRef;

  redeclare function extends phase "Return phase"
  algorithm
    phase := 0;
  end phase;

  redeclare replaceable function extends phaseVoltages
  "Return phase to neutral voltages"
  algorithm
    v := 0.5*{V, -V};
  end phaseVoltages;

  redeclare function extends phaseCurrents "Return phase currents"
  algorithm
    i := {I, -I};
  end phaseCurrents;

  redeclare function extends phasePowers "Return phase powers"
  algorithm
    p := {P, 0};
  end phasePowers;

  redeclare function extends phasePowers_vi "Return phase powers"
  algorithm
    p := v.*i;
  end phasePowers_vi;

  redeclare replaceable function extends systemVoltage
  "Return system voltage as function of phase voltages"
  algorithm
    V := v[1] - v[2];
  end systemVoltage;

  redeclare function extends systemCurrent
  "Return system current as function of phase currents"
  algorithm
    I := (i[1] - i[2])/2;
  end systemCurrent;

  redeclare function extends activePower
  "Return total power as function of phase powers"
  algorithm
    P := v*i;
  end activePower;
end TwoConductor;


within Buildings.Electrical;
package Transmission "Package with models for transmission lines"
  extends Modelica.Icons.Package;
end Transmission;


within Buildings.Electrical.Transmission;
package BaseClasses "Package that contains partial models for lines and cables"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Partial cable line dispersion model. This partial model contains parameters and variables needed to parametrize a
generic cable. The resistance, inductance and capacitance
are computed by the functions associated to the type of cable selected.
The type of cable is specified using a record that inherits from

Buildings.Electrical.Transmission.BaseClasses.BaseCable such as (

Buildings.Electrical.Transmission.LowVoltageCables.Generic or

Buildings.Electrical.Transmission.MediumVoltageCables.Generic).
The record contains functions that depending on the properties of cable compute its
resistance, inductance or capacitance.

within Buildings.Electrical.Transmission.BaseClasses;
partial model PartialBaseLine "Partial cable line dispersion model"
  parameter Modelica.Units.SI.Length l(min=0) "Length of the line";
  parameter Modelica.Units.SI.Power P_nominal(min=0)
    "Nominal power of the line";
  parameter Modelica.Units.SI.Voltage V_nominal(min=0, start=220)
    "Nominal voltage of the line";
  final parameter Modelica.Units.SI.Frequency f_n=50
    "Frequency considered in the definition of cables properties";

  parameter Boolean use_C = false
    "Set to true to add a capacitance in the center of the line"
  parameter Buildings.Electrical.Types.Load modelMode=Buildings.Electrical.Types.Load.FixedZ_steady_state
    "Select between steady state and dynamic model"
  parameter Boolean use_T = false
    "If true, enables the input for the temperature of the cable"
  parameter Modelica.Units.SI.Temperature TCable=T_ref
    "Fixed temperature of the cable"

  parameter Buildings.Electrical.Types.CableMode mode=Buildings.Electrical.Types.CableMode.automatic
    "Select if choosing the cable automatically or between a list of commercial options"

  replaceable parameter
    Buildings.Electrical.Transmission.LowVoltageCables.Generic
     commercialCable constrainedby
    Buildings.Electrical.Transmission.BaseClasses.BaseCable
    "Commercial cables options"

  final parameter Modelica.Units.SI.Temperature T_ref=commercialCable.T_ref
    "Reference temperature of the line"
  final parameter Modelica.Units.SI.Temperature M=commercialCable.M
    "Temperature constant (R_actual = R*(M + T_heatPort)/(M + T_ref))";
  final parameter Modelica.Units.SI.Resistance R=commercialCable.lineResistance(
      l,
      f_n,
      commercialCable) "Resistance of the cable"
  final parameter Modelica.Units.SI.Inductance L=commercialCable.lineInductance(
      l,
      f_n,
      commercialCable)
    "Inductance of the cable due to mutual and self inductance"
  final parameter Modelica.Units.SI.Capacitance C=
      commercialCable.lineCapacitance(
      l,
      f_n,
      commercialCable) "Capacitance of the cable"
  Buildings.HeatTransfer.Sources.PrescribedTemperature cableTemp
    "Temperature of the cable"
  Modelica.Blocks.Interfaces.RealInput T if use_T "Temperature of the cable"
  Modelica.Blocks.Sources.RealExpression cableTemperature(y=T_in)
    "Temperature of the cable"
protected
  Modelica.Blocks.Interfaces.RealInput T_in
    "Internal variable for conditional temperature";
equation
  assert(L>=0 and R>=0 and C>=0, "The parameters R,L,C must be positive. Check cable properties and size.");
  connect(T_in, T);

  if not use_T then
    T_in = TCable;
  end if;

  connect(cableTemperature.y, cableTemp.T)
end PartialBaseLine;


Partial cable line dispersion model. This partial model extends the model
Buildings.Electrical.Transmission.BaseClasses.PartialBaseLine.
It adds two generalized electric connectors.

within Buildings.Electrical.Transmission.BaseClasses;
partial model PartialLine "Partial cable line dispersion model"
  extends Buildings.Electrical.Interfaces.PartialTwoPort;
  extends Buildings.Electrical.Transmission.BaseClasses.PartialBaseLine;
  Real VoltageLosses(unit = "1") = abs(PhaseSystem_p.systemVoltage(terminal_p.v) -
    PhaseSystem_n.systemVoltage(terminal_n.v))/
    Buildings.Utilities.Math.Functions.smoothMax(
      PhaseSystem_p.systemVoltage(terminal_p.v),
      PhaseSystem_n.systemVoltage(terminal_n.v),
      1.0) "Percentage of voltage losses across the line";
protected
  parameter Integer n_ = size(terminal_n.i,1) "Number of cables";
  parameter Real nominal_i_ = P_nominal / V_nominal
    "Nominal current flowing through the line";
  parameter Real nominal_v_ = V_nominal "Nominal voltage of the line";
end PartialLine;


Partial model that represent an electric network. This partial model represents a generalized electrical network.

within Buildings.Electrical.Transmission.BaseClasses;
partial model PartialNetwork "Partial model that represent an electric network"
  parameter Modelica.Units.SI.Voltage V_nominal(min=0, start=110)
    "Nominal voltage of the lines in the network";
  replaceable parameter Buildings.Electrical.Transmission.Grids.PartialGrid grid
    "Record that describe the grid with the number of nodes, links, connections, etc."
  replaceable Buildings.Electrical.Interfaces.BaseTerminal terminal[grid.nNodes]
    "Electric terminals for each node of the network"
  replaceable Buildings.Electrical.Transmission.BaseClasses.PartialBaseLine lines[grid.nLinks](
    each mode=Buildings.Electrical.Types.CableMode.commercial,
    l={grid.l[i, 1] for i in 1:grid.nLinks},
    each P_nominal=1000,
    each V_nominal=V_nominal)
    "Array of line models, each line connecting two nodes of the grid";
end PartialNetwork;


Partial model of an inductive element that links two electrical connectors. Partial model of an inductance that links two generalized electrical connectors.

within Buildings.Electrical.Transmission.BaseClasses;
partial model PartialTwoPortInductance
  "Partial model of an inductive element that links two electrical connectors"
  extends Interfaces.PartialTwoPort;
  parameter Modelica.Units.SI.Inductance L "Inductance"
equation
  Connections.branch(terminal_p.theta, terminal_n.theta);
  terminal_p.theta = terminal_n.theta;

  terminal_p.i = - terminal_n.i;
end PartialTwoPortInductance;


Partial model of a resistive element that links two electrical connectors. Partial model of a resistance that links two generalized electrical connectors.

within Buildings.Electrical.Transmission.BaseClasses;
partial model PartialTwoPortResistance
  "Partial model of a resistive element that links two electrical connectors"
  extends Interfaces.PartialTwoPort;
  extends Modelica.Electrical.Analog.Interfaces.ConditionalHeatPort(T = T_ref);
  parameter Modelica.Units.SI.Resistance R "Resistance at temperature T_ref";
  parameter Modelica.Units.SI.Temperature T_ref=298.15 "Reference temperature";
  parameter Modelica.Units.SI.Temperature M=507.65
    "Temperature constant (R_actual = R*(M + T_heatPort)/(M + T_ref))";
  Modelica.Units.SI.Resistance R_actual
    "Actual resistance = R*(M + T_heatPort)/(M + T_ref) ";
equation
  Connections.branch(terminal_p.theta, terminal_n.theta);
  terminal_p.theta = terminal_n.theta;

  assert(R_actual>=0,
   "The value of R_actual must be positive, check reference and actual temperatures.");

  R_actual =R*(M + Modelica.Units.Conversions.to_degC(T_heatPort))/(M +
    Modelica.Units.Conversions.to_degC(T_ref));

  terminal_p.i = - terminal_n.i;
end PartialTwoPortResistance;


Partial model of an RLC element that links two electrical connectors. Partial model of a resistance that links two generalized electrical connectors.

within Buildings.Electrical.Transmission.BaseClasses;
partial model PartialTwoPortRLC
  "Partial model of an RLC element that links two electrical connectors"
  extends Buildings.Electrical.Interfaces.PartialTwoPort;
  extends Modelica.Electrical.Analog.Interfaces.ConditionalHeatPort(T = T_ref);
  parameter Modelica.Units.SI.Resistance R "Resistance at temperature T_ref"
  parameter Modelica.Units.SI.Temperature T_ref=298.15 "Reference temperature";
  parameter Modelica.Units.SI.Temperature M=507.65
    "Temperature constant (R_actual = R*(M + T_heatPort)/(M + T_ref))";
  parameter Modelica.Units.SI.Capacitance C "Capacity";
  parameter Modelica.Units.SI.Inductance L "Inductance";
  parameter Modelica.Units.SI.Voltage V_nominal(min=0, start=110)
    "Nominal voltage (V_nominal >= 0)"
  Modelica.Units.SI.Resistance R_actual
    "Actual resistance = R*(M + T_heatPort)/(M + T_ref) ";
equation
  Connections.branch(terminal_p.theta, terminal_n.theta);
  terminal_p.theta = terminal_n.theta;

  assert(R_actual>=0,
   "The value of R_actual must be positive, check reference and actual temperatures");

  R_actual =R*(M + Modelica.Units.Conversions.to_degC(T_heatPort))/(M +
    Modelica.Units.Conversions.to_degC(T_ref));
end PartialTwoPortRLC;


within Buildings.Electrical.Transmission;
package Functions "Package that contains functions to compute cable properties"
  extends Modelica.Icons.Package;
end Functions;


This package contains validation models for the classes in
<a href=\

within Buildings.Electrical.Transmission.Functions;
package Validation
  extends Modelica.Icons.ExamplesPackage;
end Validation;


Validation model for the function that selects the cable. This model validates

Buildings.Electrical.Transmission.Functions.selectCable_low
for a different range of currents.

within Buildings.Electrical.Transmission.Functions.Validation;
model SelectCable_low
  "Validation model for the function that selects the cable"
  extends Modelica.Icons.Example;

  parameter Modelica.Units.SI.Voltage V_nominal=480 "Rated voltage";

  parameter Modelica.Units.SI.Power[:] P_nominal=I_nominal*V_nominal/
      safety_factor "Rated power";
  parameter Modelica.Units.SI.Current[:] I_nominal={65,95,110,130,170,220,230}
       .- 10 "Nominal current";

  parameter Real safety_factor = 1.2 "Safety factor";

  parameter Buildings.Electrical.Transmission.LowVoltageCables.Generic[:] cab = Buildings.Electrical.Transmission.Functions.selectCable_low(
    P_nominal = P_nominal,
    V_nominal = V_nominal)
    "Selected cable";
end SelectCable_low;


Validation model for the function that selects the cable. This model validates

Buildings.Electrical.Transmission.Functions.selectCable_med
for a different range of currents.

within Buildings.Electrical.Transmission.Functions.Validation;
model SelectCable_med
  "Validation model for the function that selects the cable"
  extends Modelica.Icons.Example;

  parameter Modelica.Units.SI.Voltage V_nominal=25e3 "Rated voltage";

  parameter Modelica.Units.SI.Power[:] P_nominal=I_nominal*V_nominal/
      safety_factor "Rated power";
  parameter Modelica.Units.SI.Current[:] I_nominal={195,250,285,375,450,640,800}
       .- 10 "Nominal current";

  parameter Real safety_factor = 1.2 "Safety factor";

  parameter Buildings.Electrical.Transmission.MediumVoltageCables.Generic[:] cab = Buildings.Electrical.Transmission.Functions.selectCable_med(
    P_nominal = P_nominal,
    V_nominal = V_nominal)
    "Selected cable";
end SelectCable_med;


Grid model inspired to the IEEE 34 Node test feeder. This model represents a grid inspired by the IEEE 34 node test feeder.
In this example, the cable types and lengths have been modified in order to
represent a typical distribution feeder.

within Buildings.Electrical.Transmission.Grids;
record IEEE_34_AL120 "Grid model inspired to the IEEE 34 Node test feeder"
  extends Buildings.Electrical.Transmission.Grids.PartialGrid(
    nNodes=34,
    nLinks=33,
    l=[48;16;16;40;32;16;16;16;16;16;16;32;32;16;32;32;32;48;48;32;32;16;16;16;
        16;16;32;32;16;32;16;16;16],
    fromTo=[[1,2]; [2,3]; [3,4]; [4,5]; [4,6]; [6,7]; [7,8]; [9,26]; [10,26]; [
        11,9]; [12,11]; [13,10]; [14,10]; [15,14]; [16,15]; [17,27]; [18,27]; [
        19,31]; [20,31]; [21,32]; [22,32]; [23,20]; [24,23]; [25,24]; [26,8]; [
        27,29]; [28,16]; [29,16]; [30,17]; [31,17]; [32,19]; [33,22]; [34,18]],
    redeclare Buildings.Electrical.Transmission.LowVoltageCables.Generic cables=
       {LowVoltageCables.PvcAl120(),LowVoltageCables.PvcAl120(),
        LowVoltageCables.PvcAl120(),LowVoltageCables.PvcAl120(),
        LowVoltageCables.PvcAl120(),LowVoltageCables.PvcAl120(),
        LowVoltageCables.PvcAl120(),LowVoltageCables.PvcAl120(),
        LowVoltageCables.PvcAl120(),LowVoltageCables.PvcAl120(),
        LowVoltageCables.PvcAl120(),LowVoltageCables.PvcAl120(),
        LowVoltageCables.PvcAl120(),LowVoltageCables.PvcAl120(),
        LowVoltageCables.PvcAl120(),LowVoltageCables.PvcAl70(),
        LowVoltageCables.PvcAl70(),LowVoltageCables.PvcAl35(),
        LowVoltageCables.PvcAl35(),LowVoltageCables.PvcAl35(),
        LowVoltageCables.PvcAl35(),LowVoltageCables.PvcAl35(),
        LowVoltageCables.PvcAl35(),LowVoltageCables.PvcAl35(),
        LowVoltageCables.PvcAl120(),LowVoltageCables.PvcAl70(),
        LowVoltageCables.PvcAl70(),LowVoltageCables.PvcAl70(),
        LowVoltageCables.PvcAl70(),LowVoltageCables.PvcAl70(),
        LowVoltageCables.PvcAl35(),LowVoltageCables.PvcAl35(),
        LowVoltageCables.PvcAl70()});

   /*
   LEFT HERE TO CHECK CONSISTENCY

   LenVec={
   0,48,16,16,40,
   32,16,16,16,16,
   16,16,32,32,16,
   32,32,32,48,48,
   32,32,16,16,16,
   16,16,32,32,16,
   32,16,16,16},

    CabTyp={
               ,.PvcAl120(),.PvcAl120(),.PvcAl120(),.PvcAl120(),
    .PvcAl120(),.PvcAl120(),.PvcAl120(),.PvcAl120(),.PvcAl120(),
    .PvcAl120(),.PvcAl120(),.PvcAl120(),.PvcAl120(),.PvcAl120(),
    .PvcAl120(),.PvcAl70(),.PvcAl70(),.PvcAl35(),.PvcAl35(),
    .PvcAl35(),.PvcAl35(),.PvcAl35(),.PvcAl35(),.PvcAl35(),
    .PvcAl120(),.PvcAl70(),.PvcAl70(),.PvcAl70(),.PvcAl70(),
    .PvcAl70(),.PvcAl35(),.PvcAl35(),.PvcAl70()});

   */
end IEEE_34_AL120;


within Buildings.Electrical.Transmission;
package Grids "Package that contains different types of grids"
  extends Modelica.Icons.MaterialPropertiesPackage;
end Grids;


Partial model that represents a generalized grid. This abstract grid model specifies the topology of the network by

within Buildings.Electrical.Transmission.Grids;
record PartialGrid "Partial model that represents a generalized grid"
  extends Modelica.Icons.MaterialProperty;
  parameter Integer nNodes "Number of nodes of the grid";
  parameter Integer nLinks "Number of links connecting the nodes";
  parameter Integer fromTo[nLinks,2]
    "Indexes [i,1]->[i,2] of the nodes connected by link i";
  parameter Modelica.Units.SI.Length l[nLinks,1](each min=0)
    "Length of the cable";
  replaceable Buildings.Electrical.Transmission.BaseClasses.BaseCable cables[nLinks]
    "Array that contains the characteristics of each cable";
end PartialGrid;


Simple model of a grid with 2 nodes and 1 link. This model represents a simple grid with two nodes and a single link between them.

within Buildings.Electrical.Transmission.Grids;
record TestGrid2Nodes "Simple model of a grid with 2 nodes and 1 link"
  extends Buildings.Electrical.Transmission.Grids.PartialGrid(
    nNodes=2,
    nLinks=1,
    fromTo=[[1,2]],
    l=[200],
    redeclare Buildings.Electrical.Transmission.LowVoltageCables.Generic
    cables = {LowVoltageCables.Cu35()});
end TestGrid2Nodes;


Simple model of a grid with 2 nodes and 1 link for medium voltage. This model represents a simple grid with two nodes and a single link between them.
This model differs from

Buildings.Electrical.Transmission.Grids.TestGrid2Nodes because it defines a medium voltage
cable instead of a low voltage cable.

within Buildings.Electrical.Transmission.Grids;
record TestGrid2NodesMedium
  "Simple model of a grid with 2 nodes and 1 link for medium voltage"
  extends Buildings.Electrical.Transmission.Grids.PartialGrid(
    nNodes=2,
    nLinks=1,
    fromTo=[[1,2]],
    l=[200],
    redeclare Buildings.Electrical.Transmission.MediumVoltageCables.Generic
    cables = {MediumVoltageCables.Annealed_Al_30()});
end TestGrid2NodesMedium;


within Buildings.Electrical.Transmission;
package LowVoltageCables "Package of low voltage electricity cables used in distribution grid"
  extends Modelica.Icons.MaterialPropertiesPackage;
end LowVoltageCables;


within Buildings.Electrical.Transmission;
package MediumVoltageCables "Package of medium voltage electricity cables used in distribution grid"
  extends Modelica.Icons.MaterialPropertiesPackage;
end MediumVoltageCables;


Package that contains cables materials

within Buildings.Electrical.Transmission;
package Types "Package that contains cables materials"
  extends Modelica.Icons.TypesPackage;
end Types;


Select automatically the size of the cable.

within Buildings.Electrical.Types;
type CableMode = enumeration(
    automatic "Select automatically the size of the cable",
    commercial "Select the cable from a list of commercial options")
  "Enumeration that defines how a cable can be parameterized"


Assume i=0 during homotopy initialization.

within Buildings.Electrical.Types;
type InitMode = enumeration(
    zero_current "Assume i=0 during homotopy initialization",
    linearized "Uses linear model during homotopy initialization")
  "Enumeration that defines the type of initialization assumption can be used for a load model"


Fixed Z, steady-state.

within Buildings.Electrical.Types;
type Load = enumeration(
    FixedZ_steady_state "Fixed Z, steady-state",
    FixedZ_dynamic "Fixed Z, dynamic",
    VariableZ_P_input "Variable Z, P input",
    VariableZ_y_input "Variable Z, y input")
  "Enumeration that defines the modeling assumption of the load."


within Buildings.Electrical;
package Types "This package contains new types used within the Electrical package"
  extends Modelica.Icons.TypesPackage;
end Types;


within Buildings.Electrical;
package Utilities "Package with models and functions that are used by other models"
  extends Modelica.Icons.Package;
end Utilities;


Voltage controller

within Buildings.Electrical.Utilities;
model VoltageControl "Voltage controller"
  replaceable package PhaseSystem =
      Buildings.Electrical.PhaseSystems.PartialPhaseSystem constrainedby
    Buildings.Electrical.PhaseSystems.PartialPhaseSystem "Phase system"
  parameter Modelica.Units.SI.Voltage V_nominal
    "Nominal voltage of the node to be controlled";
  parameter Real vThresh(min=0.0, max=1.0) = 0.1
    "Threshold that activates voltage ctrl (ratio of nominal voltage)";
  parameter Modelica.Units.SI.Time tDelay=300
    "Time to wait before plugging the load back";
  parameter Modelica.Units.SI.Time T=0.01
    "Time constant representing the switching time";
  parameter Real y_start = 1.0 "Initial value of the control output signal";
  final parameter Modelica.Units.SI.Voltage Vmin=V_nominal*(1 - vThresh)
    "Low threshold";
  final parameter Modelica.Units.SI.Voltage Vmax=V_nominal*(1 + vThresh)
    "High threshold";
  Modelica.Blocks.Interfaces.RealOutput y(start = y_start, stateSelect = StateSelect.prefer)
    "Control signal"
  replaceable Buildings.Electrical.Interfaces.Terminal terminal(
    redeclare replaceable package PhaseSystem = PhaseSystem)
    "Generalized terminal"
  Buildings.Electrical.Utilities.Controllers.StateMachineVoltCtrl ctrl(
    V_nominal=V_nominal,
    vThresh=vThresh,
    tDelay=tDelay)
    "Model that implements the state machines voltage controller";
initial equation
  y = y_start;
equation

  // Output of the control block
  y + T*der(y) = ctrl.y;

  // Voltage measurements
  ctrl.V = terminal.PhaseSystem.systemVoltage(terminal.v);

  // The controller does not consume current
  terminal.i = zeros(PhaseSystem.n);
end VoltageControl;


within Buildings.Electrical.Utilities;
package Controllers "Package that contains state machines and control models used by the utilities"
extends Modelica.Icons.BasesPackage;
end Controllers;


This model represents a simple voltage controller that unplug a load when
  there is a voltage fluctuation higher that a given threshold.. Function that implements a state machine that detects voltage
deviations. If the voltage input V exceeds the
nominal value V_nominal by more than 1+Vtr
then the control signal y becones zero for
a period equal to tDelay.

within Buildings.Electrical.Utilities.Controllers;
model StateMachineVoltCtrl "This model represents a simple voltage controller that unplug a load when
  there is a voltage fluctuation higher that a given threshold."
  Modelica.Blocks.Interfaces.RealInput V "Voltage of the node to be controlled";
  parameter Modelica.Units.SI.Voltage V_nominal
    "Nominal voltage of the node to be controlled";
  parameter Real vThresh(min=0.0, max=1.0) = 0.1
    "Threshold that activates voltage ctrl (ratio of nominal voltage)";
  parameter Modelica.Units.SI.Time tDelay=300
    "Time to wait before plugging the load back";
  output Real y
    "Output signal that represents whether the load should be connected to the grid or not";
protected
  discrete Boolean connected
    "Boolean variable that indicates when the load is connected";
  discrete Real tSwitch "Time instant when the last event occurred";
initial algorithm
  // Initialize with load connected and last event at t = 0
  connected := true;
  tSwitch := 0;
equation

  // Output for every state, connected or not
  if connected then
    y = 1.0;
  else
    y = 0.0;
  end if;

algorithm

  // Detect an overshoot in the voltage
  when
      (connected and (V > V_nominal*(1+vThresh))) then
    tSwitch := time;
    connected := false;
  end when;

  // Transition between not connected and connected again after the delay time has been elapsed
  when
      (not connected and time >= tSwitch + tDelay) then
    connected := true;
  end when;
end StateMachineVoltCtrl;


within Buildings.Electrical.Utilities;
package Examples "This package contais tests for check the correctness of the models"
extends Modelica.Icons.ExamplesPackage;
end Examples;


within Buildings.Electrical.Utilities.Examples;
model TestVoltageCTRL
  "This test check the correctness of the voltage controller model"
  extends Modelica.Icons.Example;
  VoltageControl voltageControl(
  redeclare Buildings.Electrical.DC.Interfaces.Terminal_p terminal,
    redeclare package PhaseSystem =
        Buildings.Electrical.PhaseSystems.TwoConductor,
    V_nominal=120,
    tDelay=2) "Voltage controller"
  DC.Sources.VoltageSource sou "Varriable voltage source"
  Modelica.Electrical.Analog.Basic.Ground ground
  Modelica.Blocks.Sources.Sine cosine(
    amplitude=20,
    f=0.1,
    phase=0,
    offset=120) "Variable voltage signal"
  Modelica.Blocks.Sources.Constant Vtr_high(k=120*(1 + 0.1))
    "Voltage threshold high"
equation
  connect(sou.terminal, voltageControl.terminal)
  connect(ground.p, sou.n)
  connect(cosine.y, sou.V_in)
end TestVoltageCTRL;


within Buildings;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


within Buildings.Examples;
model SimpleHouse
  "Illustrative example of a simple heating, ventilation and room model"
  extends Modelica.Icons.Example;

  package MediumAir = Buildings.Media.Air;
  package MediumWater = Buildings.Media.Water;

  parameter Modelica.Units.SI.Area AWall=100 "Wall area";
  parameter Modelica.Units.SI.Area AWin=5 "Window area";
  parameter Real gWin(min=0, max=1, unit="1") = 0.3 "Solar heat gain coefficient of window";
  parameter Modelica.Units.SI.Volume VZone=AWall*3 "Wall area";
  parameter Modelica.Units.SI.HeatFlowRate QHea_flow_nominal=700
    "Nominal capacity of heating system";
  parameter Modelica.Units.SI.MassFlowRate mWat_flow_nominal=QHea_flow_nominal/
      10/4200 "Nominal mass flow rate for water loop";
  parameter Modelica.Units.SI.MassFlowRate mAir_flow_nominal=VZone*2*1.2/3600
    "Nominal mass flow rate for air loop";

  parameter Modelica.Units.SI.PressureDifference dpAir_nominal=200
    "Pressure drop at nominal mass flow rate for air loop";
  parameter Boolean allowFlowReversal=false
    "= false because flow will not reverse in these circuits";

  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor walCap(
    T(fixed=true),
    C=10*AWall*0.05*1000*1000)
    "Thermal mass of walls"
  Fluid.MixingVolumes.MixingVolume zon(
    redeclare package Medium = MediumAir,
    V=VZone,
    nPorts=2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mAir_flow_nominal,
    massDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial)
    "Very based zone air model"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor conRes(R=1/2/AWall)
    "Thermal resistance for convective heat transfer with h=2"
  Fluid.HeatExchangers.Radiators.RadiatorEN442_2 rad(
    redeclare package Medium = MediumWater,
    T_a_nominal=273.15 + 50,
    T_b_nominal=273.15 + 40,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    allowFlowReversal=allowFlowReversal,
    Q_flow_nominal=QHea_flow_nominal)
                                 "Radiator"

  Fluid.Sources.Boundary_pT bouAir(
    redeclare package Medium = MediumAir,
    nPorts=2,
    use_T_in=true) "Air boundary with constant temperature"
  Fluid.Sources.Boundary_pT bouWat(redeclare package Medium = MediumWater,
      nPorts=1) "Pressure bound for water circuit"
  BoundaryConditions.WeatherData.ReaderTMY3 weaDat(
    filNam=Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
    "Weather data reader"
  BoundaryConditions.WeatherData.Bus weaBus "Weather data bus"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor walRes(R=0.25/AWall/
        0.04) "Thermal resistor for wall: 25 cm of rockwool"
  Buildings.HeatTransfer.Sources.PrescribedTemperature TOut
    "Exterior temperature boundary condition"
  Fluid.HeatExchangers.HeaterCooler_u heaWat(
    redeclare package Medium = MediumWater,
    m_flow_nominal=mWat_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    allowFlowReversal=allowFlowReversal,
    dp_nominal=5000,
    Q_flow_nominal=QHea_flow_nominal)
                                 "Heater for water circuit"

  Fluid.Movers.FlowControlled_m_flow pum(
    redeclare package Medium = MediumWater,
    use_riseTime=false,
    m_flow_nominal=mWat_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    allowFlowReversal=allowFlowReversal,
    nominalValuesDefineDefaultPressureCurve=true,
    inputType=Buildings.Fluid.Types.InputType.Stages,
    massFlowRates=mWat_flow_nominal*{1}) "Pump"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor senTemZonAir
    "Zone air temperature sensor"
  Fluid.Actuators.Dampers.Exponential vavDam(
    redeclare package Medium = MediumAir,
    from_dp=true,
    m_flow_nominal=mAir_flow_nominal,
    dpDamper_nominal=10,
    dpFixed_nominal=dpAir_nominal - 10) "Damper"

  Fluid.Movers.FlowControlled_dp fan(
    redeclare package Medium = MediumAir,
    dp_nominal=dpAir_nominal,
    use_riseTime=false,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    nominalValuesDefineDefaultPressureCurve=true,
    m_flow_nominal=mAir_flow_nominal,
    show_T=true) "Constant head fan"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow win
    "Very simple window model"
  Fluid.HeatExchangers.ConstantEffectiveness hexRec(
    redeclare package Medium1 = MediumAir,
    redeclare package Medium2 = MediumAir,
    dp1_nominal=0,
    dp2_nominal=0,
    m1_flow_nominal=mAir_flow_nominal,
    m2_flow_nominal=mAir_flow_nominal,
    eps=0.85) "Heat exchanger for heat recuperation"
  Modelica.Blocks.Logical.Hysteresis hysRad(uLow=273.15 + 20, uHigh=273.15 + 22)
    "Hysteresis controller for radiator"
  Modelica.Blocks.Logical.Not not1
    "negation for enabling heating when temperatur is low"
  Modelica.Blocks.Math.BooleanToReal booToRea "Boolean to real"
  Modelica.Blocks.Sources.Constant con_dp(k=dpAir_nominal) "Pressure head"

  Modelica.Blocks.Math.Gain gaiWin(k=AWin*gWin)
    "Gain for window solar transmittance and area as HGloHor is in W/m2"
  Modelica.Blocks.Math.BooleanToInteger booToInt "Boolean to integer"
  Controls.Continuous.LimPID conDam(
      controllerType=Modelica.Blocks.Types.SimpleController.P,
      yMin=0.25) "Controller for damper"
  Modelica.Blocks.Sources.Constant TSetRoo(k=273.15 + 24)
    "Room temperature set point for air system"
  Fluid.HeatExchangers.SensibleCooler_T cooAir(
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    allowFlowReversal=allowFlowReversal,
    m_flow_nominal=mAir_flow_nominal,
    dp_nominal=0,
    redeclare package Medium = MediumAir) "Cooling for supply air"
  Modelica.Blocks.Sources.Constant TSupAirCoo(k=273.15 + 20)
    "Cooling setpoint for supply air"
  Buildings.Fluid.Sensors.TemperatureTwoPort TFanIn(
    redeclare final package Medium = MediumAir,
    final m_flow_nominal=mAir_flow_nominal,
    tau=0) "Temperature at fan inlet"
  Buildings.Fluid.Sensors.TemperatureTwoPort TFanOut(
    redeclare final package Medium = MediumAir,
    final m_flow_nominal=mAir_flow_nominal,
    tau=0) "Temperature at fan outlet"
equation
  connect(conRes.port_a, zon.heatPort)
  connect(weaDat.weaBus, weaBus)
  connect(walRes.port_b, walCap.port)
  connect(TOut.T, weaBus.TDryBul)
  connect(TOut.port, walRes.port_a)
  connect(heaWat.port_b, rad.port_a)
  connect(bouWat.ports[1], heaWat.port_a)
  connect(rad.port_b, pum.port_a)
  connect(senTemZonAir.port, zon.heatPort)
  connect(bouAir.ports[1], hexRec.port_b1)
  connect(rad.heatPortCon, zon.heatPort)
  connect(not1.y, booToRea.u)
  connect(not1.u, hysRad.y)
  connect(booToRea.y, heaWat.u)
  connect(heaWat.port_a, pum.port_b)
  connect(con_dp.y, fan.dp_in)
  connect(gaiWin.y, win.Q_flow)
  connect(gaiWin.u, weaBus.HGloHor)
  connect(booToInt.u, not1.y)
  connect(booToInt.y, pum.stage)
  connect(vavDam.port_b, zon.ports[1])
  connect(senTemZonAir.T, hysRad.u)
  connect(senTemZonAir.T,conDam. u_s)
  connect(conDam.y, vavDam.y)
  connect(TSetRoo.y,conDam. u_m)
  connect(cooAir.port_b, vavDam.port_a)
  connect(TSupAirCoo.y, cooAir.TSet)
  connect(bouAir.T_in, weaBus.TDryBul)
  connect(bouAir.ports[2], hexRec.port_a2)
  connect(hexRec.port_a1, zon.ports[2])
  connect(conRes.port_b, walCap.port)
  connect(win.port, walCap.port)
  connect(rad.heatPortRad, walCap.port)
  connect(hexRec.port_b2, TFanIn.port_a)
  connect(TFanIn.port_b, fan.port_a)
  connect(fan.port_b, TFanOut.port_a)
  connect(TFanOut.port_b, cooAir.port_a)
end SimpleHouse;


Model of data center that approximates the trim and respond logic. This model is the chilled water plant with continuous time control.
The trim and respond logic is approximated by a PI controller which
significantly reduces computing time. The model is described at

Buildings.Examples.ChillerPlant.

within Buildings.Examples.ChillerPlant;
model DataCenterContinuousTimeControl
  "Model of data center that approximates the trim and respond logic"
  extends Buildings.Examples.ChillerPlant.BaseClasses.DataCenter;
  extends Modelica.Icons.Example;

  BaseClasses.Controls.TrimAndRespondContinuousTimeApproximation triAndRes
    "Continuous time approximation for trim and respond controller"
equation
  connect(feedback.y, triAndRes.u)
  connect(triAndRes.y, linPieTwo.u)
end DataCenterContinuousTimeControl;


Model of data center with trim and respond control. This model is the chilled water plant with trim and respond control,
which is a discrete time control logic.

within Buildings.Examples.ChillerPlant;
model DataCenterDiscreteTimeControl
  "Model of data center with trim and respond control"
  extends Buildings.Examples.ChillerPlant.BaseClasses.DataCenter;
  extends Modelica.Icons.Example;

  BaseClasses.Controls.TrimAndRespond triAndRes(
    yEqu0=0,
    samplePeriod=120,
    uTri=0,
    yDec=-0.03,
    yInc=0.03) "Trim and respond controller"
equation
  connect(feedback.y, triAndRes.u)
  connect(triAndRes.y, linPieTwo.u)
end DataCenterDiscreteTimeControl;


Model of a data center connected to renewable energy generation. This model illustrates a data center with DC and AC load.
The electrical supply is from a grid, from wind turbines and from PV.
The battery is charged during the night and discharged during
the day in such a way that it is fully charged and discharged.
This control logic is implemented using a finite state machine
inside the model con.

within Buildings.Examples.ChillerPlant;
model DataCenterRenewables
  "Model of a data center connected to renewable energy generation"
  extends Modelica.Icons.Example;
  BaseClasses.DataCenterContinuousTimeControl dataCenterContinuousTimeControl
  Buildings.Electrical.DC.Sources.WindTurbine winTur(
    scale=200e3,
    h=50,
    V_nominal=480) "Wind turbines"
  Electrical.DC.Sources.PVSimpleOriented pv(
    A=200e3/800/0.12,
    til=0.34906585039887,
    azi=-0.78539816339745,
    V_nominal=480) "PV array"
  Buildings.Electrical.DC.Storage.Battery bat(
    EMax=500e3*4*3600,
    V_nominal=480) "Battery"
  Buildings.Electrical.AC.OnePhase.Conversion.ACDCConverter conv(
    conversionFactor=480/480,
    eta=0.9) "AC/DC converter"
  Buildings.Electrical.AC.OnePhase.Sources.Grid gri(
    f=60,
    V=480,
    phiSou=0)
  Buildings.BoundaryConditions.WeatherData.Bus
    weaBus "Weather data bus"
  BaseClasses.Controls.BatteryControl con "Battery controller"
  Buildings.Electrical.DC.Loads.Conductor dcLoad(
    mode=Buildings.Electrical.Types.Load.VariableZ_P_input,
    V_nominal=480)
  Buildings.Electrical.AC.OnePhase.Loads.Inductive acLoad(
    mode=Buildings.Electrical.Types.Load.VariableZ_P_input,
    V_nominal=480)
equation
  connect(dataCenterContinuousTimeControl.weaBus, weaBus)
  connect(weaBus.winSpe, winTur.vWin)

  connect(bat.SOC, con.SOC)
  connect(con.y, bat.P)
  connect(dataCenterContinuousTimeControl.PDC, dcLoad.Pow)
  connect(pv.terminal, conv.terminal_p)
  connect(winTur.terminal, conv.terminal_p)
  connect(bat.terminal, conv.terminal_p)
  connect(dcLoad.terminal, conv.terminal_p)
  connect(dataCenterContinuousTimeControl.PAC, acLoad.Pow)
  connect(acLoad.terminal, gri.terminal)
  connect(conv.terminal_n, gri.terminal)
  connect(dataCenterContinuousTimeControl.weaBus, pv.weaBus)
end DataCenterRenewables;


within Buildings.Examples;
package ChillerPlant "Chiller plant with water side economizer for data center"

extends Modelica.Icons.ExamplesPackage;
end ChillerPlant;


within Buildings.Examples.ChillerPlant.BaseClasses;
partial model DataCenter
  "Primary only chiller plant system with water-side economizer"
  replaceable package MediumA = Buildings.Media.Air "Medium model";
  replaceable package MediumW = Buildings.Media.Water "Medium model";
  parameter Modelica.Units.SI.MassFlowRate mAir_flow_nominal=roo.QRoo_flow/(
      1005*15) "Nominal mass flow rate at fan";
  parameter Modelica.Units.SI.Power P_nominal=80E3
    "Nominal compressor power (at y=1)";
  parameter Modelica.Units.SI.TemperatureDifference dTEva_nominal=10
    "Temperature difference evaporator inlet-outlet";
  parameter Modelica.Units.SI.TemperatureDifference dTCon_nominal=10
    "Temperature difference condenser outlet-inlet";
  parameter Real COPc_nominal=3 "Chiller COP";
  parameter Modelica.Units.SI.MassFlowRate mCHW_flow_nominal=2*roo.QRoo_flow/(
      4200*20) "Nominal mass flow rate at chilled water";

  parameter Modelica.Units.SI.MassFlowRate mCW_flow_nominal=2*roo.QRoo_flow/(
      4200*6) "Nominal mass flow rate at condenser water";

  parameter Modelica.Units.SI.PressureDifference dp_nominal=500
    "Nominal pressure difference";
  Buildings.Fluid.Movers.FlowControlled_m_flow fan(
    redeclare package Medium = MediumA,
    m_flow_nominal=mAir_flow_nominal,
    dp(start=249),
    m_flow(start=mAir_flow_nominal),
    nominalValuesDefineDefaultPressureCurve=true,
    use_riseTime=false,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    T_start=293.15,
    dp_nominal=750) "Fan for air flow through the data center"
  Buildings.Fluid.HeatExchangers.DryCoilCounterFlow cooCoi(
    redeclare package Medium1 = MediumW,
    redeclare package Medium2 = MediumA,
    m2_flow_nominal=mAir_flow_nominal,
    m1_flow_nominal=mCHW_flow_nominal,
    m1_flow(start=mCHW_flow_nominal),
    m2_flow(start=mAir_flow_nominal),
    dp2_nominal=249*3,
    UA_nominal=mAir_flow_nominal*1006*5,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp1_nominal(displayUnit="Pa") = 1000 + 89580)
    "Cooling coil"
  Modelica.Blocks.Sources.Constant mFanFlo(k=mAir_flow_nominal)
    "Mass flow rate of fan"
  BaseClasses.SimplifiedRoom roo(
    redeclare package Medium = MediumA,
    nPorts=2,
    rooLen=50,
    rooWid=30,
    rooHei=3,
    m_flow_nominal=mAir_flow_nominal,
    QRoo_flow=500000) "Room model"
  Buildings.Fluid.Movers.FlowControlled_dp pumCHW(
    redeclare package Medium = MediumW,
    m_flow_nominal=mCHW_flow_nominal,
    m_flow(start=mCHW_flow_nominal),
    dp(start=325474),
    nominalValuesDefineDefaultPressureCurve=true,
    use_riseTime=false,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal=130000) "Chilled water pump"
  Buildings.Fluid.Storage.ExpansionVessel expVesCHW(redeclare package Medium =
        MediumW, V_start=1) "Expansion vessel"
  Buildings.Fluid.HeatExchangers.CoolingTowers.YorkCalc cooTow(
    redeclare package Medium = MediumW,
    m_flow_nominal=mCW_flow_nominal,
    PFan_nominal=6000,
    TAirInWB_nominal(displayUnit="degC") = 283.15,
    TApp_nominal=6,
    dp_nominal=14930 + 14930 + 74650,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Cooling tower"
  Buildings.Fluid.Movers.FlowControlled_m_flow pumCW(
    redeclare package Medium = MediumW,
    m_flow_nominal=mCW_flow_nominal,
    dp(start=214992),
    nominalValuesDefineDefaultPressureCurve=true,
    use_riseTime=false,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal=130000) "Condenser water pump"
  Buildings.Fluid.HeatExchangers.ConstantEffectiveness wse(
    redeclare package Medium1 = MediumW,
    redeclare package Medium2 = MediumW,
    m1_flow_nominal=mCW_flow_nominal,
    m2_flow_nominal=mCHW_flow_nominal,
    eps=0.8,
    dp2_nominal=0,
    dp1_nominal=0) "Water side economizer (Heat exchanger)"
  Buildings.Fluid.Actuators.Valves.TwoWayLinear val5(
    redeclare package Medium = MediumW,
    m_flow_nominal=mCW_flow_nominal,
    dpValve_nominal=20902,
    dpFixed_nominal=89580,
    y_start=1,
    use_strokeTime=false) "Control valve for condenser water loop of chiller"
  Buildings.Fluid.Actuators.Valves.TwoWayLinear val1(
    redeclare package Medium = MediumW,
    m_flow_nominal=mCHW_flow_nominal,
    dpValve_nominal=20902,
    use_strokeTime=false)
    "Bypass control valve for economizer. 1: disable economizer, 0: enable economoizer"
  Buildings.Fluid.Storage.ExpansionVessel expVesChi(redeclare package Medium =
        MediumW, V_start=1)
  Buildings.Examples.ChillerPlant.BaseClasses.Controls.WSEControl wseCon
  Modelica.Blocks.Sources.RealExpression expTowTApp(y=cooTow.TApp_nominal)
    "Cooling tower approach"
  Buildings.Fluid.Chillers.ElectricEIR chi(
    redeclare package Medium1 = MediumW,
    redeclare package Medium2 = MediumW,
    m1_flow_nominal=mCW_flow_nominal,
    m2_flow_nominal=mCHW_flow_nominal,
    dp2_nominal=0,
    dp1_nominal=0,
    per=Buildings.Fluid.Chillers.Data.ElectricEIR.ElectricEIRChiller_Carrier_19XR_742kW_5_42COP_VSD(),
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
  Buildings.Fluid.Actuators.Valves.TwoWayLinear val6(
    redeclare package Medium = MediumW,
    m_flow_nominal=mCHW_flow_nominal,
    dpValve_nominal=20902,
    dpFixed_nominal=14930 + 89580,
    y_start=1,
    use_strokeTime=false,
    from_dp=true)
    "Control valve for chilled water leaving from chiller"
  Buildings.Examples.ChillerPlant.BaseClasses.Controls.ChillerSwitch chiSwi(
      deaBan(displayUnit="K") = 2.2)
    "Control unit switching chiller on or off "
  Buildings.Examples.ChillerPlant.BaseClasses.Controls.LinearPiecewiseTwo
    linPieTwo(
    x0=0,
    x2=1,
    x1=0.5,
    y11=1,
    y21=273.15 + 5.56,
    y10=0.2,
    y20=273.15 + 22) "Translate the control signal for chiller setpoint reset"
  Modelica.Blocks.Sources.Constant TAirSet(k=273.15 + 27)
    "Set temperature for air supply to the room"
  Modelica.Blocks.Math.BooleanToReal chiCon "Contorl signal for chiller"
  Buildings.Fluid.Actuators.Valves.TwoWayLinear val4(
    redeclare package Medium = MediumW,
    m_flow_nominal=mCW_flow_nominal,
    dpValve_nominal=20902,
    dpFixed_nominal=59720,
    y_start=0,
    use_strokeTime=false)
    "Control valve for condenser water loop of economizer"
  Buildings.Fluid.Sensors.TemperatureTwoPort TAirSup(redeclare package Medium =
        MediumA, m_flow_nominal=mAir_flow_nominal)
    "Supply air temperature to data center"
  Buildings.Fluid.Sensors.TemperatureTwoPort TCHWEntChi(redeclare package
      Medium = MediumW, m_flow_nominal=mCHW_flow_nominal)
    "Temperature of chilled water entering chiller"
  Buildings.Fluid.Sensors.TemperatureTwoPort TCWLeaTow(redeclare package Medium =
        MediumW, m_flow_nominal=mCW_flow_nominal)
    "Temperature of condenser water leaving the cooling tower"
  Modelica.Blocks.Sources.Constant cooTowFanCon(k=1)
    "Control singal for cooling tower fan"
  Buildings.Fluid.Actuators.Valves.TwoWayEqualPercentage valByp(
    redeclare package Medium = MediumW,
    m_flow_nominal=mCHW_flow_nominal,
    dpValve_nominal=20902,
    dpFixed_nominal=14930,
    y_start=0,
    use_strokeTime=false,
    from_dp=true)          "Bypass valve for chiller."
  Buildings.Examples.ChillerPlant.BaseClasses.Controls.KMinusU KMinusU(k=1)
  Buildings.Fluid.Actuators.Valves.TwoWayLinear val3(
    redeclare package Medium = MediumW,
    m_flow_nominal=mCHW_flow_nominal,
    dpValve_nominal=20902,
    dpFixed_nominal=59720 + 1000,
    use_strokeTime=false)
    "Control valve for economizer. 0: disable economizer, 1: enable economoizer"
  Buildings.Fluid.Sensors.TemperatureTwoPort TCHWLeaCoi(redeclare package
      Medium = MediumW, m_flow_nominal=mCHW_flow_nominal)
    "Temperature of chilled water leaving the cooling coil"
  Buildings.BoundaryConditions.WeatherData.ReaderTMY3 weaData(filNam=
        Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
  BoundaryConditions.WeatherData.Bus weaBus
  Modelica.Blocks.Math.Gain gain(k=20*6485)
  Modelica.Blocks.Math.Feedback feedback
  Modelica.Blocks.Logical.GreaterThreshold greaterThreshold
  Modelica.Blocks.Logical.Or or1
  Modelica.Blocks.Math.BooleanToReal mCWFlo(realTrue=mCW_flow_nominal)
    "Mass flow rate of condenser loop"
  Modelica.Blocks.Sources.RealExpression PHVAC(y=fan.P + pumCHW.P + pumCW.P +
        cooTow.PFan + chi.P) "Power consumed by HVAC system"
  Modelica.Blocks.Sources.RealExpression PIT(y=roo.QSou.Q_flow)
    "Power consumed by IT"
  Modelica.Blocks.Continuous.Integrator EHVAC(initType=Modelica.Blocks.Types.Init.InitialState,
      y_start=0) "Energy consumed by HVAC"
  Modelica.Blocks.Continuous.Integrator EIT(initType=Modelica.Blocks.Types.Init.InitialState,
      y_start=0) "Energy consumed by IT"
equation
  connect(expVesCHW.port_a, cooCoi.port_b1)
  connect(expTowTApp.y, wseCon.towTApp)
  connect(chiSwi.y, chiCon.u)
  connect(cooTow.port_b, pumCW.port_a)
  connect(val5.port_a, chi.port_b1)
  connect(expVesChi.port_a, chi.port_b1)
  connect(val4.port_a, wse.port_b1)
  connect(chiSwi.y, chi.on)
  connect(linPieTwo.y[2], chi.TSet)
  connect(chiCon.y, val5.y)
  connect(linPieTwo.y[2], chiSwi.TSet)

  connect(cooTowFanCon.y, cooTow.y)
  connect(cooCoi.port_b2, fan.port_a)
  connect(mFanFlo.y, fan.m_flow_in)

  connect(wse.port_a2, val3.port_b)
  connect(wseCon.y2, val1.y)
  connect(wseCon.y1, val3.y)
  connect(wseCon.y1, val4.y)
  connect(TAirSup.port_a, fan.port_b)
  connect(roo.airPorts[1],TAirSup. port_b)
  connect(roo.airPorts[2], cooCoi.port_a2)
  connect(TCHWLeaCoi.port_a, pumCHW.port_b)
  connect(TCHWEntChi.port_b, valByp.port_a)
  connect(TCHWEntChi.port_a, val1.port_b)
  connect(val1.port_a, TCHWLeaCoi.port_b)
  connect(val3.port_a, TCHWLeaCoi.port_b)
  connect(TCWLeaTow.port_b, chi.port_a1)
  connect(TCWLeaTow.port_b, wse.port_a1)
  connect(TCHWEntChi.T, chiSwi.chiCHWST)
  connect(wseCon.wseCWST, TCWLeaTow.T)
  connect(wseCon.wseCHWST, TCHWLeaCoi.T)
  connect(weaData.weaBus, weaBus)
  connect(wseCon.TWetBul, weaBus.TWetBul)
  connect(cooTow.TAir, weaBus.TWetBul)
  connect(TCHWEntChi.port_a, wse.port_b2)
  connect(valByp.port_b, val6.port_b)
  connect(TCHWEntChi.port_b, chi.port_a2)
  connect(val5.port_b, cooTow.port_a)
  connect(val4.port_b, cooTow.port_a)
  connect(pumCW.port_b, TCWLeaTow.port_a)

  connect(chiCon.y, KMinusU.u)
  connect(KMinusU.y, valByp.y)
  connect(chiCon.y, val6.y)
  connect(linPieTwo.y[1], gain.u)
  connect(gain.y, pumCHW.dp_in)

  connect(TAirSet.y, feedback.u2)
  connect(TAirSup.T, feedback.u1)
  connect(chi.port_b2, val6.port_a)
  connect(pumCHW.port_a, cooCoi.port_b1)
  connect(greaterThreshold.u, wseCon.y1)
  connect(or1.u1, greaterThreshold.y)
  connect(or1.u2, chiSwi.y)
  connect(or1.y, mCWFlo.u)
  connect(mCWFlo.y, pumCW.m_flow_in)
  connect(PHVAC.y, EHVAC.u)
  connect(PIT.y, EIT.u)
  connect(cooCoi.port_a1, val6.port_b)
end DataCenter;


Alternate current power required for IT.

within Buildings.Examples.ChillerPlant.BaseClasses;
model DataCenterContinuousTimeControl
  extends Buildings.Examples.ChillerPlant.DataCenterContinuousTimeControl;
  Modelica.Blocks.Interfaces.RealOutput PAC
    "Alternate current power required for IT"
  Modelica.Blocks.Interfaces.RealOutput PDC
    "Direct current power required for IT"
equation
  connect(PHVAC.y, PAC)
  connect(PIT.y, PDC)
end DataCenterContinuousTimeControl;


within Buildings.Examples.ChillerPlant;
package BaseClasses "Package with base classes for Buildings.Examples.ChillerPlant"
extends Modelica.Icons.BasesPackage;
end BaseClasses;


Simplified data center room

within Buildings.Examples.ChillerPlant.BaseClasses;
model SimplifiedRoom "Simplified data center room"
  extends Buildings.BaseClasses.BaseIcon;
  replaceable package Medium = Modelica.Media.Interfaces.PartialMedium
    "Medium model";
  parameter Integer nPorts=0 "Number of parts"
  parameter Modelica.Units.SI.Length rooLen "Length of the room";
  parameter Modelica.Units.SI.Length rooWid "Width of the room";
  parameter Modelica.Units.SI.Height rooHei "Height of the room";
  parameter Modelica.Units.SI.Power QRoo_flow
    "Heat generation of the computer room";

  Buildings.Fluid.MixingVolumes.MixingVolume rooVol(
    redeclare package Medium = Medium,
    nPorts=nPorts,
    V=rooLen*rooWid*rooHei,
    m_flow_nominal=m_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    final T_start=293.15,
    final prescribedHeatFlowRate=true) "Volume of air in the room"
  Modelica.Fluid.Vessels.BaseClasses.VesselFluidPorts_b airPorts[nPorts](
      redeclare each package Medium = Medium) "Fluid inlets and outlets"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow QSou
    "Heat source of the room"
  Modelica.Blocks.Sources.Ramp ramp(
    height=QRoo_flow,
    offset=0,
    duration=36000,
    startTime=0)
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal
    "Nominal mass flow rate";
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor TAir
    "Room air temperature"
  Modelica.Blocks.Interfaces.RealOutput TRooAir(unit="K", displayUnit="degC")
    "Room air temperature"
equation
  connect(rooVol.ports, airPorts)
  connect(QSou.port, rooVol.heatPort)
  connect(ramp.y, QSou.Q_flow)
  connect(TAir.port, rooVol.heatPort)
  connect(TAir.T, TRooAir)
end SimplifiedRoom;


Controller for battery. Block for a battery controller. The battery is charged during night if its charge is below
a threshold. It remains charging until it is full.
During day, it discharges provided that its charge is above a threshold. It remains
discharging until it is empty.

within Buildings.Examples.ChillerPlant.BaseClasses.Controls;
model BatteryControl "Controller for battery"

  Modelica.Blocks.Interfaces.RealInput SOC "State of charge"
  Modelica.Blocks.Interfaces.RealOutput y
    "Power charged or discharged from battery"
  Modelica.Blocks.Logical.LessThreshold lessThreshold(threshold=0.5)
  Modelica.Blocks.Logical.GreaterEqualThreshold greaterEqualThreshold(threshold=
       0.99)
  Modelica.Blocks.Sources.BooleanExpression isDay(y=mod(time, 86400) > 7*3600
         and mod(time, 86400) <= 19*3600) "Outputs true if it is day time"
  Modelica.Blocks.Logical.Not not1
  Modelica.Blocks.Logical.And and1
  Modelica.Blocks.Logical.And and2
  Modelica.Blocks.Logical.GreaterThreshold greaterThreshold(threshold=0.8)
  Modelica.Blocks.Logical.LessEqualThreshold lessEqualThreshold(threshold=
        0.01)
  Modelica.Blocks.Math.MultiSwitch multiSwitch1(
    nu=2,
    expr={200e3,-400e3})
  Modelica.StateGraph.InitialStep off(nIn=1, nOut=1)
                                      "Off state"
  inner Modelica.StateGraph.StateGraphRoot stateGraphRoot
  Modelica.StateGraph.Alternative alternative(nBranches=2)
    "Splitter for alternative branches"
  Modelica.StateGraph.TransitionWithSignal t1(enableTimer=true, waitTime=1)
    "Transition to charge"
  Modelica.StateGraph.TransitionWithSignal t2(enableTimer=true, waitTime=1)
    "Transition to discharge"
  Modelica.StateGraph.StepWithSignal charge(nIn=1, nOut=1)
                                            "Charge battery"
  Modelica.StateGraph.StepWithSignal discharge(nIn=1, nOut=1)
                                               "Discharge battery"
  Modelica.StateGraph.TransitionWithSignal t3 "Transition to off"
  Modelica.StateGraph.TransitionWithSignal t4 "Transition to off"
equation

  connect(lessThreshold.u, SOC)
  connect(greaterEqualThreshold.u, SOC)
  connect(not1.u, isDay.y)
  connect(and1.u1, not1.y)
  connect(lessThreshold.y, and1.u2)
  connect(isDay.y, and2.u1)
  connect(greaterThreshold.u, SOC)
  connect(greaterThreshold.y, and2.u2)
  connect(lessEqualThreshold.u, SOC)
  connect(multiSwitch1.y, y)
  connect(off.outPort[1], alternative.inPort)
  connect(t1.outPort, charge.inPort[1])
  connect(t2.outPort, discharge.inPort[1])
  connect(charge.outPort[1], t3.inPort)
  connect(discharge.outPort[1], t4.inPort)
  connect(alternative.outPort, off.inPort[1])
  connect(and1.y, t1.condition)
  connect(and2.y, t2.condition)
  connect(greaterEqualThreshold.y, t3.condition)
  connect(lessEqualThreshold.y, t4.condition)
  connect(t1.inPort, alternative.split[1])
  connect(t2.inPort, alternative.split[2])
  connect(t3.outPort, alternative.join[1])
  connect(t4.outPort, alternative.join[2])
  connect(charge.active, multiSwitch1.u[1])
  connect(discharge.active, multiSwitch1.u[2])
end BatteryControl;


Control unit for enabling/disabling chiller.

within Buildings.Examples.ChillerPlant.BaseClasses.Controls;
block ChillerSwitch "Control unit for enabling/disabling chiller"
  extends Modelica.Blocks.Icons.Block;
  Modelica.Blocks.Interfaces.RealInput chiCHWST(
    final quantity="ThermodynamicTemperature",
    final unit="K")
    "Chiller chilled water supply temperature (water entering chiller)"
  Modelica.Blocks.Interfaces.BooleanOutput y
    "Control signal for chiller. 1: Enable, 0: Disable"
  Modelica.Blocks.Interfaces.RealInput TSet(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") "Set temperature of chiller"
  parameter Modelica.Units.SI.Temperature deaBan
    "Dead band of temperature to prevent chiller short cycling";
  Modelica.Blocks.Logical.Hysteresis hysteresis(uLow=0, uHigh=deaBan)
  Modelica.Blocks.Math.Add add(k1=+1, k2=-1)
equation
  connect(hysteresis.y, y)

  connect(chiCHWST, add.u1)
  connect(TSet, add.u2)
  connect(add.y, hysteresis.u)
end ChillerSwitch;


Output y=k-u.

within Buildings.Examples.ChillerPlant.BaseClasses.Controls;
block KMinusU "Output y=k-u"
  extends Modelica.Blocks.Icons.Block;
public
  parameter Real k "Sum of u and y";
  Modelica.Blocks.Interfaces.RealInput u "Input"
  Modelica.Blocks.Interfaces.RealOutput y "Output"
equation
  y = k - u;
end KMinusU;


A two-pieces linear piecewise function.

within Buildings.Examples.ChillerPlant.BaseClasses.Controls;
block LinearPiecewiseTwo "A two-pieces linear piecewise function"
  extends Modelica.Blocks.Icons.Block;
  parameter Real x0 "First interval [x0, x1]";
  parameter Real x1 "First interval [x0, x1] and second interval (x1, x2]";
  parameter Real x2 "Second interval (x1, x2]";
  parameter Real y10 "y[1] at u = x0";
  parameter Real y11 "y[1] at u = x1";
  parameter Real y20 "y[2] at u = x1";
  parameter Real y21 "y[2] at u = x2";
  Modelica.Blocks.Interfaces.RealInput u "Set point"
  Modelica.Blocks.Interfaces.RealOutput y[2] "Connectors of Real output signal"
  Buildings.Controls.SetPoints.Table y1Tab(table=[x0, y10; x1, y11; x2, y11])
    "Table for y[1]"
  Buildings.Controls.SetPoints.Table y2Tab(table=[x0, y20; x1, y20; x2, y21])
    "Table for y[2]"
equation
  connect(u, y1Tab.u)
  connect(u, y2Tab.u)
  connect(y1Tab.y, y[1])
  connect(y2Tab.y, y[2])
end LinearPiecewiseTwo;


within Buildings.Examples.ChillerPlant.BaseClasses;
package Controls "Package with control components for Buildings.Examples.ChillerPlant"
extends Modelica.Icons.VariantsPackage;
end Controls;


Count the number of actuators that have request.

within Buildings.Examples.ChillerPlant.BaseClasses.Controls;
block RequestCounter "Count the number of actuators that have request"
  extends Modelica.Blocks.Icons.Block
  parameter Integer nAct "Number of actuators";
  parameter Real uTri "Value to trigger a request from actuator";
  Modelica.Blocks.Interfaces.IntegerOutput nInc
    "Number of actuators requesting control signal increase"
  Modelica.Blocks.Interfaces.RealInput uAct[nAct] "Input signal from actuators"
algorithm
  nInc := 0;
  for i in 1:nAct loop
    if uAct[i] > uTri then
      nInc := nInc + 1;
    end if;
  end for;
end RequestCounter;


Trim and respond logic. This model implements the trim and respond logic. The model samples the outputs of actuators every tSam.
   The control sequence is as follows:

within Buildings.Examples.ChillerPlant.BaseClasses.Controls;
block TrimAndRespond "Trim and respond logic"
  extends Modelica.Blocks.Interfaces.DiscreteSISO(firstTrigger(start=false, fixed=true));
  parameter Real uTri "Value to triggering the request for actuator";
  parameter Real yEqu0 "y setpoint when equipment starts";
  parameter Real yDec(max=0) "y decrement (must be negative)";
  parameter Real yInc(min=0) "y increment (must be positive)";

  Modelica.Blocks.Logical.GreaterEqualThreshold incY(threshold=0)
    "Outputs true if y needs to be increased"
  Modelica.Blocks.Logical.Switch swi
  Sampler sam(samplePeriod=samplePeriod) "Sampler"

  Modelica.Blocks.Sources.Constant conYDec(k=yDec) "y decrease"
  Modelica.Blocks.Sources.Constant conYInc(k=yInc) "y increase"
  UnitDelay uniDel1(
    y_start=yEqu0,
    samplePeriod=samplePeriod,
    startTime=samplePeriod)
  Modelica.Blocks.Math.Add add
  Modelica.Blocks.Nonlinear.Limiter lim(uMax=1, uMin=0) "State limiter"

  // The UnitDelay and Sampler is reimplemented to avoid in Dymola 2016 the translation warning
  //   The initial conditions for variables of type Boolean are not fully specified.
  //   Dymola has selected default initial conditions.
  //   Assuming fixed default start value for the discrete non-states:
  //     ...firstTrigger(start = false)
  //     ...

protected
  block UnitDelay
    extends Modelica.Blocks.Discrete.UnitDelay(
      firstTrigger(start=false, fixed=true));
  end UnitDelay;

  block Sampler
    extends Modelica.Blocks.Discrete.Sampler(
      firstTrigger(start=false, fixed=true));
  end Sampler;
equation
  connect(lim.y, y)

  connect(add.y, lim.u)

  connect(uniDel1.y, add.u2)

  connect(incY.y, swi.u2)
  connect(sam.y, incY.u)
  connect(lim.y, uniDel1.u)
  connect(swi.y, add.u1)
  connect(swi.u3, conYDec.y)
  connect(conYInc.y, swi.u1)
  connect(sam.u, u)
end TrimAndRespond;


Trim and respond logic. This model implements a continuous time approximation to the trim and respond
   control algorithm.

within Buildings.Examples.ChillerPlant.BaseClasses.Controls;
block TrimAndRespondContinuousTimeApproximation "Trim and respond logic"
  extends Modelica.Blocks.Interfaces.SISO;

  Buildings.Controls.Continuous.LimPID conPID(
    Td=1,
    yMax=1,
    yMin=0,
    reverseActing=false,
    Ti=120,
    k=0.1)
  Modelica.Blocks.Sources.Constant const(k=0)
equation
  connect(const.y, conPID.u_s)
  connect(conPID.y, y)
  connect(u, conPID.u_m)
end TrimAndRespondContinuousTimeApproximation;


Control unit for WSE. This component decides if the WSE is set to on or off.
The WSE is enabled when

within Buildings.Examples.ChillerPlant.BaseClasses.Controls;
model WSEControl "Control unit for WSE"
  parameter Modelica.Units.SI.TemperatureDifference dTOff=1
    "Temperature difference to switch WSE off";
  parameter Modelica.Units.SI.TemperatureDifference dTW=1
    "Temperature difference that is added to WSE on guard";
  Modelica.Blocks.Interfaces.RealInput wseCHWST(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC")
    "WSE chilled water supply temperature (water entering WSE)"
  Modelica.Blocks.Interfaces.RealOutput y2
    "Control signal for chiller shutoff valve"
  Modelica.Blocks.Interfaces.RealInput TWetBul(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") "Wet bulb temperature"
  Modelica.Blocks.Interfaces.RealInput towTApp(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") "Cooling tower approach"
  Modelica.Blocks.Interfaces.RealInput wseCWST(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC")
    "WSE condenser water supply temperature (water entering WSE)"
  Modelica.Blocks.Math.BooleanToReal booToRea2
  Modelica.Blocks.Interfaces.RealOutput y1
    "Control signal for WSE shutoff valve"
  Modelica.StateGraph.InitialStepWithSignal off(
    nOut=1,
    nIn=1)
  Modelica.StateGraph.Transition T1(
    waitTime=1200,
    condition=wseCHWST > 0.9*TWetBul + towTApp + dTW,
    enableTimer=true)
  Modelica.StateGraph.Step  on(nIn=1, nOut=1)
  Modelica.StateGraph.Transition  T2(
     waitTime=1200,
    condition=wseCHWST < wseCWST + dTOff,
    enableTimer=true)
  Modelica.Blocks.Math.BooleanToReal booToRea1(realTrue=0, realFalse=1)
  inner Modelica.StateGraph.StateGraphRoot stateGraphRoot
    "Root of the state graph"
equation

  connect(booToRea2.y, y2)
  connect(off.outPort[1], T1.inPort)
  connect(T1.outPort, on.inPort[1])
  connect(on.outPort[1], T2.inPort)
  connect(T2.outPort, off.inPort[1])
  connect(booToRea1.y, y1)
  connect(off.active, booToRea1.u)
  connect(off.active, booToRea2.u)
end WSEControl;


Test model for battery control. This model simulates a battery block controller.

within Buildings.Examples.ChillerPlant.BaseClasses.Controls.Examples;
model BatteryControl "Test model for battery control"
  extends Modelica.Icons.Example;
  Buildings.Examples.ChillerPlant.BaseClasses.Controls.BatteryControl
    con "Battery control"
  Modelica.Blocks.Sources.Sine SOC(
    f=1/86400,
    offset=0.5,
    amplitude=0.6) "State of charge"
equation
  connect(SOC.y, con.SOC)
end BatteryControl;


within Buildings.Examples.ChillerPlant.BaseClasses.Controls.Examples;
model ChillerSetPointControl
  "Test model for chiller setpoint control using TrimAndResponse and LinearPieceWiseTwo"
  extends Modelica.Icons.Example;
  package Medium1 = Buildings.Media.Water;
  package Medium2 = Buildings.Media.Water;
  package MediumAir = Buildings.Media.Air "Medium model";
  parameter Modelica.Units.SI.MassFlowRate mAir_flow_nominal=61.6*2
    "Nominal mass flow rate at fan";
  parameter Real COPc_nominal=3 "Chiller COP";
  parameter Modelica.Units.SI.MassFlowRate mCHW_flow_nominal=15.2
    "Nominal mass flow rate at chilled water";
  parameter Modelica.Units.SI.MassFlowRate mCW_flow_nominal=mCHW_flow_nominal/
      COPc_nominal*(COPc_nominal + 1)
    "Nominal mass flow rate at condenser water";
  parameter Real QRoo=100;
  Buildings.Examples.ChillerPlant.BaseClasses.Controls.TrimAndRespond triAndRes(
    yEqu0=0.1,
    uTri=0.8,
    yDec=-0.03,
    yInc=0.03,
    samplePeriod=120)
  Buildings.Examples.ChillerPlant.BaseClasses.Controls.LinearPiecewiseTwo
    linPieTwo(
    x0=0,
    x2=1,
    y20=273.15 + 12.78,
    y21=273.15 + 7.22,
    x1=0.5,
    y10=0.1,
    y11=1)
  Buildings.Fluid.Chillers.ElectricEIR chi(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    m1_flow_nominal=mCW_flow_nominal,
    m2_flow_nominal=mCHW_flow_nominal,
    dp1_nominal=6000,
    dp2_nominal=3000,
    per=Buildings.Fluid.Chillers.Data.ElectricEIR.ElectricEIRChiller_York_YK_1881kW_6_53COP_Vanes(),
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial) "Chiller"

  Buildings.Fluid.HeatExchangers.ConstantEffectiveness coi(
    redeclare package Medium1 = Medium2,
    m1_flow_nominal=mCHW_flow_nominal,
    dp1_nominal=3000,
    dp2_nominal=3000,
    redeclare package Medium2 = MediumAir,
    m2_flow_nominal=mAir_flow_nominal,
    eps=1.0) "Cooling coil"
  Buildings.Fluid.Sources.Boundary_pT sin1(redeclare package Medium = Medium1,
      nPorts=1)
  Buildings.Fluid.Sources.MassFlowSource_T sou1(
    redeclare package Medium = Medium1,
    nPorts=1,
    use_T_in=false,
    m_flow=mCW_flow_nominal,
    T=283.15)
  Modelica.Blocks.Sources.Constant const(k=273.15 + 20)
  Buildings.Controls.Continuous.LimPID limPID(
    reverseActing=false,
    y_start=1,
    yMin=0,
    k=10,
    Ti=0.01,
    Td=10) "PI controller"
  Buildings.Fluid.Sensors.TemperatureTwoPort TRet(redeclare package Medium =
        MediumAir, m_flow_nominal=999)
  Buildings.Fluid.Movers.FlowControlled_m_flow pum(
    nominalValuesDefineDefaultPressureCurve=true,
    m_flow_nominal=1.2*mCHW_flow_nominal,
    dp(start=40474),
    redeclare package Medium = Medium2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    init=Modelica.Blocks.Types.Init.InitialState) "Chilled water pump"
  Buildings.Fluid.Storage.ExpansionVessel expVesChi(
    V_start=1,
    redeclare package Medium = Medium2)
  Modelica.Blocks.Sources.BooleanConstant booleanConstant1(k=true)
  Modelica.Blocks.Math.Gain gain(k=mCHW_flow_nominal)
  Buildings.Fluid.Sources.MassFlowSource_T sou2(
    use_T_in=true,
    redeclare package Medium = MediumAir,
    m_flow=mAir_flow_nominal,
    T=291.15,
    nPorts=1)
  Buildings.Fluid.Sources.Boundary_pT sin2(redeclare package Medium =
        MediumAir, nPorts=1)
  Modelica.Blocks.Sources.Sine sine(
    amplitude=5,
    offset=273.15 + 25,
    f=1/20000)
  Modelica.Blocks.Continuous.FirstOrder firstOrder1(y_start=273.15 + 10, T=chi.tau1
        /2,
    initType=Modelica.Blocks.Types.Init.InitialState)
  Buildings.Fluid.Sensors.TemperatureTwoPort TSup(redeclare package Medium =
        MediumAir, m_flow_nominal=999)
equation
  connect(sou1.ports[1], chi.port_a1)
  connect(coi.port_a1, chi.port_b2)
  connect(TRet.T, limPID.u_m)
  connect(chi.port_a2, pum.port_b)
  connect(pum.port_a, coi.port_b1)
  connect(chi.port_a2, expVesChi.port_a)
  connect(booleanConstant1.y, chi.on)
  connect(gain.y, pum.m_flow_in)
  connect(sou2.T_in, sine.y)
  connect(chi.port_b1, sin1.ports[1])
  connect(const.y, limPID.u_s)
  connect(TRet.port_b, coi.port_b2)
  connect(TRet.port_a, sin2.ports[1])
  connect(linPieTwo.y[2], firstOrder1.u)
  connect(firstOrder1.y, chi.TSet)
  connect(coi.port_a2, TSup.port_a)
  connect(TSup.port_b, sou2.ports[1])
  connect(limPID.y, triAndRes.u)
  connect(triAndRes.y, linPieTwo.u)
  connect(gain.u, linPieTwo.y[1])
end ChillerSetPointControl;


Test model for ChillerSwitch.

within Buildings.Examples.ChillerPlant.BaseClasses.Controls.Examples;
model ChillerSwitch "Test model for ChillerSwitch"
  extends Modelica.Icons.Example;
  Modelica.Blocks.Sources.Sine TSet(
    f=0.0002,
    offset=12,
    amplitude=8)
  Modelica.Blocks.Sources.Sine CHWST(
    f=0.0001,
    amplitude=5,
    offset=15)
  Buildings.Examples.ChillerPlant.BaseClasses.Controls.ChillerSwitch chiSwi(
      deaBan(displayUnit="K") = 3)
equation
  connect(TSet.y, chiSwi.TSet)
  connect(CHWST.y, chiSwi.chiCHWST)
end ChillerSwitch;


Test model for KMinusU.

within Buildings.Examples.ChillerPlant.BaseClasses.Controls.Examples;
model KMinusU "Test model for KMinusU"
  extends Modelica.Icons.Example;
  Modelica.Blocks.Sources.Sine pulse(
    f=0.001,
    amplitude=0.5,
    offset=0.5,
    phase=-1.5707963267949)
  Buildings.Examples.ChillerPlant.BaseClasses.Controls.KMinusU kMinU(k=1)
equation
  connect(pulse.y, kMinU.u)
end KMinusU;


Test model for LinearPiecewiseTwo.

within Buildings.Examples.ChillerPlant.BaseClasses.Controls.Examples;
model LinearPiecewiseTwo "Test model for LinearPiecewiseTwo"
  extends Modelica.Icons.Example;
  Modelica.Blocks.Sources.Sine pulse(
    f=0.001,
    amplitude=0.5,
    offset=0.5,
    phase=-1.5707963267949)
  Buildings.Examples.ChillerPlant.BaseClasses.Controls.LinearPiecewiseTwo
    linPieTwo(
    x0=0,
    x1=0.5,
    x2=1,
    y10=5,
    y11=15,
    y20=55,
    y21=42)
equation
  connect(pulse.y, linPieTwo.u)
end LinearPiecewiseTwo;


Test of components

within Buildings.Examples.ChillerPlant.BaseClasses.Controls;
package Examples "Test of components"
extends Modelica.Icons.ExamplesPackage;
end Examples;


Test model for RequestCounter.

within Buildings.Examples.ChillerPlant.BaseClasses.Controls.Examples;
model RequestCounter "Test model for RequestCounter"
  extends Modelica.Icons.Example;
  Buildings.Examples.ChillerPlant.BaseClasses.Controls.RequestCounter reqCou(
      nAct=3, uTri=0.8)
  Modelica.Blocks.Sources.Constant act3(k=0.95)
  Modelica.Blocks.Sources.Pulse act1(period=10)
  Modelica.Blocks.Sources.Sine act2(f=0.3, offset=1)
equation
  connect(act1.y, reqCou.uAct[1])
  connect(act2.y, reqCou.uAct[2])
  connect(act3.y, reqCou.uAct[3])
end RequestCounter;


Test model for TrimAndRespond.

within Buildings.Examples.ChillerPlant.BaseClasses.Controls.Examples;
model TrimAndRespond "Test model for TrimAndRespond"
  extends Modelica.Icons.Example;

  Modelica.Blocks.Sources.Sine act3(f=0.002, offset=0.2)
  Modelica.Blocks.Sources.Pulse act1(period=500)
  Modelica.Blocks.Sources.Sine act2(f=0.001, offset=0.3)
  Buildings.Examples.ChillerPlant.BaseClasses.Controls.TrimAndRespond triAndRes[3](
    each uTri=0.9,
    each yEqu0=0.1,
    each yDec=-0.01,
    each yInc=0.02,
    each samplePeriod=20)
equation
  connect(act1.y, triAndRes[1].u)
  connect(act2.y, triAndRes[2].u)
  connect(act3.y, triAndRes[3].u)
end TrimAndRespond;


Test model for WSEControl.

within Buildings.Examples.ChillerPlant.BaseClasses.Controls.Examples;
model WSEControl "Test model for WSEControl"
  extends Modelica.Icons.Example;
  Modelica.Blocks.Sources.Pulse wseCHWST(
    period=300,
    amplitude=15,
    offset=273.15 + 5) "WSE chilled water supply temperature"
  Modelica.Blocks.Sources.Constant wseCWST(k=273.15 + 10)
    "WSE condenser water supply temperature"
  Buildings.Examples.ChillerPlant.BaseClasses.Controls.WSEControl wseCon
    "Controller for the water-side economizer"
  Modelica.Blocks.Sources.Constant TWetBub(k=273.15 + 5) "Wet bulb temperature"
  Modelica.Blocks.Sources.Constant TTowApp(k=5) "Cooling tower approach"
equation
  connect(TWetBub.y, wseCon.TWetBul)
  connect(TTowApp.y, wseCon.towTApp)
  connect(wseCHWST.y, wseCon.wseCHWST)
  connect(wseCWST.y, wseCon.wseCWST)
end WSEControl;