Model representing a generic two port system for conversion. This model extends the base class

AixLib.Electrical.Interfaces.PartialTwoPort
model and declares the variables
v_p and i_p that represents the voltage and the
current at the terminal_p, and the variables
v_n and i_n that represents the voltage and the
current at the terminal_n.
These variables are used in conversion models such as transformers and AC/DC converters.

within AixLib.Electrical.Interfaces;
model PartialConversion
  "Model representing a generic two port system for conversion"
  extends AixLib.Electrical.Interfaces.PartialTwoPort;
  Modelica.Units.SI.Voltage v_p "Voltage drop between the two positive pins";
  Modelica.Units.SI.Voltage v_n "Voltage drop between the two negative pins";
  Modelica.Units.SI.Current i_p "Current flowing through the positive pins";
  Modelica.Units.SI.Current i_n "Current flowing through the negative pins";
equation
  i_p = PhaseSystem_p.systemCurrent(terminal_p.i);
  i_n = PhaseSystem_n.systemCurrent(terminal_n.i);

  v_p = PhaseSystem_p.systemVoltage(terminal_p.v);
  v_n = PhaseSystem_n.systemVoltage(terminal_n.v);
end PartialConversion;


within AixLib.Electrical.Interfaces;
model PartialTwoPort "Model of a generic two port component with phase systems"

  replaceable package PhaseSystem_p =
      AixLib.Electrical.PhaseSystems.PartialPhaseSystem constrainedby
    AixLib.Electrical.PhaseSystems.PartialPhaseSystem
    "Phase system of terminal p"

  replaceable package PhaseSystem_n =
      AixLib.Electrical.PhaseSystems.PartialPhaseSystem constrainedby
    AixLib.Electrical.PhaseSystems.PartialPhaseSystem
    "Phase system of terminal n"

  extends AixLib.Electrical.Interfaces.PartialBaseTwoPort(
    redeclare replaceable AixLib.Electrical.Interfaces.Terminal terminal_n
      constrainedby AixLib.Electrical.Interfaces.Terminal(
        redeclare replaceable package PhaseSystem = PhaseSystem_n),
    redeclare replaceable AixLib.Electrical.Interfaces.Terminal terminal_p
      constrainedby AixLib.Electrical.Interfaces.Terminal(
        redeclare replaceable package PhaseSystem=PhaseSystem_p));
end PartialTwoPort;


Partial model of a resistive load. This is a model of a generic resistive load. This model is an extension of the base load model

AixLib.Electrical.Interfaces.Load.

within AixLib.Electrical.Interfaces;
partial model ResistiveLoad "Partial model of a resistive load"
  extends Load;
end ResistiveLoad;


Partial model of a generic source.

within AixLib.Electrical.Interfaces;
model Source "Partial model of a generic source."
  replaceable package PhaseSystem =
      AixLib.Electrical.PhaseSystems.OnePhase constrainedby
    AixLib.Electrical.PhaseSystems.PartialPhaseSystem "Phase system"
  parameter Boolean potentialReference = true
    "Serve as potential root for the reference angle theta"
  parameter Boolean definiteReference = false
    "Serve as definite root for the reference angle theta"
  Modelica.Units.SI.Power S[PhaseSystem.n]=PhaseSystem.phasePowers_vi(terminal.v,
      terminal.i) "Complex power S[1] = P, S[2]= Q";
  Modelica.Units.SI.Angle phi=PhaseSystem.phase(terminal.v) - PhaseSystem.phase(
      -terminal.i) "Phase shift with respect to reference angle";
  replaceable AixLib.Electrical.Interfaces.Terminal terminal(
    redeclare final replaceable package PhaseSystem = PhaseSystem)
    "Generalized terminal"
protected
  function j = PhaseSystem.j;
equation
  if potentialReference then
      if definiteReference then
        Connections.root(terminal.theta);
      else
        Connections.potentialRoot(terminal.theta);
      end if;
  end if;
end Source;


Generalized electric terminal

within AixLib.Electrical.Interfaces;
connector Terminal "Generalized electric terminal"
  extends AixLib.Electrical.Interfaces.BaseTerminal;
replaceable package PhaseSystem = PhaseSystems.PartialPhaseSystem
    "Phase system"
PhaseSystem.Voltage v[PhaseSystem.n] "Voltage vector";
flow PhaseSystem.Current i[PhaseSystem.n](each start=0) "Current vector";
PhaseSystem.ReferenceAngle theta[PhaseSystem.m]
    "Optional vector of phase angles";
end Terminal;


Partial model of a generic variable voltage source.. This model represents a generic variable voltage source. The model has a boolean
flag use_V_in, when this flag is equal to true
the voltage of the source is imposed by the input variable V_in.
When the flag is equal to false the voltage source is equal to the parameter V.

within AixLib.Electrical.Interfaces;
model VariableVoltageSource
  "Partial model of a generic variable voltage source."
  extends AixLib.Electrical.Interfaces.Source;
  parameter Boolean use_V_in = true "If true, the voltage is an input";
  parameter Modelica.Units.SI.Voltage V=1 "Value of constant voltage"
  Modelica.Blocks.Interfaces.RealInput V_in(unit="V", min=0, start = 1)
    if use_V_in "Input voltage"
protected
  Modelica.Blocks.Interfaces.RealInput  V_in_internal(unit="V")
    "Hidden value of the input voltage for the conditional connector";
equation

  // Connection between the conditional and inner connector
  connect(V_in,V_in_internal);

  // If the voltage is fixed, inner connector value is equal to parameter V
  if use_V_in == false then
    V_in_internal = V;
  end if;
end VariableVoltageSource;


Model of a general induction machine working as generator or electric motor. Model of an electric induction machine that includes the calculation
  of:

within AixLib.Electrical.Machines;
model InductionMachine
  "Model of a general induction machine working as generator or electric motor"
  import AixLib;
  extends Modelica.Electrical.Machines.Icons.TransientMachine;

  parameter Modelica.Units.SI.Frequency n0=f_1/p
    "Idling speed of the electric machine"
  parameter Modelica.Units.SI.Frequency n_nominal=1530/60 "Rated rotor speed"
  parameter Modelica.Units.SI.Frequency f_1=50 "Frequency"
  parameter Modelica.Units.SI.Voltage U_1=400 "Rated voltage"
  parameter Modelica.Units.SI.Current I_elNominal=P_elNominal/(sqrt(3)*U_1*
      cosPhi) "Rated current"
  parameter Modelica.Units.SI.Current I_1_start=if P_Mec_nominal <= 15000 then
      7.2*I_elNominal else 8*I_elNominal
    "Motor start current (realistic factors used from DIN VDE 2650/2651)"
  parameter Modelica.Units.SI.Power P_elNominal=15000
    "Nominal electrical power of electric machine"
  parameter Modelica.Units.SI.Power P_Mec_nominal=P_elNominal*(1 + s_nominal/
      0.22) "Nominal mechanical power of electric machine"
  parameter Modelica.Units.SI.Torque M_nominal=P_Mec_nominal/(2*Modelica.Constants.pi
      *n_nominal) "Nominal torque of electric machine"
  parameter Modelica.Units.SI.Torque M_til=2*M_nominal
    "Tilting torque of electric machine (realistic factor used from DIN VDE 2650/2651)"
  parameter Modelica.Units.SI.Torque M_start=if P_Mec_nominal <= 4000 then 1.6*
      M_nominal elseif P_Mec_nominal >= 22000 then 1*M_nominal else 1.25*
      M_nominal
    "Starting torque of electric machine (realistic factor used from DIN VDE 2650/2651)"
  parameter Modelica.Units.SI.Inertia J_Gen=1
    "Moment of inertia of the electric machine (default=0.5kg.m2)"
  parameter Real s_nominal=abs(1-n_nominal*p/f_1) "Nominal slip of electric machine"
  parameter Real s_til=abs((s_nominal*(M_til/M_nominal)+s_nominal*sqrt(abs(((M_til/M_nominal)^2)-1+2*s_nominal*((M_til/M_nominal)-1))))/(1-2*s_nominal*((M_til/M_nominal)-1)))
   "Tilting slip of electric machine"
  parameter Real p=2 "Number of pole pairs"
  parameter Real cosPhi=0.8 "Power factor of electric machine (default=0.8)"
  parameter Real calFac=1
    "Calibration factor for electric power outuput (default=1)"
  parameter Real gearRatio=1 "Transmission ratio (engine speed / generator speed)"

  Modelica.Units.SI.Frequency n=inertia.w/(2*Modelica.Constants.pi)
    "Speed of machine rotor [1/s]";
  Modelica.Units.SI.Current I_1 "Electric current of machine stator";
  Modelica.Units.SI.Power P_E "Electrical power at the electric machine";
  Modelica.Units.SI.Power P_Mec "Mechanical power at the electric machine";
  Modelica.Units.SI.Power CalQ_Loss
    "Calculated heat flow from electric machine";
  Modelica.Units.SI.Torque M "Torque at electric machine";
  Real s=1-n*p/f_1 "Current slip of electric machine";
  Real eta "Total efficiency of the electric machine (as motor)";
  Real calI_1 = 1/(1+((k-1)/((s_nominal^2)-k))*((s^2)+rho1*abs(s)+rho0));
  Boolean OpMode = (n<=n0) "Operation mode (true=motor, false=generator)";
  Boolean SwitchOnOff = isOn "Operation of electric machine (true=On, false=Off)";
  Modelica.Mechanics.Rotational.Components.Inertia inertia(       w(fixed=false), J=J_Gen)
  Modelica.Blocks.Sources.RealExpression electricTorque(y=M)
  Modelica.Mechanics.Rotational.Sources.Torque torque
  Modelica.Mechanics.Rotational.Interfaces.Flange_a flange_Machine

  Modelica.Mechanics.Rotational.Components.IdealGear transmission(ratio=
        gearRatio)
  Modelica.Blocks.Interfaces.BooleanInput isOn
  Modelica.Blocks.Interfaces.RealOutput electricCurrent
  Modelica.Blocks.Interfaces.RealOutput electricPower
  Modelica.Blocks.Interfaces.RealOutput rotationalSpeed
  Modelica.Blocks.Sources.RealExpression current(y=I_1)
  Modelica.Blocks.Sources.RealExpression power(y=P_E)
  Modelica.Blocks.Sources.RealExpression speed(y=n)

