namespace IStation.Service { /// /// 调度分析辅助类 /// public partial class ScheduleHelper { #region ViewModel private class AnalysisConclusionViewModel : Model.AnalysisParameter { public AnalysisConclusionViewModel() { } public AnalysisConclusionViewModel(Model.AnalysisParameter rhs) : base(rhs) { } public AnalysisConclusionViewModel(Model.AnalysisParameter rhs, int flag) : base(rhs) { this.Flag = flag; } public int Flag { get; set; } } #endregion #region Private Variable private readonly decimal _frequency_min = 25; private readonly decimal _frequency_max = 50; private readonly decimal _frequency_space = 1;//频率间隔 private readonly double _start_stop_loss_coefficient = 0.95;//泵启停损失系数 private double _sel_opt_flow_excess = 1;//可选方案的流量余量 private readonly double _sel_opt_pump_pressure_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.AnalysisParameter _service_analysis_parameter = new(); private readonly Service.AnalysisDeviation _service_analysis_deviation = new(); private readonly Service.AnalysisFactor _service_analysis_factor = 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> _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; // 频率限制列表 private Dictionary _flag_cumulative_runtime_dict = null; // 泵累计运行时长字典 private List _priority_open_flag_list = null; // 优先开泵列表 private List _analysis_deviation_list = null;//分析偏差 #endregion /// /// 初始化 /// public void Initial(List current_open_flag_list, Model.ScheduleConfig schedule_config, List analysis_deviation_list) { _current_open_flag_list = current_open_flag_list; _min_open_count = 1; _max_open_count = 0; _must_open_flag_list = null; _must_close_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; _flag_cumulative_runtime_dict = null; _priority_open_flag_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; _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; _flag_cumulative_runtime_dict = schedule_config.FlagCumulativeRuntimeDict; _priority_open_flag_list = schedule_config.PriorityOpenFlagList; } _analysis_deviation_list = analysis_deviation_list; } #region OptAnaCombine /// /// 获取最优组合 /// /// /// /// /// /// public AnaCombine GetOptAnaCombine ( List pump_list, Dictionary flag_inlet_water_level_dict, double target_flow, double target_pressure ) { #region 初始化参数 if (pump_list == null || !pump_list.Any()) { return default; } var current_open_flag_list = _current_open_flag_list; var min_open_count = _min_open_count; var max_open_count = _max_open_count < 1 ? pump_list.Count : _max_open_count; var must_open_flag_list = _must_open_flag_list; var must_close_flag_list = _must_close_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 flag_cumulative_runtime_dict = _flag_cumulative_runtime_dict; var priority_open_flag_list = _priority_open_flag_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_pressure = Math.Round(target_pressure, 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_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 DEBUG water_supply_min = 0; #endif 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 flag_cumulative_runtime_loss_ratio_dict = new Dictionary(); var exist_flag_cumulative_runtime_dict = flag_cumulative_runtime_dict != null && flag_cumulative_runtime_dict.Count > 0; if (exist_flag_cumulative_runtime_dict) { flag_cumulative_runtime_loss_ratio_dict = GetFlagCumulativeRuntimeLossRatioDict(flag_cumulative_runtime_dict); } #endregion #region 存在-优先开泵列表 var priority_open_flag_list_remark = string.Empty; var exist_priority_open_flag_list = priority_open_flag_list != null && priority_open_flag_list.Count > 0; if (exist_priority_open_flag_list) { priority_open_flag_list = priority_open_flag_list.OrderBy(x => x).ToList(); priority_open_flag_list_remark = IntListHelper.ToString(priority_open_flag_list); } #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 (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; } } } 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_pressure ); 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_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(); } } //泵累计运行时长(待验证) if (exist_flag_cumulative_runtime_dict) { flag_cumulative_runtime_loss_ratio_dict = GetFlagCumulativeRuntimeLossRatioDict(flag_cumulative_runtime_dict); foreach (var flag in combine) { var loss_ratio = flag_cumulative_runtime_loss_ratio_dict[flag]; combine_merit_ratio *= loss_ratio; } } //优先开泵列表 if (exist_priority_open_flag_list) { //foreach (var flag in priority_open_flag_list) //{ // if (combine.Contains(flag)) // { // combine_merit_ratio *= 1.05; // } //} //目前逻辑 优先开泵==必开方案 var combine_remark = IntListHelper.ToString(combine.OrderBy(x => x)); if (!combine_remark.Contains(priority_open_flag_list_remark)) continue; } #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_pressure ); 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_pressure ) { 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.Get(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_pressure_diff = target_pressure - inlet_water_level + combine_deviation_factor + _sel_opt_pump_pressure_excess; current_pressure_diff = Math.Round(current_pressure_diff, 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_parameter.GetList(run_flag, limit.Min, limit.Max, current_pressure_diff); } else { //定频泵 可能最小压差超过目标压差 var min_pressure_diff_conclusion = _service_analysis_parameter.GetMinPressureDiff(run_flag); if (min_pressure_diff_conclusion != null && min_pressure_diff_conclusion.PressureDiff > current_pressure_diff) { conclusion_list = new List() { min_pressure_diff_conclusion }; } else { var is_bp = pump_bp_dict[flag]; if (is_bp) { conclusion_list = _service_analysis_parameter.GetList(run_flag, current_pressure_diff); } else { conclusion_list = new List() { min_pressure_diff_conclusion }; } } } 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) { if (GlobalHelper.IsStation1(combine)) { _sel_opt_flow_excess= 0.995; } var flow_excess = target_flow * _sel_opt_flow_excess; if (max_supply_flow < 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; } double eff = 0, wp = 0, uwp = 0; wp = Curve.PumpCalculateHelper.CalculateWP(total_power, total_flow); foreach (var ana_pump in opt_ana_combine.AnaFrePumps) { var pump_flow = ana_pump.Flow; var pump_eff = ana_pump.Eff; var pump_uwp = ana_pump.UWP; eff += pump_eff * pump_flow / total_flow; uwp += pump_uwp * pump_flow / total_flow; } opt_ana_combine.TotalFlow = total_flow; opt_ana_combine.TotalPressure = target_pressure; opt_ana_combine.TotalPower = total_power; opt_ana_combine.TotalEfficiency = eff; 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 cl_ex_list_list_list = new List>>(); //默认1hz内能求出满足目标需求的排列组合,不满足继续迭代 var frequency_iteration_count = 5;//频率迭代次数 var frequency_iteration_space = 1d;//频率迭代间隔 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 (!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.PressureDiff = opt_cl_ex.PressureDiff; ana_fre_pump.Power = opt_cl_ex.Power; ana_fre_pump.Eff = PumpCalculateHelper.CalculateE(ana_fre_pump.Flow, ana_fre_pump.Head, ana_fre_pump.Power); ana_fre_pump.WP = PumpCalculateHelper.CalculateWP(ana_fre_pump.Power, ana_fre_pump.Flow); ana_fre_pump.UWP = PumpCalculateHelper.CalculateUWP(ana_fre_pump.Power, ana_fre_pump.Flow, ana_fre_pump.Head); ana_fre_pump.Frequency = opt_cl_ex.Hz; ana_fre_pump.Speed = opt_cl_ex.Hz / 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(); 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; } /// /// 获取泵累计运行时长损失系数字典 /// /// /// public Dictionary GetFlagCumulativeRuntimeLossRatioDict(Dictionary flag_cumulative_runtime_dict) { var rating_value = 24 * 5; var flag_cumulative_runtime_loss_ratio_dict = new Dictionary(); foreach (var item in flag_cumulative_runtime_dict) { var flag = item.Key; var cumulative_runtime = item.Value; var level = cumulative_runtime / rating_value / 100; var loss_ratio = 1 - level; flag_cumulative_runtime_loss_ratio_dict.Add(flag, loss_ratio); } return flag_cumulative_runtime_loss_ratio_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.Hz <= fre_current_max && x.Hz >= 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_list = _analysis_deviation_list?.Where(x => x.RunFlags.SequenceEqual(flags)).ToList(); if (analysis_deviation_list == null || !analysis_deviation_list.Any()) { Yw.LogHelper.Error($"[{Yw.Untity.IntListHelper.ToString(flags)}]组合不存在偏差系数!"); return deviation_factor_dict; } var a = flow; var flow_dev = flow; Model.AnalysisDeviation analysis_deviation = null; for (int i = 0; i < 6; i++) { flow_dev += i * 50; analysis_deviation = analysis_deviation_list.Where(x => x.MinFlow <= flow_dev && flow_dev <= x.MaxFlow).FirstOrDefault(); if (analysis_deviation != null) break; } if (analysis_deviation == null) { Yw.LogHelper.Error($"[{Yw.Untity.IntListHelper.ToString(flags)}]组合不存在偏差系数!"); return deviation_factor_dict; } foreach (var flag in flags) { var pressure_diff = 0d; if (analysis_deviation.PressureDiff != null && analysis_deviation.PressureDiff.ContainsKey(flag)) { pressure_diff = analysis_deviation.PressureDiff[flag]; } deviation_factor_dict[flag] = pressure_diff; } return deviation_factor_dict; } #endregion #region Expand /// /// 获取变频泵列表 根据工况计算 /// /// /// /// /// /// /// /// public List GetAnaFrePumpListByWorking( List pumps, Dictionary flag_rpm_dic, Dictionary flag_inlet_water_level_dict, Dictionary flag_head_dic, double total_flow, bool ues_deviation_factor = false ) { if (pumps == null || !pumps.Any()) { return default; } if (flag_rpm_dic == null || !flag_rpm_dic.Any()) { return default; } var run_flag_list = flag_rpm_dic.Where(x => x.Value > 1).Select(x => x.Key).OrderBy(x => x).ToList(); var ana_fre_pump_list = new List(); foreach (var flag in run_flag_list) { var pump = pumps.Find(x => x.Flag == flag); if (pump == null) continue; var rpm = flag_rpm_dic[flag]; if (rpm < 1) 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 = 0; 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]; } if (ues_deviation_factor) { var combine_deviation_factor_dict = GetCombineDeviationFactorDict(total_flow, run_flag_list);//修正组合曲线和模型的偏差扬程 if (combine_deviation_factor_dict != null && combine_deviation_factor_dict.ContainsKey(flag)) { var combine_deviation_factor = combine_deviation_factor_dict[flag]; //组合偏差系数 head -= combine_deviation_factor; } } flow = curveQH.GetInterPointLastX(head) ?? 0; if (flow < 0) continue; var fre_pump = new AnaFrePump(); fre_pump.Flag = flag; fre_pump.Flow = flow; fre_pump.Head = head; fre_pump.Power = curveQP.GetFitPointY(flow); fre_pump.PressureDiff = head - Curve.PumpCalculateHelper.CalculateOtherPress(flow, pump.Ic, pump.Oc, null, null); fre_pump.Eff = Curve.PumpCalculateHelper.CalculateE(fre_pump.Flow, fre_pump.Head, fre_pump.Power); fre_pump.Frequency = rpm / pump.Nr * 50; fre_pump.Speed = rpm; ana_fre_pump_list.Add(fre_pump); } return ana_fre_pump_list; } /// /// 获取变频泵列表 根据工况计算 /// /// /// /// /// /// /// /// /// /// public List GetAnaFrePumpListByWorking( List pumps, Dictionary flag_rpm_dic, Dictionary flag_inlet_water_level_dict, Dictionary flag_flow_dic, Dictionary flag_head_dic, double total_flow, out Dictionary flag_curve_head_dic, bool ues_deviation_factor = false ) { flag_curve_head_dic = new Dictionary(); if (pumps == null || !pumps.Any()) { return default; } if (flag_rpm_dic == null || !flag_rpm_dic.Any()) { return default; } var run_flag_list = flag_rpm_dic.Where(x => x.Value > 1).Select(x => x.Key).OrderBy(x => x).ToList(); var ana_fre_pump_list = new List(); foreach (var flag in run_flag_list) { var pump = pumps.Find(x => x.Flag == flag); if (pump == null) continue; var rpm = flag_rpm_dic[flag]; if (rpm < 1) continue; var hz = Math.Round(rpm / pump.Nr * 50, 1); var CurveQH50 = pump.CurveQH; var CurveQP50 = pump.CurveQP; var curveQH = Curve.PumpCalculateHelper.CalculateSimilarQH(CurveQH50, pump.Nr, rpm); var curveQP = Curve.PumpCalculateHelper.CalculateSimilarQP(CurveQP50, pump.Nr, rpm); double flow = 0, head = 0; 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]; } if (ues_deviation_factor) { //var combine_deviation_factor_dict = GetCombineDeviationFactorDict(total_flow, run_flag_list);//修正组合曲线和模型的偏差扬程 //if (combine_deviation_factor_dict != null && combine_deviation_factor_dict.ContainsKey(flag)) //{ // var combine_deviation_factor = combine_deviation_factor_dict[flag]; //组合偏差系数 // head -= combine_deviation_factor; //} } flow = curveQH.GetInterPointLastX(head) ?? 0; if (flow < 0) continue; var working_flow = flag_flow_dic[flag]; flag_curve_head_dic[flag] = curveQH.GetFitPointY(working_flow); var fre_pump = new AnaFrePump(); fre_pump.Flag = flag; fre_pump.Flow = flow; fre_pump.Head = head; fre_pump.Power = curveQP.GetFitPointY(flow); fre_pump.PressureDiff = head - Curve.PumpCalculateHelper.CalculateOtherPress(flow, pump.Ic, pump.Oc, null, null); fre_pump.Eff = Curve.PumpCalculateHelper.CalculateE(fre_pump.Flow, fre_pump.Head, fre_pump.Power); fre_pump.Frequency = rpm / pump.Nr * 50; fre_pump.Speed = rpm; ana_fre_pump_list.Add(fre_pump); } return ana_fre_pump_list; } #endregion } }