namespace IStation.Algorithm
{
///
/// 调度分析辅助类
///
public partial class ScheduleHelper
{
#region ViewModel
private class AnalysisConclusionViewModel : Model.AnalysisConclusion
{
public AnalysisConclusionViewModel() { }
public AnalysisConclusionViewModel(Model.AnalysisConclusion rhs) : base(rhs) { }
public AnalysisConclusionViewModel(Model.AnalysisConclusion rhs, int flag) : base(rhs)
{
this.Flag = flag;
}
public int Flag { get; set; }
}
#endregion
private readonly decimal _frequency_min = 28;
private readonly decimal _frequency_max = 50;
private readonly decimal _frequency_space = 1;//频率间隔
private readonly double _start_stop_loss_coefficient = 0.95;//泵启停损失系数
private readonly double _sel_opt_flow_excess = 1;//可选方案的流量余量
private readonly double _sel_opt_pump_head_excess = 0;//可选方案的单泵扬程默认抬升余量
private readonly double _sel_opt_flow_deviation_ratio = 0.05;//可选方案的流量偏差比
private readonly double _sel_opt_reasonable_flow_deviation_ratio = 0.005;//合理的方案的流量偏差比
private readonly Service.AnalysisConclusion _service_analysis_conclusion = new();
private readonly Service.AnalysisDeviation _service_analysis_deviation = new();
private int _min_open_count;//最小开泵数量
private int _max_open_count;//最大开泵数量
private List _current_open_flag_list = null;// 当前开泵列表
private List _must_open_flag_list = null; // 必开泵列表
private List _must_close_flag_list = null; // 必关泵列表
private List _long_time_run_flag_list = null; // 长时间运行的泵列表
private List _short_time_run_flag_list = null; // 短时间运行的泵列表
private List> _forbidden_flag_combine_list = null; // 禁用泵组合
private List> _associative_flag_combine_list = null; // 关联泵组合
private List> _same_section_flag_combine_list = null; // 同段泵组合
private List _water_supply_limit_list = null; //供水限制列表
private List _frequency_limit_list = null; // 频率限制列表
///
/// 初始化
///
public void Initial(List current_open_flag_list, Model.ScheduleConfig schedule_config)
{
_min_open_count = 1;
_max_open_count = 0;
_current_open_flag_list = current_open_flag_list;
_must_open_flag_list = null;
_must_close_flag_list = null;
_long_time_run_flag_list = null;
_short_time_run_flag_list = null;
_forbidden_flag_combine_list = null;
_associative_flag_combine_list = null;
_same_section_flag_combine_list = null;
_water_supply_limit_list = null;
_frequency_limit_list = null;
if (schedule_config != null)
{
_min_open_count = schedule_config.MinOpenCount;
_max_open_count = schedule_config.MaxOpenCount;
_must_open_flag_list = schedule_config.MustOpenFlagList;
_must_close_flag_list = schedule_config.MustCloseFlagList;
_long_time_run_flag_list = schedule_config.LongTimeRunFlagList;
_short_time_run_flag_list = schedule_config.ShortTimeRunFlagList;
_forbidden_flag_combine_list = schedule_config.ForbiddenFlagCombineList;
_associative_flag_combine_list = schedule_config.AssociativeFlagCombineList;
_same_section_flag_combine_list = schedule_config.SameSectionFlagCombineList;
_water_supply_limit_list = schedule_config.WaterSupplyLimitList;
_frequency_limit_list = schedule_config.FrequencyLimitList;
}
}
#region OptAnaCombine
///
/// 获取最优组合
///
///
///
///
///
///
///
public AnaCombine GetOptAnaCombine
(
List pump_list,
List same_type_flag_group_first,
Dictionary flag_inlet_water_level_dict,
double target_flow,
double target_head
)
{
#region 初始化参数
if (pump_list == null || !pump_list.Any())
{
return default;
}
var min_open_count = _min_open_count;
var max_open_count = _max_open_count < 1 ? pump_list.Count : _max_open_count;
var current_open_flag_list = _current_open_flag_list;
var must_open_flag_list = _must_open_flag_list;
var must_close_flag_list = _must_close_flag_list;
var long_time_run_flag_list = _long_time_run_flag_list;
var short_time_run_flag_list = _short_time_run_flag_list;
var forbidden_flag_combine_list = _forbidden_flag_combine_list;
var associative_flag_combine_list = _associative_flag_combine_list;
var same_section_flag_combine_list = _same_section_flag_combine_list;
var water_supply_limit_list = _water_supply_limit_list;
var frequency_limit_list = _frequency_limit_list;
var pump_bp_dict = pump_list.ToDictionary(x => x.Flag, x => x.IsBp);
var pump_nr_dict = pump_list.ToDictionary(x => x.Flag, x => x.Nr);
var pump_flag_list = pump_list.Select(x => x.Flag).ToList();
var combine_merit_ratio = 1d;//组合择优率
target_flow = Math.Round(target_flow, 1);
target_head = Math.Round(target_head, 1);
#endregion
#region 初始化规则
#region 存在-必开泵列表
var must_open_flag_list_remark = string.Empty;
var exist_must_open_flag_list = must_open_flag_list != null && must_open_flag_list.Count > 0;
if (exist_must_open_flag_list)
{
must_open_flag_list = must_open_flag_list.OrderBy(x => x).ToList();
must_open_flag_list_remark = IntListHelper.ToString(must_open_flag_list);
}
#endregion
#region 存在-必关泵列表
var exist_must_close_flag_list = must_close_flag_list != null && must_close_flag_list.Count > 0;
#endregion
#region 存在-长时间运行泵列表
var exist_long_time_run_flag_list = long_time_run_flag_list != null && long_time_run_flag_list.Count > 0;
#endregion
#region 存在-短时间运行泵列表
var short_time_run_flag_list_remark = string.Empty;
var exist_short_time_run_flag_list = short_time_run_flag_list != null && short_time_run_flag_list.Count > 0;
if (exist_short_time_run_flag_list)
{
short_time_run_flag_list = short_time_run_flag_list.OrderBy(x => x).ToList();
short_time_run_flag_list_remark = IntListHelper.ToString(short_time_run_flag_list);
}
#endregion
#region 存在-禁用组合
var exist_forbidden_flag_combine_list = forbidden_flag_combine_list != null && forbidden_flag_combine_list.Count > 0;
#endregion
#region 存在-关联组合
var exist_associative_flag_combine_list = associative_flag_combine_list != null && associative_flag_combine_list.Count > 0;
#endregion
#region 存在-同段泵组合
Dictionary> same_section_combine_dict = new();
var exist_same_section_flag_combine_list = same_section_flag_combine_list != null && same_section_flag_combine_list.Count > 0;
if (exist_same_section_flag_combine_list)
{
same_section_combine_dict = GetSameSectionCombineDict(same_section_flag_combine_list, pump_list.Count);
}
#endregion
#region 存在-供水限制
var exist_water_supply_limit_list = water_supply_limit_list != null && water_supply_limit_list.Count > 0;
if (exist_water_supply_limit_list)
{
var water_supply_min = water_supply_limit_list.Min(x => x.Min);
var water_supply_max = water_supply_limit_list.Max(x => x.Max);
if (target_flow < water_supply_min || target_flow > water_supply_max)
{
return default;
}
}
#endregion
#region 存在-频率限制
var frequency_limit_flag_dict = new Dictionary();
var exist_frequency_limit_list = frequency_limit_list != null && frequency_limit_list.Count > 0;
if (exist_frequency_limit_list)
{
frequency_limit_flag_dict = frequency_limit_list.ToDictionary(x => x.Flag, x => x);
}
#endregion
#region 存在-当前开泵列表 (是否切泵)
var exist_current_open_flag_list = current_open_flag_list != null && current_open_flag_list.Count > 0;
if (exist_current_open_flag_list)
{
//供水限制
var exist_limit = false;
#if DEBUG
#else
if (exist_water_supply_limit_list)
{
var limit = water_supply_limit_list.Find(x => x.PumpCount == current_open_flag_list.Count);
if (limit != null)
{
if (target_flow < limit.Min || target_flow > limit.Max)
{
exist_limit = true;
}
}
}
#endif
if (!exist_limit)
{
var opt_ana_combine = GetOptAnaCombine
(
current_open_flag_list,
combine_merit_ratio,
flag_inlet_water_level_dict,
pump_nr_dict,
pump_bp_dict,
exist_frequency_limit_list,
frequency_limit_flag_dict,
target_flow,
target_head
);
if (opt_ana_combine != null)
return opt_ana_combine;
}
}
#endregion
#endregion
#region 调度分析
var opt_ana_combine_list = new List();
for (int pump_count = min_open_count; pump_count <= max_open_count; pump_count++)
{
if (pump_count == 1)
{
var max_total_flow = pump_list.Max(x => x.Qr);
if (max_total_flow < target_flow)
continue;
}
#region 供水限制
//供水限制
if (exist_water_supply_limit_list)
{
var exist_limit = false;
foreach (var limit in water_supply_limit_list)
{
if (limit.PumpCount == pump_count)
{
if (target_flow < limit.Min || target_flow > limit.Max)
{
exist_limit = true;
break;
}
}
}
if (exist_limit)
continue;
}
#endregion
var combine_list = GetCombineList(pump_flag_list, pump_count);//排列组合
foreach (var combine in combine_list)
{
combine_merit_ratio = 1;
#region 规则过滤
//必开
if (exist_must_open_flag_list)
{
var combine_remark = IntListHelper.ToString(combine.OrderBy(x => x));
if (!combine_remark.Contains(must_open_flag_list_remark))
continue;
}
//必关
if (exist_must_close_flag_list)
{
var exist_intersected = combine.Intersect(must_close_flag_list).Count() > 0;
if (exist_intersected)
continue;
}
//长时间运行的泵
if (exist_long_time_run_flag_list)
{
var exist_intersected = combine.Intersect(long_time_run_flag_list).Count() > 0;
if (exist_intersected)
continue;
}
//短时间运行的泵
if (exist_short_time_run_flag_list)
{
var combine_remark = IntListHelper.ToString(combine.OrderBy(x => x));
if (!combine_remark.Contains(short_time_run_flag_list_remark))
continue;
}
//禁用组合
if (exist_forbidden_flag_combine_list)
{
var exist_equal = false;
foreach (var flag_list in forbidden_flag_combine_list)
{
if (combine.SequenceEqual(flag_list))
{
exist_equal = true;
break;
}
}
if (exist_equal)
continue;
}
//同段泵组合
if (exist_same_section_flag_combine_list)
{
var exist_equal = false;
foreach (var flag_list in same_section_combine_dict[pump_count])
{
//相同
if (combine.SequenceEqual(flag_list))
{
exist_equal = true;
break;
}
//包含
if (flag_list.Intersect(combine).Count() == flag_list.Length)
{
exist_equal = true;
break;
}
}
if (exist_equal)
continue;
}
//关联组合
if (exist_associative_flag_combine_list)
{
var exist_intersected = false;
foreach (var flag_list in associative_flag_combine_list)
{
var except_count = combine.Except(flag_list).Count();
if (except_count != flag_list.Count && except_count > 0)
{
exist_intersected = true;
}
}
if (exist_intersected)
continue;
}
int start_stop_count = 0;//启停数量
//当前开泵列表
if (exist_current_open_flag_list)
{
var start_pump_count = combine.Except(current_open_flag_list).Count();
var close_pump_count = current_open_flag_list.Except(combine).Count();
start_stop_count = start_pump_count + close_pump_count;//启停数量
}
else
{
start_stop_count = combine.Count();
if (exist_must_open_flag_list)
{
start_stop_count = combine.Except(must_open_flag_list).Count();
}
}
#endregion
var total_loss_ratio = Math.Pow(_start_stop_loss_coefficient, start_stop_count);//启停一次损失些能耗
combine_merit_ratio *= total_loss_ratio;
var opt_ana_combine = GetOptAnaCombine
(
combine,
combine_merit_ratio,
flag_inlet_water_level_dict,
pump_nr_dict,
pump_bp_dict,
exist_frequency_limit_list,
frequency_limit_flag_dict,
target_flow,
target_head
);
if (opt_ana_combine == null)
continue;
opt_ana_combine_list.Add(opt_ana_combine);
}
//如果当前循环已经满足,不需要再加泵
if (opt_ana_combine_list.Any())
{
break;
}
}
if (opt_ana_combine_list.Count < 1)
return default;
opt_ana_combine_list = opt_ana_combine_list.OrderBy(x => x.TotalPower).OrderByDescending(x => x.MeritRatio).ToList();
var opt = opt_ana_combine_list.First();
opt.Round();
return opt;
#endregion
}
///
/// 获取最优组合
///
///
///
///
///
///
///
///
///
///
///
private AnaCombine GetOptAnaCombine
(
IEnumerable combine,
double combine_merit_ratio,
Dictionary flag_inlet_water_level_dict,
Dictionary pump_nr_dict,
Dictionary pump_bp_dict,
bool exist_frequency_limit_list,
Dictionary frequency_limit_flag_dict,
double target_flow,
double target_head
)
{
if (combine == null || !combine.Any())
return default;
//先修正组合曲线和模型的偏差扬程
var combine_deviation_factor_dict = GetCombineDeviationFactorDict(target_flow, combine);
var conclusion_ex_list_list = new List>();
var conclusion_ex_list_dict = new Dictionary>();
double max_supply_flow = 0;
foreach (var flag in combine)
{
var run_flag = RunFlagHelper.GetRunFlag(flag, pump_bp_dict[flag]);
//进口水位
var inlet_water_level = flag_inlet_water_level_dict[flag];
//组合修正系数
var combine_deviation_factor = combine_deviation_factor_dict[flag];
var current_target_head = target_head - inlet_water_level + combine_deviation_factor + _sel_opt_pump_head_excess;
current_target_head = Math.Round(current_target_head, 1);
//频率限制
var conclusion_list = new List();
if (exist_frequency_limit_list && frequency_limit_flag_dict.ContainsKey(flag))
{
var limit = frequency_limit_flag_dict[flag];
conclusion_list = _service_analysis_conclusion.GetList(run_flag, limit.Min, limit.Max, current_target_head);
}
else
{
//定频泵 可能最小扬程超过目标扬程
var min_head_conclusion = _service_analysis_conclusion.GetMinHead(run_flag);
if (min_head_conclusion != null && min_head_conclusion.Head > current_target_head)
{
conclusion_list = new List() { min_head_conclusion };
}
else
{
conclusion_list = _service_analysis_conclusion.GetList(run_flag, current_target_head);
}
}
if (conclusion_list == null || !conclusion_list.Any())
{
break;
}
max_supply_flow += conclusion_list.Max(x => x.Flow);
var conclusion_ex_list = conclusion_list.Select(x => new AnalysisConclusionViewModel(x, flag)).ToList();
conclusion_ex_list_list.Add(conclusion_ex_list);
conclusion_ex_list_dict[flag] = conclusion_ex_list;
}
if (conclusion_ex_list_list.Count != combine.Count())
return default;
if (max_supply_flow < target_flow * _sel_opt_flow_excess)
return default;
var opt_ana_combine = GetOptAnaCombine(conclusion_ex_list_dict, pump_nr_dict, pump_bp_dict, target_flow);
if (opt_ana_combine == null)
return default;
var total_flow = opt_ana_combine.TotalFlow;
var total_power = opt_ana_combine.TotalPower;
if (total_flow < target_flow * _sel_opt_flow_excess)
return default;
var total_flow_deviation_ratio = Math.Abs((1 - Math.Abs((total_flow / target_flow))));
if (total_flow_deviation_ratio > _sel_opt_flow_deviation_ratio)
return default;
if (total_flow_deviation_ratio > _sel_opt_reasonable_flow_deviation_ratio)
{
combine_merit_ratio -= total_flow_deviation_ratio;
}
var actual_target_head = target_head;
var inlet_water_head = flag_inlet_water_level_dict.Average(x => x.Value);
if (inlet_water_head > 0)
{
actual_target_head = target_head - inlet_water_head;
actual_target_head = Math.Round(actual_target_head, 2);
}
var efficiency = Curve.PumpCalculateHelper.CalculateE(total_flow, actual_target_head, total_power);
var wp = Curve.PumpCalculateHelper.CalculateWP(total_power, total_flow);
var uwp = Curve.PumpCalculateHelper.CalculateUWP(total_power, total_flow, actual_target_head);
opt_ana_combine.TotalFlow = total_flow;
opt_ana_combine.TotalHead = target_head;
opt_ana_combine.TotalPower = total_power;
opt_ana_combine.TotalEfficiency = efficiency;
opt_ana_combine.WP = wp;
opt_ana_combine.UWP = uwp;
opt_ana_combine.MeritRatio = combine_merit_ratio;
return opt_ana_combine;
}
///
/// 获取最优组合
///
///
///
///
///
///
private AnaCombine GetOptAnaCombine(
Dictionary> conclusion_ex_list_dict,
Dictionary pump_nr_dict,
Dictionary pump_bp_dict,
double target_flow
)
{
if (conclusion_ex_list_dict == null || !conclusion_ex_list_dict.Any())
return default;
var frequency_min = (double)_frequency_min;
var frequency_max = (double)_frequency_max;
var frequency_space = (double)_frequency_space;
var all_fre_conclusion_ex_list_list = new List>();
var all_fix_conclusion_ex_list_list = new List>();
foreach (var item in conclusion_ex_list_dict)
{
var flag = item.Key;
var cl_list = item.Value;
if (pump_bp_dict[flag])
{
all_fre_conclusion_ex_list_list.Add(cl_list);
}
else
{
all_fix_conclusion_ex_list_list.Add(cl_list);
}
}
var low_hz_list = all_fre_conclusion_ex_list_list.Select(x => x.Min(x => x.Pump)).ToList();
var max_hz_list = all_fre_conclusion_ex_list_list.Select(x => x.Max(x => x.Pump)).ToList();
//频率按间隔分组
var frequency_iteration_count = 5;
var frequency_iteration_space = 1d;
var cl_ex_list_list_list = new List>>();
for (int i = 0; i < frequency_iteration_count; i++)
{
var current_frequency_space = frequency_space + (i * frequency_iteration_space);
cl_ex_list_list_list = FrequencyFilters(target_flow, frequency_min, frequency_max, current_frequency_space, all_fre_conclusion_ex_list_list, all_fix_conclusion_ex_list_list);
if (cl_ex_list_list_list.Any())
{
break;
}
if (i == 3)
{
}
}
if (!cl_ex_list_list_list.Any())
{
return default;
}
//分组排列组合求最优
var ana_combine_list = new List();
foreach (var item_cl_ex_list_list in cl_ex_list_list_list)
{
var cl_ex_list_list = CartesianProduct(item_cl_ex_list_list, target_flow);
var opt_cl_ex_list = cl_ex_list_list.OrderBy(x => x.Sum(x => x.Power)).FirstOrDefault();
if (opt_cl_ex_list != null && opt_cl_ex_list.Any())
{
var ana_combine = new AnaCombine();
ana_combine.Flags = new List();
ana_combine.AnaFrePumps = new List();
foreach (var opt_cl_ex in opt_cl_ex_list)
{
var flag = opt_cl_ex.Flag;
ana_combine.Flags.Add(flag);
ana_combine.TotalFlow += opt_cl_ex.Flow;
ana_combine.TotalPower += opt_cl_ex.Power;
var ana_fre_pump = new AnaFrePump();
ana_fre_pump.Flag = flag;
ana_fre_pump.Flow = opt_cl_ex.Flow;
ana_fre_pump.Head = opt_cl_ex.Head;
ana_fre_pump.Power = opt_cl_ex.Power;
ana_fre_pump.Efficiency = Curve.PumpCalculateHelper.CalculateE(ana_fre_pump.Flow, ana_fre_pump.Head, ana_fre_pump.Power);
ana_fre_pump.Frequency = opt_cl_ex.Pump;
ana_fre_pump.Speed = opt_cl_ex.Pump / 50 * pump_nr_dict[flag];
ana_combine.AnaFrePumps.Add(ana_fre_pump);
}
ana_combine.FlagCount = opt_cl_ex_list.Count;
ana_combine.Remark = IntListHelper.ToString(ana_combine.Flags);
ana_combine_list.Add(ana_combine);
}
}
if (!ana_combine_list.Any())
return default;
var opt_ana_combine = ana_combine_list.OrderBy(x => x.TotalPower).First();
return opt_ana_combine;
}
///
/// 获取同段泵组合
///
///
///
///
public Dictionary> GetSameSectionCombineDict(List> same_section_flag_combine_list, int pump_list_count)
{
Dictionary> same_section_combine_dict = new();
var exist_same_section_flag_combine_list = _same_section_flag_combine_list != null && _same_section_flag_combine_list.Count > 0;
if (exist_same_section_flag_combine_list)
{
for (int pump_count = 1; pump_count <= pump_list_count; pump_count++)
{
same_section_combine_dict[pump_count] = new List();
switch (pump_count)
{
case 2:
{
foreach (var same_section_flag_combine in same_section_flag_combine_list)
{
var combine_list = GetCombineList(same_section_flag_combine, 2);
same_section_combine_dict[pump_count].AddRange(combine_list);
}
}
break;
case 3:
{
foreach (var same_section in same_section_flag_combine_list)
{
var combine_list = GetCombineList(same_section, 3);
same_section_combine_dict[pump_count].AddRange(combine_list);
}
}
break;
case 4:
{
foreach (var same_section in same_section_flag_combine_list)
{
var combine_list3 = GetCombineList(same_section, 3);
same_section_combine_dict[pump_count].AddRange(combine_list3);
if (same_section.Count > 3)
{
var combine_list = GetCombineList(same_section, 4);
same_section_combine_dict[pump_count].AddRange(combine_list);
}
}
}
break;
case 5:
{
foreach (var same_section in same_section_flag_combine_list)
{
if (same_section.Count > 3)
{
var combine_list = GetCombineList(same_section, 4);
same_section_combine_dict[pump_count].AddRange(combine_list);
}
}
}
break;
case 6:
{
foreach (var same_section in same_section_flag_combine_list)
{
if (same_section.Count > 3)
{
var combine_list = GetCombineList(same_section, 4);
same_section_combine_dict[pump_count].AddRange(combine_list);
}
}
}
break;
default:
break;
}
}
}
return same_section_combine_dict;
}
///
/// 过滤频率分组
///
///
///
///
///
///
///
///
private List>> FrequencyFilters(
double target_flow,
double frequency_min,
double frequency_max,
double frequency_space,
List> all_fre_conclusion_ex_list_list,
List> all_fix_conclusion_ex_list_list)
{
double fix_total_flow = 0;
var exist_all_fix_conclusion_ex_list_list = all_fix_conclusion_ex_list_list.Any();
if (exist_all_fix_conclusion_ex_list_list)
{
fix_total_flow = all_fix_conclusion_ex_list_list.Sum(x => x.Sum(x => x.Flow));
}
//频率按间隔分组
var cl_ex_list_list_list = new List>>();
for (double fre_current_min = frequency_min; fre_current_min <= frequency_max; fre_current_min++)
{
var fre_current_max = fre_current_min + frequency_space;
var skip_current = false;
var total_flow_current = 0d;
var cl_ex_list_list = new List>();
foreach (var conclusion_ex_list in all_fre_conclusion_ex_list_list)
{
var cl_ex_list = conclusion_ex_list.Where(x => x.Pump <= fre_current_max && x.Pump >= fre_current_min).ToList();
if (cl_ex_list == null || !cl_ex_list.Any())
{
skip_current = true;
break;
}
total_flow_current += cl_ex_list.Max(x => x.Flow);
cl_ex_list_list.Add(cl_ex_list);
}
if (skip_current)
continue;
if (exist_all_fix_conclusion_ex_list_list)
{
total_flow_current += fix_total_flow;
cl_ex_list_list.AddRange(all_fix_conclusion_ex_list_list);
}
if (total_flow_current < target_flow * _sel_opt_flow_excess)
continue;
cl_ex_list_list_list.Add(cl_ex_list_list);
}
return cl_ex_list_list_list;
}
///
/// 获取排列组合列表(笛卡尔乘积)
///
private List> CartesianProduct(List> lstSplit, double target_flow)
{
long count = 1;
lstSplit.ForEach(item => count *= item.Count);
var lstResult = new List>();
for (long i = 0; i < count; ++i)
{
var lstTemp = new List();
long j = 1;
var lstFre = new List();
double totalFlow = 0;
lstSplit.ForEach(item =>
{
j *= item.Count;
var index = (i / (count / j)) % item.Count;
var index_int = (int)index;
var obj = item[index_int];
totalFlow += obj.Flow;
lstTemp.Add(obj);
});
if (totalFlow < target_flow * _sel_opt_flow_excess)
continue;
lstResult.Add(lstTemp);
}
return lstResult;
}
///
/// 获取排列组合
///
///
///
///
private List GetCombineList(List flags, int count)
{
var combine = IStation.Curve.PermutationAndCombination.GetCombination(flags.ToArray(), count);
return combine;
}
///
/// 获取组合偏差系数字典
///
/// 总流量
/// 组合标志
///
private Dictionary GetCombineDeviationFactorDict(double flow, IEnumerable flags)
{
var deviation_factor_dict = new Dictionary();
foreach (var flag in flags)
{
deviation_factor_dict.Add(flag, 0);
}
var analysis_deviation = _service_analysis_deviation.GetByFlowAndRunFlags(flow, flags);
if (analysis_deviation == null)
{
return deviation_factor_dict;
}
foreach (var flag in flags)
{
var scada_correction_factor = 0d;
var model_correction_factor = 0d;
var model_correction_factor_use = 0d;
if (analysis_deviation.CurveDeviation != null && analysis_deviation.CurveDeviation.ContainsKey(flag))
{
scada_correction_factor = analysis_deviation.CurveDeviation[flag];
}
if (analysis_deviation.ModelDeviation != null && analysis_deviation.ModelDeviation.ContainsKey(flag))
{
model_correction_factor = analysis_deviation.ModelDeviation[flag];
}
if (model_correction_factor < 0)
{
model_correction_factor_use = Math.Abs(model_correction_factor);
}
else
{
model_correction_factor_use = -model_correction_factor;
}
var correction_factor = scada_correction_factor + model_correction_factor_use;
deviation_factor_dict[flag] = correction_factor;
}
return deviation_factor_dict;
}
#endregion
#region Expand
///
/// 获取最优组合 工况计算
///
///
///
///
///
///
///
///
public AnaCombine GetOptAnaCombineByWorking(
List pumps,
Dictionary flag_rpm_dic,
Dictionary flag_inlet_water_level_dict,
Dictionary flag_head_dic,
double target_flow,
double target_head
)
{
if (pumps == null || !pumps.Any())
{
return default;
}
if (flag_rpm_dic == null || !flag_rpm_dic.Any())
{
return default;
}
target_flow = Math.Round(target_flow, 1);
target_head = Math.Round(target_head, 1);
double total_flow = 0;
double total_power = 0;
var ana_fre_pump_list = new List();
foreach (var item in flag_rpm_dic)
{
var pump = pumps.Find(x => x.Flag == item.Key);
if (pump == null)
continue;
var rpm = Math.Round(item.Value, 1);
if (rpm == 0)
continue;
var curveQH = Curve.PumpCalculateHelper.CalculateSimilarQH(pump.CurveQH, pump.Nr, rpm);
var curveQP = Curve.PumpCalculateHelper.CalculateSimilarQP(pump.CurveQP, pump.Nr, rpm);
double flow = 0, head = target_head;
if (flag_head_dic != null && flag_head_dic.ContainsKey(pump.Flag))
{
head = flag_head_dic[pump.Flag];
}
if (flag_inlet_water_level_dict != null && flag_inlet_water_level_dict.ContainsKey(pump.Flag))
{
head -= flag_inlet_water_level_dict[pump.Flag];
}
flow = curveQH.GetInterPointLastX(head) ?? 0;
if (flow < 0)
continue;
var fre_pump = new AnaFrePump();
fre_pump.Flag = item.Key;
fre_pump.Flow = flow;
fre_pump.Head = head;
fre_pump.Power = curveQP.GetFitPointY(flow);
fre_pump.Efficiency = Curve.PumpCalculateHelper.CalculateE(fre_pump.Flow, fre_pump.Head, fre_pump.Power);
fre_pump.Frequency = rpm / pump.Nr * 50;
fre_pump.Speed = rpm;
total_flow += flow;
total_power += fre_pump.Power;
ana_fre_pump_list.Add(fre_pump);
}
var efficiency = Curve.PumpCalculateHelper.CalculateE(total_flow, target_head, total_power);
var wp = Curve.PumpCalculateHelper.CalculateWP(total_power, total_flow);
var uwp = Curve.PumpCalculateHelper.CalculateUWP(total_power, total_flow, target_head);
var opt = new AnaCombine();
opt.AnaFrePumps = ana_fre_pump_list;
opt.Flags = new List();
opt.TotalFlow = total_flow;
opt.TotalHead = target_head;
opt.TotalPower = total_power;
opt.TotalEfficiency = efficiency;
opt.WP = wp;
opt.UWP = uwp;
opt.Flags = opt.Flags.OrderBy(x => x).ToList();
opt.FlagCount = opt.Flags.Count;
opt.Remark = IntListHelper.ToString(opt.Flags);
opt.MeritRatio = 1;
opt.Round();
return opt;
}
#endregion
}
}