Skip to content

Commit

Permalink
Merge branch 'release/v2.0.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelduchesne committed Apr 30, 2020
2 parents 996487b + 9980818 commit 458e82c
Show file tree
Hide file tree
Showing 32 changed files with 192 additions and 167 deletions.
88 changes: 69 additions & 19 deletions DistrictEnergy/DHRunLPModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
using System.Collections.Generic;
using System.Linq;
using DistrictEnergy.Helpers;
using DistrictEnergy.Metrics;
using DistrictEnergy.Networks.Loads;
using DistrictEnergy.Networks.ThermalPlants;
using Google.OrTools.LinearSolver;
using Rhino;
using Rhino.Commands;
using Umi.RhinoServices.Context;

namespace DistrictEnergy
{
Expand All @@ -15,31 +17,42 @@ public class DHRunLPModel : Command
public DHRunLPModel()
{
Instance = this;
Qin = new Dictionary<(int, IThermalPlantSettings), Variable>();
Qout = new Dictionary<(int, IThermalPlantSettings), Variable>();
S = new Dictionary<(int, IThermalPlantSettings), Variable>();
P = new Dictionary<(int, IThermalPlantSettings), Variable>();
}

/// <summary>
/// Input energy flow at each supply module of the energy hub at each time step"
/// </summary>
public Dictionary<(int, IThermalPlantSettings), Variable> P { get; set; }
public Dictionary<(int, IThermalPlantSettings), Variable> P =
new Dictionary<(int, IThermalPlantSettings), Variable>();

/// <summary>
/// Storage state at each storage module of the energy hub at each time step"
/// </summary>
public Dictionary<(int, IThermalPlantSettings), Variable> S { get; set; }
public Dictionary<(int, IThermalPlantSettings), Variable> S =
new Dictionary<(int, IThermalPlantSettings), Variable>();

/// <summary>
/// Output energy flow at each storage module of the energy hub at each time step"
/// </summary>
public Dictionary<(int, IThermalPlantSettings), Variable> Qout { get; set; }
public Dictionary<(int, IThermalPlantSettings), Variable> Qout =
new Dictionary<(int, IThermalPlantSettings), Variable>();

/// <summary>
/// Input energy flow at each storage module of the energy hub at each time step"
/// </summary>
public Dictionary<(int, IThermalPlantSettings), Variable> Qin { get; set; }
public Dictionary<(int, IThermalPlantSettings), Variable> Qin =
new Dictionary<(int, IThermalPlantSettings), Variable>();

/// <summary>
/// DistrictLoad Demand (Umi Buildings + Losses)
/// </summary>
public Dictionary<(int, LoadTypes, AbstractDistrictLoad), double> Load =
new Dictionary<(int, LoadTypes, AbstractDistrictLoad), double>();

/// <summary>
/// Exported Energy. Subject To LargeNumber Cost.
/// </summary>
public Dictionary<(int, LoadTypes), Variable> E = new Dictionary<(int, LoadTypes), Variable>();

///<summary>The only instance of the DHRunLPModel command.</summary>
public static DHRunLPModel Instance { get; private set; }
Expand All @@ -54,9 +67,10 @@ protected override Result RunCommand(RhinoDoc doc, RunMode mode)

private void Main()
{
ClearVariables();
DHSimulateDistrictEnergy.Instance.PreSolve();
// Create the linear solver with the CBC backend.
var solver = Solver.CreateSolver("SimpleMipProgram", "GLOP_LINEAR_PROGRAMMING");
var solver = Solver.CreateSolver("SimpleLP", "GLOP_LINEAR_PROGRAMMING");

// Define Model Variables. Here each variable is the supply power of each available supply module
int timeSteps = (int) DistrictControl.PlanningSettings.TimeSteps; // Number of Time Steps
Expand All @@ -69,7 +83,7 @@ private void Main()
{
for (var t = 0; t < timeSteps * dt; t += dt)
{
P[(t, supplymodule)] = solver.MakeNumVar(0.0, supplymodule.Capacity / supplymodule.Efficiency * dt,
P[(t, supplymodule)] = solver.MakeNumVar(0.0, double.PositiveInfinity,
string.Format($"P_{t}_{supplymodule.Name}"));
}
}
Expand Down Expand Up @@ -98,15 +112,15 @@ private void Main()
$"Computed {Qin.Count + Qout.Count + S.Count} S variables in {watch.ElapsedMilliseconds} milliseconds");

// Exports (per supply module)
var E = new Dictionary<(int, LoadTypes), Variable>();
for (var t = 0; t < timeSteps * dt; t += dt)
{
E[(t, LoadTypes.Elec)] = solver.MakeNumVar(0.0, double.PositiveInfinity, $"Export{t}_Electricity");
E[(t, LoadTypes.Cooling)] = solver.MakeNumVar(0.0, double.PositiveInfinity, $"Export{t}_Cooling");
E[(t, LoadTypes.Heating)] = solver.MakeNumVar(0.0, double.PositiveInfinity, $"Export{t}_Heating");
}

RhinoApp.WriteLine("Number of variables = " + solver.NumVariables());

var Load = new Dictionary<(int, LoadTypes, AbstractDistrictLoad), double>();
foreach (var load in DistrictControl.Instance.ListOfDistrictLoads)
{
for (int t = 0; t < timeSteps * dt; t += dt)
Expand All @@ -131,7 +145,7 @@ private void Main()
.Select(x => x.Value).ToArray()
.Sum() ==
Load.Where(x => x.Key.Item2 == loadTypes && x.Key.Item1 == i).Select(o => o.Value)
.Sum());
.Sum() + E[(i, loadTypes)]);
}
}

