diff --git a/DistrictEnergy/DHRunLPModel.cs b/DistrictEnergy/DHRunLPModel.cs
index d071a25..54f2448 100644
--- a/DistrictEnergy/DHRunLPModel.cs
+++ b/DistrictEnergy/DHRunLPModel.cs
@@ -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
{
@@ -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>();
}
///
/// Input energy flow at each supply module of the energy hub at each time step"
///
- public Dictionary<(int, IThermalPlantSettings), Variable> P { get; set; }
+ public Dictionary<(int, IThermalPlantSettings), Variable> P =
+ new Dictionary<(int, IThermalPlantSettings), Variable>();
///
/// Storage state at each storage module of the energy hub at each time step"
///
- public Dictionary<(int, IThermalPlantSettings), Variable> S { get; set; }
+ public Dictionary<(int, IThermalPlantSettings), Variable> S =
+ new Dictionary<(int, IThermalPlantSettings), Variable>();
///
/// Output energy flow at each storage module of the energy hub at each time step"
///
- public Dictionary<(int, IThermalPlantSettings), Variable> Qout { get; set; }
+ public Dictionary<(int, IThermalPlantSettings), Variable> Qout =
+ new Dictionary<(int, IThermalPlantSettings), Variable>();
///
/// Input energy flow at each storage module of the energy hub at each time step"
///
- public Dictionary<(int, IThermalPlantSettings), Variable> Qin { get; set; }
+ public Dictionary<(int, IThermalPlantSettings), Variable> Qin =
+ new Dictionary<(int, IThermalPlantSettings), Variable>();
+
+ ///
+ /// DistrictLoad Demand (Umi Buildings + Losses)
+ ///
+ public Dictionary<(int, LoadTypes, AbstractDistrictLoad), double> Load =
+ new Dictionary<(int, LoadTypes, AbstractDistrictLoad), double>();
+
+ ///
+ /// Exported Energy. Subject To LargeNumber Cost.
+ ///
+ public Dictionary<(int, LoadTypes), Variable> E = new Dictionary<(int, LoadTypes), Variable>();
///The only instance of the DHRunLPModel command.
public static DHRunLPModel Instance { get; private set; }
@@ -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
@@ -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}"));
}
}
@@ -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)
@@ -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)]);
}
}
@@ -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)]);
}
}
@@ -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())
{
@@ -190,6 +224,7 @@ private void Main()
solarSupply.AvailableArea);
}
}
+ // Todo: Add wind constraints
// Storage Rules
foreach (var storage in DistrictControl.Instance.ListOfPlantSettings.OfType())
@@ -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());
@@ -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);
}
}
@@ -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();
@@ -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:");
@@ -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)
diff --git a/DistrictEnergy/DistrictControl.xaml.cs b/DistrictEnergy/DistrictControl.xaml.cs
index 2acfa4c..5d9fb61 100644
--- a/DistrictEnergy/DistrictControl.xaml.cs
+++ b/DistrictEnergy/DistrictControl.xaml.cs
@@ -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;
diff --git a/DistrictEnergy/Networks/ThermalPlants/AbsorptionChiller.cs b/DistrictEnergy/Networks/ThermalPlants/AbsorptionChiller.cs
index aee9e48..405628e 100644
--- a/DistrictEnergy/Networks/ThermalPlants/AbsorptionChiller.cs
+++ b/DistrictEnergy/Networks/ThermalPlants/AbsorptionChiller.cs
@@ -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 ConversionMatrix { get; set; }
public override List Input { get; set; }
public override List Output { get; set; }
diff --git a/DistrictEnergy/Networks/ThermalPlants/BatteryBank.cs b/DistrictEnergy/Networks/ThermalPlants/BatteryBank.cs
index a2f690b..8f23e8a 100644
--- a/DistrictEnergy/Networks/ThermalPlants/BatteryBank.cs
+++ b/DistrictEnergy/Networks/ThermalPlants/BatteryBank.cs
@@ -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;
@@ -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;
+ }
}
}
\ No newline at end of file
diff --git a/DistrictEnergy/Networks/ThermalPlants/CombinedHeatNPower.cs b/DistrictEnergy/Networks/ThermalPlants/CombinedHeatNPower.cs
index dda1b37..51bb557 100644
--- a/DistrictEnergy/Networks/ThermalPlants/CombinedHeatNPower.cs
+++ b/DistrictEnergy/Networks/ThermalPlants/CombinedHeatNPower.cs
@@ -25,8 +25,8 @@ public CombinedHeatNPower()
/// Tracking Mode
///
[DataMember]
- [DefaultValue(TrakingModeEnum.Thermal)]
- public TrakingModeEnum TMOD_CHP { get; set; } = TrakingModeEnum.Thermal;
+ [DefaultValue(LoadTypes.Heating)]
+ public LoadTypes TMOD_CHP { get; set; } = LoadTypes.Heating;
///
/// Capacity as percent of peak electric load (%)
@@ -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();
}
@@ -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 ConversionMatrix { get; set; }
public override List Input { get; set; }
public override List 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
- }
}
\ No newline at end of file
diff --git a/DistrictEnergy/Networks/ThermalPlants/CustomCoolingSupplyModule.cs b/DistrictEnergy/Networks/ThermalPlants/CustomCoolingSupplyModule.cs
index 4359f89..9d21c25 100644
--- a/DistrictEnergy/Networks/ThermalPlants/CustomCoolingSupplyModule.cs
+++ b/DistrictEnergy/Networks/ThermalPlants/CustomCoolingSupplyModule.cs
@@ -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 ConversionMatrix { get; set; }
public override List Input { get; set; }
public override List Output { get; set; }
diff --git a/DistrictEnergy/Networks/ThermalPlants/CustomElectricitySupplyModule.cs b/DistrictEnergy/Networks/ThermalPlants/CustomElectricitySupplyModule.cs
index 7ece398..388e862 100644
--- a/DistrictEnergy/Networks/ThermalPlants/CustomElectricitySupplyModule.cs
+++ b/DistrictEnergy/Networks/ThermalPlants/CustomElectricitySupplyModule.cs
@@ -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 ConversionMatrix { get; set; }
public override List Input { get; set; }
public override List Output { get; set; }
diff --git a/DistrictEnergy/Networks/ThermalPlants/CustomEnergySupplyModule.cs b/DistrictEnergy/Networks/ThermalPlants/CustomEnergySupplyModule.cs
index a03f55d..446d874 100644
--- a/DistrictEnergy/Networks/ThermalPlants/CustomEnergySupplyModule.cs
+++ b/DistrictEnergy/Networks/ThermalPlants/CustomEnergySupplyModule.cs
@@ -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 ConversionMatrix { get; set; }
public abstract override double Efficiency { get; }
diff --git a/DistrictEnergy/Networks/ThermalPlants/CustomHeatingSupplyModule.cs b/DistrictEnergy/Networks/ThermalPlants/CustomHeatingSupplyModule.cs
index 55eb5d6..93113b5 100644
--- a/DistrictEnergy/Networks/ThermalPlants/CustomHeatingSupplyModule.cs
+++ b/DistrictEnergy/Networks/ThermalPlants/CustomHeatingSupplyModule.cs
@@ -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 ConversionMatrix { get; set; }
public override List Input { get; set; }
public override List Output { get; set; }
diff --git a/DistrictEnergy/Networks/ThermalPlants/Dispatchable.cs b/DistrictEnergy/Networks/ThermalPlants/Dispatchable.cs
index e951350..936eeda 100644
--- a/DistrictEnergy/Networks/ThermalPlants/Dispatchable.cs
+++ b/DistrictEnergy/Networks/ThermalPlants/Dispatchable.cs
@@ -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
@@ -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);
}
}
diff --git a/DistrictEnergy/Networks/ThermalPlants/ElectricChiller.cs b/DistrictEnergy/Networks/ThermalPlants/ElectricChiller.cs
index 1850f7f..0d3f178 100644
--- a/DistrictEnergy/Networks/ThermalPlants/ElectricChiller.cs
+++ b/DistrictEnergy/Networks/ThermalPlants/ElectricChiller.cs
@@ -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 ConversionMatrix { get; set; }
public override List Input { get; set; }
public override List Output { get; set; }
diff --git a/DistrictEnergy/Networks/ThermalPlants/ElectricHeatPump.cs b/DistrictEnergy/Networks/ThermalPlants/ElectricHeatPump.cs
index b1a3a48..9f645ab 100644
--- a/DistrictEnergy/Networks/ThermalPlants/ElectricHeatPump.cs
+++ b/DistrictEnergy/Networks/ThermalPlants/ElectricHeatPump.cs
@@ -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 ConversionMatrix { get; set; }
public override List Input { get; set; }
public override List Output { get; set; }
diff --git a/DistrictEnergy/Networks/ThermalPlants/GridElectricity.cs b/DistrictEnergy/Networks/ThermalPlants/GridElectricity.cs
index 21b915c..7e03e40 100644
--- a/DistrictEnergy/Networks/ThermalPlants/GridElectricity.cs
+++ b/DistrictEnergy/Networks/ThermalPlants/GridElectricity.cs
@@ -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 ConversionMatrix { get; set; }
public override List Input { get; set; }
public override List Output { get; set; }
diff --git a/DistrictEnergy/Networks/ThermalPlants/GridGas.cs b/DistrictEnergy/Networks/ThermalPlants/GridGas.cs
index 3eeb8ab..741b6cc 100644
--- a/DistrictEnergy/Networks/ThermalPlants/GridGas.cs
+++ b/DistrictEnergy/Networks/ThermalPlants/GridGas.cs
@@ -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 ConversionMatrix { get; set; }
public override List Input { get; set; }
public override List Output { get; set; }
diff --git a/DistrictEnergy/Networks/ThermalPlants/HotWaterStorage.cs b/DistrictEnergy/Networks/ThermalPlants/HotWaterStorage.cs
index 4a3b6c4..7148492 100644
--- a/DistrictEnergy/Networks/ThermalPlants/HotWaterStorage.cs
+++ b/DistrictEnergy/Networks/ThermalPlants/HotWaterStorage.cs
@@ -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;
@@ -55,5 +56,10 @@ public HotWaterStorage()
public override double MaxChargingRate => Capacity > 0 ? Capacity / AUT_HWT : 0;
public override double MaxDischargingRate => Capacity > 0 ? Capacity / AUT_HWT : 0;
public override double StartingCapacity => Capacity * TANK_START;
+ public override double Capacity => CalcCapacity();
+ private double CalcCapacity()
+ {
+ return DistrictControl.Instance.ListOfDistrictLoads.Where(x => x.LoadType == LoadTypes.Heating).Select(v => v.Input.Average()).Sum() * AUT_HWT * 24;
+ }
}
}
\ No newline at end of file
diff --git a/DistrictEnergy/Networks/ThermalPlants/IThermalPlantSettings.cs b/DistrictEnergy/Networks/ThermalPlants/IThermalPlantSettings.cs
index 4204e86..d8c8840 100644
--- a/DistrictEnergy/Networks/ThermalPlants/IThermalPlantSettings.cs
+++ b/DistrictEnergy/Networks/ThermalPlants/IThermalPlantSettings.cs
@@ -68,5 +68,6 @@ public interface IThermalPlantSettings
[JsonIgnore] GraphCost FixedCost { get; }
[JsonIgnore] GraphCost VariableCost { get; }
[JsonIgnore] double TotalCost { get; }
+ [JsonIgnore] double CapacityFactor { get; }
}
}
\ No newline at end of file
diff --git a/DistrictEnergy/Networks/ThermalPlants/NatGasBoiler.cs b/DistrictEnergy/Networks/ThermalPlants/NatGasBoiler.cs
index ff7696c..8d87bd6 100644
--- a/DistrictEnergy/Networks/ThermalPlants/NatGasBoiler.cs
+++ b/DistrictEnergy/Networks/ThermalPlants/NatGasBoiler.cs
@@ -31,6 +31,7 @@ public NatGasBoiler()
public override Guid Id { get; set; } = Guid.NewGuid();
public override LoadTypes OutputType => LoadTypes.Heating;
public override LoadTypes InputType => LoadTypes.Gas;
+ public override double CapacityFactor => 1;
public override Dictionary ConversionMatrix { get; set; }
public override List Input { get; set; }
public override List Output { get; set; }
diff --git a/DistrictEnergy/Networks/ThermalPlants/PhotovoltaicArray.cs b/DistrictEnergy/Networks/ThermalPlants/PhotovoltaicArray.cs
index 9e4e4cd..3abad07 100644
--- a/DistrictEnergy/Networks/ThermalPlants/PhotovoltaicArray.cs
+++ b/DistrictEnergy/Networks/ThermalPlants/PhotovoltaicArray.cs
@@ -50,6 +50,7 @@ public PhotovoltaicArray()
[DataMember] [DefaultValue(1313)] public override double F { get; set; } = 1313;
[DataMember] [DefaultValue(0)] public override double V { get; set; }
public override double Capacity => CalcCapacity();
+ public override double CapacityFactor => OFF_PV;
private double CalcCapacity()
{
diff --git a/DistrictEnergy/Networks/ThermalPlants/SolarThermalCollector.cs b/DistrictEnergy/Networks/ThermalPlants/SolarThermalCollector.cs
index 269fb0f..2fe3222 100644
--- a/DistrictEnergy/Networks/ThermalPlants/SolarThermalCollector.cs
+++ b/DistrictEnergy/Networks/ThermalPlants/SolarThermalCollector.cs
@@ -55,6 +55,7 @@ public SolarThermalCollector()
[DataMember] [DefaultValue(7191)] public override double F { get; set; } = 7191;
[DataMember] [DefaultValue(0.00887)] public override double V { get; set; } = 0.00887;
public override double Capacity => CalcCapacity();
+ public override double CapacityFactor => OFF_SHW;
private double CalcCapacity()
{
diff --git a/DistrictEnergy/Networks/ThermalPlants/Storage.cs b/DistrictEnergy/Networks/ThermalPlants/Storage.cs
index b2d7533..8f8768a 100644
--- a/DistrictEnergy/Networks/ThermalPlants/Storage.cs
+++ b/DistrictEnergy/Networks/ThermalPlants/Storage.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Windows.Media;
using DistrictEnergy.Helpers;
using LiveCharts.Defaults;
@@ -18,7 +19,7 @@ public abstract class Storage : IThermalPlantSettings
public abstract double StartingCapacity { get; }
public abstract double F { get; set; }
public abstract double V { get; set; }
- public double Capacity { get; set; }
+ public abstract double Capacity { get; }
public abstract string Name { get; set; }
public Guid Id { get; set; } = Guid.NewGuid();
public abstract LoadTypes OutputType { get; }
@@ -30,5 +31,6 @@ public abstract class Storage : IThermalPlantSettings
public GraphCost FixedCost => new FixedCost(this);
public GraphCost VariableCost => new VariableCost(this, 200);
public double TotalCost => FixedCost.Cost + VariableCost.Cost;
+ public double CapacityFactor => 1;
}
}
\ No newline at end of file
diff --git a/DistrictEnergy/Networks/ThermalPlants/WindTurbine.cs b/DistrictEnergy/Networks/ThermalPlants/WindTurbine.cs
index 3cd3cb2..c43e2db 100644
--- a/DistrictEnergy/Networks/ThermalPlants/WindTurbine.cs
+++ b/DistrictEnergy/Networks/ThermalPlants/WindTurbine.cs
@@ -64,6 +64,7 @@ public WindTurbine()
[DataMember] [DefaultValue(1347)] public override double F { get; set; } = 1347;
[DataMember] [DefaultValue(0)] public override double V { get; set; }
public override double Capacity => CalcCapacity();
+ public override double CapacityFactor => OFF_WND;
private double CalcCapacity()
{
diff --git a/DistrictEnergy/Properties/AssemblyInfo.cs b/DistrictEnergy/Properties/AssemblyInfo.cs
index 6b94467..563a144 100644
--- a/DistrictEnergy/Properties/AssemblyInfo.cs
+++ b/DistrictEnergy/Properties/AssemblyInfo.cs
@@ -24,7 +24,7 @@
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyProduct("DistricEnergyPlugIn")]
-[assembly: AssemblyVersion("2.0.1.*")]
+[assembly: AssemblyVersion("2.0.2.*")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
diff --git a/DistrictEnergy/ViewModels/CombinedHeatAndPowerViewModel.cs b/DistrictEnergy/ViewModels/CombinedHeatAndPowerViewModel.cs
index d11720c..44f26d0 100644
--- a/DistrictEnergy/ViewModels/CombinedHeatAndPowerViewModel.cs
+++ b/DistrictEnergy/ViewModels/CombinedHeatAndPowerViewModel.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using DistrictEnergy.Helpers;
using DistrictEnergy.Networks.ThermalPlants;
namespace DistrictEnergy.ViewModels
@@ -16,10 +17,10 @@ public CombinedHeatAndPowerViewModel()
public new static CombinedHeatAndPowerViewModel Instance { get; set; }
- public IList PosibleTrackingModes =>
- Enum.GetValues(typeof(TrakingModeEnum)).Cast().ToList();
+ public IList PosibleTrackingModes =>
+ new List() {LoadTypes.Elec, LoadTypes.Heating};
- public TrakingModeEnum TMOD_CHP
+ public LoadTypes TMOD_CHP
{
get => DistrictControl.Instance.ListOfPlantSettings.OfType().First().TMOD_CHP;
set
diff --git a/DistrictEnergy/ViewModels/ElectricGenerationViewModel.cs b/DistrictEnergy/ViewModels/ElectricGenerationViewModel.cs
index b06abd8..575ddf2 100644
--- a/DistrictEnergy/ViewModels/ElectricGenerationViewModel.cs
+++ b/DistrictEnergy/ViewModels/ElectricGenerationViewModel.cs
@@ -173,7 +173,6 @@ public double AUT_BAT
{
DistrictControl.Instance.ListOfPlantSettings.OfType().First().AUT_BAT = value;
OnPropertyChanged();
- CalcBatCapacity();
}
}
@@ -217,23 +216,6 @@ public double V_BAT
}
}
- public double BatCapacity
- {
- get { return _windCapacity; }
- set
- {
- DistrictControl.Instance.ListOfPlantSettings.OfType().First().Capacity = value;
- OnPropertyChanged();
- }
- }
-
- private void CalcBatCapacity()
- {
- // todo Define a more advanced capacity formulation
- BatCapacity = DistrictControl.Instance.ListOfDistrictLoads.Where(x => x.LoadType == LoadTypes.Elec).Select(v => v.Input.Average()).Sum() *
- DistrictControl.Instance.ListOfPlantSettings.OfType().First().AUT_BAT * 24;
- }
-
#endregion
}
}
\ No newline at end of file
diff --git a/DistrictEnergy/ViewModels/HotWaterViewModel.cs b/DistrictEnergy/ViewModels/HotWaterViewModel.cs
index 1f295f6..0387ecc 100644
--- a/DistrictEnergy/ViewModels/HotWaterViewModel.cs
+++ b/DistrictEnergy/ViewModels/HotWaterViewModel.cs
@@ -60,7 +60,6 @@ public double OFF_EHP
{
DistrictControl.Instance.ListOfPlantSettings.OfType().First().OFF_EHP = value / 100;
OnPropertyChanged();
- CalcHpCapacity();
}
}
@@ -118,22 +117,6 @@ public double V_EHP
}
}
- public double HpCapacity
- {
- get { return _hpCapacity; }
- set
- {
- _hpCapacity = value;
- OnPropertyChanged();
- }
- }
-
- private void CalcHpCapacity()
- {
- HpCapacity = DistrictControl.Instance.ListOfPlantSettings.OfType().First().OFF_EHP *
- DistrictControl.Instance.ListOfDistrictLoads.Where(x => x.LoadType == LoadTypes.Heating).Select(v => v.Input.Max()).Sum();
- }
-
#endregion
#region HWSto
@@ -145,7 +128,6 @@ public double AUT_HWT
{
DistrictControl.Instance.ListOfPlantSettings.OfType().First().AUT_HWT = value;
OnPropertyChanged();
- CalcHwStoCapacityCapacity();
}
}
@@ -179,23 +161,6 @@ public double V_HWT
}
}
- public double HwStoCapacity
- {
- get { return _hwStoCapacity; }
- set
- {
- DistrictControl.Instance.ListOfPlantSettings.OfType().First().Capacity = value;
- OnPropertyChanged();
- }
- }
-
- private void CalcHwStoCapacityCapacity()
- {
- // todo Define a more advanced capacity formulation
- HwStoCapacity = DistrictControl.Instance.ListOfDistrictLoads.Where(x=>x.LoadType == LoadTypes.Heating).Select(v=>v.Input.Average()).Sum() *
- DistrictControl.Instance.ListOfPlantSettings.OfType().First().AUT_HWT * 24;
- }
-
#endregion
#region SolarThermal
diff --git a/DistrictEnergy/ViewModels/LoadsViewModel.cs b/DistrictEnergy/ViewModels/LoadsViewModel.cs
index 42e5985..be4db27 100644
--- a/DistrictEnergy/ViewModels/LoadsViewModel.cs
+++ b/DistrictEnergy/ViewModels/LoadsViewModel.cs
@@ -161,7 +161,7 @@ private void UpdateLoadsChart(object sender, EventArgs e)
SeriesCollection.Clear();
DemandLineCollection.Clear();
- // Plot Demand (Negative)
+ // Plot District Demand (Negative)
var plot_duration = args.TimeSteps;
foreach (var demand in DistrictControl.Instance.ListOfDistrictLoads)
{
@@ -171,7 +171,7 @@ private void UpdateLoadsChart(object sender, EventArgs e)
{
Values = demand.Input.ToDateTimePoint().Split(plot_duration)
.Select(v => new DateTimePoint(v.First().DateTime, -v.Sum())).AsGearedValues(),
- Title = "[+] " + demand.Name,
+ Title = $"[{demand.LoadType}] {demand.Name}",
LineSmoothness = lineSmoothness,
LabelPoint = KWhLabelPointFormatter,
AreaLimit = 0,
@@ -191,63 +191,36 @@ private void UpdateLoadsChart(object sender, EventArgs e)
Total = Total.Zip(demand.Input, (a, b) => a + b).ToArray();
}
- // Plot Additional Demand from Supply Modules (Negative)
- foreach (var dispatchable in DistrictControl.Instance.ListOfPlantSettings.OfType()
- .Where(x =>
- x.InputType == LoadTypes.Cooling || x.InputType == LoadTypes.Heating ||
- x.InputType == LoadTypes.Elec))
- {
- if (dispatchable.Input.Sum() > 0)
- {
- var series = new GStackedAreaSeries
- {
- Values = dispatchable.Input.Split(plot_duration)
- .Select(v => new DateTimePoint(v.First().DateTime, -v.Sum())).AsGearedValues(),
- Title = "[+] " + dispatchable.Name,
- LineSmoothness = lineSmoothness,
- LabelPoint = KWhLabelPointFormatter,
- AreaLimit = 0,
- Fill = dispatchable.Fill
- };
- SeriesCollection.Add(series);
- }
-
- Total = Total.Zip(dispatchable.Input, (a, b) => a + b.Value).ToArray();
- }
-
- // Plot Total Demand as Line
- // var gLineSeries = new GLineSeries
- // {
- // Values = Total.AsChartValues(),
- // Title = "Total",
- // //LineSmoothness = lineSmoothness,
- // LabelPoint = KWhLabelPointFormatter,
- // Stroke = new SolidColorBrush(Color.FromRgb(0, 0, 0)),
- // Fill = null,
- // };
- // SeriesCollection.Add(gLineSeries);
- // Panel.SetZIndex(gLineSeries, 60);
-
-
- // Plot Supply (Positive)
- foreach (var supply in DistrictControl.Instance.ListOfPlantSettings.OfType().Where(x =>
+ // Plot Plant Supply & Demand
+ foreach (var plant in DistrictControl.Instance.ListOfPlantSettings.OfType().Where(x =>
x.OutputType == LoadTypes.Cooling ||
x.OutputType == LoadTypes.Heating ||
x.OutputType == LoadTypes.Elec))
- if (supply.Output.Sum() > 0)
+ {
+ foreach (var cMat in plant.ConversionMatrix.Where(x =>
+ x.Key == LoadTypes.Cooling ||
+ x.Key == LoadTypes.Heating ||
+ x.Key == LoadTypes.Elec))
{
- var series = new GStackedAreaSeries
+ var loadType = cMat.Key;
+ var eff = cMat.Value;
+ if (plant.Input.Sum() > 0)
{
- Values = supply.Output.Split(plot_duration)
- .Select(v => new DateTimePoint(v.First().DateTime, v.Sum())).AsGearedValues(),
- Title = supply.Name,
- LineSmoothness = lineSmoothness,
- LabelPoint = KWhLabelPointFormatter,
- AreaLimit = 0,
- Fill = supply.Fill
- };
- SeriesCollection.Add(series);
+ var series = new GStackedAreaSeries
+ {
+ Values = plant.Input.Split(plot_duration).Select(v =>
+ new DateTimePoint(v.First().DateTime, v.Select(o => o.Value * eff).Sum()))
+ .AsGearedValues(),
+ Title = $"[{loadType}] {plant.Name}",
+ LineSmoothness = lineSmoothness,
+ LabelPoint = KWhLabelPointFormatter,
+ AreaLimit = 0,
+ Fill = plant.Fill
+ };
+ SeriesCollection.Add(series);
+ }
}
+ }
StorageSeriesCollection.Clear();
foreach (var storage in DistrictControl.Instance.ListOfPlantSettings.OfType())
@@ -270,7 +243,20 @@ private void UpdateLoadsChart(object sender, EventArgs e)
{
Values = storage.Output.Split(plot_duration)
.Select(v => new DateTimePoint(v.First().DateTime, v.Sum())).AsGearedValues(),
- Title = storage.Name,
+ Title = $"[{storage.OutputType}] {storage.Name} Out",
+ Fill = storage.Fill,
+ LineSmoothness = lineSmoothness,
+ AreaLimit = 0,
+ LabelPoint = KWhLabelPointFormatter,
+ });
+ IsStorageVisible = true;
+
+ // Plot Demand From Storage
+ SeriesCollection.Add(new GStackedAreaSeries()
+ {
+ Values = storage.Input.Split(plot_duration)
+ .Select(v => new DateTimePoint(v.First().DateTime, -v.Sum())).AsGearedValues(),
+ Title = $"[{storage.OutputType}] {storage.Name} In",
Fill = storage.Fill,
LineSmoothness = lineSmoothness,
AreaLimit = 0,
diff --git a/DistrictEnergy/Views/PlantSettings/ChilledWaterView.xaml b/DistrictEnergy/Views/PlantSettings/ChilledWaterView.xaml
index e55d921..91e57b4 100644
--- a/DistrictEnergy/Views/PlantSettings/ChilledWaterView.xaml
+++ b/DistrictEnergy/Views/PlantSettings/ChilledWaterView.xaml
@@ -72,7 +72,7 @@
- Electric Chiller
+ Electric Chiller
diff --git a/DistrictEnergy/Views/PlantSettings/CombinedHeatAndPowerView.xaml b/DistrictEnergy/Views/PlantSettings/CombinedHeatAndPowerView.xaml
index b429215..5ffd2fd 100644
--- a/DistrictEnergy/Views/PlantSettings/CombinedHeatAndPowerView.xaml
+++ b/DistrictEnergy/Views/PlantSettings/CombinedHeatAndPowerView.xaml
@@ -85,7 +85,7 @@
-
+
diff --git a/DistrictEnergy/Views/PlantSettings/HotWaterView.xaml b/DistrictEnergy/Views/PlantSettings/HotWaterView.xaml
index 7cc9b74..c44b753 100644
--- a/DistrictEnergy/Views/PlantSettings/HotWaterView.xaml
+++ b/DistrictEnergy/Views/PlantSettings/HotWaterView.xaml
@@ -87,7 +87,7 @@
().Where(x =>
+ x.OutputType == LoadTypes.Cooling ||
+ x.OutputType == LoadTypes.Heating ||
+ x.OutputType == LoadTypes.Elec))
{
- TextBlock name = new TextBlock();
- name.Text = plant.Name;
- NamePlantStack.Children.Add(name);
- Grid.SetColumn(name, 2);
+ foreach (var cMat in plant.ConversionMatrix)
+ {
+ var loadType = cMat.Key;
+ var eff = cMat.Value;
+ if (plant.Input.Sum() > 0)
+ {
+ TextBlock name = new TextBlock();
+ name.Text = $"[{loadType}] {plant.Name}";
+ NamePlantStack.Children.Add(name);
+ Grid.SetColumn(name, 2);
- TextBlock demandValue = new TextBlock();
- demandValue.Text = plant.Input.Max().ToString("N2");
- PeakPlantStack.Children.Add(demandValue);
- Grid.SetColumn(name, 2);
+ TextBlock demandValue = new TextBlock();
+ demandValue.Text = plant.Input.Select(v =>v.Value * eff).Max().ToString("N2");
+ PeakPlantStack.Children.Add(demandValue);
+ Grid.SetColumn(name, 2);
- TextBlock energyValue = new TextBlock();
- energyValue.Text = plant.Input.Sum().ToString("N2");
- EnergyPlantStack.Children.Add(energyValue);
- Grid.SetColumn(name, 2);
+ TextBlock energyValue = new TextBlock();
+ energyValue.Text = plant.Input.Select(v => v.Value * eff).Sum().ToString("N2");
+ EnergyPlantStack.Children.Add(energyValue);
+ Grid.SetColumn(name, 2);
+ }
+ }
}
}
}
diff --git a/SetupProject/DistrictPlugInInstaller.wixproj b/SetupProject/DistrictPlugInInstaller.wixproj
index 80c82b0..2e77824 100644
--- a/SetupProject/DistrictPlugInInstaller.wixproj
+++ b/SetupProject/DistrictPlugInInstaller.wixproj
@@ -6,7 +6,7 @@
3.10
2a10a76b-558f-424d-965b-d2c84703cee0
2.0
- DistrictPluginInstaller-4.433-2020-dev-2.0.1
+ DistrictPluginInstaller-4.433-2020-dev-2.0.2
Package
DistrictPlugInInstaller