-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathWaterVolumeChangeDA.cs
209 lines (189 loc) · 7.66 KB
/
WaterVolumeChangeDA.cs
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
using System;
using System.Collections.Generic;
using DHI.Generic.MikeZero;
using DHI.Mike1D.Engine;
using DHI.Mike1D.Engine.ModuleData;
using DHI.Mike1D.Engine.ModuleHD;
using DHI.Mike1D.Generic;
using DHI.Mike1D.Mike1DDataAccess;
using DHI.Mike1D.Plugins;
using DHI.Mike1D.ResultDataAccess;
namespace DHI.Mike1D.Examples.Scripts
{
public class WaterVolumeChangeDA
{
private Mike1DController _mike1dController;
private EngineNet _engineNet;
private DAWaterVolumeChangeCalculator _daWaterVolumeChangeCalculator;
/// <summary>
/// Calculate volume change due to DA and save to result file
/// </summary>
[Script]
public void Initialize(IMike1DController controller)
{
controller.ControllerEvent += ControllerOnControllerEvent;
}
private void ControllerOnControllerEvent(object sender, ControllerEventArgs e)
{
if (e.State == ControllerState.Initialized)
{
_mike1dController = (Mike1DController)sender;
_mike1dController.Mike1DData.ResultSpecifications[0].WhatAddUnique(DAWaterVolumeChangeCalculator.QuantVolChangeDa);
_mike1dController.Mike1DData.ResultSpecifications[0].WhatAddUnique(DAWaterVolumeChangeCalculator.QuantAccVolChangeDA);
}
if (e.State == ControllerState.Preparing)
{
_engineNet = _mike1dController.EngineNet;
CreateVolCalculator(_engineNet);
_engineNet.EvaluateHDImplicitSourcesEvent += PostHDTimeStepEvent;
}
if (e.State == ControllerState.Finalizing)
{
string totalAddedWater = _daWaterVolumeChangeCalculator.GetAccumulatedAddedVolume().ToString();
_mike1dController.DiagnosticsHandler.NewMessage(DiagnosticsHandler.MessageType.Info, "DA - Total added water volume: "+ totalAddedWater+" m3");
}
}
private void PostHDTimeStepEvent()
{
_daWaterVolumeChangeCalculator.UpdatePostHDValues();
}
public void CreateVolCalculator(EngineNet engineNet)
{
_daWaterVolumeChangeCalculator = DAWaterVolumeChangeCalculator.Create(engineNet);
engineNet.DataModule.AddDataItem(_daWaterVolumeChangeCalculator);
}
}
/// <summary>
/// Helper class to calculate the change of volume of water in a timestep in the network
/// </summary>
public class DAWaterVolumeChangeCalculator : EngineDataItemAllArray<double>
{
private HDModule _hdModule;
EngineDataItemAll<double> _volPostHd;
EngineDataItemAll<double> _volAccumulated;
public static Quantity QuantVolChangeDa = new Quantity("WaterVolumeChangeDA", "DA - Water volume change", eumItem.eumIVolume);
public static Quantity QuantAccVolChangeDA = new Quantity(
"WaterVolumeAccumulatedChangeDA", "DA - Accumulated water volume change", eumItem.eumIVolume);
internal DAWaterVolumeChangeCalculator(EngineNet engineNet, IQuantity quantity)
: base(engineNet, quantity)
{
_hdModule = engineNet.HDModule;
_volPostHd = new EngineDataItemAll<double>(engineNet, new Quantity());
_volPostHd.SetupDataForNodes(engineNet);
_volPostHd.SetupDataForReaches(engineNet, (gp) => (gp is HGridPoint));
_volPostHd.GenericData = new EngineDataGeneric<double>() { Values = new double[1] };
_volAccumulated = new EngineDataItemAll<double>(engineNet, QuantAccVolChangeDA);
_volAccumulated.SetupDataForNodes(engineNet);
_volAccumulated.SetupDataForReaches(engineNet, (gp) => (gp is HGridPoint));
_volAccumulated.GenericData = new EngineDataGeneric<double>() { Values = new double[1] };
engineNet.DataModule.AddDataItem(_volAccumulated);
}
///<summary>
/// Create helper class for calculating total inflow to a reach
///</summary>
///<param name="engineNet"></param>
public static DAWaterVolumeChangeCalculator Create(EngineNet engineNet)
{
DAWaterVolumeChangeCalculator res = new DAWaterVolumeChangeCalculator(engineNet, QuantVolChangeDa);
res.SetupDataForNodes(engineNet);
res.SetupDataForReaches(engineNet, (gp) => (gp is HGridPoint));
res.GenericData = new EngineDataGeneric<double>() { Values = new double[1] };
return res;
}
public double GetAccumulatedAddedVolume()
{
return System.Math.Round(_volAccumulated.GenericData[0],1);
}
public void UpdatePostHDValues()
{
{
double sum = 0;
EngineNet engineNet = _engineNet;
for (int i = 0; i < engineNet.Nodes.Count; i++)
{
//if (NodesData[i] == null) continue;
var engineNodeSewer = engineNet.Nodes[i] as EngineNodeVolume;
if (engineNodeSewer == null) continue;
IHDNode hdNode = _hdModule.GetNode(engineNodeSewer);
if (hdNode == null) continue;
double volume = engineNodeSewer.GetVolume(hdNode.WaterLevelNp1);
_volPostHd.NodesData[i].Value = volume;
sum += volume;
}
for (int i = 0; i < engineNet.Reaches.Count; i++)
{
IEngineDataReach<double> reachData = _volPostHd.ReachesData[i];
if (reachData == null) continue;
IHDReach hdReach = _hdModule.GetReach(engineNet.Reaches[i]);
if (hdReach == null) continue;
for (int j = 0; j < reachData.IndexList.Length; j++)
{
int jgp = reachData.IndexList[j];
IHDHGridPoint hgp = hdReach.GridPoints[jgp] as IHDHGridPoint;
if (hgp == null)
reachData[j] = 0;
else
{
reachData[j] = hgp.WaterVolumeNp1;
sum += hgp.WaterLevelNp1;
}
}
}
// Store total
GenericData[0] = sum;
}
}
/// <inheritdoc />
public override void UpdateValues()
{
// if pull version, values are extracted when requested, and no action is required here.
// If not pull, this needs to update the data and store it.
{
double sum = 0;
EngineNet engineNet = _engineNet;
for (int i = 0; i < engineNet.Nodes.Count; i++)
{
//if (NodesData[i] == null) continue;
var engineNodeSewer = engineNet.Nodes[i] as EngineNodeVolume;
if (engineNodeSewer == null) continue;
IHDNode hdNode = _hdModule.GetNode(engineNodeSewer);
if (hdNode == null) continue;
double volumeN = _volPostHd.NodesData[i].Value;
double volumeNp1 = engineNodeSewer.GetVolume(hdNode.WaterLevelNp1);
double volumechange = volumeNp1 - volumeN;
sum += volumechange;
NodesData[i] = volumechange;
_volAccumulated.NodesData[i].Value += volumechange;
}
for (int i = 0; i < engineNet.Reaches.Count; i++)
{
IEngineDataReach<double> reachDataPostHD = _volPostHd.ReachesData[i];
IEngineDataReach<double> reachDataAcc = _volAccumulated.ReachesData[i];
IEngineDataReach<double> reachData = ReachesData[i];
if (reachData == null) continue;
IHDReach hdReach = _hdModule.GetReach(engineNet.Reaches[i]);
if (hdReach == null) continue;
for (int j = 0; j < reachData.IndexList.Length; j++)
{
int jgp = reachData.IndexList[j];
IHDHGridPoint hgp = hdReach.GridPoints[jgp] as IHDHGridPoint;
if (hgp == null)
reachData[j] = 0;
else
{
double volumeN = reachDataPostHD[j];
double volumeNp1 = hgp.WaterVolumeNp1;
double volumeChange = volumeNp1 - volumeN;
sum += volumeChange;
reachData[j] = volumeChange;
reachDataAcc[j] += volumeChange;
}
}
}
// Store total
GenericData[0] = sum;
_volAccumulated.GenericData[0] += sum;
}
}
}
}