Expand All @@ -148,7 +162,7 @@ private void Main()
.Select(x => x.Value).ToArray()
.Sum() ==
Load.Where(x => x.Key.Item2 == loadTypes && x.Key.Item1 == i).Select(o => o.Value)
.Sum());
.Sum() + E[(i, loadTypes)]);
}
}

Expand Down Expand Up @@ -181,6 +195,26 @@ private void Main()
}
}

// Capacity Constraints
foreach (var inputFlow in P.Where(x =>
x.Key.Item2.OutputType == LoadTypes.Elec || x.Key.Item2.OutputType == LoadTypes.Heating ||
x.Key.Item2.OutputType == LoadTypes.Cooling))
{
var loadType = inputFlow.Key.Item2.OutputType;
var i = inputFlow.Key.Item1;
solver.Add(inputFlow.Value * inputFlow.Key.Item2.ConversionMatrix[loadType] <=
inputFlow.Key.Item2.CapacityFactor *
(
P.Where(k => k.Key.Item2.ConversionMatrix.ContainsKey(loadType) && k.Key.Item1 == i)
.Select(k => k.Value * k.Key.Item2.ConversionMatrix[loadType]).ToArray().Sum() +
Qin.Where(k => k.Key.Item2.OutputType == loadType && k.Key.Item1 == i)
.Select(x => x.Value).ToArray().Sum() -
Qout.Where(k => k.Key.Item2.OutputType == loadType && k.Key.Item1 == i)
.Select(x => x.Value).ToArray().Sum() +
Load.Where(x => x.Key.Item2 == loadType && x.Key.Item1 == i).Select(o => o.Value).Sum())
);
}

// Solar & Wind Constraints
foreach (var solarSupply in DistrictControl.Instance.ListOfPlantSettings.OfType<ISolar>())
{
Expand All @@ -190,6 +224,7 @@ private void Main()
solarSupply.AvailableArea);
}
}
// Todo: Add wind constraints

// Storage Rules
foreach (var storage in DistrictControl.Instance.ListOfPlantSettings.OfType<Storage>())
Expand All @@ -201,6 +236,7 @@ private void Main()
// (1 / storage.DischargingEfficiency) * Qout[(0, storage)]);

// storage content initial <= final, both variable
// Todo: Why Skip first timestep
solver.Add(S.Where(x => x.Key.Item2 == storage).Select(o => o.Value).Skip(1).First() <=
S.Where(x => x.Key.Item2 == storage).Select(o => o.Value).Last());