protected
  parameter Real rho0=s_til^2 "Calculation variable for analytical approach (Aree, 2017)"
  parameter Real rho1=(M_start*(1+s_til^2)-2*s_til*M_til)/(M_til-M_start) "Calculation variable for analytical approach (Aree, 2017)"
  parameter Real rho3=(M_til*M_start*(1-s_til)^2)/(M_til-M_start) "Calculation variable for analytical approach (Aree, 2017)"
  parameter Real k=((I_elNominal/I_1_start)^2)*(((s_nominal^2)+rho1*s_nominal+rho0)/(1+rho1+rho0)) "Calculation variable for analytical approach (Aree, 2017)"

equation

if noEvent(SwitchOnOff) then

  I_1=sign(s)*I_1_start*sqrt(abs((1+((k-1)/((s_nominal^2)-k))*(s^2)*(1+rho1+rho0))*calI_1));
  P_E=if noEvent(s>0) then sqrt(3)*I_1*U_1*cosPhi elseif noEvent(s<0) then calFac*(P_Mec+CalQ_Loss) else 1;
  P_Mec=2*Modelica.Constants.pi*M*n;
  CalQ_Loss= (calFac-1)*P_E + 2*Modelica.Constants.pi*M*(s*n0)/0.22;
  M=sign(s)*(rho3*abs(s))/((s^2)+rho1*abs(s)+rho0);
  eta=if noEvent(s>0) then abs(P_Mec/(P_E+1))
  elseif noEvent(s<0) then abs(P_E/(P_Mec-1)) else 0;

else

  I_1=0;
  P_E=0;
  P_Mec=0;
  CalQ_Loss=0;
  M=if noEvent(s<0) then sign(s)*(rho3*abs(s))/((s^2)+rho1*abs(s)+rho0) else 0;
  eta=0;

  end if;

  connect(electricTorque.y, torque.tau)
  connect(torque.flange, inertia.flange_a)
  connect(inertia.flange_b, transmission.flange_b)
  connect(transmission.flange_a, flange_Machine)
  connect(current.y, electricCurrent)
  connect(power.y, electricPower)
  connect(speed.y, rotationalSpeed)
end InductionMachine;


Inverter model including system management.

within AixLib.Electrical.Machines;
model PVInverterRMS "Inverter model including system management"

  parameter Modelica.Units.SI.Power uMax2=3800
    "Upper limits of input signals (MaxOutputPower)";
 Modelica.Blocks.Interfaces.RealOutput PVPowerRmsW(
  final quantity="Power",
  final unit="W")
  "Output power of the PV system including the inverter"
 Modelica.Blocks.Interfaces.RealInput DCPowerInput(
  final quantity="Power",
  final unit="W")
  "DC output power of PV panels as input for the inverter"
 Modelica.Blocks.Nonlinear.Limiter MaxOutputPower(
   uMax(
    final quantity="Power",
    final displayUnit="Nm/s")=uMax2,
   uMin=0)
   "Limitier for maximum output power"
 Modelica.Blocks.Tables.CombiTable1Ds EfficiencyConverterSunnyBoy3800(
   tableOnFile=false,
   table=[0,0.798700;100,0.848907;200,0.899131;250,0.911689;300,0.921732;350,0.929669;400,0.935906;450,0.940718;500,0.943985;550,0.946260;600,0.947839;700,0.950638;800,0.952875;900,0.954431;1000,0.955214;1250,0.956231;1500,0.956449;2000,0.955198;2500,0.952175;3000,0.948659;3500,0.944961;3800,0.942621])
     "Efficiency of the inverter for different operating points"
 Modelica.Blocks.Math.Product Product2
     "Multiplies the output power of the PV cell with the efficiency of the inverter "

equation
  connect(Product2.u2,EfficiencyConverterSunnyBoy3800.y[1])
  connect(Product2.y,MaxOutputPower.u)
  connect(MaxOutputPower.y,PVPowerRmsW)
  connect(Product2.u1,DCPowerInput)
  connect(EfficiencyConverterSunnyBoy3800.u,DCPowerInput)
end PVInverterRMS;


rpm.

within AixLib.Electrical.Machines.Examples;
model InductionMotor
  extends Modelica.Icons.Example;
  InductionMachine inductionMachine(inertia(phi(fixed=true, start=0), w(
          fixed=true, start=0)))
  Modelica.Mechanics.Rotational.Sources.QuadraticSpeedDependentTorque
    quadraticSpeedDependentTorque(tau_nominal=-100, w_nominal(displayUnit="rpm")=
         inductionMachine.n0)
  Modelica.Blocks.Sources.BooleanPulse booleanPulse(period=100, startTime=0)
equation
  connect(quadraticSpeedDependentTorque.flange, inductionMachine.flange_Machine)
  connect(booleanPulse.y, inductionMachine.isOn)
end InductionMotor;


<html><p>
  This package contains test examples for the use of induction machine
  models.
</p>
</html>

within AixLib.Electrical.Machines;
package Examples
  extends Modelica.Icons.ExamplesPackage;
end Examples;


DC system

within AixLib.Electrical.PhaseSystems;
package DirectCurrent "DC system"
  extends PartialPhaseSystem(phaseSystemName="DirectCurrent", n=1, 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 := {V};
  end phaseVoltages;

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

  redeclare function extends phasePowers "Return phase powers"
  algorithm
    p := {P};
  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];
  end systemVoltage;

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

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


Single phase two connectors AC system

within AixLib.Electrical.PhaseSystems;
package OnePhase "Single phase two connectors AC system"
  extends PartialPhaseSystem(phaseSystemName="OnePhase", 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 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];
  end rotate;

  redeclare function extends product
  "Multiply two complex numbers represented by vectors x[2] and y[2]"
  algorithm
    z := {x[1]*y[1] - x[2]*y[2], x[1]*y[2] + x[2]*y[1]};
  end product;

  redeclare function extends divide
  "Divide two complex numbers represented by vectors x[2] and y[2]"
  algorithm
    z := {x[1]*y[1] + x[2]*y[2], x[2]*y[1] - x[1]*y[2]}/(y[1]^2 + y[2]^2);
  end divide;

  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)};
  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[1]*i[1] + v[2]*i[2], v[2]*i[1] - v[1]*i[2]};
  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] + v[2]*i[2]
    P := v*i;
  end activePower;
end OnePhase;


Phase systems used in power connectors

