duheng
2025-03-18 7ee0220b5f5626deef516b6e5c417bfa201e5a88
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// 创建一个 Stopwatch 实例 
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Text;
 
 
Console.WriteLine("开始模拟...");
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
 
var file_path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "1897563622226399232.inp");
 
var pressure = 0d;
var minDemand = 50.0;   // 最小总需水量(m³/h)
var maxDemand = 500.0;  // 最大总需水量(m³/h)
var calcCount = 20000;           // 计算次数
 
 
var list = new List<SimulationResult>(calcCount);
using (var helper = new Yw.Epanet.InteropXHelper())
{
    var err = helper.Open(file_path, "", "");
    err = helper.GetCount(Yw.Epanet.eCountType.Node, out int nodeCount);
    err = helper.OpenH();
 
    var allDemands = GenerateDemandMatrix(minDemand, maxDemand, nodeCount, calcCount);
    for (int i = 0; i < calcCount; i++)
    {
        helper.InitH(false);
        var demands = allDemands[i];
        for (int nodeIdx = 1; nodeIdx <= nodeCount; nodeIdx++)
        {
            double demand = demands[nodeIdx - 1];
            err = helper.SetNodeValue(nodeIdx, Yw.Epanet.eNodeProperty.BaseDemand, demand);
        }
 
        helper.RunH(out long t);
 
        var result = new SimulationResult();
        for (int nodeIdx = 1; nodeIdx <= nodeCount; nodeIdx++)
        {
            pressure = 0;
            helper.GetNodeValue(nodeIdx, Yw.Epanet.eNodeProperty.Pressure, out pressure);
            result.UpdateMaxPressure(nodeIdx, pressure);
        }
        helper.NextH(out long tstep);
        list.Add(result);
    }
 
 
    helper.Close();
 
}
 
 
 
stopwatch.Stop();
 
Console.WriteLine("所有模拟已完成。");
Console.WriteLine($"总时间:{stopwatch.Elapsed.TotalSeconds}");
 
var strBuild = new StringBuilder();
foreach (var item in list)
{
    var pressureList = item.MaxPressures.Values.ToList();
    strBuild.AppendLine($"{pressureList.Min()},{pressureList.Max()}");
}
 
Console.WriteLine(strBuild.ToString());
Console.ReadLine();
Console.ReadKey();
 
 
 
/// <summary>
/// 生成需水量矩阵(基于遗传算法的随机分配策略[2](@ref))
/// </summary>
double[][] GenerateDemandMatrix(double minDemand, double maxDemand, int nodeCount, int totalSteps)
{
    var demandMatrix = new double[totalSteps][];
    double stepSize = (maxDemand - minDemand) / (totalSteps - 1);
    var rand = new Random();
    for (int step = 0; step < totalSteps; step++)
    {
        double totalDemand = minDemand + step * stepSize;
        demandMatrix[step] = GenerateRandomDemands(rand, nodeCount, totalDemand);
    }
    return demandMatrix;
}
 
/// <summary>
/// 随机分配总需水量到各节点(符合案例中的用水量分配逻辑[1](@ref))
/// </summary>
double[] GenerateRandomDemands(Random rand, int nodeCount, double totalDemand)
{
    double[] demands = new double[nodeCount];
    double remaining = totalDemand;
 
    // 加权随机分配算法
    for (int i = 0; i < nodeCount - 1; i++)
    {
        double maxPossible = remaining / (nodeCount - i);
        demands[i] = rand.NextDouble() * maxPossible;
        remaining -= demands[i];
    }
    demands[nodeCount - 1] = remaining;  // 确保总和准确 
    return demands;
}
 
double[,] GenerateAllDemands(int nodeCount, int totalIterations, double[] weValues)
{
 
    double[,] demands = new double[totalIterations, nodeCount];
    Parallel.For(0, totalIterations, iter =>
    {
        var rand = new Random();
        for (int node = 0; node < nodeCount; node++)
        {
            // 遗传算法式选择
            int idx = rand.Next(weValues.Length);
 
            // 20%概率变异
            if (rand.NextDouble() < 0.2)
                idx = (idx + 1) % weValues.Length;
            demands[iter, node] = weValues[idx];
        }
    });
    return demands;
}
 
public class SimulationResult
{
    public ConcurrentDictionary<int, double> MaxPressures { get; } = new();
 
    public void UpdateMaxPressure(int nodeId, double pressure)
    {
        MaxPressures.AddOrUpdate(nodeId, pressure,
            (id, old) => Math.Max(old, pressure));
    }
}