Expand Down Expand Up @@ -229,7 +265,7 @@ private void Main()
for (int t = dt; t < timeSteps * dt; t += dt)
{
objective.SetCoefficient(P[(t, supplymodule)],
supplymodule.F * DistrictEnergy.Settings.AnnuityFactor + supplymodule.V * dt);
supplymodule.F * DistrictEnergy.Settings.AnnuityFactor / dt + supplymodule.V);
}
}

Expand All @@ -238,13 +274,13 @@ private void Main()
for (int t = dt; t < timeSteps * dt; t += dt)
{
objective.SetCoefficient(S[(t, storage)],
storage.F * DistrictEnergy.Settings.AnnuityFactor + storage.V * dt);
storage.F * DistrictEnergy.Settings.AnnuityFactor / dt + storage.V);
}
}

foreach (var variable in E)
{
objective.SetCoefficient(variable.Value, 1000000);
objective.SetCoefficient(variable.Value, UmiContext.Current.ProjectSettings.ElectricityDollars);
}

objective.SetMinimization();
Expand Down Expand Up @@ -283,11 +319,15 @@ private void Main()
storage.Stored = S.Where(x => x.Key.Item2 == storage).Select(v => v.Value.SolutionValue())
.ToDateTimePoint();
RhinoApp.WriteLine(
$"{storage.Name} = Qin {storage.Input.Sum()}; Qout {storage.Output.Sum()}; EndStorageState {storage.Stored.Last().Value}");
$"{storage.Name} = Qin {storage.Input.Sum()}; Qout {storage.Output.Sum()}; Storage Balance {storage.Input.Sum() - storage.Output.Sum()}");
}

// Write Exports
RhinoApp.WriteLine($"Export_Electricity = {E.Select(x => x.Value.SolutionValue()).ToArray().Sum()}");
foreach (LoadTypes loadTypes in Enum.GetValues(typeof(LoadTypes)))
{
var sum = E.Where(o => o.Key.Item2 == loadTypes).Select(x => x.Value.SolutionValue()).ToArray().Sum();
if (sum > 0) RhinoApp.WriteLine($"Export_{loadTypes} = {sum}");
}


RhinoApp.WriteLine("\nAdvanced usage:");
Expand All @@ -297,6 +337,16 @@ private void Main()
OnCompletion(new SimulationCompleted() {TimeSteps = timeSteps, Period = dt});
}

private void ClearVariables()
{
P.Clear();
Qin.Clear();
Qout.Clear();
S.Clear();
Load.Clear();
E.Clear();
}

public event EventHandler Completion;