within AixLib.Electrical;
package PhaseSystems "Phase systems used in power connectors"
  extends Modelica.Icons.Package;
  import      Modelica.Units.SI;
  import Modelica.Constants.pi;
end PhaseSystems;


Base package of all phase systems

within AixLib.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 AixLib.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 AixLib.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 AixLib.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 AixLib.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;


Model that determines the DC performance of a Silicium-based PV array.

within AixLib.Electrical.PVSystem;
model PVSystem
  "Model that determines the DC performance of a Silicium-based PV array"

 replaceable parameter AixLib.DataBase.SolarElectric.PVBaseDataDefinition data
 constrainedby AixLib.DataBase.SolarElectric.PVBaseDataDefinition
 "PV Panel data definition"

 replaceable model IVCharacteristics =
    AixLib.Electrical.PVSystem.BaseClasses.PartialIVCharacteristics
    "Model for determining the I-V characteristics of a PV array"

 replaceable model CellTemperature =
    AixLib.Electrical.PVSystem.BaseClasses.PartialCellTemperature
    "Model for determining the cell temperature of a PV array"

 parameter Real n_mod
    "Number of connected PV modules";
  parameter Modelica.Units.SI.Angle til "Surface's tilt angle (0:flat)"
  parameter Modelica.Units.SI.Angle azi "Surface's azimut angle (0:South)"
  parameter Modelica.Units.SI.Angle lat "Location's Latitude"
  parameter Modelica.Units.SI.Angle lon "Location's Longitude"
 parameter Real alt(final quantity="Length", final unit="m")
   "Site altitude in Meters, default= 1"
  parameter Modelica.Units.SI.Time timZon(displayUnit="h")
    "Time zone. Should be equal with timZon in ReaderTMY3, if PVSystem and ReaderTMY3 are used together."
 parameter Real groRef(final unit="1") = 0.2
  "Ground reflectance (default=0.2)
  Urban environment: 0.14 - 0.22
  Grass: 0.15 - 0.25
  Fresh grass: 0.26
  Fresh snow: 0.82
  Wet snow: 0.55-0.75
  Dry asphalt: 0.09-0.15
  Wet Asphalt: 0.18
  Concrete: 0.25-0.35
  Red tiles: 0.33
  Aluminum: 0.85
  Copper: 0.74
  New galvanized steel: 0.35
  Very dirty galvanized steel: 0.08"

  parameter Boolean use_ParametersGlaz=false
    "= false if standard values for glazing can be used"

  parameter Real glaExtCoe(final unit="1/m") = 4
  "Glazing extinction coefficient (for glass = 4)"

  parameter Real glaThi(final unit="m") = 0.002
  "Glazing thickness (for most cells = 0.002 m)"

  parameter Real refInd(final unit="1", min=0) = 1.526
  "Effective index of refraction of the cell cover (glass = 1.526)"

  IVCharacteristics iVCharacteristics(final n_mod=n_mod,
  final data=data)
    "Model for determining the I-V characteristics of a PV array"

  CellTemperature cellTemperature(final data=data)
    "Model for determining the cell temperature of a PV array"

 Modelica.Blocks.Interfaces.RealOutput DCOutputPower(
  final quantity="Power",
  final unit="W")
  "DC output power of the PV array"

  BaseClasses.PVRadiationHorizontal    pVRadiationHorizontalTRY(
   final lat = lat,
   final lon = lon,
   final alt = alt,
   final til = til,
   final azi = azi,
   final groRef = groRef,
   final timZon = timZon,
   final glaExtCoe=glaExtCoe,
   final glaThi=glaThi,
   final refInd=refInd)
   "Radiation and absorptance model for PV simulations"

  BoundaryConditions.WeatherData.Bus weaBus
equation

  connect(pVRadiationHorizontalTRY.radTil, iVCharacteristics.radTil)
  connect(pVRadiationHorizontalTRY.absRadRat, iVCharacteristics.absRadRat)
  connect(pVRadiationHorizontalTRY.radTil, cellTemperature.radTil)
  connect(iVCharacteristics.eta, cellTemperature.eta)
  connect(cellTemperature.T_c, iVCharacteristics.T_c)
  connect(iVCharacteristics.DCOutputPower, DCOutputPower)
  connect(weaBus.winSpe, cellTemperature.winVel)
  connect(weaBus.TDryBul, cellTemperature.T_a)
  connect(weaBus.HGloHor, pVRadiationHorizontalTRY.radHor)
end PVSystem;


Empirical model for determining the cell temperature of a PV module mounted with the
  module backsite close to the ground.

within AixLib.Electrical.PVSystem.BaseClasses;
model CellTemperatureMountingCloseToGround
  "Empirical model for determining the cell temperature of a PV module mounted with the
  module backsite close to the ground"

 extends AixLib.Electrical.PVSystem.BaseClasses.PartialCellTemperature;

equation

 T_c = if noEvent(radTil >= Modelica.Constants.eps) then
 radTil*(exp(-2.98-0.0471*winVel))+(T_a)+radTil/1000*1
 else
 (T_a);
end CellTemperatureMountingCloseToGround;


Empirical model for determining the cell temperature of a PV module mounted with the
  module backsite in contact with the ground.

within AixLib.Electrical.PVSystem.BaseClasses;
model CellTemperatureMountingContactToGround
  "Empirical model for determining the cell temperature of a PV module mounted with the
  module backsite in contact with the ground"

extends AixLib.Electrical.PVSystem.BaseClasses.PartialCellTemperature;

equation

 T_c = if noEvent(radTil >= Modelica.Constants.eps) then
     radTil*(exp(-2.81-0.0455*winVel))+(T_a)
 else
 (T_a);
end CellTemperatureMountingContactToGround;


Empirical model for determining the cell temperature of a PV module mounted on an
   open rack.

within AixLib.Electrical.PVSystem.BaseClasses;
model CellTemperatureOpenRack
   "Empirical model for determining the cell temperature of a PV module mounted on an
   open rack"

 extends AixLib.Electrical.PVSystem.BaseClasses.PartialCellTemperature;

  final parameter Modelica.Units.SI.Temperature T_a_0=293.15
    "Reference ambient temperature";
 final parameter Real coeff_trans_abs = 0.9
 "Module specific coefficient as a product of transmission and absorption.
 It is usually unknown and set to 0.9 in literature";

equation

 T_c = if noEvent(radTil >= Modelica.Constants.eps) then
 (T_a)+(T_NOCT-T_a_0)*radTil/radNOCT*9.5/(5.7+3.8*winVel)*(1-eta/coeff_trans_abs)
 else
 (T_a);
end CellTemperatureOpenRack;


Analytical 5-p model for PV I-V
  characteristics (Batzelis et al.,2016) with temp. dependency of the
  5 parameters based on (DeSoto et al.,2006).

within AixLib.Electrical.PVSystem.BaseClasses;
model IVCharacteristics5pAnalytical "Analytical 5-p model for PV I-V
  characteristics (Batzelis et al.,2016) with temp. dependency of the
  5 parameters based on (DeSoto et al.,2006)"

extends PartialIVCharacteristics;

// Main parameters under standard conditions

  Modelica.Units.SI.ElectricCurrent I_ph0
    "Photo current under standard conditions";
  Modelica.Units.SI.ElectricCurrent I_s0
    "Saturation current under standard conditions";
  Modelica.Units.SI.Resistance R_s0
    "Series resistance under standard conditions";
  Modelica.Units.SI.Resistance R_sh0
    "Shunt resistance under standard conditions";
 Real a_0(unit = "V")
    "Modified diode ideality factor under standard conditions";
 Real w_0(final unit = "1")
    "MPP auxiliary correlation coefficient under standard conditions";

