using Accord;
|
using Accord.Genetic;
|
using Optimization1D;
|
|
using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;
|
namespace IStation
|
{
|
public class EpanetHelper
|
{
|
EPAFunctionGUI epaFunction;
|
|
const float MAX_ENERGE = 99999999999;
|
|
|
/// <summary>
|
/// err问题
|
/// </summary>
|
private string ReportQuestion(int err)
|
{
|
ErrorDefine errorDefine = new ErrorDefine();
|
#region [秦白云飞修订]2021-4-30
|
//新增目的:查看报错问题
|
//新增
|
|
#if DEBUG
|
throw (new Exception(errorDefine.getErrorTxt(err)));
|
#endif
|
#endregion [秦白云飞修订]2021-4-30
|
|
return errorDefine.getErrorTxt(err);
|
}
|
|
#region const_mode
|
public const int EN_ELEVATION = 0; // { Mode parameters }
|
public const int EN_BASEDEMAND = 1;
|
public const int EN_PATTERN = 2;
|
public const int EN_EMITTER = 3;
|
public const int EN_INITQUAL = 4;
|
public const int EN_SOURCEQUAL = 5;
|
public const int EN_SOURCEPAT = 6;
|
public const int EN_SOURCETYPE = 7;
|
public const int EN_TANKLEVEL = 8;
|
public const int EN_DEMAND = 9;
|
public const int EN_HEAD = 10;
|
public const int EN_PRESSURE = 11;
|
public const int EN_QUALITY = 12;
|
public const int EN_SOURCEMASS = 13;
|
public const int EN_INITVOLUME = 14;
|
public const int EN_MIXMODEL = 15;
|
public const int EN_MIXZONEVOL = 16;
|
#endregion
|
|
#region type_model
|
enum Type_EPAObject
|
{
|
Node = 0,
|
Link = 1,
|
Pump = 2,
|
Tank = 3
|
}
|
#endregion
|
|
#region other
|
Dictionary<ModelInput.eType, Type_EPAObject> Typelist = new Dictionary<ModelInput.eType, Type_EPAObject>() { { ModelInput.eType.level, Type_EPAObject.Tank }, { ModelInput.eType.flow, Type_EPAObject.Node }, { ModelInput.eType.press_out, Type_EPAObject.Tank }, { ModelInput.eType.pump_run, Type_EPAObject.Pump }, { ModelInput.eType.press_in, Type_EPAObject.Tank }, { ModelInput.eType.valve_initstatus, Type_EPAObject.Link } };
|
|
List<ModelOutput.eType> const_list_nodeType = new List<ModelOutput.eType> { ModelOutput.eType.EN_JUNCTION, ModelOutput.eType.EN_RESERVOIR, ModelOutput.eType.EN_TANK };
|
List<ModelOutput.eType> const_list_linkType = new List<ModelOutput.eType> { ModelOutput.eType.EN_CVPIPE, ModelOutput.eType.EN_PIPE, ModelOutput.eType.EN_PUMP, ModelOutput.eType.EN_PRV, ModelOutput.eType.EN_PSV, ModelOutput.eType.EN_FCV, ModelOutput.eType.EN_TCV, ModelOutput.eType.EN_GPV };
|
|
enum Method
|
{
|
Count = 0,
|
Sum = 1,
|
Avg = 2
|
}
|
|
string GetTypeValue(int typeCode, int ObjType, Method method, out float Value, int valueCode = -1)
|
{
|
Value = -1;
|
List<float> listValue = new List<float>();
|
float result = 0;
|
int err = 0;
|
if (ObjType == 0)
|
{
|
int NLink1 = 0;
|
err = EpanetBase.ENgetcount(EpanetBase.Const_class.Const_Component.EN_NODECOUNT, ref NLink1);
|
if (err > 9) return ReportQuestion(err);
|
for (int i = 1; i < NLink1; i++)
|
{
|
int type = -1;
|
err = EpanetBase.ENgetnodetype(i, ref type);
|
if (err > 9) return ReportQuestion(err);
|
if (type == typeCode)
|
{
|
if (method == Method.Count)
|
result++;
|
else
|
{
|
float value = -1;
|
err = EpanetBase.ENgetnodevalue(i, valueCode, ref value);
|
if (err > 9) return ReportQuestion(err);
|
listValue.Add(value);
|
}
|
}
|
}
|
}
|
else
|
{
|
int NLink1 = 0; //int pump_count = 0;
|
err = EpanetBase.ENgetcount(EpanetBase.Const_class.Const_Component.EN_LINKCOUNT, ref NLink1);
|
if (err > 9) return ReportQuestion(err);
|
for (int i = 1; i < NLink1; i++)
|
{
|
int type = -1;
|
err = EpanetBase.ENgetlinktype(i, ref type);
|
if (err > 9) return ReportQuestion(err);
|
|
if (type == typeCode)
|
{
|
if (method == Method.Count)
|
result++;
|
else
|
{
|
float value = -1;
|
err = EpanetBase.ENgetlinkvalue(i, valueCode, ref value);
|
if (err > 9) return ReportQuestion(err);
|
listValue.Add(value);
|
}
|
}
|
}
|
}
|
if (method == Method.Sum)
|
{
|
result = 0;
|
for (int i = 0; i < listValue.Count; i++)
|
result += listValue[i];
|
}
|
else if (method == Method.Avg)
|
{
|
result = 0;
|
for (int i = 0; i < listValue.Count; i++)
|
result += listValue[i];
|
result /= listValue.Count;
|
}
|
Value = result;
|
|
return null;
|
}
|
string SetPumpValue(List<bool> isfreq, float value, List<string> Combine)
|
{
|
int err = 0;
|
if (value != -1)
|
for (int i = 0; i < Combine.Count; i++)
|
{
|
|
if (!isfreq[i]) //工频泵
|
{
|
if (value > 0)
|
{
|
err = SetItemValue(Combine[i], 1, Type_EPAObject.Pump);
|
if (err > 9) return ReportQuestion(err);
|
return null;
|
|
|
}
|
else
|
{
|
err = SetItemValue(Combine[i], 0, Type_EPAObject.Pump);
|
if (err > 9) return ReportQuestion(err);
|
return null;
|
}
|
}
|
err = SetItemValue(Combine[i], value / 50.0, Type_EPAObject.Pump);
|
if (err > 9) return ReportQuestion(err);
|
}
|
|
return null;
|
}
|
string SetPumpValue(List<bool> isfreq, double[] value, List<string> Combine)
|
{
|
int err = 0;
|
for (int i = 0; i < Combine.Count; i++)
|
{
|
|
if (!isfreq[i]) //工频泵
|
{
|
if (value[i] > 0)
|
{
|
err = SetItemValue(Combine[i], 1, Type_EPAObject.Pump);
|
if (err > 9) return ReportQuestion(err);
|
return null;
|
|
|
}
|
else
|
{
|
err = SetItemValue(Combine[i], 0, Type_EPAObject.Pump);
|
if (err > 9) return ReportQuestion(err);
|
return null;
|
}
|
}
|
err = SetItemValue(Combine[i], value[i] / 50.0, Type_EPAObject.Pump);
|
if (err > 9) return ReportQuestion(err);
|
}
|
|
return null;
|
}
|
int SetTypeValue(List<ModelInput> InputData, ModelInput.eType type, float value = -1, int Num = 0)
|
{
|
int err = 0;
|
var InputData_type = (InputData as List<ModelInput>).FindAll(m => (m.Type == type));
|
if (value == -1)
|
for (int i = 0; i < InputData_type.Count; i++)
|
{
|
err = SetItemValue(InputData_type[i].ObjectID, InputData_type[i].Value, Typelist[type]);
|
if (err > 9) return err;
|
}
|
if (value != -1)
|
for (int i = 1; i <= Num; i++)
|
{
|
err = SetItemValue(type + "_" + i.ToString(), value, Typelist[type]);
|
if (err > 9) return err;
|
}
|
return err;
|
}
|
int SetItemValue(string ID, dynamic value, Type_EPAObject type_Obj)
|
{
|
int Index = -1;
|
int err = 0;
|
switch (type_Obj)
|
{
|
case (Type_EPAObject.Tank):
|
|
err = EpanetBase.ENgetnodeindex(ID, ref Index);
|
err = EpanetBase.ENsetnodevalue(Index, EN_TANKLEVEL, value); //源头压力基数
|
break;
|
case (Type_EPAObject.Node):
|
err = EpanetBase.ENgetnodeindex(ID, ref Index);
|
err = EpanetBase.ENsetnodevalue(Index, EN_BASEDEMAND, value); //源头压力基数
|
break;
|
case (Type_EPAObject.Pump):
|
float speed = (float.Parse(value.ToString()));
|
if (speed < 0.1) speed = 0;
|
if (speed > 0)
|
err = EpanetBase.ENsetlinkvalue(Index, 4, 1);
|
else
|
err = EpanetBase.ENsetlinkvalue(Index, 4, 0);
|
//float speed = float.Parse(value.ToString());
|
err = EpanetBase.ENgetlinkindex(ID, ref Index);
|
//err = EpanetBase.ENsetlinkvalue(Index, 5, speed);
|
err = EpanetBase.ENsetinistatus(ID, speed.ToString());
|
//err = EpanetBase.ENsaveinpfile("C:\\EPA\\修改后" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".inp");
|
if (err > 9) return err;
|
|
|
break;
|
case (Type_EPAObject.Link):
|
err = EpanetBase.ENgetlinkindex(ID, ref Index);
|
err = EpanetBase.ENsetlinkvalue(Index, EpanetBase.Const_class.Const_Link.EN_INITSTATUS, value);
|
break;
|
default:
|
err = -1;
|
break;
|
}
|
|
return err;
|
|
|
|
|
}
|
|
/// <summary>
|
///
|
/// </summary>
|
/// <returns></returns>
|
public int GetOutputString(out List<ModelOutputNode> ListOutputNode, out List<ModelOutputLink> ListOutputLink)
|
{
|
int err = 0;
|
//string result = null;
|
ListOutputNode = new List<ModelOutputNode>();
|
ListOutputLink = new List<ModelOutputLink>();
|
int Njunction = 0;
|
err = EpanetBase.ENgetcount(EpanetBase.Const_class.Const_Component.EN_NODECOUNT, ref Njunction);
|
if (err > 9) return err;
|
|
int NLink = 0;
|
err = EpanetBase.ENgetcount(EpanetBase.Const_class.Const_Component.EN_LINKCOUNT, ref NLink);
|
if (err > 9) return err;
|
List<float> output = new List<float>() { Njunction, NLink };
|
|
for (int i = 1; i <= Njunction; i++)
|
{
|
ModelOutputNode mOutput = new ModelOutputNode();
|
StringBuilder ID = new StringBuilder();
|
|
float Value = 0; int type = -1;
|
err = EpanetBase.ENgetnodeid(i, ID);
|
if (err > 9) return err;
|
|
mOutput.ObjectID = ID.ToString();
|
err = EpanetBase.ENgetnodetype(i, ref type);
|
if (err > 9) return err;
|
mOutput.Type = (ModelOutputNode.eType)type;
|
var list_ValueIndex = mOutput.Get_list_ValueIndex();
|
for (int j = 0; j < list_ValueIndex.Length; j++)
|
{
|
|
err = EpanetBase.ENgetnodevalue(i, list_ValueIndex[j], ref Value); //源头压力基数
|
if (err > 9) return err;
|
//if (Value <= 0.0001) Value = 0;
|
mOutput.SetValue(j, Value);
|
|
|
}
|
ListOutputNode.Add(mOutput);
|
}
|
for (int i = 1; i <= NLink; i++)
|
{
|
ModelOutputLink mOutput = new ModelOutputLink();
|
StringBuilder idBuilder = new StringBuilder();
|
//mOutput.Value = new List<float>();
|
float Value = 0; int type = -1;
|
err = EpanetBase.ENgetlinkid(i, idBuilder); //源头压力基数
|
if (err > 9) return err;
|
mOutput.ObjectID = idBuilder.ToString();
|
err = EpanetBase.ENgetlinktype(i, ref type);
|
if (err > 9) return err;
|
mOutput.Type = (ModelOutputLink.eType)(type + 10);
|
var list_ValueIndex = mOutput.Get_list_ValueIndex();
|
for (int j = 0; j < list_ValueIndex.Length; j++)
|
{
|
err = EpanetBase.ENgetlinkvalue(i, list_ValueIndex[j], ref Value); //源头压力基数
|
if (err > 9) return err;
|
//if (Value <= 0.0001) Value = 0;
|
mOutput.SetValue(j, Value);
|
}
|
ListOutputLink.Add(mOutput);
|
}
|
return err;
|
}
|
private string SetPumpStatus()
|
{
|
int NLink = 0; int err = 0;
|
err = EpanetBase.ENgetcount(EpanetBase.Const_class.Const_Component.EN_LINKCOUNT, ref NLink);
|
if (err > 9) return ReportQuestion(err);
|
|
|
for (int i = 1; i <= NLink; i++)
|
{
|
//ModelOutputLink mOutput = new ModelOutputLink();
|
//StringBuilder idBuilder = new StringBuilder();
|
////mOutput.Value = new List<float>();
|
//float Value = 0;
|
//err = EpanetBase.ENgetlinkid(i, idBuilder); //源头压力基数
|
//if (err > 9) return ReportQuestion(err);
|
//mOutput.ObjectID = idBuilder.ToString();
|
int type = -1;
|
err = EpanetBase.ENgetlinktype(i, ref type);
|
if (err > 9) return ReportQuestion(err);
|
if (type == EpanetBase.Const_class.Const_Link_types.EN_PUMP)
|
{
|
|
err = EpanetBase.ENsetlinkvalue(i, EpanetBase.Const_class.Const_Link.EN_INITSTATUS, 0);
|
|
}
|
|
}
|
return null;
|
}
|
#endregion
|
|
|
private bool _isInitialSuccess = false;
|
|
/// <summary>
|
/// 初始化
|
/// </summary>
|
/// <param name="file"></param>
|
/// <returns></returns>
|
public string Initial(string file)
|
{
|
|
if (!System.IO.File.Exists(file))
|
return "inp 不存在";
|
var err = EpanetBase.ENopen(file, "0.rpt", "0.bin");
|
if (err == 0)
|
{
|
_isInitialSuccess = true;
|
return null;
|
}
|
return ReportQuestion(err);
|
}
|
|
public string GetResultByFlowAndPumpStatus(List<ModelInput> InputData, out List<ModelOutputNode> modelOutputNodes, out List<ModelOutputLink> modelOutputLinks)
|
{
|
#region 初始判断
|
|
modelOutputLinks = null;
|
modelOutputNodes = null;
|
int err = 0;
|
//string result = null;
|
if (!_isInitialSuccess)
|
return "初始化不成功";
|
if (InputData == null)
|
return "输入参数为空";
|
#endregion
|
#region 传参计算
|
err = SetTypeValue(InputData, ModelInput.eType.press_in);
|
if (err > 9) return ReportQuestion(err);
|
err = SetTypeValue(InputData, ModelInput.eType.flow);
|
if (err > 9) return ReportQuestion(err);
|
err = SetTypeValue(InputData, ModelInput.eType.pump_run);
|
if (err > 9) return ReportQuestion(err);
|
err = SetTypeValue(InputData, ModelInput.eType.level);
|
if (err > 9) return ReportQuestion(err);
|
err = SetTypeValue(InputData, ModelInput.eType.valve_initstatus);
|
if (err > 9) return ReportQuestion(err);
|
|
err = EpanetBase.ENsolveH();
|
if (err > 9) return ReportQuestion(err);
|
#endregion
|
/* var path = System.IO.Directory.GetCurrentDirectory() + @"\model\out.inp";
|
err = EpanetBase.ENsaveinpfile(path);
|
if (err > 9) return ReportQuestion(err);*/
|
#region 返回结果
|
err = GetOutputString(out modelOutputNodes, out modelOutputLinks);
|
if (err > 9) return ReportQuestion(err);
|
return null;
|
#endregion
|
|
}
|
|
public string GetResultByPressAndPumpStatus(List<ModelInput> InputData, out List<ModelOutputNode> modelOutputNodes, out List<ModelOutputLink> modelOutputLinks)
|
{
|
|
|
#region 初始判断
|
|
modelOutputLinks = null;
|
modelOutputNodes = null;
|
//string result = null;
|
int err = 0;
|
if (!_isInitialSuccess)
|
return "初始化不成功";
|
if (InputData == null)
|
return "输入参数为空";
|
#endregion
|
|
#region 传参计算
|
err = SetTypeValue(InputData, ModelInput.eType.press_in);
|
if (err > 9) return ReportQuestion(err);
|
err = SetTypeValue(InputData, ModelInput.eType.press_out);
|
if (err > 9) return ReportQuestion(err);
|
err = SetTypeValue(InputData, ModelInput.eType.pump_run);
|
if (err > 9) return ReportQuestion(err);
|
err = SetTypeValue(InputData, ModelInput.eType.level);
|
if (err > 9) return ReportQuestion(err);
|
err = SetTypeValue(InputData, ModelInput.eType.valve_initstatus);
|
if (err > 9) return ReportQuestion(err);
|
|
err = EpanetBase.ENsolveH();
|
if (err > 9) return ReportQuestion(err);
|
#endregion
|
/* var path = System.IO.Directory.GetCurrentDirectory() + @"\model\out.inp";
|
err = EpanetBase.ENsaveinpfile(path);
|
if (err > 9) return ReportQuestion(err);*/
|
#region 返回结果
|
err = GetOutputString(out modelOutputNodes, out modelOutputLinks);
|
if (err > 9) return ReportQuestion(err);
|
return null;
|
#endregion
|
}
|
|
/// <summary>
|
/// 获取水泵转速比组合
|
/// </summary>
|
/// <param name="InputData"></param>
|
/// <param name="List_Combine"></param>
|
/// <param name="List_modelOutputNodes"></param>
|
/// <param name="List_modelOutputLinks"></param>
|
/// <param name="opt_combines"></param>
|
/// <param name="opt_energes"></param>
|
/// <param name="populationSize"></param>
|
/// <param name="iterations"></param>
|
/// <param name="range"></param>
|
/// <param name="accuracy"></param>
|
/// <returns></returns>
|
public string GetResultByFlowAndPress(List<ModelInput> InputData, List<List<string>> List_Combine,
|
out List<List<ModelOutputNode>> List_modelOutputNodes, out List<List<ModelOutputLink>> List_modelOutputLinks,
|
out List<List<double>> opt_combines, out List<double> opt_energes, double rangeMin = 0.8, double rangeMax = 1,
|
int populationSize = 40, int iterations = 20, double accuracy = 0.1)
|
{
|
|
#region 初始判断
|
List_modelOutputNodes = new List<List<ModelOutputNode>>();
|
List_modelOutputLinks = new List<List<ModelOutputLink>>();
|
opt_combines = new List<List<double>>();
|
opt_energes = new List<double>();
|
string result = null;
|
var range = new DoubleRange(rangeMin, rangeMax);
|
|
if (!_isInitialSuccess)
|
return "初始化不成功";
|
if (InputData == null)
|
return "输入参数为空";
|
#endregion
|
|
//float min_energe = MAX_ENERGE;
|
for (int i = 0; i < List_Combine.Count; i++)
|
{
|
List<ModelOutputNode> modelOutputNodes;
|
List<ModelOutputLink> modelOutputLinks;
|
List<double> opt_combine = new List<double>();
|
double energe;
|
calcParms parms;
|
var dr = new DoubleRange(range.Min * 50, range.Max * 50);
|
result = InputInit(InputData, List_Combine[i], out parms, dr.Min, dr.Max);
|
if (result != null)
|
return result;
|
string result0 = _GetResultByFlowAndPress(InputData, List_Combine[i], out modelOutputNodes, out modelOutputLinks, out opt_combine, out energe, dr.Min, dr.Max, populationSize, iterations, accuracy);
|
List_modelOutputNodes.Add(modelOutputNodes);
|
List_modelOutputLinks.Add(modelOutputLinks);
|
for (var j = 0; j < opt_combine.Count; j++) opt_combine[j] /= 50.0;
|
opt_combines.Add(opt_combine);
|
opt_energes.Add(energe);
|
}
|
return result;
|
}
|
|
#region other
|
public void GetResult(double[] list_bestresult)
|
{
|
List<ModelOutputNode> nodes = null;
|
List<ModelOutputLink> links = null;
|
List<double> pumpflows = null;
|
//double out_energe = 999999999f;
|
double[] li = new double[list_bestresult.Length];
|
for (int i = 0; i < li.Length; i++) li[i] = list_bestresult[i];
|
this.epaFunction.GetResult(li, out nodes, out links, out pumpflows, true);
|
}
|
private string _GetResultByFlowAndPress(List<ModelInput> InputData, List<string> combine, out List<ModelOutputNode> modelOutputNodes, out List<ModelOutputLink> modelOutputLinks, out List<double> List_Hz, out double energe, double rangeMin = 0.8, double rangeMax = 1, int populationSize = 40, int iterations = 20, double accuracy = 0.1)
|
{
|
|
|
#region 初始判断
|
modelOutputNodes = null;
|
modelOutputLinks = null;
|
//string result = null;
|
//int err = 0;
|
List_Hz = new List<double>();
|
energe = 9999999999;
|
#endregion
|
#region 初始设置
|
SetPumpStatus();
|
#endregion
|
var range = new DoubleRange(rangeMin, rangeMax);
|
SearchSolution(combine, out List_Hz, out modelOutputNodes, out modelOutputLinks, out energe, rangeMin, rangeMax, populationSize, iterations, accuracy);
|
return "";
|
}
|
|
private void SearchSolution(List<string> combine, out List<double> list_BestHzs, out List<ModelOutputNode> modelOutputNodes, out List<ModelOutputLink> modelOutputLinks, out double energe, double rangeMin = 0.8, double rangeMax = 1, int populationSize = 40, int iterations = 20, double accuracy = 0.1)
|
{
|
var list_BestEnerge = new List<double>();
|
list_BestHzs = new List<double>();
|
var list_AvgHz = new List<double>();
|
|
modelOutputNodes = null;
|
modelOutputLinks = null;
|
energe = 999999999f;
|
|
|
var range = new DoubleRange(rangeMin, rangeMax);
|
var num_Total = range.Length / accuracy;
|
|
|
var LENGTH_PUMP = 0;
|
var value_LENGTH_PUMP = 1;
|
var i = 0;
|
while (value_LENGTH_PUMP < num_Total && i < 1000)
|
{
|
value_LENGTH_PUMP *= 2;
|
LENGTH_PUMP += 1;
|
i++;
|
}
|
|
var chromosomeLength = combine.Count * LENGTH_PUMP;
|
BinaryChromosome ancestor = new BinaryChromosome(chromosomeLength);
|
|
|
|
EPAFunctionGUI fitnessFunction = this.epaFunction;
|
var IntselectionMethod = 0;
|
object obj;
|
if (IntselectionMethod != 0)
|
{
|
if (IntselectionMethod != 1)
|
{
|
ISelectionMethod selectionMethod = new RouletteWheelSelection();
|
obj = selectionMethod;
|
}
|
else
|
{
|
obj = new RankSelection();
|
}
|
}
|
else
|
{
|
obj = new EliteSelection();
|
}
|
|
var optimizationMode = 1;
|
epaFunction.Mode = ((optimizationMode != 0) ? OptimizationFunctionXD.Modes.Minimization : OptimizationFunctionXD.Modes.Maximization);
|
Population population = new Population(populationSize, ancestor, fitnessFunction, (ISelectionMethod)obj);
|
|
int num = 1;
|
//double[,] array = new double[showOnlyBest ? 1 : populationSize, 2];
|
List<ResultCombine> list_result = new List<ResultCombine>();
|
//float[,] array = new double[showOnlyBest ? 1 : populationSize,combine.Count+1];
|
bool needToStop = false;
|
bool showOnlyBest = true;
|
while (!needToStop)
|
{
|
population.RunEpoch();
|
list_result.Clear();
|
if (showOnlyBest)
|
{
|
list_result.Add(new ResultCombine());
|
list_result[0].arrayHz = epaFunction.Translate(population.BestChromosome);
|
list_result[0].totalEnerge = epaFunction.OptimizationFunction(list_result[0].arrayHz);
|
Console.WriteLine($"迭代次数{num},总能耗{list_result[0].totalEnerge}");
|
|
}
|
else
|
{
|
for (int j = 0; j < populationSize; j++)
|
{
|
list_result.Add(new ResultCombine());
|
list_result[j].arrayHz = epaFunction.Translate(population[j]);
|
list_result[j].totalEnerge = epaFunction.OptimizationFunction(list_result[j].arrayHz);
|
}
|
}
|
//chart.UpdateDataSeries("avg", array);
|
//SetText(currentIterationBox, num.ToString());
|
|
double[] list_bestresult = (epaFunction.Translate(population.BestChromosome));
|
double bestEnerge = epaFunction.OptimizationFunction(list_bestresult);
|
|
|
|
|
//SetText(currentValueBox, bestEnerge.ToString());
|
List<double> pumpflows = null;
|
|
this.epaFunction.GetResult(list_bestresult, out modelOutputNodes, out modelOutputLinks, out pumpflows, false);
|
|
|
double sum = 0;
|
|
energe = bestEnerge;
|
|
sum /= list_bestresult.Length;
|
list_BestEnerge.Add(bestEnerge);
|
list_AvgHz.Add(sum);
|
list_BestHzs = list_bestresult.ToList();
|
|
|
|
num++;
|
if (iterations != 0 && num > iterations)
|
{
|
|
break;
|
}
|
|
}
|
}
|
|
public string InputInit(List<ModelInput> InputData, List<string> combine, out calcParms parms, double rangeMin = 0.8, double rangeMax = 1)
|
{
|
string result = null;
|
#region 初始判断
|
parms = null;
|
//string result = null;
|
int err = 0;
|
|
var doubleRange = new DoubleRange(rangeMin, rangeMax);
|
|
#endregion
|
|
|
|
err = SetTypeValue(InputData, ModelInput.eType.press_in);
|
if (err > 9) return ReportQuestion(err);
|
err = SetTypeValue(InputData, ModelInput.eType.flow);
|
if (err > 9) return ReportQuestion(err);
|
err = SetTypeValue(InputData, ModelInput.eType.level);
|
if (err > 9) return ReportQuestion(err);
|
err = SetTypeValue(InputData, ModelInput.eType.valve_initstatus);
|
if (err > 9) return ReportQuestion(err);
|
|
List<bool> list_isfrequence = new List<bool>();
|
combine.ForEach(ID => { bool isFre = InputData.Find(data => data.ObjectID == ID).Value == 1; list_isfrequence.Add(isFre); });
|
var pressOutPoit = InputData.FindAll((m) => m.Type == ModelInput.eType.press_out).Select(p => (double)p.Value).ToList();
|
var flowPointID = InputData.FindAll((m) => m.Type == ModelInput.eType.flow).Select(f => f.ObjectID).ToList();
|
List<int> flowPointIndex = new List<int>();
|
|
|
flowPointID.ForEach(FID =>
|
{
|
if (result != null) return;
|
int index = -1;
|
err = EpanetBase.ENgetnodeindex(FID, ref index);
|
flowPointIndex.Add(index);
|
if (err > 9) result = ReportQuestion(err);
|
});
|
if (result != null) return result;
|
|
parms = new calcParms
|
{
|
list_isfrequence = list_isfrequence,
|
flowPointIndex = flowPointIndex,
|
demandPress = pressOutPoit
|
|
};
|
#region 计算单泵的长度
|
|
var range = doubleRange;
|
|
double accuracy = 0.1;
|
var num_Total = range.Length / accuracy;
|
|
|
var LENGTH_PUMP = 0;
|
var value_LENGTH_PUMP = 1;
|
var i = 0;
|
while (value_LENGTH_PUMP < num_Total && i < 1000)
|
{
|
value_LENGTH_PUMP *= 2;
|
LENGTH_PUMP += 1;
|
i++;
|
}
|
|
#endregion
|
List<DoubleRange> drs = new List<DoubleRange>();
|
combine.ForEach(m => { drs.Add(range); });
|
|
epaFunction = new EPAFunctionGUI(drs.ToArray(), LENGTH_PUMP, parms, this, combine);
|
return null;
|
}
|
|
float accur = 0.1f;
|
// <summary>
|
/// 二分查找
|
/// </summary>
|
/// <param name="arr"></param>
|
/// <param name="low">开始索引 0</param>
|
/// <param name="high">结束索引 </param>
|
/// <param name="key">要查找的对象</param>
|
/// <returns></returns>
|
private float BinarySearch(List<string> combine, List<bool> list_isfrequence, int flowPointIndex, float lowHz, float highHz, float pressure)
|
{
|
|
string result = null;
|
float mid = (lowHz + highHz) / 2;
|
if (lowHz > highHz)
|
return -1;
|
else
|
{
|
if (highHz - lowHz <= accur)
|
{
|
|
return mid;
|
}
|
|
}
|
float press_out;
|
float energe;
|
result = getPressByPumps(combine, list_isfrequence, mid, flowPointIndex, out press_out, out energe);
|
if (result != null) return -1;
|
|
|
if (press_out > pressure)
|
return BinarySearch(combine, list_isfrequence, flowPointIndex, lowHz, mid, pressure);
|
else
|
return BinarySearch(combine, list_isfrequence, flowPointIndex, mid, highHz, pressure);
|
|
}
|
|
private string getPressByPumps(List<string> combine, List<bool> isfrequence, float Hz, int flowPointIndex, out float press, out float energe)
|
{
|
int err = 0;
|
|
#region 初始判断
|
|
press = 0;
|
energe = 99999999f;
|
string result = null;
|
#endregion
|
|
|
|
var PressNodeID = -1;
|
result = SetPumpValue(isfrequence, 0, combine);
|
if (result != null) return result;
|
|
result = SetPumpValue(isfrequence, ((float)Hz), combine);
|
if (result != null) return result;
|
|
|
|
//err = EpanetBase.ENsaveinpfile(@"D:\Desktop\C程序设计\项目源码\水力建模\eptools\out.inp");
|
|
float PressValue = -1;
|
int t = 0;
|
//err = EpanetBase.ENinitH(0);
|
//err = EpanetBase.ENrunH(ref t);
|
err = EpanetBase.ENsolveH();
|
if (err > 9) return ReportQuestion(err);
|
err = EpanetBase.ENgetnodevalue(flowPointIndex, EpanetBase.Const_class.Const_Node.EN_HEAD, ref PressValue);
|
if (err > 9) return ReportQuestion(err);
|
press = PressValue;
|
|
float TotalEnerge = 9999999999f;
|
|
result = GetTypeValue(EpanetBase.Const_class.Const_Link_types.EN_PUMP, 1, Method.Sum, out TotalEnerge, EpanetBase.Const_class.Const_Link.EN_ENERGY);
|
if (result != null) return result;
|
energe = TotalEnerge;
|
|
|
|
return result;
|
}
|
|
public string getPressByPumps(List<string> combine, List<bool> isfrequence, double[] list_Hz, List<int> flowPointIndex, out List<double> press, out double energe, out List<ModelOutputNode> modelOutputNodes, out List<ModelOutputLink> modelOutputLinks, out List<double> pumpflows, bool isNeedOutput = false, string path = null)
|
{
|
int err = 0;
|
|
#region 初始判断
|
modelOutputNodes = null;
|
modelOutputLinks = null;
|
pumpflows = null;
|
press = new List<double>();
|
|
energe = 99999999f;
|
string result = null;
|
#endregion
|
|
|
|
var PressNodeID = -1;
|
result = SetPumpValue(isfrequence, 0, combine);
|
if (result != null) return result;
|
|
result = SetPumpValue(isfrequence, list_Hz, combine);
|
if (result != null) return result;
|
|
|
|
//err = EpanetBase.ENsaveinpfile(@"D:\Desktop\C程序设计\项目源码\水力建模\eptools\out.inp");
|
|
List<float> PressValue = new List<float>();
|
int t = 0;
|
//err = EpanetBase.ENinitH(0);
|
//err = EpanetBase.ENrunH(ref t);
|
//path = @"D:\Desktop\C程序设计\项目源码\水力建模\eptools_v2\Debug\model\out.inp";
|
//EpanetBase.ENsaveinpfile(path);
|
err = EpanetBase.ENsolveH();
|
if (err > 9) return ReportQuestion(err);
|
if (result != null) return result;
|
|
|
var press0 = new List<double>();
|
flowPointIndex.ForEach(FIndex =>
|
{
|
if (result != null) return;
|
float PressValue0 = -1;
|
err = EpanetBase.ENgetnodevalue(FIndex, EpanetBase.Const_class.Const_Node.EN_HEAD, ref PressValue0);
|
press0.Add(PressValue0);
|
if (err > 9) result = ReportQuestion(err);
|
});
|
press = press0;
|
|
|
|
float TotalEnerge = 9999999999f;
|
|
result = GetTypeValue(EpanetBase.Const_class.Const_Link_types.EN_PUMP, 1, Method.Sum, out TotalEnerge, EpanetBase.Const_class.Const_Link.EN_ENERGY);
|
if (result != null) return result;
|
|
bool isCannotDeliver = false;
|
|
combine.ForEach(pump_id =>
|
{
|
if (isCannotDeliver) return;
|
int pumpindex = -1;
|
if ((err = EpanetBase.ENgetlinkindex(pump_id, ref pumpindex)) > 9) { result = ReportQuestion(err); return; }
|
float pumpstatus = -1;
|
if ((err = EpanetBase.ENgetlinkvalue(pumpindex, EpanetBase.Const_class.Const_Link.EN_STATUS, ref pumpstatus)) > 9) { result = ReportQuestion(err); return; }
|
float pumpFlow = -1;
|
err = EpanetBase.ENgetlinkvalue(pumpindex, EpanetBase.Const_class.Const_Link.EN_FLOW, ref pumpFlow);
|
if (pumpstatus == 0 || pumpFlow <= 50) isCannotDeliver = true;
|
});
|
if (isCannotDeliver) return null;
|
energe = TotalEnerge;
|
|
|
if (isNeedOutput)
|
{
|
var pf = new List<double>();
|
combine.ForEach(pump_id =>
|
{
|
|
int pumpindex = -1;
|
err = EpanetBase.ENgetlinkindex(pump_id, ref pumpindex); if (err > 9) ;
|
float pumpFlow = -1;
|
err = EpanetBase.ENgetlinkvalue(pumpindex, EpanetBase.Const_class.Const_Link.EN_FLOW, ref pumpFlow);
|
pf.Add(pumpFlow);
|
});
|
pumpflows = pf;
|
EpanetBase.ENsaveinpfile(path);
|
GetOutputString(out modelOutputNodes, out modelOutputLinks);
|
}
|
return result;
|
}
|
|
public string GetPumpList(out List<Pump> pumps)
|
{
|
#region 初始判断
|
|
//modelOutputLinks = null;
|
//modelOutputNodes = null;
|
string result = null;
|
int err = 0;
|
pumps = new List<Pump>();
|
if (!_isInitialSuccess)
|
return "初始化不成功";
|
//if (InputData == null)
|
// return "输入参数为空";
|
#endregion
|
|
|
|
#region 获取
|
|
int NLink1 = 0;
|
err = EpanetBase.ENgetcount(EpanetBase.Const_class.Const_Component.EN_NODECOUNT, ref NLink1);
|
if (err > 9) return ReportQuestion(err);
|
for (int i = 1; i <= NLink1; i++)
|
{
|
int type = -1;
|
err = EpanetBase.ENgetnodetype(i, ref type);
|
if (err > 9) return ReportQuestion(err);
|
if (type == EpanetBase.Const_class.Const_Link_types.EN_PUMP)
|
{
|
Pump pump = new Pump();
|
|
err = EpanetBase.ENgetlinkvalue(i, EpanetBase.Const_class.Const_Link.EN_STATUS, ref pump.value);
|
if (err > 9) return ReportQuestion(err);
|
|
StringBuilder s = new StringBuilder();
|
err = EpanetBase.ENgetlinkid(i, s);
|
pump.ID = s.ToString();
|
if (err > 9) return ReportQuestion(err);
|
|
pump.index = i;
|
|
pumps.Add(pump);
|
|
}
|
}
|
|
|
|
|
return null;
|
|
|
|
|
|
#endregion
|
}
|
}
|
public class Pump
|
{
|
public string ID = null;
|
public int index;
|
public float value;
|
|
}
|
public class calcParms
|
{
|
public List<bool> list_isfrequence = null;
|
public List<int> flowPointIndex = null;
|
public List<double> demandPress = null;
|
}
|
public class ResultCombine
|
{
|
public double[] arrayHz ;
|
public double totalEnerge;
|
}
|
#endregion
|
|
}
|
|
|