ningshuxia
2025-03-31 d321346f204a69b1929cc39098a5d88f44509e7b
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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
using IStation.Epanet.Enums;
using System.Runtime.InteropServices;
using System.Text;
 
namespace IStation.Epanet
{
    /// <summary>
    ///     IStation.Epanet 程序员工具包(EPANET2.2.DLL)中的函数声明。
    ///     这些是构成 DLL 的外部函数。
    /// </summary> 
    public class EpanetMethods
    {
        /// <summary>文件名称 ("epanet2.2.dll").</summary>
        private const string EPANETDLL = "epanet2.2.dll";
 
        /// <summary>Epanet dll 调用约定</summary>
        private const CallingConvention CONVENTION = CallingConvention.StdCall;
 
        /// <summary>Epanet dll 方法的字符串字符集</summary>
        private const CharSet CHARSET = CharSet.Ansi;
 
        /// <summary>Epanet dll 的字符串类型</summary>
        private const UnmanagedType STRING = UnmanagedType.LPStr;
 
        // private const int MAXFNAME = 259;
 
        /// <summary>Epanet dll id 字符串(Node.Id、Link.Id 等)的最大字符数</summary>
        public const int MAXID = 31;
 
        /// <summary>Epanet dll 错误字符串的最大字符数,*.inp 文件中的行数。</summary>
        public const int MAXMSG = 79;
 
        /// <summary>Delegate for <see cref="ENepanet" /> progress callback.</summary>
        /// <param name="message">从 IStation.Epanet dll 传递的状态信息。</param>
        [UnmanagedFunctionPointer(CONVENTION)]
        public delegate void ViewProgCallback([MarshalAs(STRING)] string message);
 
        #region 打开和关闭 IStation.Epanet 系统的功能
 