// Additional parameters and constants

 constant Real e=Modelica.Math.exp(1.0)
   "Euler's constant";
 constant Real pi=Modelica.Constants.pi
   "Pi";
 constant Real k(final unit="J/K") = 1.3806503e-23
   "Boltzmann's constant";
 constant Real q( unit = "A.s")= 1.602176620924561e-19
   "Electron charge";
  parameter Modelica.Units.SI.Energy E_g0=1.79604e-19
    "Band gap energy under standard conditions for Si";
 parameter Real C=0.0002677
    "Band gap temperature coefficient for Si";

  Modelica.Units.SI.ElectricCurrent I_mp(start=0.5*I_mp0) "MPP current";

  Modelica.Units.SI.Voltage V_mp "MPP voltage";

  Modelica.Units.SI.Energy E_g "Band gap energy";

  Modelica.Units.SI.ElectricCurrent I_s "Saturation current";

  Modelica.Units.SI.ElectricCurrent I_ph "Photo current";

  Modelica.Units.SI.Resistance R_s "Series resistance";

  Modelica.Units.SI.Resistance R_sh "Shunt resistance";

 Real a(final unit = "V", start = 1.3)
    "Modified diode ideality factor";

  Modelica.Units.SI.Power P_mod "Output power of one PV module";

 Real w(final unit = "1", start = 0)
   "MPP auxiliary correlation coefficient";

  Modelica.Units.SI.Voltage V_oc
    "Open circuit voltage under operating conditions";

equation

// Analytical parameter extraction equations under standard conditions (Batzelis et al., 2016)

 a_0 = V_oc0*(1-T_c0*beta_Voc)/(50.1-T_c0*alpha_Isc);

 w_0 = AixLib.Electrical.PVSystem.BaseClasses.Wsimple(exp(1/(a_0/V_oc0)+1));

 R_s0 = (a_0*(w_0-1)-V_mp0)/I_mp0;

 R_sh0 = a_0*(w_0-1)/(I_sc0*(1-1/w_0)-I_mp0);

 I_ph0 = (1+R_s0/R_sh0)*I_sc0;

 I_s0 = I_ph0*exp(-1/(a_0/V_oc0));

// Parameter extrapolation equations to operating conditions (DeSoto et al.,2006)

 a/a_0 = T_c/T_c0;

 I_s/I_s0 = (T_c/T_c0)^3*exp(1/k*(E_g0/T_c0-E_g/T_c));

 E_g/E_g0 = 1-C*(T_c-T_c0);

 R_s = R_s0;

 I_ph = if absRadRat > 0 then absRadRat*(I_ph0+TCoeff_Isc*(T_c-T_c0))
 else
  0;

 R_sh/R_sh0 = if noEvent(absRadRat > 0.001) then 1/absRadRat
 else
  0;

//Simplified Power correlations at MPP using lambert W function (Batzelis et al., 2016)

 I_mp = if noEvent(absRadRat <= 0.0011 or w<=0.001) then 0
 else
 I_ph*(1-1/w)-a*(w-1)/R_sh;

 V_mp = if absRadRat <= 0 then 0
 else
 a*(w-1)-R_s*I_mp;

 V_oc = if I_ph >= 0.01  then
 a*log(abs((I_ph/I_s+1)))
 else
 0;

 w = if noEvent(V_oc >= 0.001) then
 AixLib.Electrical.PVSystem.BaseClasses.Wsimple(exp(1/(a/V_oc)+1))
 else
 0;

//I-V curve equation - use if P at a given V is needed (e.g. battery loading scenarios without MPP tracker)
//I = I_ph - I_s*(exp((V+I*R_s)/(a))-1) - (V + I*R_s)/(R_sh);

// Efficiency and Performance

 eta= if noEvent(radTil <= 0.01) then 0
 else
 P_mod/(radTil*A_pan);

 P_mod = V_mp*I_mp;

 DCOutputPower=max(0, min(P_Max*n_mod, P_mod*n_mod));
end IVCharacteristics5pAnalytical;


Partial model for determining the cell temperature of a PV moduleConnector
  for PV record data.

within AixLib.Electrical.PVSystem.BaseClasses;
partial model PartialCellTemperature
  "Partial model for determining the cell temperature of a PV moduleConnector
  for PV record data"

// Parameters from module data sheet
 replaceable parameter AixLib.DataBase.SolarElectric.PVBaseDataDefinition data
 constrainedby AixLib.DataBase.SolarElectric.PVBaseDataDefinition
 "PV Panel data definition"

  final parameter Modelica.Units.SI.Efficiency eta_0=data.eta_0
    "Efficiency under standard conditions";

  final parameter Modelica.Units.SI.Temperature T_NOCT=data.T_NOCT
    "Cell temperature under NOCT conditions";

 final parameter Real radNOCT(final quantity="Irradiance",
    final unit="W/m2")= 800
    "Irradiance under NOCT conditions";
 Modelica.Blocks.Interfaces.RealInput T_a(final quantity=
    "Temp_C", final unit="K")
    "Ambient temperature"

 Modelica.Blocks.Interfaces.RealInput winVel(final quantity= "Velocity",
    final unit= "m/s")
    "Wind velocity"

 Modelica.Blocks.Interfaces.RealInput eta(final quantity="Efficiency",
      final unit="1",
      min=0)
    "Efficiency of the PV module under operating conditions"

 Modelica.Blocks.Interfaces.RealInput radTil(final quantity="Irradiance",
    final unit="W/m2")
    "Total solar irradiance on the tilted surface"

 Modelica.Blocks.Interfaces.RealOutput T_c(final quantity=
    "ThermodynamicTemperature", final unit="K")
    "Cell temperature"
end PartialCellTemperature;


Partial model for IV Characteristic of a PV module.

within AixLib.Electrical.PVSystem.BaseClasses;
partial model PartialIVCharacteristics
"Partial model for IV Characteristic of a PV module"

replaceable parameter AixLib.DataBase.SolarElectric.PVBaseDataDefinition data
constrainedby AixLib.DataBase.SolarElectric.PVBaseDataDefinition
"PV Panel data definition"

// Adjustable input parameters

parameter Real n_mod(final quantity=
  "NumberOfModules", final unit="1") "Number of connected PV modules"

// Parameters from module data sheet

final parameter Modelica.Units.SI.Efficiency eta_0=data.eta_0
"Efficiency under standard conditions";

final parameter Real n_ser=data.n_ser
  "Number of cells connected in series on the PV panel";

final parameter Modelica.Units.SI.Area A_pan=data.A_pan
"Area of one Panel, must not be confused with area of the whole module";

final parameter Modelica.Units.SI.Area A_mod=data.A_mod
"Area of one module (housing)";

final parameter Modelica.Units.SI.Voltage V_oc0=data.V_oc0
"Open circuit voltage under standard conditions";

final parameter Modelica.Units.SI.ElectricCurrent I_sc0=data.I_sc0
"Short circuit current under standard conditions";

final parameter Modelica.Units.SI.Voltage V_mp0=data.V_mp0
"MPP voltage under standard conditions";

final parameter Modelica.Units.SI.ElectricCurrent I_mp0=data.I_mp0
"MPP current under standard conditions";

final parameter Modelica.Units.SI.Power P_Max=data.P_mp0*1.05
"Maximal power of one PV module under standard conditions. P_MPP with 5 % tolerance. This is used to limit DCOutputPower.";

final parameter Real TCoeff_Isc(unit = "A/K")=data.TCoeff_Isc
  "Temperature coefficient for short circuit current, >0";

final parameter Real TCoeff_Voc(unit = "V/K")=data.TCoeff_Voc
  "Temperature coefficient for open circuit voltage, <0";

final parameter Modelica.Units.SI.LinearTemperatureCoefficient alpha_Isc=data.alpha_Isc
"Normalized temperature coefficient for short circuit current, >0";

final parameter Modelica.Units.SI.LinearTemperatureCoefficient beta_Voc=data.beta_Voc
"Normalized temperature coefficient for open circuit voltage, <0";

final parameter Modelica.Units.SI.LinearTemperatureCoefficient gamma_Pmp=data.gamma_Pmp
"Normalized temperature coefficient for power at MPP";

final parameter Modelica.Units.SI.Temperature T_c0=25 + 273.15
"Thermodynamic cell temperature under standard conditions";

Modelica.Blocks.Interfaces.RealOutput DCOutputPower(
final quantity="Power",
final unit="W")
"DC output power of the PV array"

Modelica.Blocks.Interfaces.RealOutput eta(
final quantity="Efficiency",
final unit="1",
min=0)
"Efficiency of the PV module under operating conditions"

Modelica.Blocks.Interfaces.RealInput T_c(final quantity=
  "ThermodynamicTemperature", final unit="K")
  "Cell temperature"

Modelica.Blocks.Interfaces.RealInput absRadRat(final unit= "1")
  "Ratio of absorbed radiation under operating conditions to standard conditions"

Modelica.Blocks.Interfaces.RealInput radTil(final unit="W/m2")
  "Total solar irradiance on the tilted surface"