protected virtual void OnCompletion(EventArgs e)
Expand Down
2 changes: 1 addition & 1 deletion DistrictEnergy/DistrictControl.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ private void OnSimCaseChanged(object sender, SelectionChangedEventArgs e)
{
ChilledWaterViewModel.Instance.OFF_ABS = 100;
CombinedHeatAndPowerViewModel.Instance.OFF_CHP = 100;
CombinedHeatAndPowerViewModel.Instance.TMOD_CHP = TrakingModeEnum.Electrical;
CombinedHeatAndPowerViewModel.Instance.TMOD_CHP = LoadTypes.Elec;
ElectricGenerationViewModel.Instance.OFF_PV = 0;
HotWaterViewModel.Instance.OFF_EHP = 0;
HotWaterViewModel.Instance.OFF_SHW = 0;
Expand Down
1 change: 1 addition & 0 deletions DistrictEnergy/Networks/ThermalPlants/AbsorptionChiller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ private double CalcCapacity()
public override Guid Id { get; set; } = Guid.NewGuid();
public override LoadTypes OutputType { get; } = LoadTypes.Cooling;
public override LoadTypes InputType => LoadTypes.Heating;
public override double CapacityFactor => OFF_ABS;
public override Dictionary<LoadTypes, double> ConversionMatrix { get; set; }
public override List<DateTimePoint> Input { get; set; }
public override List<DateTimePoint> Output { get; set; }
Expand Down
6 changes: 6 additions & 0 deletions DistrictEnergy/Networks/ThermalPlants/BatteryBank.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Serialization;
using System.Windows.Media;
using DistrictEnergy.Helpers;
Expand Down Expand Up @@ -63,5 +64,10 @@ public BatteryBank()
public override double MaxChargingRate => Capacity > 0 ? Capacity / AUT_BAT : 0;
public override double MaxDischargingRate => Capacity > 0 ? Capacity / AUT_BAT : 0;
public override double StartingCapacity => Capacity * BAT_START;
public override double Capacity => CalcCapacity();
private double CalcCapacity()
{
return DistrictControl.Instance.ListOfDistrictLoads.Where(x => x.LoadType == LoadTypes.Elec).Select(v => v.Input.Average()).Sum() * AUT_BAT * 24;
}
}
}
18 changes: 6 additions & 12 deletions DistrictEnergy/Networks/ThermalPlants/CombinedHeatNPower.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ public CombinedHeatNPower()
/// Tracking Mode
/// </summary>
[DataMember]
[DefaultValue(TrakingModeEnum.Thermal)]
public TrakingModeEnum TMOD_CHP { get; set; } = TrakingModeEnum.Thermal;
[DefaultValue(LoadTypes.Heating)]
public LoadTypes TMOD_CHP { get; set; } = LoadTypes.Heating;

/// <summary>
/// Capacity as percent of peak electric load (%)
Expand Down Expand Up @@ -70,10 +70,10 @@ private double CalcCapacity()
if (DistrictControl.Instance is null) return 0;
switch (TMOD_CHP)
{
case TrakingModeEnum.Electrical:
case LoadTypes.Elec:
return OFF_CHP * DistrictControl.Instance.ListOfDistrictLoads
.Where(x => x.LoadType == LoadTypes.Elec).Select(v => v.Input.Max()).Sum();
case TrakingModeEnum.Thermal:
case LoadTypes.Heating:
return OFF_CHP * DistrictControl.Instance.ListOfDistrictLoads
.Where(x => x.LoadType == LoadTypes.Heating).Select(v => v.Input.Max()).Sum();
}
Expand All @@ -86,19 +86,13 @@ private double CalcCapacity()
public override string Name { get; set; } = "Combined Heat&Power";

public override Guid Id { get; set; } = Guid.NewGuid();
public override LoadTypes OutputType => LoadTypes.Elec;
public override LoadTypes OutputType => TMOD_CHP;
public override LoadTypes InputType => LoadTypes.Gas;
public override double CapacityFactor => OFF_CHP;
public override Dictionary<LoadTypes, double> ConversionMatrix { get; set; }
public override List<DateTimePoint> Input { get; set; }
public override List<DateTimePoint> Output { get; set; }
public override double Efficiency => ConversionMatrix[OutputType];
public override SolidColorBrush Fill { get; set; } = new SolidColorBrush(Color.FromRgb(247, 96, 21));
}