        /// <summary>执行完整的EPANETH模拟</summary>
        /// <param name="f1">输入文件名</param>
        /// <param name="f2">输出报告文件名</param>
        /// <param name="f3">可选二进制输出文件名</param>
        /// <param name="pviewprog">
        ///     Pointer to a user-supplied function (<see cref="ViewProgCallback" />) which accepts
        ///     a character string as its argument; see note below.
        /// </param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///         The <paramref name="pviewprog" /> argument is a pointer to a callback
        ///         function that takes a character string (char *) as its only parameter.
        ///         The function would reside in and be used by the calling
        ///         program to display the progress messages that IStation.Epanet generates
        ///         as it carries out its computations. If this feature is not
        ///         needed then the argument should be <c>null</c>.
        ///     </para>
        ///     <para>
        ///         ENepanet is a stand-alone function and does not interact with
        ///         any of the other functions in the toolkit.
        ///     </para>
        ///     <para>
        ///         If there is no need to save IStation.Epanet's binary output file
        ///         then <paramref name="f3" /> can be an empty string ("").
        ///     </para>
        ///     <para>
        ///         The vfunc function pointer allows the calling program
        ///         to display a progress message generated by IStation.Epanet during its
        ///         computations.
        ///     </para>
        ///     <example>
        ///         A typical function for a console application might look as follows:
        ///         <code>
        ///     static void  WriteConsole(string s)  {  
        ///         System.Console.WriteLine(s);  
        ///     }  
        /// </code>
        ///         and somewhere in the calling program the following declarations would appear:
        ///         <code>
        ///     Pviewprog vfunc = WriteConsole;
        ///     ENepanet(f1, f2, f3, vfunc);
        /// </code>
        ///         If such a function is not desired then this argument should be null.
        ///     </example>
        ///     <para>
        ///         <see cref="ENepanet" /> is used mainly to link the IStation.Epanet engine to third-party
        ///         user interfaces that build network input files and display the results of a
        ///         network analysis.
        ///     </para>
        /// </remarks>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true, CharSet = CHARSET,
            BestFitMapping = false, ThrowOnUnmappableChar = true)]
        public static extern ErrorCode ENepanet(
            [MarshalAs(STRING)] string f1,
            [MarshalAs(STRING)] string f2,
            [MarshalAs(STRING), Optional, DefaultParameterValue("")] string f3,
            [Optional, DefaultParameterValue(null)] ViewProgCallback pviewprog);
 
        /// <summary>打开工具箱,为了分析特定配水系统</summary>
        /// <param name="f1">输入文件名 </param>
        /// <param name="f2">输出报告文件名</param>
        /// <param name="f3">可选二进制输出文件名</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     If there is no need to save IStation.Epanet's binary Output file
        ///     then <paramref name="f3" /> can be an empty string ("").
        ///     <see cref="ENopen" /> must be called before any of the other
        ///     toolkit functions (except <see cref="ENepanet" />) are used.
        /// </remarks>
        /// <seealso cref="ENclose" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true, CharSet = CHARSET,
            BestFitMapping = false, ThrowOnUnmappableChar = true), PreserveSig]
        public static extern ErrorCode ENopen(
            [MarshalAs(STRING)] string f1,
            [MarshalAs(STRING)] string f2,
            [MarshalAs(STRING), Optional, DefaultParameterValue("")] string f3);
 
        /// <summary>将所有当前管网输入数据写入到文件,利用EPANETH输入文件的格式</summary>
        /// <param name="filename">数据保存的文件名</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     The data saved reflect any changes made by calls to
        ///     the <c>ENsetxxx</c> family of functions since IStation.Epanet
        ///     data was first loaded using <see cref="ENopen" />.
        /// </remarks>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true, CharSet = CHARSET,
            BestFitMapping = false, ThrowOnUnmappableChar = true)]
        public static extern ErrorCode ENsaveinpfile([MarshalAs(STRING)] string filename);
 
        /// <summary>关闭工具箱系统(包括所有正在处理的文件)</summary>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <see cref="ENclose" /> must be called when all processing has been completed,
        ///     even if an error condition was encountered.
        /// </remarks>
        /// <seealso cref="ENopen" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENclose();
 
        #endregion
 
        #region 运行水力分析的功能
 
        /// <summary>
        ///    执行一次完整的水力模拟,所有时段的结果写入二进制水力文件 
        /// </summary>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     利用<see cref="ENsolveH" />产生独立完整的水力结果,或者作为水质分析的输入。为了将水力结果写入
        ///     报告文件,其后也调入到<see cref="ENsaveH" />和<see cref="ENreport" />。 
        ///     不要使用 <see cref="ENopenH" />, <see cref="ENinitH" />, <see cref="ENrunH" />, <see cref="ENnextH" />, 和 <see cref="ENcloseH" />
        ///     连接到<see cref="ENsolveH" />。
        /// </remarks>
        /// <example>
        ///     <code>
        ///     ENopen("net1.inp", "net1.rpt", "");
        ///     ENsolveH();
        ///     ENsolveQ();
        ///     ENreport();
        ///     ENclose(); 
        /// </code>
        /// </example>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENsolveH();
 
        /// <summary>
        ///     将水力模拟结果从二进制水力文件转换到二进制输出文件,其中结果仅仅以均匀时间间隔进行报告
        /// </summary>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///         <see cref="ENsaveH" />仅在水力分析后执行,并在均匀报告间隔的结果需要转换为EPANETH的二进制
        ///         输出文件时使用。这种情况,利用<see cref="ENreport" />将输出报告写入EPANETH报告文件。
        ///     </para>
        ///     <para>
        ///         在EPANETH输入文件([TIMES]节)或者通过利用<see cref="ENsettimeparam" />函数,可以设置报告时间。
        ///     </para>
        /// </remarks>
        /// <seealso cref="ENreport" />
        /// <seealso cref="ENsettimeparam" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENsaveH();
 
        /// <summary>打开水力分析系统</summary>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>  
        ///         在第一次执行水力分析之前调用<see cref="ENopenH" />,
        ///         利用<see cref="ENinitH" /> - <see cref="ENrunH" /> - <see cref="ENnextH" />系列。
        ///         在调用<see cref="ENcloseH" />,以关闭水力分析系统之前,可以进行多次分析。 
        ///     </para>
        ///     <para>
        ///         如果<see cref="ENsolveH" />用于运行完整的水力分析,不要调用该函数。
        ///     </para>
        /// </remarks>
        /// <seealso cref="ENinitH" />
        /// <seealso cref="ENrunH" />
        /// <seealso cref="ENnextH" />
        /// <seealso cref="ENcloseH" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENopenH();
 
        /// <summary>在执行水力分析之前,初始化蓄水池水位、管段状态和设置,以及模拟钟表时间</summary>
        /// <param name="saveflag">
        ///     0-1标志,说明水力结果是否保存到水力文件
        /// </param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///         利用<see cref="ENrunH" />和<see cref="ENnextH" />.执行水力分析之前,应调用<see cref="ENinitH"/>。
        ///         调用<see cref="ENinitH" />之前,必须已经调用<see cref="ENopenH" />。
        ///         如果整个水力分析调用了<see cref="ENsolveH" />,将不再调用<see cref="ENinitH" />。
        ///     </para>
        ///     <para> 
        ///         如果将进行随后的水质运行,saveflag 设置为1,利用<see cref="ENreport" />产生报告,
        ///         或者利用<see cref="ENsavehydfile" />保存二进制水力文件。  
        ///     </para>
        /// </remarks>
        /// <seealso cref="ENopenH" />
        /// <seealso cref="ENrunH" />
        /// <seealso cref="ENnextH" />
        /// <seealso cref="ENcloseH" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENinitH(int saveflag);
 
        /// <summary>执行简单时段水力分析,检索当前模拟钟表时间<paramref name="t" /></summary>
        /// <param name="t">
        ///     当前模拟钟表时间,以秒计 (no need to supply a value for <paramref name="t" />).
        /// </param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///     利用<see cref="ENrunH" />结合<see cref="ENnextH" />在do ..while循环中,为了分析延时模拟中每一时段的水力特性。
        ///     该过程自动更新模拟钟表时间,因此将t处理为只读变量。
        ///     </para>
        ///     <para>
        ///     在执行<see cref="ENrunH" /> – <see cref="ENnextH" />循环以前,必须调用<see cref="ENinitH" />。
        ///     对于该函数使用的例子,参见<see cref="ENnextH" />。
        ///     </para>
        /// </remarks>
        /// <seealso cref="ENopenH" />
        /// <seealso cref="ENinitH" />
        /// <seealso cref="ENnextH" />
        /// <seealso cref="ENcloseH" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENrunH(out int t);
 
        /// <summary>
        ///     确定延时模拟下一次水力时间发生前的时间长度
        /// </summary>
        /// <param name="tstep">
        ///     时间(以秒计),直到下一次水力时间发生;或者为0,如果在模拟时段的末端。
        /// </param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///     该函数与<see cref="ENrunH" />一起使用,执行延时水力分析(见以下例子)
        ///     </para>
        ///     <para>
        ///     tstep的数值,应处理为只读变量。作为以下较小值自动计算:
        ///         <list type="bullet">
        ///             <item>时间间隔,直到下一水力时间步长开始;</item>
        ///             <item>时间间隔,直到下一报告时间步长开始;</item>
        ///             <item>时间间隔,直到下一需水量发生改变开始;</item>
        ///             <item>时间间隔,直到水池注满或者排空;</item>
        ///             <item>时间间隔,直到规则控制停止;</item>
        ///         </list>
        ///     </para>
        /// </remarks>
        /// <example>
        ///     <code>
        ///     int t, tstep;
        ///     
        ///     ENopenH();
        ///     ENinitH(0);
        ///     
        ///     do {
        ///         ENrunH(out t);
        ///         /* Retrieve hydraulic results for time t */
        ///         ENnextH(out tstep);
        ///     } while (tstep > 0);
        ///     
        ///     ENcloseH(); 
        /// </code>
        /// </example>
        /// <seealso cref="ENopenH" />
        /// <seealso cref="ENinitH" />
        /// <seealso cref="ENrunH" />
        /// <seealso cref="ENcloseH" />
        /// <seealso cref="ENsettimeparam" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENnextH(out int tstep);
 
        /// <summary>关闭水力分析系统,释放所有分配内存</summary>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     在利用<see cref="ENinitH" /> - <see cref="ENrunH" /> - <see cref="ENnextH" />执行所有水力分析之后,调用<see cref="ENcloseH" />。
        ///     如果使用 <see cref="ENsolveH" />,不要调用该函数。
        /// </remarks>
        /// <seealso cref="ENopenH" />
        /// <seealso cref="ENinitH" />
        /// <seealso cref="ENrunH" />
        /// <seealso cref="ENnextH" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENcloseH();
 
        /// <summary>将当前二进制水力文件的内容保存到一个文件</summary>
        /// <param name="fileName">水力结果应被保存的文件名</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///         将该函数用于将当前水力结果集保存到一个文件,便于后处理或者以后时间使用,通过调用<see cref="ENusehydfile" />函数 
        ///     </para>
        ///     <para>
        ///         水力文件包含了节点需水量和水头,以及管段流量,状态和设置,对于所有水力时间步长,甚至中间数值。 
        ///     </para>
        ///     <para>
        ///     调用该函数之前,水力结果必须产生和保存,通过调用<see cref="ENsolveH" />
        ///     或者<see cref="ENinitH" /> - <see cref="ENrunH" /> -  <see cref="ENnextH" />序列,
        ///     具有<see cref="ENinitH" />的保存标志参数设置为1(true)。
        ///     </para>
        /// </remarks>
        /// <seealso cref="ENusehydfile" />
        /// <seealso cref="ENsolveH" />
        /// <seealso cref="ENinitH" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true, CharSet = CHARSET,
            BestFitMapping = false, ThrowOnUnmappableChar = true)]
        public static extern ErrorCode ENsavehydfile([MarshalAs(STRING)] string fileName);
 
        /// <summary>将指定文件的内容作为当前二进制水力文件</summary>
        /// <param name="fileName">含了当前管网水力分析结果的文件名</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///         调用该函数,拒绝原先保存的水力分析结果集。
        ///         这些结果被检查,为了查看是否它们匹配一下参数,相关于当前被分析的管网:节点总数、水池和水库总数、管段总数、水泵总数、阀门总数和模拟历时。
        ///     </para>
        ///     <para>
        ///         当水力分析系统仍旧开启时,不能够调用该函数(即<see cref="ENopenH" />已经被调用,但是 <see cref="ENcloseH" /> 还没有)。 
        ///     </para>
        /// </remarks>
        /// <seealso cref="ENsavehydfile" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true, CharSet = CHARSET,
            BestFitMapping = false, ThrowOnUnmappableChar = true)]
        public static extern ErrorCode ENusehydfile([MarshalAs(STRING)] string fileName);
 
        #endregion
 
        #region 运行水质分析的功能
 
        /// <summary>
        ///     执行完整的水质模拟,结果具有均匀报告间隔,写入EPANETH二进制输出文件
        /// </summary>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        /// 在调用<see cref="ENsolveQ">之前,必须已经执行水力分析,并保存到二进制水力文件。
        /// 为了将水力和水质结果写入报告文件,后面跟着调用<see cref="ENreport" />。
        /// 不能够将<see cref="ENopenQ" />, <see cref="ENinitQ" />, <see cref="ENrunQ" />, <see cref="ENnextQ" />和<see cref="ENcloseQ" />,与<see cref="ENsolveQ" />一起使用。 
        /// </remarks>
        /// <example>
        ///     <code>
        ///     ENopen("net1.inp", "net1.rpt", "");  
        ///     ENsolveH();  
        ///     ENsolveQ();  
        ///     ENreport();  
        ///     ENclose();    
        /// </code>
        /// </example>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENsolveQ();
 
        /// <summary>打开水质分析系统</summary>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///     调用<see cref="ENopenQ" />之前,首先执行水质分析,依次利用<see cref="ENinitQ" /> - <see cref="ENrunQ" /> - <see cref="ENnextQ" />(or <see cref="ENstepQ" />)。
        ///     为了关闭水质分析系统调用<see cref="ENcloseQ" />之前,可以进行多重水质分析。  
        ///     <para>
        ///         如果利用<see cref="ENsolveQ" />进行完整水质分析,不要调用该函数。
        ///     </para>
        /// </remarks>
        /// <seealso cref="ENinitQ" />
        /// <seealso cref="ENrunQ" />
        /// <seealso cref="ENnextQ" />
        /// <seealso cref="ENstepQ" />
        /// <seealso cref="ENcloseQ" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENopenQ();
 
        /// <summary>在执行水质分析之前,初始化水质和模拟钟表时间</summary>
        /// <param name="saveFlag">
        ///     0-1标志,说明分析结果是否以均匀报告时段保存到EPANETH二进制输出文件。
        /// </param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///         在利用<see cref="ENrunQ" />联合<see cref="ENnextQ" />或者<see cref="ENstepQ" />执行水质分析之前,调用<see cref="ENinitQ" />。
        ///     </para>
        ///     <para>
        ///         必须在调用<see cref="ENinitQ" />之前调用<see cref="ENopenQ" />。 
        ///         如果调用<see cref="ENsolveQ" />执行完整水质分析,不需调用<see cref="ENinitQ" />。
        ///     </para>
        ///     <para>
        ///         如果希望利用<see cref="ENreport" />产生报告,或者希望将计算结果保存为二进制输出文件,设置 saveflag为1。
        ///     </para>
        /// </remarks>
        /// <seealso cref="ENopenQ" />
        /// <seealso cref="ENrunQ" />
        /// <seealso cref="ENnextQ" />
        /// <seealso cref="ENstepQ" />
        /// <seealso cref="ENcloseQ" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENinitQ(int saveFlag);
 
        /// <summary>
        ///     在下一时段水质分析的开始,使水力和水质分析结果可用,其中时段的开始返回为<paramref name="t" />.
        /// </summary>
        /// <param name="t">
        ///    当前模拟钟表时间,以秒计 (no need to supply a value for <paramref name="t" />).
        /// </param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///         在do...while循环中利用<see cref="ENrunQ" />和<see cref="ENnextQ" />,为了访问延时模拟每一水力时段开始时的水质结果。
        ///         或者在do...while循环中将它与<see cref="ENstepQ" />一起使用,为了访问每一水质时间步长开始时的结果。
        ///         怎样编制这种循环的例子,参见每一函数说明。
        ///     </para>
        ///     <para>
        ///         在执行<see cref="ENrunQ" /> - <see cref="ENnextQ" /> (or <see cref="ENstepQ" />)循环之前,必须调用<see cref="ENinitQ" />。
        ///     </para>
        ///     <para>
        ///         模拟的当前时刻<paramref name="t" />由保存在水力分析中的信息确定,然后进行水质分析。它为只读变量。  
        ///     </para>
        /// </remarks>
        /// <seealso cref="ENopenQ" />
        /// <seealso cref="ENinitQ" />
        /// <seealso cref="ENnextQ" />
        /// <seealso cref="ENstepQ" />
        /// <seealso cref="ENcloseQ" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENrunQ(out int t);
 
        /// <summary>水质模拟前进到下一水力时段的开始</summary>
        /// <param name="tstep">
        ///     时刻(以秒计),直到下一水力事件发生;或者为零,如果在模拟时段的末端
        /// </param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///     该函数用在<c>do...while</c>循环中,利用<see cref="ENrunQ" />执行延时水质分析。
        ///     允许在模拟的每一水力时段访问水质结果。
        ///     水质演算和反应以更小的时间步长,在内部执行。
        ///     利用<see cref="ENstepQ" />代替该函数,如果需要访问每一水质事件步长后的结果。 
        ///     </para>
        ///     <para> 
        ///     <paramref name="tstep" />的值是根据水质分析之前的水力分析所保存的信息确定的。将其视为只读变量。 
        ///     </para>
        /// </remarks>
        /// <example>
        ///     <code>
        ///     int t, tstep;
        ///     ENsolveH(); /* Generate and save hydraulics */
        ///     ENopenQ();
        ///     ENinitQ(false);
        ///     
        ///     do {
        ///         ENrunQ(out t);
        ///         /* Monitor results at time t, which   */
        ///         /* begins a new hydraulic time period */
        ///         ENnextQ(out tstep);
        ///     } while (tstep > 0);
        /// 
        ///     ENcloseQ();              
        /// </code>
        /// </example>
        /// <seealso cref="ENopenQ" />
        /// <seealso cref="ENinitQ" />
        /// <seealso cref="ENrunQ" />
        /// <seealso cref="ENcloseQ" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENnextQ(out int tstep);
 
        /// <summary>
        ///    水质模拟前进一个水质时间步长。保留整个模拟中的时间范围在<paramref name="tleft" />中
        /// </summary>
        /// <param name="tleft">保留在整个模拟历时中的秒。 机翻:总模拟时间的剩余秒数</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///         该函数用在<see cref="ENrunQ" />的<c>do...while</c>循环中,执行延时水质模拟。
        ///         允许访问模拟每一水质时间步长的水质结果,而不是像<see cref="ENnextQ" />的每一水力时段的开始。
        ///     </para>
        ///     <para>
        ///         使用参数<paramref name="tleft" />,确定何时不再需要调用<see cref="ENrunQ" />,因为达到模拟时段的末尾(即当tleft = 0 时)。  
        ///     </para>
        ///     <para>
        ///         将 <paramref name="tleft" />处理为只读变量(不需要赋值)。  
        ///     </para>
        /// </remarks>
        /// <example>
        ///     <code>
        ///     int t, tleft;
        ///     
        ///     ENsolveH(); /* Generate &amp; save hydraulics */
        ///     ENopenQ();
        ///     ENinitQ(false);
        ///     
        ///     do {
        ///         ENrunQ(out t);
        ///         /* Monitor results at time t */
        ///         ENstepQ(out tleft);
        ///     } while (tleft > 0);
        /// 
        ///     ENcloseQ(); 
        /// </code>
        /// </example>
        /// <seealso cref="ENopenQ" />
        /// <seealso cref="ENinitQ" />
        /// <seealso cref="ENrunQ" />
        /// <seealso cref="ENcloseQ" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENstepQ(out int tleft);
 
        /// <summary>关闭水质分析系统,释放所有分配的内存</summary>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///      在利用<see cref="ENinitQ" /> - <see cref="ENrunQ" /> - <see cref="ENnextQ" />
        ///     (or <see cref="ENstepQ" />) 系列函数调用执行所有水质分析之后,调用<see cref="ENcloseQ" />。
        ///     如果使用了<see cref="ENsolveQ" />,将不需要调用该函数。
        /// </remarks>
        /// <seealso cref="ENopenQ" />
        /// <seealso cref="ENinitQ" />
        /// <seealso cref="ENrunQ" />
        /// <seealso cref="ENstepQ" />
        /// <seealso cref="ENnextQ" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENcloseQ();
 
        #endregion
 
        #region 生成输出报告的功能
 
        /// <summary>将一行文本写入报告文件</summary>
        /// <param name="line">文本</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true, CharSet = CHARSET,
            BestFitMapping = false, ThrowOnUnmappableChar = true)]
        public static extern ErrorCode ENwriteline([MarshalAs(STRING)] string line);
 
        /// <summary>将模拟结果的格式化文本报告写入到报告文件</summary>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///         调用<see cref="ENreport" />之前,必须已经进行了完整的水力分析或者完整的水力水质分析,结果保存在文件中。
        ///         在前者情况中,也必须首先调用<see cref="ENsaveH" />,为了将结果从水力文件转换到输出文件。 
        ///     </para>
        ///     <para> 
        ///         报告的格式受到EPANETH输入文件[REPORT]节的命令所控制,或者通过与<see cref="ENsetreport" /> 函数一起公布的类似命令。 
        ///     </para>
        /// </remarks>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENreport();
 
        /// <summary>将报告选项重置为默认值</summary>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///         清除任何出现在EPANETH输入文件[REPORT]节中的报告格式命令,或者利用<see cref="ENsetreport" />函数所公布的
        ///     </para>
        ///     <para>调用该函数后,默认报告选项生效。</para>
        ///     <para>
        ///         这些为:
        ///         <list type="bullet">
        ///             <item>没有状态报告</item>
        ///             <item>没有能量报告</item>
        ///             <item>没有节点报告</item>
        ///             <item>没有管段报告</item>
        ///             <item>节点变量报告为2位小数位</item>
        ///             <item>管段变量报告为两位小数位 (摩擦因子为3位)</item>
        ///             <item>报告的节点变量为标高、水头、压强和水质</item>
        ///             <item>报告的管段变量为流量、流速和水头损失</item>
        ///         </list>
        ///     </para>
        /// </remarks>
        /// <seealso cref="ENreport" />
        /// <seealso cref="ENsetreport" />
        /// <seealso cref="ENsetstatusreport" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENresetreport();
 
        /// <summary>公布报告格式命令,格式命令与EPANETH输入文件的[REPORT]节中使用的相同</summary>
        /// <param name="command">报告格式命令文本</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///         调用<see cref="ENresetreport" />,明确原来报告格式命令,出现在输入文件中,或者通过调用 <see cref="ENsetreport" /> 或者 <see cref="ENsetstatusreport" />公布
        ///     </para>
        ///     <para>
        ///         模拟的格式结果可以写入到报告文件,利用<see cref="ENreport" />函数
        ///     </para>
        /// </remarks>
        /// <seealso cref="ENreport" />
        /// <seealso cref="ENresetreport" />
        /// <seealso cref="ENsetstatusreport" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true, CharSet = CHARSET,
    BestFitMapping = false, ThrowOnUnmappableChar = true)]
        public static extern ErrorCode ENsetreport([MarshalAs(STRING)] string command);
 
        #endregion
 
        #region 检索network信息的功能
 
        /// <summary>
        ///    读取分配给最近一次 更新源代码的编号。
        ///    该编号由常量<c> CODEVERSION</c> 设置的,从 20001 开始, 每更新一次增加 1.
        /// </summary>
        /// <param name="v">Version number of the source code.</param>
        /// <returns>错误代码<see cref="ErrorCode" /> (should always be 0).</returns>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetversion(out int v);
 
        /// <summary>
        ///     检索简单控制语句的参数。
        ///     控制的索引在以及剩余的参数返回控制参数。
        /// </summary>
        /// <param name="cindex">
        ///    控制语句索引 (控制是从1开始的索引,次序为输入到EPENETH输入文件的[CONTROLS]节中)
        /// </param>
        /// <param name="ctype">控制类型代码<see cref="ControlType" /></param>
        /// <param name="lindex">控制管段的索引</param>
        /// <param name="setting">控制设置数值</param>
        /// <param name="nindex">控制节点的索引
        ///     Index of controlling node (0 for <see cref="ControlType.Timer" />
        ///     or <see cref="ControlType.TimeOfDay" /> control).
        /// </param>
        /// <param name="level">
        ///     对于基于时间控制的控制行为(以秒计)的控制水位或者水位控制的压力或者控制时间的数值 
        /// </param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///         Controls are indexed starting from 1 in the order in which they were
        ///         entered into the [CONTROLS] section of the IStation.Epanet input file.
        ///     </para>
        ///     <para>
        ///         对于管道,设置为0,意味着管道被关闭;为1意味着它是开启的。
        ///         对于水泵,设置包含了水泵转速,为0,意味着水泵被关闭,为1意味着处于常规转速。
        ///         对于阀门,设置是指阀门的压力、流量或者损失系数值,取决于阀门类型
        ///     </para>
        ///     <para>
        ///        对于计时器或者钟表时间控制,nindex参数等于0
        ///     </para>
        ///     <para>
        ///         See <see cref="ENsetcontrol" /> for an example of using this function.
        ///     </para>
        /// </remarks>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetcontrol(
            int cindex,
            out ControlType ctype,
            out int lindex,
            out float setting,
            out int nindex,
            out float level);
 
        /// <summary>检索指定类型的管网组件数量</summary>
        /// <param name="code">组件编号<see cref="CountType" /></param>
        /// <param name="count">管网中countcode组件的数量</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///         管网中连接节点的数量等于节点总数减去水池和水库总数。  
        ///     </para>
        ///     <para>
        ///         对于在输入文件描述的组件,工具箱内没有设施添加或者删除功能。
        ///     </para>
        /// </remarks>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetcount(CountType code, out int count);
 
        /// <summary>检索特定分析选项的数值</summary>
        /// <param name="code">选项编号<see cref="MiscOption" /></param>
        /// <param name="value">选项值</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetoption(MiscOption code, out float value);
 
        /// <summary>检索指定分析时间参数的数值</summary>
        /// <param name="code">时间参数编号 <see cref="TimeParameter" /></param>
        /// <param name="value">参数值</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgettimeparam(TimeParameter code, out int value);
 
        /// <summary>检索表明使用单位的代码数,为了表达所有流量</summary>
        /// <param name="code">流量范围代码号的数值<see cref="FlowUnitsType" /></param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///          在EPANETH输入文件的[OPTIONS]节指定流量单位。
        ///     </para>
        ///     <para>
        ///         流量单位取升或者立方米,说明所有其它量将采用公制单位;否则使用美制单位。(见计量单位)。
        ///     </para>
        /// </remarks>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetflowunits(out FlowUnitsType code);
 
        /// <summary>检索特定时间模式的索引</summary>
        /// <param name="id">模式ID</param>
        /// <param name="index">模式索引</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>模式索引是从1开始的连续整数</remarks>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true, CharSet = CHARSET,
            BestFitMapping = false, ThrowOnUnmappableChar = true)]
        public static extern ErrorCode ENgetpatternindex([MarshalAs(STRING)] string id, out int index);
 
        /// <summary>检索特定时间模式的ID标签</summary>
        /// <param name="index">模式索引</param>
        /// <param name="id">模式ID</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para><paramref name="id" /> must be able to hold <see cref="MAXID" /> characters.</para>
        ///     <para>模式索引是从1开始的连续整数</para>
        /// </remarks>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetpatternid(int index, [MarshalAs(STRING)] StringBuilder id);
 
        /// <summary>检索特定时间模式中的时段总数</summary>
        /// <param name="index">模式索引</param>
        /// <param name="len">模式中时段总数</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>模式索引是从1开始的连续整数</remarks>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetpatternlen(int index, out int len);
 
        /// <summary>检索时间模式中特定时段的乘子</summary>
        /// <param name="index">模式索引</param>
        /// <param name="period">时间模式范围内的时段</param>
        /// <param name="value">时段的乘子</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>模式索引和时段是从1开始的连续整数</remarks>
        /// <seealso cref="ENgetpatternindex" />
        /// <seealso cref="ENgetpatternlen" />
        /// <seealso cref="ENsetpatternvalue" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetpatternvalue(int index, int period, out float value);
 
        /// <summary>检索调用水质分析的类型</summary>
        /// <param name="qualcode">水质分析代码<see cref="QualType" /></param>
        /// <param name="tracenode">源头跟踪分子中跟踪的节点索引</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     当qualcode不为EN_TRACE时,tracenode的数值将为0
        ///     The <paramref name="tracenode" /> value will be 0 when <paramref name="qualcode" />
        ///     is not <see cref="QualType.Trace" />.
        /// </remarks>
        /// <seealso cref="ENsetqualtype" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetqualtype(out QualType qualcode, out int tracenode);
 
        /// <summary>检索与特定错误或者警告代码相关的信息文本</summary>
        /// <param name="err">错误或者警告代码</param>
        /// <param name="errmsg">对应于errcode的错误或者警告信息的文本</param>
        /// <param name="n">errmsg 的最大长度 (should be <see cref="MAXMSG" /> characters).</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>错误信息字符串的长度至少应为 <see cref="MAXMSG" /> 个字符.</remarks>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true, BestFitMapping = false,
            ThrowOnUnmappableChar = true)]
        public static extern ErrorCode ENgeterror(ErrorCode err, [MarshalAs(STRING), Out] StringBuilder errmsg, int n);
 
        #endregion
 
        #region 检索node数据的功能
 
        /// <summary>检索具有指定ID的节点索引</summary>
        /// <param name="id">节点ID</param>
        /// <param name="index">节点索引</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>节点索引是从1开始的连续整数</remarks>
        /// <seealso cref="ENgetnodeid" />  
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true, CharSet = CHARSET,
            BestFitMapping = false, ThrowOnUnmappableChar = true)]
        public static extern ErrorCode ENgetnodeindex([MarshalAs(STRING)] string id, out int index);
 
        /// <summary>
        ///     检索具有指定索引的ID标签
        /// </summary>
        /// <param name="index">节点索引</param>
        /// <param name="id">节点ID</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para><paramref name="id" /> must be able to hold <see cref="MAXID" /> characters.</para>
        ///     <para>节点索引是从1开始的连续整数</para>
        /// </remarks>
        /// <seealso cref="ENgetnodeindex" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true, BestFitMapping = false,
            ThrowOnUnmappableChar = true)]
        public static extern ErrorCode ENgetnodeid(int index, [MarshalAs(STRING), Out] StringBuilder id);
 
        /// <summary>
        ///     检索指定节点的节点类型编号
        /// </summary>
        /// <param name="index">节点索引</param>
        /// <param name="code">节点类型编号 <see cref="NodeType" /></param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>节点索引是从1开始的连续整数</remarks>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetnodetype(int index, out NodeType code);
 
        /// <summary>
        ///     检索特定管段参数值
        /// </summary>
        /// <param name="index">节点索引</param>
        /// <param name="code">节点参数代号 <see cref="NodeValue" /></param>
        /// <param name="value">参数值</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///         节点索引是从1开始的连续整数
        ///     </para>
        ///     <para>
        ///         返回值的单位取决于在 IStation.Epanet 输入文件中用于流量的单位。
        ///     </para>
        /// </remarks>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetnodevalue(int index, NodeValue code, out float value);
 
        #endregion
 
        #region 检索link数据的功能
 
        /// <summary>
        ///     检索具有特定ID的管段索引
        /// </summary>
        /// <param name="id">管段ID</param>
        /// <param name="index">管段索引</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>管段索引是从1开始的连续整数</remarks>
        /// <seealso cref="ENgetlinkid" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true, CharSet = CHARSET,
            BestFitMapping = false, ThrowOnUnmappableChar = true)]
        public static extern ErrorCode ENgetlinkindex([MarshalAs(STRING)] string id, out int index);
 
        /// <summary>检索具有特定指标的管段的ID标签</summary>
        /// <param name="index">管段索引</param>
        /// <param name="id">管段ID</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para><paramref name="id" /> must be able to hold <see cref="MAXID" /> characters.</para>
        ///     <para>管段索引是从1开始的连续整数</para>
        /// </remarks>
        /// <seealso cref="ENgetlinkindex" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true, BestFitMapping = false,
            ThrowOnUnmappableChar = true)]
        public static extern ErrorCode ENgetlinkid(int index, [MarshalAs(STRING), Out] StringBuilder id);
 
        /// <summary>检索特定管段的类型编号</summary>
        /// <param name="index">管段索引</param>
        /// <param name="code">管段类型代号<see cref="LinkType" /></param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>管段索引是从1开始的连续整数</remarks>
        /// <seealso cref="ENgetlinkindex" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetlinktype(int index, out LinkType code);
 
        /// <summary>
        ///     检索指定管段端点节点的索引
        /// </summary>
        /// <param name="index">管段索引</param>
        /// <param name="fnode">管段起始节点索引</param>
        /// <param name="tnode">管段终止节点索引</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>节点和管段索引是从1开始的连续整数</para>
        ///     <para>
        ///         管段起始和终止节点定义在EPANETH输入文件中。
        ///         没有考虑管段的实际流向。
        ///     </para>
        /// </remarks>
        /// <seealso cref="ENgetlinkindex" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetlinknodes(int index, out int fnode, out int tnode);
 
        /// <summary>
        ///     检索指定管段参数值
        /// </summary>
        /// <param name="index">管段索引</param>
        /// <param name="code">管段参数代号<see cref="LinkValue" /></param>
        /// <param name="value">参数值</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>管段索引是从1开始的连续整数</para>
        ///     <para> 
        ///     EN_DIAMETER     0     直径 
        ///     EN_LENGTH       1     长度
        ///     EN_ROUGHNESS     2     粗糙系数
        ///     EN_MINORLOSS     3     局部损失系数
        ///     EN_INITSTATUS     4     初始管段状态 (0 = 关闭, 1 = 开启)
        ///     EN_INITSETTING  5     初始管道粗糙度初始水泵转速初始阀门设置
        ///     EN_KBULK         6     主流反应系数
        ///     EN_KWALL         7     管壁反应系数
        ///     EN_FLOW         8     流量
        ///     EN_VELOCITY     9     流速
        ///     EN_HEADLOSS     10 水头损失
        ///     EN_STATUS         11 实际管段状态 (0 = 关闭, 1 = 开启)
        ///     EN_SETTING         12 管道粗糙系数实际水泵转速实际阀门设置
        ///     EN_ENERGY         13 消耗能量,以千瓦计
        ///    (参数8 - 13 (EN_FLOW到EN_ENERGY)为计算值。其他为设计参数)
        ///     </para>
        ///     <para>
        ///        如果从指定管段起始节点流向指定终止节点,流量为正;否则为负。  
        ///        返回的数值单位,取决于EPANETH输入文件中流量使用的单位。
        ///     </para>
        /// </remarks>
        /// <seealso cref="ENgetlinkindex" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetlinkvalue(int index, LinkValue code, out float value);
 
        #endregion
 
        #region 更改network数据的功能
 
        /// <summary>设置特定简单控制语句的参数</summary>
        /// <param name="cindex">
        ///     控制索引是从1开始的,顺序中它们被输入,在EPANETH的输入文件的[CONTROLS]节。
        /// </param>
        /// <param name="ctype">控制类型代码 <see cref="ControlType" /></param>
        /// <param name="lindex">被控制管段的索引</param>
        /// <param name="setting">控制设置的数值</param>
        /// <param name="nindex">控制节点的索引 
        ///     index of controlling node (0 for <see cref="ControlType.Timer" />
        ///     or <see cref="ControlType.TimeOfDay" /> control)
        /// </param>
        /// <param name="level">
        ///     对于水位控制的控制水位或者压力的数值,或者控制行为的时间(以秒计),对于基于时间的控制
        /// </param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks> 
        ///     <para>
        ///     对于管道, setting为0,意味着管道关闭,为1意味着它是开启的。
        ///     对于水泵, setting包含了水泵转速,为0意味着水泵关闭,为1意味着在常规转速下开启。
        ///     对于阀门, setting指阀门压力、流量或者损失系数,取决于阀门类型。
        ///     </para>
        ///     <para>
        ///         对于计时器或者钟表时间控制,设置<paramref name="nindex" /> 参数为0
        ///     </para>
        ///     <para>
        ///         对于水位控制,如果控制节点 <paramref name="nindex" />为水池,那么level参数应为高于池底的水位(而不是标高)。否则level应为连接节点压力。 
        ///     </para>
        ///     <para>
        ///         为除去关于特定管段的控制,设置<paramref name="lindex" />参数为0。函数中其它参数的数值将被忽略。 
        ///     </para>
        /// </remarks>
        /// <example>
        ///     本例将ENgetcontrol and ENsetcontrol用于改变节点的低水位设置,控制管段,具有索引 thelink 到新的数值newlevel。 
        ///     This example uses <see cref="ENgetcontrol" /> and <see cref="ENsetcontrol" />
        ///     to change the low level setting on the node that controls a link with
        ///     index <c>thelink</c> to a new value <c>newlevel</c>.
        ///     <code>
        ///     int numctrls, lindex, nindex, thelink = 1;
        ///     float setting, level, newlevel = 1f;
        ///     ControlType ctype;
        /// 
        ///     ENgetcount(CountType.Control, out numctrls);
        /// 
        ///     for (int i = 1; i &lt;= numctrls; i++) {
        ///         ENgetcontrol(i, out ctype, out lindex, out setting, out nindex, out level);
        ///         if (ctype == ControlType.Lowlevel &amp;&amp; lindex == thelink) {
        ///             ENsetcontrol(i, ctype, lindex, setting, nindex, newlevel);
        ///             break;
        ///         }
        ///     }
        ///     </code>
        /// </example>
        /// <seealso cref="ENgetcontrol" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENsetcontrol(
            int cindex,
            ControlType ctype,
            int lindex,
            float setting,
            int nindex,
            float level);
 
        /// <summary>
        ///     设置特定节点的参数值
        /// </summary>
        /// <param name="index">节点索引</param>
        /// <param name="code">节点参数代码 <see cref="NodeValue" /></param>
        /// <param name="v">parameter value</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>节点索引是从1开始的连续整数</para>
        ///     <para>
        ///         提供的数值单位取决于在 IStation.Epanet 输入文件中用于流量的单位。
        ///     </para>
        /// </remarks>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENsetnodevalue(int index, NodeValue code, float v);
 
        /// <summary>
        ///     设置指定管段的参数值
        /// </summary>
        /// <param name="index">管段索引</param>
        /// <param name="code">节点参数代码<see cref="LinkValue" /></param>
        /// <param name="v">parameter value</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>管段索引是从1开始的连续整数</para>
        ///     <para>
        ///         数值单位取决于在EPANETH输入文件中使用的流量范围(参见计量单位)
        ///     </para>
        ///     <para>
        ///     
        ///        ps(pdf):对于存在的管段状态或者设置,在模拟开始之前,利用EN_INITSTATUS和  EN_INITSETTING设置设计数值。
        ///         在模拟执行的同时,利用EN_STATUS和EN_SETTING 改变这些数值(在ENrunH - ENnextH循环范围内)。
        ///         
        ///        ps(英文翻译):使用 <see cref="LinkValue.InitStatus" /> 和 <see cref="LinkValue.InitSetting" />
        ///        设置link状态或设置的设计值,这些值在仿真开始前就已存在。 使用 <see cref="LinkValue.Status" /> 和 <see cref="LinkValue.Setting" /> 
        ///        可以在运行仿真时(在 <see cref="ENrunH" /> - <see cref="ENnextH" /> 循环内)更改这些值。
        ///         
        ///         Use <see cref="LinkValue.InitStatus" /> and <see cref="LinkValue.InitSetting" />
        ///         to set the design value for a link's status or setting that exists prior to the
        ///         start of a simulation. Use <see cref="LinkValue.Status" /> and
        ///         <see cref="LinkValue.Setting" /> to change these values while a simulation
        ///         is being run (within the <see cref="ENrunH" /> - <see cref="ENnextH" /> loop).
        ///          
        ///     </para>
        ///     <para>
        ///         如果控制阀具有明确的状态,设置为<see cref="StatusType.Open" />或者<see cref="StatusType.Closed" />。
        ///         需要再次启用,在模拟过程中必须采用<see cref="LinkValue.Setting" />参数提供虚拟的阀门设置数值。
        ///         对于管道<see cref="LinkValue.Roughness" />或者<see cref="LinkValue.InitSetting" />用于改变粗糙系数。 
        ///     </para>
        ///     <para>
        ///         For pipes, either <see cref="LinkValue.Roughness" />
        ///         or <see cref="LinkValue.InitSetting" /> can be used to change roughness.
        ///     </para>
        /// </remarks>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENsetlinkvalue(int index, LinkValue code, float v);
 
        /// <summary> 
        ///     添加一个新的时间模式,附加到现有模式的末尾
        /// </summary>
        /// <param name="id">新模式的 ID 名称</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>ID 标签应包含不超过 31 个字符</para>
        ///     <para>新模式将包含一个时间段,其乘数系数为 1</para>
        ///     <para> 
        ///         使用 <see cref="ENsetpattern" /> 函数,首先用 <see cref="ENgetpatternindex" /> 函数获取模式的索引,然后用一组特定的乘数填充模式。 
        ///     </para>
        /// </remarks>
        /// <example>
        ///     <code>
        ///     string  patId = "NewPattern";  
        ///     float[] patFactors = new[] {0.8f, 1.1f, 1.4f, 1.1f, 0.8f, 0.7f};  
        ///     int   patIndex;  
        ///     ENaddpattern(patId);  
        ///     ENgetpatternindex(patId, out patIndex); 
        ///     ENsetpattern(patIndex, patFactors, 6); 
        /// </code>
        /// </example>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true, CharSet = CHARSET,
            BestFitMapping = false, ThrowOnUnmappableChar = true)]
        public static extern ErrorCode ENsetpattern([MarshalAs(STRING)] string id);
 
        /// <summary>
        ///     设置指定时间模式的所有乘子
        /// </summary>
        /// <param name="index">时间模式索引</param>
        /// <param name="f">整个模式的乘子</param>
        /// <param name="n">模式中因子总数</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>模式索引是从1开始的连续整数</para>
        ///     <para>
        ///         <paramref name="f" /> Factors点到基于零的数组,包含了nfactors的元素
        ///     </para>
        ///     <para>
        ///         使用该函数重新定义(和重新设置尺寸)时间模式;利用<see cref="ENsetpatternvalue" />,修改模式指定时段的模式因子。  
        ///     </para>
        /// </remarks>
        /// <seealso cref="ENgetpatternindex" />
        /// <seealso cref="ENgetpatternlen" />
        /// <seealso cref="ENgetpatternvalue" />
        /// <seealso cref="ENsetpatternvalue" />
        /// <seealso cref="ENaddpattern" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENsetpattern(
            int index,
            [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.R4, SizeParamIndex = 2), In] float[] f,
            int n);
 
        /// <summary>
        ///     设置时间模式内特定时段的乘子因子
        /// </summary>
        /// <param name="index">时间模式索引</param>
        /// <param name="period">时间模式内的时段</param>
        /// <param name="value">时段的乘子因子</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>模式索引是从1开始的连续整数</para>
        ///     <para>
        ///         利用 <see cref="ENsetpattern" /> 重新设置时间模式内的所有因子.
        ///     </para>
        /// </remarks>
        /// <seealso cref="ENgetpatternindex" />
        /// <seealso cref="ENgetpatternlen" />
        /// <seealso cref="ENgetpatternvalue" />
        /// <seealso cref="ENsetpattern" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENsetpatternvalue(int index, int period, float value);
 
        /// <summary>设置时间参数值</summary>
        /// <param name="code">时间参数代码<see cref="TimeParameter" /></param>
        /// <param name="value">时间参数值,以秒计</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     Do not change time parameters after calling <see cref="ENinitH" /> in a
        ///     hydraulic analysis or <see cref="ENinitQ" /> in a water quality analysis.
        /// </remarks>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENsettimeparam(TimeParameter code, int value);
 
        /// <summary>设置特定分析选项的数值</summary>
        /// <param name="code">选项编号<see cref="MiscOption" /></param>
        /// <param name="v">选项值</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENsetoption(MiscOption code, float v);
 
        /// <summary>设置水力状态报告的水平</summary>
        /// <param name="statuslevel">状态报告的水平<see cref="StatusLevel" /></param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///         当水力模拟逐渐展开时,状态报告将管网元素的水力状态变化写入到报告文件
        ///         具有三种水平的报告<see cref="StatusLevel" />: 
        ///         <list type="number">
        ///             <item>无状态报告</item>
        ///             <item>常规报告</item>
        ///             <item>完整状态报告</item>
        ///         </list>
        ///     </para>
        ///     <para>
        ///         完整状态报告包含了求解系统水力方程组,在模拟的每一时间步长的收敛信息。主要用于调试目的。
        ///     </para>
        ///     <para>
        ///         如果将在应用程序中执行许多次水力分析,建议状态报告关闭(<paramref name="statuslevel" /> = <see cref="StatusLevel.None" />)。 
        ///     </para>
        /// </remarks>
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENsetstatusreport(StatusLevel statuslevel);
 
        /// <summary>设置被调用水质分析的类型</summary>
        /// <param name="qualcode">水质分析代码 <see cref="QualType" /></param>
        /// <param name="chemname">被分析化学成分名称</param>
        /// <param name="chemunits">化学成分计量单位</param>
        /// <param name="tracenode">源头跟踪分析中被跟踪节点的ID</param>
        /// <returns>错误代码<see cref="ErrorCode" /></returns>
        /// <remarks>
        ///     <para>
        ///         如果不进行化学成分分析,化学成分名称和单位可以为空字符串。如果不进行源头跟踪分析,跟踪节点保留名称。
        ///     </para>
        ///     <para>
        ///         注意跟踪节点通过ID指定而不是索引。
        ///     </para>
        /// </remarks>
        /// <seealso cref="ENgetqualtype" />
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true, CharSet = CHARSET,
            BestFitMapping = false, ThrowOnUnmappableChar = true)]
        public static extern ErrorCode ENsetqualtype(
            QualType qualcode,
            [MarshalAs(STRING), Optional, DefaultParameterValue("")] string chemname,
            [MarshalAs(STRING), Optional, DefaultParameterValue("")] string chemunits,
            [MarshalAs(STRING), Optional, DefaultParameterValue("")] string tracenode);
 
        #endregion
 
 
        #region 曲线
 
 
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetpumptype(int link_index, out int curve_index);
 
 
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetheadcurveindex(int link_index, out int curve_index);
 
 
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENsetheadcurveindex(int linkIndex, int curve_index);
 
 
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true, CharSet = CHARSET,
            BestFitMapping = false, ThrowOnUnmappableChar = true)]
        public static extern ErrorCode ENaddcurve([MarshalAs(STRING)] string id);
 
 
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENdeletecurve(int index);
 
 
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetcurveindex([MarshalAs(STRING)] string id, out int index);
 
 
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true, BestFitMapping = false,
              ThrowOnUnmappableChar = true)]
        public static extern ErrorCode ENgetcurveid(int index, [MarshalAs(STRING), Out] StringBuilder id);
 
 
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true, CharSet = CHARSET,
               BestFitMapping = false, ThrowOnUnmappableChar = true)]
        public static extern ErrorCode ENsetcurveid(int index, [MarshalAs(STRING), Optional, DefaultParameterValue("")] string id);
 
 
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
 
        public static extern ErrorCode ENgetcurvelen(int index, out int len);
 
 
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetcurvetype(int index, out int type);
 
 
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENsetcurvetype(int index, int type);
 
 
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetcurvevalue(int curve_index, int point_index, out float x, out float y);
 
 
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENsetcurvevalue(int curve_index, int point_index, float x, float y);
 
 
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENgetcurve(int index, [MarshalAs(STRING)] StringBuilder id, out int nPoints,
              [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.R4, SizeParamIndex = 2), Out] float[] xValues,
              [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.R4, SizeParamIndex = 2), Out] float[] yValues);
 
        [DllImport(EPANETDLL, CallingConvention = CONVENTION, ExactSpelling = true)]
        public static extern ErrorCode ENsetcurve(int index,
            [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.R4, SizeParamIndex = 2), In] float[] xValues,
            [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.R4, SizeParamIndex = 2), In] float[] yValues,
            int nPoints);
 
 
        #endregion
 
    }
 
}