end PartialIVCharacteristics;


PV radiation and absorptance model - input: total irradiance on horizontal plane.

within AixLib.Electrical.PVSystem.BaseClasses;
model PVRadiationHorizontal "PV radiation and absorptance model - input: total irradiance on horizontal plane"

 parameter Real lat(final quantity = "Angle",
   final unit = "rad",
   displayUnit = "deg") "Latitude"

 parameter Real lon(final quantity = "Angle",
   final unit = "rad",
   displayUnit = "deg") "Longitude"

 parameter Real  alt(final quantity="Length", final unit="m")
   "Site altitude in Meters, default= 1"

 parameter Real til(final quantity = "Angle",
   final unit = "rad",
   displayUnit = "deg")
   "Surface tilt. til=90 degree for walls; til=0 for ceilings; til=180 for roof"

 parameter Real  azi(final quantity = "Angle",
   final unit = "rad",
   displayUnit = "deg")
   "Module surface azimuth. azi=-90 degree if normal of surface outward unit points towards east; azi=0 if it points towards south"

 parameter Real timZon(final quantity="Time",
   final unit="s", displayUnit="h")
   "Time zone in seconds relative to GMT"

 parameter Real groRef(final unit="1") "Ground refelctance"

 // Air mass parameters for mono-SI
  parameter Real b_0=0.935823;
  parameter Real b_1=0.054289;
  parameter Real b_2=-0.008677;
  parameter Real b_3=0.000527;
  parameter Real b_4=-0.000011;

  parameter Real radTil0(final quantity="Irradiance",
  final unit= "W/m2") = 1000 "total solar radiation on the horizontal surface
  under standard conditions";

  parameter Real G_sc(final quantity="Irradiance",
  final unit = "W/m2") = 1376 "Solar constant";

  parameter Real glaExtCoe(final unit="1/m") = 4
  "Glazing extinction coefficient for glass";

  parameter Real glaThi(final unit="m") = 0.002
  "Glazing thickness for most PV cell panels";

  parameter Real refInd(final unit="1", min=0) = 1.526
  "Effective index of refraction of the cell cover (glass)";

  parameter Real tau_0(final unit="1", min=0)=
   exp(-(glaExtCoe*glaThi))*(1 - ((refInd - 1)/(refInd + 1))
  ^2) "Transmittance at standard conditions (incAng=refAng=0)";

  Real cloTim(final quantity="Time",
   final unit="s", displayUnit="h")
   "Local clock time";

  Real nDay(final quantity="Time",final unit="s")
    "Day number with units of seconds";

  Real radHorBea(final quantity="Irradiance",
   final unit= "W/m2")
   "Beam solar radiation on the horizontal surface";

  Real radHorDif(final quantity="Irradiance",
   final unit= "W/m2")
   "Diffuse solar radiation on the horizontal surface";

  Real k_t(final unit="1", start=0.5) "Clearness index";

  Real airMas(final unit="1", min=0) "Air mass";

  Real airMasMod(final unit="1", min=0) "Air mass modifier";

  Modelica.Units.SI.Angle incAngGro "Incidence angle for ground reflection";

  Modelica.Units.SI.Angle incAngDif "Incidence angle for diffuse radiation";

  Real incAngMod(final unit="1", min=0) "Incidence angle modifier";

  Real incAngModGro(final unit="1", min=0) "Incidence angle modifier for ground refelction";

  Real incAngModDif(final unit="1", min=0)
  "Incidence angle modifier for diffuse radiation";

  Modelica.Units.SI.Angle refAng "Angle of refraction";

  Modelica.Units.SI.Angle refAngGro "Angle of refraction for ground reflection";

  Modelica.Units.SI.Angle refAngDif
    "Angle of refraction for diffuse irradiation";

  Real tau(final unit="1", min=0)
  "Transmittance of the cover system";

  Real tau_ground(final unit="1", min=0)
  "Transmittance of the cover system for ground reflection";

  Real tau_diff(final unit="1", min=0)
  "Transmittance of the cover system for diffuse radiation";

  Real R_b(final unit="1", min=0)
   "Ratio of irradiance on tilted surface to horizontal surface";

  Modelica.Units.SI.Angle zen "Zenith angle";

  AixLib.BoundaryConditions.SolarGeometry.BaseClasses.SolarHourAngle
    solHouAng
    "Solar hour angle";

  AixLib.BoundaryConditions.WeatherData.BaseClasses.LocalCivilTime locTim(
    timZon=timZon,
    lon=lon)
    "Block that computes the local civil time";

  AixLib.BoundaryConditions.WeatherData.BaseClasses.SolarTime solTim
    "Block that computes the solar time";

  AixLib.BoundaryConditions.WeatherData.BaseClasses.EquationOfTime eqnTim
    "Block that computes the equation of time";

  AixLib.BoundaryConditions.SolarGeometry.BaseClasses.Declination decAng
    "Declination angle";

  AixLib.BoundaryConditions.SolarGeometry.BaseClasses.IncidenceAngle incAng(
   azi=azi,
   til=til,
   lat=lat) "Incidence angle";

  AixLib.BoundaryConditions.SolarGeometry.BaseClasses.ZenithAngle zenAng(
   lat=lat) "Zenith angle";

  AixLib.Utilities.Time.ModelTime modTim "Block that outputs simulation time";

  Modelica.Blocks.Interfaces.RealOutput radTil(final quantity="Irradiance",
   final unit= "W/m2")
   "Total solar radiation on the tilted surface"

  Modelica.Blocks.Interfaces.RealOutput absRadRat(final unit= "1", min=0)
   "Ratio of absorbed radiation under operating conditions to standard conditions"

  Modelica.Blocks.Interfaces.RealInput radHor(final quantity="Irradiance",
   final unit= "W/m2")
   "Total solar irradiance on the horizontal surface"

equation

 connect(solTim.solTim, solHouAng.solTim);

 connect(locTim.locTim, solTim.locTim);

 connect(eqnTim.eqnTim, solTim.equTim);

 connect(decAng.decAng, incAng.decAng);

 connect(solHouAng.solHouAng, incAng.solHouAng);

 connect(decAng.decAng, zenAng.decAng);

 connect(solHouAng.solHouAng, zenAng.solHouAng);

 nDay = floor(modTim.y/86400)*86400
  "Zero-based day number in seconds (January 1=0, January 2=86400)";

 cloTim= modTim.y-nDay;

 eqnTim.nDay= nDay;

 locTim.cloTim=cloTim;

 decAng.nDay= nDay;

 zen = if zenAng.zen <= Modelica.Constants.pi/2 then
 zenAng.zen
 else
 Modelica.Constants.pi/2
 "Restriction for zenith angle";

  refAng = if noEvent(incAng.incAng >= 0.0001 and incAng.incAng <= Modelica.Constants.pi
  /2*0.999) then asin(sin(incAng.incAng)/refInd) else
  0;

  refAngGro = if noEvent(incAngGro >= 0.0001 and incAngGro <= Modelica.Constants.pi/2*
  0.999) then asin(sin(incAngGro)/refInd) else
  0;

  refAngDif = if noEvent(incAngDif >= 0.0001 and incAngDif <= Modelica.Constants.pi/2*
  0.999) then asin(sin(incAngDif)/refInd) else
  0;

  tau = if noEvent(incAng.incAng >= 0.0001 and incAng.incAng <= Modelica.Constants.pi/
  2*0.999 and refAng >= 0.0001) then exp(-(glaExtCoe*glaThi/cos(refAng)))*(1
  - 0.5*((sin(refAng - incAng.incAng)^2)/(sin(refAng + incAng.incAng)^2) + (
  tan(refAng - incAng.incAng)^2)/(tan(refAng + incAng.incAng)^2))) else
  0;

  tau_ground = if noEvent(incAngGro >= 0.0001 and refAngGro >= 0.0001) then exp(-(
  glaExtCoe*glaThi/cos(refAngGro)))*(1 - 0.5*((sin(refAngGro - incAngGro)^2)/
  (sin(refAngGro + incAngGro)^2) + (tan(refAngGro - incAngGro)^2)/(tan(
  refAngGro + incAngGro)^2))) else
  0;

  tau_diff = if noEvent(incAngDif >= 0.0001 and refAngDif >= 0.0001) then exp(-(
  glaExtCoe*glaThi/cos(refAngDif)))*(1 - 0.5*((sin(refAngDif - incAngDif)^2)/
  (sin(refAngDif + incAngDif)^2) + (tan(refAngDif - incAngDif)^2)/(tan(
  refAngDif + incAngDif)^2))) else
  0;

  incAngMod = tau/tau_0;

  incAngModGro = tau_ground/tau_0;

  incAngModDif = tau_diff/tau_0;

  airMasMod = if (b_0 + b_1*(airMas^1) + b_2*(airMas^2) + b_3*(
  airMas^3) + b_4*(airMas^4)) <= 0 then
  0 else
  b_0 + b_1*(airMas^1) + b_2*(airMas^2) + b_3*(airMas^3) + b_4*(airMas^4);

  airMas = exp(-0.0001184*alt)/(cos(zen) + 0.5057*(96.080 - zen*
  180/Modelica.Constants.pi)^(-1.634));

  incAngGro = (90 - 0.5788*til*180/Modelica.Constants.pi + 0.002693*(til*180/
  Modelica.Constants.pi)^2)*Modelica.Constants.pi/180;

  incAngDif = (59.7 - 0.1388*til*180/Modelica.Constants.pi + 0.001497*(til*180/
  Modelica.Constants.pi)^2)*Modelica.Constants.pi/180;

  R_b = if noEvent((zen >= Modelica.Constants.pi/2*0.999) or (cos(incAng.incAng)
  > cos(zen)*4)) then 4 else (cos(incAng.incAng)/cos(zen));

  radHor = radHorBea + radHorDif;

  radTil = if noEvent(radHor <= 0.1) then 0 else radHorBea*R_b + radHorDif*(0.5*(1 + cos(
  til)*(1 + (1 - (radHorDif/radHor)^2)*sin(til/2)^3)*(1 + (1 - (radHorDif/
  radHor)^2)*(cos(incAng.incAng)^2)*(cos(til)^3)))) + radHor*groRef*(1 - cos(
  til))/2;

  k_t = if noEvent(radHor <=0.001) then 0
  else
  min(1,max(0,(radHor)/(G_sc*(1.00011+0.034221*cos(2*Modelica.Constants.pi*nDay/24/60/60/365)+0.00128*sin(2*Modelica.Constants.pi*nDay/24/60/60/365)
  +0.000719*cos(2*2*Modelica.Constants.pi*nDay/24/60/60/365)+0.000077*sin(2*2*Modelica.Constants.pi*nDay/24/60/60/365))*cos(zenAng.zen)))) "after (Iqbal,1983)";

