using IStation.CalcModel;
|
using System;
|
using System.Collections.Generic;
|
using System.Data;
|
using System.Linq;
|
|
namespace IStation.Calc
|
{
|
internal partial class ErQuCalcHelper_2_递归 : ErQuCalcBaseHelper
|
{
|
protected class BlockItemList
|
{
|
public List<RunBlock> Items { get; set; }
|
public double TotalCompare;//功率或者电费(合计)
|
public double TotalFlow;
|
public double GetByTime(DateTime time)
|
{
|
//foreach (var item in this.Items)
|
//{
|
// if (item.ReservoirStartHeight >= _maxReservoirHeight || item.ReservoirEndHeight >= _maxReservoirHeight)
|
// {
|
// return ToAnaPrj(result定水量);
|
// }
|
//}
|
return 0;
|
}
|
}
|
|
#region Project 转化
|
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="opt_bundle"></param>
|
/// <returns></returns>
|
protected IStation.CalcModel.AnaPrj ToAnaPrj(BlockItemList opt_bundle)
|
{
|
if (this._startOpenPumpCount == -1 || _startOpenPumpArray == null)
|
{//不知道开始的状态
|
return ToAnaPrj未知开始状态(opt_bundle);
|
}
|
else
|
{//已知道开始的状态
|
return ToAnaPrj已知开始状态(opt_bundle);
|
}
|
}
|
|
protected IStation.CalcModel.AnaPrj ToAnaPrj未知开始状态(BlockItemList opt_bundle)
|
{
|
IStation.CalcModel.AnaPrj opt_prj = new IStation.CalcModel.AnaPrj();
|
opt_prj.ID = Guid.NewGuid().ToString("N");
|
opt_prj.StartTime = this._calStartTime;
|
opt_prj.EndTime = this._calEndTime;
|
opt_prj.BlockTimes = new List<AnaPrjBlockTime>();
|
opt_prj.CalcSpaceMinute = this.CalcSpaceMinute;
|
|
opt_prj.PumpSwitchs = new List<AnaPrjSwitchInfo>();
|
|
var block_time_items = (from x in opt_bundle.Items orderby x.StartIndx select x).ToArray();
|
int item_count = block_time_items.Count();
|
for (int k = 0; k < item_count; k++)
|
{
|
var block_time_item = block_time_items[k];
|
|
double sumPower_item = 0, sumFlow_item = 0, sumMoney_item = 0;
|
var block_time = new AnaPrjBlockTime();
|
block_time.StartTime = _timeList[block_time_item.StartIndx].Time;
|
block_time.EndTime = _timeList[block_time_item.EndIndx].Time;
|
//block_time.OpenPumpCount = block_time_item.PumpCount;
|
block_time.OpenPumpIndexs = this.GetOptimalPumpIndexList(block_time_item.PumpCount, false);
|
int last_index = block_time_item.EndIndx;
|
//if (k == item_count - 1)
|
// last_index = block_time_item.EndIndx + 1;
|
int start_indx = block_time_item.StartIndx;
|
|
block_time.PointTimes = new List<AnaPrjPointTime>();
|
if (block_time_item.PumpCount == 0)
|
{
|
for (int i = start_indx; i < last_index; i++)
|
{
|
var si = new AnaPrjPointTime(_timeList[i]);
|
//si.WaterLevelH = CalcReservoirHeight(_timeList[i].ReservoirDropFlowTotal, 0,
|
// block_time_item.ReservoirStartHeight);
|
si.WaterLevelH = Math.Round(
|
block_time_item.ReservoirStartHeight +
|
(block_time_item.StartIndx - i) * (-block_time_item.ReservoirStartHeight + block_time_item.ReservoirEndHeight) / (block_time_item.StartIndx - block_time_item.EndIndx), 4);
|
|
block_time.PointTimes.Add(si);
|
}
|
}
|
else
|
{
|
var td = GetTimeDataBundle(block_time_item.PumpCount);
|
|
for (int i = start_indx; i < last_index; i++)
|
{
|
var si = new AnaPrjPointTime(_timeList[i], td.TimeDatas[i], block_time_item.PumpCount);
|
si.WaterLevelH = Math.Round(
|
block_time_item.ReservoirStartHeight +
|
(block_time_item.StartIndx - i) * (-block_time_item.ReservoirStartHeight + block_time_item.ReservoirEndHeight) / (block_time_item.StartIndx - block_time_item.EndIndx), 4);
|
|
sumPower_item += td.TimeDatas[i].SumPower;
|
sumFlow_item += td.TimeDatas[i].SumFlow;
|
sumMoney_item += td.TimeDatas[i].SumMoney;
|
|
block_time.PointTimes.Add(si);
|
}
|
}
|
|
block_time.SumPower = sumPower_item;
|
block_time.SumFlow = sumFlow_item;
|
block_time.SumMoney = sumMoney_item;
|
|
opt_prj.BlockTimes.Add(block_time);
|
}
|
|
double sumPower = 0, sumFlow = 0, sumMoney = 0;
|
foreach (var block_time_item in opt_prj.BlockTimes)
|
{
|
sumPower += block_time_item.SumPower;
|
sumFlow += block_time_item.SumFlow;
|
sumMoney += block_time_item.SumMoney;
|
}
|
if (double.IsNaN(sumMoney) || double.IsInfinity(sumMoney) || sumMoney == double.MaxValue)
|
return null;
|
if (double.IsNaN(sumPower) || double.IsInfinity(sumPower) || sumPower == double.MaxValue)
|
return null;
|
opt_prj.SumMoney = sumMoney;
|
opt_prj.SumFlow = sumFlow;
|
opt_prj.SumPower = sumPower;
|
|
return opt_prj;
|
}
|
|
protected IStation.CalcModel.AnaPrj ToAnaPrj已知开始状态(BlockItemList opt_bundle)
|
{
|
IStation.CalcModel.AnaPrj opt_prj = new IStation.CalcModel.AnaPrj();
|
opt_prj.ID = Guid.NewGuid().ToString("N");
|
opt_prj.StartTime = this._calStartTime;
|
opt_prj.EndTime = this._calEndTime;
|
opt_prj.BlockTimes = new List<AnaPrjBlockTime>();
|
|
opt_prj.CalcSpaceMinute = this.CalcSpaceMinute;
|
|
var open_block_time_items = (from x in opt_bundle.Items orderby x.StartIndx select x).ToArray();
|
IStation.Calc.ErQuCalcBaseHelper.RunBlock first_open_block_time_item = open_block_time_items.First();
|
IStation.Calc.ErQuCalcBaseHelper.RunBlock finsih_open_block_time_item = open_block_time_items.Last();
|
|
//计算每个时间块的开泵数量, 包括不开泵的时间块, opt_bundle.Items 只考虑开机的时间段, 需要把没开机的也考虑进来
|
List<AnaPrjBlockTime> all_time_block = new List<AnaPrjBlockTime>();
|
|
#region 处理第一个
|
|
int block_id = 0;
|
if (first_open_block_time_item.StartIndx > 1)
|
{//开始时就关机
|
block_id++;
|
var bt1 = BuildAnaPrjBlockTime(block_id, 0, 0, first_open_block_time_item.StartIndx,
|
_start_level水库水位, first_open_block_time_item.ReservoirStartHeight);
|
if (bt1 != null)
|
all_time_block.Add(bt1);
|
|
block_id++;
|
var bt2 = BuildAnaPrjBlockTime(block_id, first_open_block_time_item.PumpCount, first_open_block_time_item.StartIndx, first_open_block_time_item.EndIndx,
|
first_open_block_time_item.ReservoirStartHeight, first_open_block_time_item.ReservoirEndHeight);
|
if (bt2 != null)
|
all_time_block.Add(bt2);
|
}
|
else
|
{
|
block_id++;
|
var bt2 = BuildAnaPrjBlockTime(block_id, first_open_block_time_item.PumpCount, 0, first_open_block_time_item.EndIndx,
|
_start_level水库水位, first_open_block_time_item.ReservoirEndHeight);
|
if (bt2 != null)
|
all_time_block.Add(bt2);
|
}
|
|
#endregion 处理第一个
|
|
#region 主体
|
|
int item_count = open_block_time_items.Count();
|
for (int k = 1; k < item_count; k++)//从1开始, 0 前面已处理
|
{
|
var block_time_item = open_block_time_items[k];
|
var blockStartTime = _timeList[block_time_item.StartIndx].Time;
|
var blockEndTime = _timeList[block_time_item.EndIndx].Time;
|
|
if (blockStartTime == all_time_block.Last().EndTime)
|
{//当前开始时间 和上次结束时间一样, 表示接上了,是连续
|
block_id++;
|
var bt2 = BuildAnaPrjBlockTime(block_id, block_time_item.PumpCount, block_time_item.StartIndx, block_time_item.EndIndx,
|
block_time_item.ReservoirStartHeight, block_time_item.ReservoirEndHeight);
|
if (bt2 != null)
|
all_time_block.Add(bt2);
|
}
|
else
|
{//不是连续, 需要加一个关机时间块
|
block_id++;
|
var bt1 = BuildAnaPrjBlockTime(block_id, 0, all_time_block.Last().EndTimeIndex, block_time_item.StartIndx,
|
all_time_block.Last().ReservoirEndHeight, block_time_item.ReservoirStartHeight);
|
if (bt1 != null)
|
all_time_block.Add(bt1);
|
|
block_id++;
|
var bt2 = BuildAnaPrjBlockTime(block_id, block_time_item.PumpCount, block_time_item.StartIndx, block_time_item.EndIndx,
|
block_time_item.ReservoirStartHeight, block_time_item.ReservoirEndHeight);
|
if (bt2 != null)
|
all_time_block.Add(bt2);
|
}
|
}
|
|
#endregion 主体
|
|
#region 最后
|
|
if (Math.Abs((_timeList[finsih_open_block_time_item.EndIndx].Time - this._calEndTime).TotalMinutes) > 15)
|
{//最后关机状态
|
//计算全部结束时水位
|
var finish_level = CalcReservoirHeight(finsih_open_block_time_item.EndIndx, _timeList.Count - 1, 0, finsih_open_block_time_item.ReservoirEndHeight);
|
|
block_id++;
|
var bt2 = BuildAnaPrjBlockTime(block_id, 0, finsih_open_block_time_item.EndIndx, _timeList.Count - 1,
|
finsih_open_block_time_item.ReservoirEndHeight, finish_level);
|
if (bt2 != null)
|
all_time_block.Add(bt2);
|
}
|
|
#endregion 最后
|
|
//计算泵组
|
var pumpSwitchList = new List<AnaPrjSwitchInfo>();
|
var first_block_item = all_time_block.First();
|
int switch_group_id = 1;
|
//开始状态
|
//IStation.LogHelper.Info("_startOpenPumpArray:"+_startOpenPumpArray + ",first_block_item.OpenPumpCount:" + first_block_item.OpenPumpCount);
|
if (BuildSwitchPumpIndexArray(ref pumpSwitchList, switch_group_id, ref first_block_item, this._startOpenPumpArray))
|
{
|
switch_group_id++;
|
}
|
|
for (int i = 1; i < all_time_block.Count; i++)//从1开始
|
{
|
var current_block_item = all_time_block[i];
|
if (BuildSwitchPumpIndexArray(ref pumpSwitchList, switch_group_id, ref current_block_item, all_time_block[i - 1].OpenPumpIndexs))
|
{
|
switch_group_id++;
|
}
|
}
|
//
|
switch_group_id++;
|
BuildSwitchPumpIndexArray4Finish(ref pumpSwitchList, switch_group_id, all_time_block.Last());
|
#region 计算具体时间, 保证时间间隔, 考虑顺序
|
|
var max_switch_group_id = switch_group_id;
|
|
var openPumpIndexSequence = IStation.AnaGlobalParas.Setting.OpenPumpIndexSequence;
|
var closePumpIndexSequence = IStation.AnaGlobalParas.Setting.ClosePumpIndexSequence;
|
|
|
var unablePumpIndexArray = IStation.AnaGlobalParas.Setting.UnablePumpIndexArray;
|
if (unablePumpIndexArray != null && unablePumpIndexArray.Count() > 0)
|
{
|
//后面再开检修的泵
|
if (openPumpIndexSequence != null)
|
{
|
var list = new List<int>();
|
foreach (var index in openPumpIndexSequence)
|
{
|
if (unablePumpIndexArray.Contains(index))
|
continue;
|
list.Add(index);
|
}
|
foreach (var index in unablePumpIndexArray)
|
{
|
list.Add(index);
|
}
|
openPumpIndexSequence = list.ToArray();
|
}
|
|
//先关闭检修的泵
|
if (closePumpIndexSequence != null)
|
{
|
var list = new List<int>();
|
foreach (var index in unablePumpIndexArray)
|
{
|
list.Add(index);
|
}
|
foreach (var index in closePumpIndexSequence)
|
{
|
if (unablePumpIndexArray.Contains(index))
|
continue;
|
list.Add(index);
|
}
|
|
closePumpIndexSequence = list.ToArray();
|
}
|
}
|
|
//IStation.LogHelper.Info(
|
// string.Format(
|
// "openPumpIndexSequence:{0},closePumpIndexSequence:{1}",
|
// string.Join(",",openPumpIndexSequence),
|
// string.Join(",", closePumpIndexSequence)));
|
|
|
|
|
|
|
var switchPumpMinuteSpace = IStation.AnaGlobalParas.Setting.SwitchPumpMinuteSpace;
|
|
for (int group_id = 1; group_id <= max_switch_group_id; group_id++)
|
{
|
var open_switch_list = pumpSwitchList.Where(x => x.GroupID == group_id && x.SwitchType == 1).ToList();
|
if (open_switch_list != null && open_switch_list.Count() > 0)
|
{
|
if (openPumpIndexSequence == null || openPumpIndexSequence.Count() == 0)
|
{
|
for (int i = 1; i < open_switch_list.Count(); i++)
|
{
|
open_switch_list[i].Time = open_switch_list[i].Time.AddMinutes(switchPumpMinuteSpace * i);
|
}
|
}
|
else
|
{
|
int cs = 0;
|
foreach (var indx in openPumpIndexSequence)
|
{
|
foreach (var srt in open_switch_list)
|
{
|
if (srt.PumpIndex == indx)
|
{
|
srt.Time = srt.Time.AddMinutes(switchPumpMinuteSpace * cs);
|
cs++;
|
}
|
}
|
}
|
}
|
}
|
var close_switch_list = pumpSwitchList.Where(x => x.GroupID == group_id && x.SwitchType == 0).ToList();
|
if (close_switch_list != null && close_switch_list.Count() > 0)
|
{
|
if (closePumpIndexSequence == null || closePumpIndexSequence.Count() == 0)
|
{
|
for (int i = 1; i < close_switch_list.Count(); i++)
|
{
|
close_switch_list[i].Time = close_switch_list[i].Time.AddMinutes(switchPumpMinuteSpace * i);
|
}
|
}
|
else
|
{
|
int cs = 0;
|
foreach (var indx in closePumpIndexSequence)
|
{
|
foreach (var srt in close_switch_list)
|
{
|
if (srt.PumpIndex == indx)
|
{
|
srt.Time = srt.Time.AddMinutes(switchPumpMinuteSpace * cs);
|
cs++;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
#endregion 计算具体时间, 保证时间间隔, 考虑顺序
|
|
//结束时的泵允许状态
|
opt_prj.EndTimeOpenPumpStatus = all_time_block.Last().OpenPumpIndexs;
|
|
if (pumpSwitchList != null)
|
{
|
//IStation.LogHelper.Info("pumpSwitchList count:" + pumpSwitchList.Count);
|
int sw_index = 1;
|
foreach (var sw in pumpSwitchList)
|
{
|
sw.Index = sw_index;
|
sw_index++;
|
}
|
opt_prj.PumpSwitchs = pumpSwitchList;
|
}
|
|
|
|
opt_prj.BlockTimes = all_time_block;
|
|
//计算总数
|
double sumPower = 0, sumFlow = 0, sumMoney = 0;
|
foreach (var block_time_item in opt_prj.BlockTimes)
|
{
|
sumPower += block_time_item.SumPower;
|
sumFlow += block_time_item.SumFlow;
|
sumMoney += block_time_item.SumMoney;
|
}
|
if (double.IsNaN(sumMoney) || double.IsInfinity(sumMoney) || sumMoney == double.MaxValue)
|
return null;
|
if (double.IsNaN(sumPower) || double.IsInfinity(sumPower) || sumPower == double.MaxValue)
|
return null;
|
opt_prj.SumMoney = sumMoney;
|
opt_prj.SumFlow = sumFlow;
|
opt_prj.SumPower = sumPower;
|
|
return opt_prj;
|
}
|
|
//构建开泵数组,返回 true 表示增加了切换, false 表示不用新增切换,
|
private bool BuildSwitchPumpIndexArray(
|
ref List<AnaPrjSwitchInfo> sw_list,
|
int switch_group_id,
|
ref AnaPrjBlockTime current_block_time_item,
|
List<int> lastOpenPumpIndexs //上次的开泵情况
|
)
|
{
|
int lastOpenPumpCount = 0;
|
if (lastOpenPumpIndexs != null)
|
{
|
lastOpenPumpCount = lastOpenPumpIndexs.Count;
|
}
|
if (lastOpenPumpCount == 0)
|
{
|
if (current_block_time_item.OpenPumpCount == 0)
|
{
|
current_block_time_item.StartSwitchGroupID = 0;//表示不用切泵
|
return false;
|
}
|
//全部重新开,就按最优的开即可
|
current_block_time_item.StartSwitchGroupID = switch_group_id;
|
current_block_time_item.OpenPumpIndexs = this.GetOptimalPumpIndexList(
|
current_block_time_item.OpenPumpCount, false);
|
foreach (var p in current_block_time_item.OpenPumpIndexs)
|
{
|
sw_list.Add(new AnaPrjSwitchInfo()
|
{
|
GroupID = switch_group_id,
|
SwitchType = 1,
|
Time = current_block_time_item.StartTime,
|
PumpIndex = p
|
});
|
}
|
|
return true;
|
}
|
else
|
{
|
if (current_block_time_item.OpenPumpCount == lastOpenPumpCount)
|
{//相同就继续
|
current_block_time_item.StartSwitchGroupID = 0;//表示不用切泵
|
current_block_time_item.OpenPumpIndexs = lastOpenPumpIndexs;
|
return false;
|
}
|
//开始NEW 数组
|
current_block_time_item.OpenPumpIndexs = new List<int>();
|
|
//判断是多开,还是要关闭
|
if (current_block_time_item.OpenPumpCount > lastOpenPumpCount)
|
{//要多开
|
foreach (var idx in lastOpenPumpIndexs)
|
{//先把原来的加进去
|
current_block_time_item.OpenPumpIndexs.Add(idx);
|
}
|
|
foreach (var idx in this._optimalPumpIndexs)
|
{//不考虑顺序
|
if (current_block_time_item.OpenPumpIndexs.Contains(idx))
|
continue;//原来有的就不加进去
|
|
//原来没有,表示要新开
|
current_block_time_item.OpenPumpIndexs.Add(idx);
|
current_block_time_item.StartSwitchGroupID = switch_group_id;
|
|
sw_list.Add(new AnaPrjSwitchInfo()
|
{
|
GroupID = switch_group_id,
|
SwitchType = 1,
|
Time = current_block_time_item.StartTime,
|
PumpIndex = idx
|
});
|
|
//如果数量正确,就退出
|
if (current_block_time_item.OpenPumpIndexs.Count == current_block_time_item.OpenPumpCount)
|
break;
|
}
|
}
|
else
|
{//要关闭一部分泵
|
|
|
foreach (var idx in this._optimalPumpIndexs)
|
{//不考虑顺序
|
if (!lastOpenPumpIndexs.Contains(idx))
|
continue;//原来都没开, 就不用考虑
|
|
current_block_time_item.StartSwitchGroupID = switch_group_id;
|
if (current_block_time_item.OpenPumpIndexs.Count == current_block_time_item.OpenPumpCount)
|
{//如果数量已经达到,就要关闭,OpenPumpIndexs的数量不会增加
|
sw_list.Add(new AnaPrjSwitchInfo()
|
{
|
GroupID = switch_group_id,
|
SwitchType = 0,//关闭
|
Time = current_block_time_item.StartTime,
|
PumpIndex = idx
|
});
|
}
|
else
|
{//原来有,就加进去,不要关闭,也不切换
|
current_block_time_item.OpenPumpIndexs.Add(idx);
|
}
|
}
|
}
|
|
return true;
|
}
|
}
|
|
//
|
private bool BuildSwitchPumpIndexArray4Finish(
|
ref List<AnaPrjSwitchInfo> sw_list,
|
int switch_group_id,
|
AnaPrjBlockTime current_block_time_item
|
)
|
{
|
if (current_block_time_item.EndTimeIndex < this._timeList.Count - 2)
|
return false;
|
|
if (current_block_time_item.OpenPumpCount == 0)
|
{//表示不用切泵
|
return false;
|
}
|
|
|
var lastOpenPumpIndexs = current_block_time_item.OpenPumpIndexs;
|
if (lastOpenPumpIndexs == null || lastOpenPumpIndexs.Count() == 0)
|
{
|
return false;
|
}
|
|
foreach (var idx in this._optimalPumpIndexs)
|
{
|
if (!lastOpenPumpIndexs.Contains(idx))
|
continue;//原来都没开, 就不用考虑
|
|
current_block_time_item.EndSwitchGroupID = switch_group_id;
|
|
sw_list.Add(new AnaPrjSwitchInfo()
|
{
|
GroupID = switch_group_id,
|
SwitchType = 0,//关闭
|
Time = current_block_time_item.EndTime,
|
PumpIndex = idx
|
});
|
|
}
|
|
|
return true;
|
|
}
|
protected AnaPrjBlockTime BuildAnaPrjBlockTime(int block_id, int open_pump_count,
|
int start_indx, int end_index,
|
double reservoir_start_height, double reservoir_end_height)
|
{
|
if (start_indx >= end_index)
|
{
|
return null;
|
}
|
AnaPrjBlockTime block_time_item = new AnaPrjBlockTime();
|
block_time_item.PointTimes = new List<AnaPrjPointTime>();
|
|
block_time_item.ID = block_id;
|
block_time_item.StartTimeIndex = start_indx;
|
block_time_item.EndTimeIndex = end_index;
|
block_time_item.ReservoirStartHeight = reservoir_start_height;
|
block_time_item.ReservoirEndHeight = reservoir_end_height;
|
block_time_item.StartTime = _timeList[start_indx].Time;
|
block_time_item.EndTime = _timeList[end_index].Time;
|
block_time_item.OpenPumpCount = open_pump_count;
|
|
double sumPower_item = 0, sumFlow_item = 0, sumMoney_item = 0;
|
if (open_pump_count == 0)
|
{
|
for (int i = start_indx; i < end_index; i++)
|
{
|
var si = new AnaPrjPointTime(_timeList[i]);
|
si.WaterLevelH = Math.Round(
|
reservoir_start_height +
|
(start_indx - i) * (-reservoir_start_height + reservoir_end_height) / (start_indx - end_index), 4);
|
|
block_time_item.PointTimes.Add(si);
|
}
|
}
|
else
|
{
|
var td = GetTimeDataBundle(open_pump_count);
|
|
for (int i = start_indx; i < end_index; i++)
|
{
|
var si = new AnaPrjPointTime(_timeList[i], td.TimeDatas[i], block_time_item.OpenPumpCount);
|
si.WaterLevelH = Math.Round(
|
reservoir_start_height +
|
(start_indx - i) * (-reservoir_start_height + reservoir_end_height) / (start_indx - end_index), 4);
|
|
sumPower_item += td.TimeDatas[i].SumPower;
|
sumFlow_item += td.TimeDatas[i].SumFlow;
|
sumMoney_item += td.TimeDatas[i].SumMoney;
|
|
block_time_item.PointTimes.Add(si);
|
}
|
}
|
|
block_time_item.SumPower = sumPower_item;
|
block_time_item.SumFlow = sumFlow_item;
|
block_time_item.SumMoney = sumMoney_item;
|
|
return block_time_item;
|
}
|
|
#endregion Project 转化
|
}
|
}
|