[DataContract(Name = "TMOD_CHP")]
public enum TrakingModeEnum
{
[EnumMember] Thermal,
[EnumMember] Electrical
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public double ComputeHeatBalance(double demand, int i)
public double[] Used = new double[8760];
public override LoadTypes OutputType => LoadTypes.Cooling;
public override LoadTypes InputType => LoadTypes.Custom;
public override double CapacityFactor => 1;
public override Dictionary<LoadTypes, double> ConversionMatrix { get; set; }
public override List<DateTimePoint> Input { get; set; }
public override List<DateTimePoint> Output { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public CustomElectricitySupplyModule()

public override LoadTypes OutputType => LoadTypes.Elec;
public override LoadTypes InputType => LoadTypes.Custom;
public override double CapacityFactor => 1;
public override Dictionary<LoadTypes, double> ConversionMatrix { get; set; }
public override List<DateTimePoint> Input { get; set; }
public override List<DateTimePoint> Output { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ public override SolidColorBrush Fill
set => throw new NotImplementedException();
}

public override double CapacityFactor { get; }

public Color Color { get; set; } = Color.FromRgb(200, 1, 0);
public abstract override Dictionary<LoadTypes, double> ConversionMatrix { get; set; }
public abstract override double Efficiency { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public CustomHeatingSupplyModule()

public override LoadTypes OutputType => LoadTypes.Heating;
public override LoadTypes InputType => LoadTypes.Custom;
public override double CapacityFactor => 1;
public override Dictionary<LoadTypes, double> ConversionMatrix { get; set; }
public override List<DateTimePoint> Input { get; set; }
public override List<DateTimePoint> Output { get; set; }
Expand Down
4 changes: 3 additions & 1 deletion DistrictEnergy/Networks/ThermalPlants/Dispatchable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public abstract class Dispatchable : IThermalPlantSettings
public GraphCost FixedCost => new FixedCost(this);
public GraphCost VariableCost => new VariableCost(this, 200);
public double TotalCost => FixedCost.Cost + VariableCost.Cost;
public abstract double CapacityFactor { get; }
}

public class FixedCost : GraphCost
Expand All @@ -41,7 +42,8 @@ public FixedCost(IThermalPlantSettings plant, byte alpha = 255)
Fill = new SolidColorBrush(Color.FromArgb(alpha, color.R, color.G, color.B));
Name = plant.Name + " Fixed Cost";
if (plant.Output != null)
Cost = plant.Output.Max() * DistrictControl.PlanningSettings.AnnuityFactor * plant.F;
Cost = plant.Output.Max() * DistrictControl.PlanningSettings.AnnuityFactor * plant.F /
(8760 / DistrictControl.PlanningSettings.TimeSteps);
}
}

Expand Down
1 change: 1 addition & 0 deletions DistrictEnergy/Networks/ThermalPlants/ElectricChiller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public ElectricChiller()
public override Guid Id { get; set; }
public override LoadTypes OutputType => LoadTypes.Cooling;
public override LoadTypes InputType => LoadTypes.Elec;
public override double CapacityFactor => 1;
public override Dictionary<LoadTypes, double> ConversionMatrix { get; set; }
public override List<DateTimePoint> Input { get; set; }
public override List<DateTimePoint> Output { get; set; }
Expand Down
1 change: 1 addition & 0 deletions DistrictEnergy/Networks/ThermalPlants/ElectricHeatPump.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ private double CalcCapacity()
public override Guid Id { get; set; } = Guid.NewGuid();
public override LoadTypes OutputType => LoadTypes.Heating;
public override LoadTypes InputType => LoadTypes.Elec;
public override double CapacityFactor => OFF_EHP;
public override Dictionary<LoadTypes, double> ConversionMatrix { get; set; }
public override List<DateTimePoint> Input { get; set; }
public override List<DateTimePoint> Output { get; set; }
Expand Down
1 change: 1 addition & 0 deletions DistrictEnergy/Networks/ThermalPlants/GridElectricity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public override double V
public override Guid Id { get; set; } = Guid.NewGuid();
public override LoadTypes OutputType => LoadTypes.Elec;
public override LoadTypes InputType => LoadTypes.GridElec;
public override double CapacityFactor => 1;
public override Dictionary<LoadTypes, double> ConversionMatrix { get; set; }
public override List<DateTimePoint> Input { get; set; }
public override List<DateTimePoint> Output { get; set; }
Expand Down
1 change: 1 addition & 0 deletions DistrictEnergy/Networks/ThermalPlants/GridGas.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public override double V
public override Guid Id { get; set; } = Guid.NewGuid();
public override LoadTypes OutputType => LoadTypes.Gas;
public override LoadTypes InputType => LoadTypes.GridGas;
public override double CapacityFactor => 1;
public override Dictionary<LoadTypes, double> ConversionMatrix { get; set; }
public override List<DateTimePoint> Input { get; set; }
public override List<DateTimePoint> Output { get; set; }
Expand Down
Loading

0 comments on commit 458e82c

Please sign in to comment.