// Erb´s diffuse fraction relation
  radHorDif = if radHor <=0.001 then 0
  elseif
       k_t <= 0.22 then
  (radHor)*(1.0-0.09*k_t)
   elseif
       k_t > 0.8 then
  (radHor)*0.165
   else
  (radHor)*(0.9511-0.1604*k_t+4.388*k_t^2-16.638*k_t^3+12.336*k_t^4);

  absRadRat = if noEvent(radHor <=0.1) then 0
  else
  airMasMod*(radHorBea/radTil0*R_b*incAngMod
  +radHorDif/radTil0*incAngModDif*(0.5*(1+cos(til)*(1+(1-(radHorDif/radHor)^2)*sin(til/2)^3)*(1+(1-(radHorDif/radHor)^2)*(cos(incAng.incAng)^2)*(cos(til)^3))))
  +radHor/radTil0*groRef*incAngModGro*(1-cos(til))/2);
end PVRadiationHorizontal;


Example of a model for determining the DC output Power of a PV array;
  Modules mounted close to the ground. Simulation to test the PVSystem model.

within AixLib.Electrical.PVSystem.Examples;
model ExamplePVSystem
  "Example of a model for determining the DC output Power of a PV array;
  Modules mounted close to the ground"
  import ModelicaServices;

 extends Modelica.Icons.Example;

  PVSystem pVSystem(
    redeclare DataBase.SolarElectric.QPlusBFRG41285 data,
    n_mod=20,
    lat(displayUnit="deg") = 0.91664692314742,
    lon(displayUnit="deg") = 0.23387411976724,
    alt=10,
    til(displayUnit="deg") = 0.26179938779915,
    azi(displayUnit="deg") = 0,
    redeclare model CellTemperature =
        BaseClasses.CellTemperatureMountingCloseToGround,
    redeclare model IVCharacteristics =
        BaseClasses.IVCharacteristics5pAnalytical,
    timZon(displayUnit="s") = weaDat.timZon)
    "Model for determining the DC output Power of a PV array; Modules mounted close to the ground (adjust to different mounting via cellTemp)"

  AixLib.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        ModelicaServices.ExternalReferences.loadResource(
        "modelica://AixLib/Resources/weatherdata/Weather_TRY_Berlin_winter.mos"),
      calTSky=AixLib.BoundaryConditions.Types.
      SkyTemperatureCalculation.HorizontalRadiation)

  Modelica.Blocks.Interfaces.RealOutput DCOutputPower(
  final quantity="Power",
  final unit="W")
  "DC output power of the PV array"

equation

  connect(pVSystem.DCOutputPower, DCOutputPower)

  connect(weaDat.weaBus, pVSystem.weaBus)
end ExamplePVSystem;


Collection of validation models

within AixLib.Electrical.PVSystem;
package Validation "Collection of validation models"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


Validation with empirical data from NIST for the date of 14.06.2016. The PVSystem model is validaded with empirical data from: https://pvdata.nist.gov/

within AixLib.Electrical.PVSystem.Validation;
model ValidationPVSystem
  "Validation with empirical data from NIST for the date of 14.06.2016"
  extends Modelica.Icons.Example;

  PVSystem pVSystem(
    redeclare DataBase.SolarElectric.SharpNUU235F2 data,
    redeclare model IVCharacteristics =
        BaseClasses.IVCharacteristics5pAnalytical,
    redeclare model CellTemperature =
        BaseClasses.CellTemperatureMountingCloseToGround,
    n_mod=312,
    til=0.17453292519943,
    azi=0,
    lat=0.68304158408499,
    lon=-1.3476664539029,
    alt=0.08,
    timZon=-18000)
    "PV System according to measurements taken from https://pvdata.nist.gov/  "
  Modelica.Blocks.Interfaces.RealOutput DCOutputPower(
  final quantity="Power",
  final unit="W")
    "DC output power of the PV array"
  BoundaryConditions.WeatherData.Bus weaBus
  Modelica.Blocks.Sources.CombiTimeTable NISTdata(
    tableOnFile=true,
    tableName="Roof2016",
    fileName=ModelicaServices.ExternalReferences.loadResource(
        "modelica://AixLib/Resources/weatherdata/NIST_onemin_Roof_2016.txt"),
    columns={3,5,2,4},
    smoothness=Modelica.Blocks.Types.Smoothness.ContinuousDerivative)
    "The PVSystem model is validaded with measurement data from: https://pvdata.nist.gov/ "

  Modelica.Blocks.Math.UnitConversions.From_degC from_degC

  Modelica.Blocks.Interfaces.RealOutput DCOutputPower_Measured(
  final quantity="Power",
  final unit="W")
    "Measured DC output power of the PV array"
  Modelica.Blocks.Math.Gain kiloWattToWatt(k=1000)
equation
  connect(pVSystem.DCOutputPower, DCOutputPower)
  connect(pVSystem.weaBus, weaBus)
  connect(NISTdata.y[2], weaBus.winSpe)
  connect(NISTdata.y[3], weaBus.HGloHor)
  connect(NISTdata.y[1], from_degC.u)
  connect(from_degC.y, weaBus.TDryBul)
  connect(NISTdata.y[4], kiloWattToWatt.u)
  connect(kiloWattToWatt.y, DCOutputPower_Measured)
end ValidationPVSystem;


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


within AixLib.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

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

AixLib.Electrical.Transmission.LowVoltageCables.Generic or

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

within AixLib.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 AixLib.Electrical.Types.Load modelMode=AixLib.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 AixLib.Electrical.Types.CableMode mode=AixLib.Electrical.Types.CableMode.automatic
    "Select if choosing the cable automatically or between a list of commercial options"

  replaceable parameter
    AixLib.Electrical.Transmission.LowVoltageCables.Generic
     commercialCable constrainedby
    AixLib.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"
  Modelica.Thermal.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
AixLib.Electrical.Transmission.BaseClasses.PartialBaseLine.
It adds two generalized electric connectors.

within AixLib.Electrical.Transmission.BaseClasses;
partial model PartialLine "Partial cable line dispersion model"
  extends AixLib.Electrical.Interfaces.PartialTwoPort;
  extends AixLib.Electrical.Transmission.BaseClasses.PartialBaseLine;
  Real VoltageLosses(unit = "1") = abs(PhaseSystem_p.systemVoltage(terminal_p.v) -
    PhaseSystem_n.systemVoltage(terminal_n.v))/
    AixLib.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 AixLib.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 AixLib.Electrical.Transmission.Grids.PartialGrid grid
    "Record that describe the grid with the number of nodes, links, connections, etc."
  replaceable AixLib.Electrical.Interfaces.BaseTerminal terminal[grid.nNodes]
    "Electric terminals for each node of the network"
  replaceable AixLib.Electrical.Transmission.BaseClasses.PartialBaseLine lines[grid.nLinks](
    each mode=AixLib.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 AixLib.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 AixLib.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 AixLib.Electrical.Transmission.BaseClasses;
partial model PartialTwoPortRLC
  "Partial model of an RLC element that links two electrical connectors"
  extends AixLib.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 AixLib.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 AixLib.Electrical.Transmission.Functions;
package Validation
  extends Modelica.Icons.ExamplesPackage;
end Validation;


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

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

within AixLib.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 AixLib.Electrical.Transmission.LowVoltageCables.Generic[:] cab = AixLib.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

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

within AixLib.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 AixLib.Electrical.Transmission.MediumVoltageCables.Generic[:] cab = AixLib.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 AixLib.Electrical.Transmission.Grids;
record IEEE_34_AL120 "Grid model inspired to the IEEE 34 Node test feeder"
  extends AixLib.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 AixLib.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 AixLib.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 AixLib.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 AixLib.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 AixLib.Electrical.Transmission.Grids;
record TestGrid2Nodes "Simple model of a grid with 2 nodes and 1 link"
  extends AixLib.Electrical.Transmission.Grids.PartialGrid(
    nNodes=2,
    nLinks=1,
    fromTo=[[1,2]],
    l=[200],
    redeclare AixLib.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

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

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


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


within AixLib.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 AixLib.Electrical.Transmission;
package Types "Package that contains cables materials"
  extends Modelica.Icons.TypesPackage;
end Types;


Select automatically the size of the cable.

within AixLib.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 AixLib.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 AixLib.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 AixLib.Electrical;
package Types "This package contains new types used within the Electrical package"
  extends Modelica.Icons.TypesPackage;
end Types;


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


Voltage controller

within AixLib.Electrical.Utilities;
model VoltageControl "Voltage controller"
  replaceable package PhaseSystem =
      AixLib.Electrical.PhaseSystems.PartialPhaseSystem constrainedby
    AixLib.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 AixLib.Electrical.Interfaces.Terminal terminal(
    redeclare replaceable package PhaseSystem = PhaseSystem)
    "Generalized terminal"
  AixLib.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 AixLib.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 AixLib.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 AixLib.Electrical.Utilities;
package Examples "This package contais tests for check the correctness of the models"
extends Modelica.Icons.ExamplesPackage;
end Examples;


within AixLib.Electrical.Utilities.Examples;
model TestVoltageCTRL
  "This test check the correctness of the voltage controller model"
  extends Modelica.Icons.Example;
  VoltageControl voltageControl(
  redeclare AixLib.Electrical.DC.Interfaces.Terminal_p terminal,
    redeclare package PhaseSystem =
        AixLib.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 AixLib;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


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

  package MediumAir = AixLib.Media.Air;
  package MediumWater = AixLib.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://AixLib/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"
  Modelica.Thermal.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_inputFilter=false,
    m_flow_nominal=mWat_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    allowFlowReversal=allowFlowReversal,
    nominalValuesDefineDefaultPressureCurve=true,
    inputType=AixLib.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_inputFilter=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"
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(hexRec.port_b2, fan.port_a)
  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(fan.port_b, cooAir.port_a)
  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)
end SimpleHouse;


within AixLib.Examples;
package Tutorial "Tutorial with step by step instructions for how to build system models"
  extends Modelica.Icons.Information;
end Tutorial;


within AixLib.Examples.Tutorial;
package SimpleHouse "Package with example for how to build a simple building envelope with a radiator heating system and ventilation system"
extends Modelica.Icons.ExamplesPackage;
end SimpleHouse;


Start file for simple house example

within AixLib.Examples.Tutorial.SimpleHouse;
model SimpleHouse0
  "Start file for simple house example"
  extends Modelica.Icons.Example;
  package MediumAir = AixLib.Media.Air "Medium model for air";
  package MediumWater = AixLib.Media.Water "Medium model for water";
  parameter Modelica.Units.SI.Area AWall = 100 "Wall area";
  parameter Modelica.Units.SI.Length dWall = 0.25 "Wall thickness";
  parameter Modelica.Units.SI.ThermalConductivity kWall = 0.04 "Wall thermal conductivity";
  parameter Modelica.Units.SI.Density rhoWall = 2000 "Wall density";
  parameter Modelica.Units.SI.SpecificHeatCapacity cpWall = 1000 "Wall specific heat capacity";
  AixLib.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource(
        "modelica://AixLib/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
    "Weather data reader"
  AixLib.BoundaryConditions.WeatherData.Bus weaBus "Weather data bus"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature TOut
    "Exterior temperature boundary condition"
equation
  connect(weaDat.weaBus, weaBus)
  connect(TOut.T, weaBus.TDryBul)
end SimpleHouse0;


Building wall model. A very simple building envelope model will be constructed manually using thermal resistors and heat capacitors.
The house consists of a wall represented by a single heat capacitor and a thermal resistor.
The boundary temperature are already included in

AixLib.Examples.Tutorial.SimpleHouse.SimpleHouse0.
The wall has a surface area of Awall=100 m2,
a thickness of dwall=25 cm,
a thermal conductivity of kwall=0.04 W/(m K),
a density of ρwall=2000 kg/m3,
and a specific heat capacity of cp,wall= 1000 J/(kg K)

within AixLib.Examples.Tutorial.SimpleHouse;
model SimpleHouse1 "Building wall model"
  extends SimpleHouse0;

  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor walCap(
    C=AWall*dWall*cpWall*rhoWall,
    T(fixed=true))
    "Thermal mass of wall"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor walRes(
    R=dWall/AWall/kWall) "Thermal resistor for wall: 25 cm of rockwool"
equation
  connect(walRes.port_b, walCap.port)
  connect(TOut.port, walRes.port_a)
end SimpleHouse1;


Building window model. The window has a surface area of 2 m2.
In this simple model we will therefore assume that
two times the outdoor solar irradiance is injected as heat onto the inside of the wall.

within AixLib.Examples.Tutorial.SimpleHouse;
model SimpleHouse2 "Building window model"
  extends SimpleHouse1;

  parameter Modelica.Units.SI.Area AWin=2 "Window area";

  Modelica.Blocks.Math.Gain gaiWin(k=AWin)
    "Gain for solar irradiance through the window"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow win
    "Very simple window model"
equation
  connect(gaiWin.y, win.Q_flow)
  connect(gaiWin.u, weaBus.HDirNor)
  connect(win.port, walCap.port)
end SimpleHouse2;


Air model

within AixLib.Examples.Tutorial.SimpleHouse;
model SimpleHouse3 "Air model"
  extends SimpleHouse2;

  parameter Modelica.Units.SI.Volume VZone=8*8*3 "Zone volume";
  parameter Modelica.Units.SI.MassFlowRate mAir_flow_nominal=1
    "Nominal mass flow rate for air loop";
  parameter Modelica.Units.SI.CoefficientOfHeatTransfer hWall=2
    "Convective heat transfer coefficient at the wall";

  Modelica.Thermal.HeatTransfer.Components.ThermalResistor conRes(R=1/hWall/
        AWall) "Thermal resistance for convective heat transfer"
  AixLib.Fluid.MixingVolumes.MixingVolume zon(
    redeclare package Medium = MediumAir,
    V=VZone,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mAir_flow_nominal) "Very simple zone air model"
equation
  connect(zon.heatPort, conRes.port_a)
  connect(conRes.port_b, walCap.port)
end SimpleHouse3;


Heating model

within AixLib.Examples.Tutorial.SimpleHouse;
model SimpleHouse4 "Heating model"
  extends SimpleHouse3;

  constant Boolean use_constantHeater=true
    "To enable/disable the connection between the constant source and heater and circulation pump";

  parameter Modelica.Units.SI.HeatFlowRate QHea_flow_nominal=3000
    "Nominal capacity of heating system";
  parameter Modelica.Units.SI.MassFlowRate mWat_flow_nominal=0.1
    "Nominal mass flow rate for water loop";

  AixLib.Fluid.HeatExchangers.Radiators.RadiatorEN442_2 rad(
    redeclare package Medium = MediumWater,
    T_a_nominal=333.15,
    T_b_nominal=313.15,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    allowFlowReversal=false,
    Q_flow_nominal=QHea_flow_nominal) "Radiator"

  AixLib.Fluid.HeatExchangers.HeaterCooler_u heaWat(
    redeclare package Medium = MediumWater,
    m_flow_nominal=mWat_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    allowFlowReversal=false,
    dp_nominal=5000,
    Q_flow_nominal=QHea_flow_nominal) "Heater for water circuit"

  Fluid.Movers.Preconfigured.FlowControlled_m_flow pum(
    redeclare package Medium = MediumWater,
    use_inputFilter=false,
    m_flow_nominal=mWat_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    allowFlowReversal=false) "Pump"

  AixLib.Fluid.Sources.Boundary_pT bouWat(
    redeclare package Medium = MediumWater,
    nPorts=1)
    "Pressure bound for water circuit"
  Modelica.Blocks.Sources.Constant conHea(k=1)
    if use_constantHeater "Gain for heater"
  Modelica.Blocks.Sources.Constant conPum(k=mWat_flow_nominal)
    if use_constantHeater "Gain for pump"
equation
  connect(heaWat.port_b,rad. port_a)
  connect(rad.port_b, pum.port_a)
  connect(heaWat.port_a, pum.port_b)
  connect(rad.heatPortCon, zon.heatPort)
  connect(rad.heatPortRad, walCap.port)
  connect(conPum.y, pum.m_flow_in)
  connect(conHea.y, heaWat.u)
  connect(bouWat.ports[1], pum.port_b)
end SimpleHouse4;


Heating controller model. Since the zone becomes too warm, a controller is required that disables the heater when a setpoint is reached.
We will implement a hysteresis controller with a setpoint of 295.15 +/- 1K (21-23°C).
A temperature sensor will measure the zone air temperature.

within AixLib.Examples.Tutorial.SimpleHouse;
model SimpleHouse5 "Heating controller model"
  extends SimpleHouse4(final use_constantHeater=false);

  Modelica.Blocks.Math.BooleanToReal booRea1(realTrue=mWat_flow_nominal)
    "Boolean to integer"
  Modelica.Blocks.Math.BooleanToReal booRea "Boolean to real"
  Modelica.Blocks.Logical.Hysteresis hysRad(uLow=273.15 + 21, uHigh=273.15 + 23)
    "Hysteresis controller for radiator"
  Modelica.Blocks.Logical.Not not1
    "Negation for enabling heating when temperature is low"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor senTemZonAir
    "Zone air temperature sensor"
equation
  connect(booRea1.u, not1.y)
  connect(not1.u,hysRad. y)
  connect(senTemZonAir.T,hysRad. u)
  connect(senTemZonAir.port, zon.heatPort)
  connect(not1.y, booRea.u)
  connect(booRea.y, heaWat.u)
  connect(booRea1.y, pum.m_flow_in)
end SimpleHouse5;


Free cooling model

within AixLib.Examples.Tutorial.SimpleHouse;
model SimpleHouse6 "Free cooling model"
  extends SimpleHouse5(
    zon(nPorts=2),
    mAir_flow_nominal=0.1,
    AWin=6);

  parameter Modelica.Units.SI.PressureDifference dpAir_nominal=200
    "Pressure drop at nominal mass flow rate for air loop";

  AixLib.Fluid.Actuators.Dampers.Exponential vavDam(
    redeclare package Medium = MediumAir,
    from_dp=true,
    m_flow_nominal=mAir_flow_nominal,
    dpDamper_nominal=dpAir_nominal)
    "Damper"
  Fluid.Movers.Preconfigured.FlowControlled_dp fan(
    redeclare package Medium = MediumAir,
    show_T=true,
    dp_nominal=dpAir_nominal,
    use_inputFilter=false,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    m_flow_nominal=mAir_flow_nominal)
    "Constant head fan"

  AixLib.Fluid.HeatExchangers.ConstantEffectiveness hexRec(
    redeclare package Medium1 = MediumAir,
    redeclare package Medium2 = MediumAir,
    dp1_nominal=10,
    dp2_nominal=10,
    m1_flow_nominal=mAir_flow_nominal,
    m2_flow_nominal=mAir_flow_nominal,
    eps=0.85) "Heat exchanger for heat recuperation"
  AixLib.Fluid.Sources.Boundary_pT bouAir(
    redeclare package Medium = MediumAir,
    use_T_in=true,
    nPorts=2) "Air boundary with constant temperature"
  Modelica.Blocks.Logical.Hysteresis hysAir(uLow=273.15 + 23, uHigh=273.15 + 25)
    "Hysteresis controller for damper"
  Modelica.Blocks.Math.BooleanToReal booRea2 "Boolean to real"
  Modelica.Blocks.Math.BooleanToReal booRea3(realTrue=dpAir_nominal)
    "Boolean to real"
equation
  connect(hexRec.port_a1, zon.ports[1])
  connect(bouAir.T_in, weaBus.TDryBul)
  connect(vavDam.port_b, zon.ports[2])
  connect(booRea2.y, vavDam.y)
  connect(hysAir.y, booRea2.u)
  connect(vavDam.port_a, fan.port_b)
  connect(bouAir.ports[1], hexRec.port_a2)
  connect(fan.port_a, hexRec.port_b2)
  connect(hexRec.port_b1, bouAir.ports[2])
  connect(booRea1.y, pum.m_flow_in)
  connect(hysAir.u, hysRad.u)
  connect(booRea3.y, fan.dp_in)
  connect(booRea3.u, hysAir.y)
end SimpleHouse6;


within AixLib;
package Fluid "Package with models for fluid flow systems"
  extends Modelica.Icons.Package;

package UsersGuide "User's Guide"
  extends Modelica.Icons.Information;

end UsersGuide;
end Fluid;


Package with type definitions

within AixLib.Fluid;
package Types "Package with type definitions"
  extends Modelica.Icons.TypesPackage;

  type EfficiencyCurves = enumeration(
      Constant "constant",
      Polynomial "Polynomial",
      QuadraticLinear "quadratic in x1, linear in x2")
    "Enumeration to define the efficiency curves";
  type CvTypes = enumeration(
      OpPoint "flow coefficient defined by m_flow_nominal/sqrt(dp_nominal)",
      Kv "Kv (metric) flow coefficient",
      Cv "Cv (US) flow coefficient",
      Av "Av (metric) flow coefficient")
    "Enumeration to define the choice of valve flow coefficient"
  type HeatExchangerConfiguration = enumeration(
      ParallelFlow "Parallel flow",
      CounterFlow "Counter flow",
      CrossFlowUnmixed "Cross flow, both streams unmixed",
      CrossFlowStream1MixedStream2Unmixed
        "Cross flow, stream 1 mixed, stream 2 unmixed",
      CrossFlowStream1UnmixedStream2Mixed
        "Cross flow, stream 1 unmixed, stream 2 mixed",
      ConstantTemperaturePhaseChange "Constant temperature phase change in one stream")
    "Enumeration for heat exchanger construction"

  type HeatExchangerFlowRegime = enumeration(
      ParallelFlow "Parallel flow",
      CounterFlow "Counter flow",
      CrossFlowUnmixed "Cross flow, both streams unmixed",
      CrossFlowCMinMixedCMaxUnmixed "Cross flow, CMin mixed,   CMax unmixed",
      CrossFlowCMinUnmixedCMaxMixed "Cross flow, CMin unmixed, CMax mixed",
      ConstantTemperaturePhaseChange "Constant temperature phase change in one stream")
    "Enumeration for heat exchanger flow configuration"
  type InputType = enumeration(
      Constant "Use parameter to set stage",
      Stages "Use integer input to select stage",
      Continuous "Use continuous, real input") "Input options for movers"
end Types;