forked from USEPA/Stormwater-Management-Model
-
Notifications
You must be signed in to change notification settings - Fork 76
/
Copy pathtoolkitAPI.c
1227 lines (1114 loc) · 34.8 KB
/
toolkitAPI.c
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
//-----------------------------------------------------------------------------
// toolkitAPI.c
//
// Project: EPA SWMM5
// Version: 5.1
// Date: 08/30/2016
// Author: B. McDonnell (EmNet LLC)
//
// Exportable Functions for Project Definition API.
//
//-----------------------------------------------------------------------------
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "headers.h"
#include "swmm5.h" // declaration of exportable functions
#include "toolkitAPI.h"
#include "hash.h"
#include "funcs.h"
//-----------------------------------------------------------------------------
// Extended API Functions
//-----------------------------------------------------------------------------
void DLLEXPORT swmm_getAPIError(int errcode, char *s)
//
// Input: errcode = error code
// Output: errmessage String
// Return: API Error
// Purpose: Get an error message
{
char *errmsg = error_getMsg(errcode);
strcpy(s, errmsg);
}
int DLLEXPORT swmm_getSimulationDateTime(int timetype, int *year, int *month, int *day,
int *hours, int *minutes, int *seconds)
//
// Input: timetype = time type to return
// Output: year, month, day, hours, minutes, seconds = int
// Return: API Error
// Purpose: Get the simulation start, end and report date times
{
int errcode = 0;
// Check if Open
if (swmm_IsOpenFlag() == FALSE)
{
errcode = ERR_API_INPUTNOTOPEN;
}
else
{
DateTime _dtime;
switch (timetype)
{
//StartDateTime (globals.h)
case 0: _dtime = StartDateTime; break;
//EndDateTime (globals.h)
case 1: _dtime = EndDateTime; break;
//ReportStart (globals.h)
case 2: _dtime = ReportStart; break;
//Current Routing Time
case 3: _dtime = NewRoutingTime; break;
default: return(ERR_API_OUTBOUNDS);
}
datetime_decodeDate(_dtime, year, month, day);
datetime_decodeTime(_dtime, hours, minutes, seconds);
}
return (errcode);
}
int DLLEXPORT swmm_setSimulationDateTime(int timetype, char *dtimestr)
//
// Input: timetype = time type to return
// DateTime String
// Return: API Error
// Purpose: Get the simulation start, end and report date times
{
// Check if Open
if(swmm_IsOpenFlag() == FALSE) return(ERR_API_INPUTNOTOPEN);
// Check if Simulation is Running
if(swmm_IsStartedFlag() == TRUE) return(ERR_API_SIM_NRUNNING);
char theDate[10];
char theTime[9];
strncpy(theDate, dtimestr, 10);
strncpy(theTime, dtimestr+11, 9);
switch(timetype)
{
//StartDateTime (globals.h)
case 0:
project_readOption("START_DATE", theDate);
project_readOption("START_TIME", theTime);
StartDateTime = StartDate + StartTime;
TotalDuration = floor((EndDateTime - StartDateTime) * SECperDAY);
// --- convert total duration to milliseconds
TotalDuration *= 1000.0;
break;
//EndDateTime (globals.h)
case 1:
project_readOption("END_DATE", theDate);
project_readOption("END_TIME", theTime);
EndDateTime = EndDate + EndTime;
TotalDuration = floor((EndDateTime - StartDateTime) * SECperDAY);
// --- convert total duration to milliseconds
TotalDuration *= 1000.0;
break;
//ReportStart (globals.h)
case 2:
project_readOption("REPORT_START_DATE", theDate);
project_readOption("REPORT_START_TIME", theTime);
ReportStart = ReportStartDate + ReportStartTime;
break;
default: return(ERR_API_OUTBOUNDS);
}
return (0);
}
int DLLEXPORT swmm_getSimulationUnit(int type, int *value)
//
// Input: type = simulation unit type
// Output: enum representation of units
// Returns: API Error
// Purpose: get simulation unit types
{
// Check if Open
if(swmm_IsOpenFlag() == FALSE) return(ERR_API_INPUTNOTOPEN);
// Output unit
switch(type)
{
// System Unit (enum.h UnitsType)
case 0: *value = UnitSystem; break;
// Flow Unit (enum.h FlowUnitsType)
case 1: *value = FlowUnits; break;
// Concentration Unit
//case 2: *value = UnitSystem; break;
// Type not available
default: return(ERR_API_OUTBOUNDS);
}
return (0);
}
int DLLEXPORT swmm_getSimulationAnalysisSetting(int type, int *value)
//
// Input: type = analysis type
// Output: setting True or False
// Returns: API Error
// Purpose: get simulation analysis setting
{
// Check if Open
if(swmm_IsOpenFlag() == FALSE) return(ERR_API_INPUTNOTOPEN);
// Output setting
switch(type)
{
// No ponding at nodes (True or False)
case 0: *value = AllowPonding; break;
// Do flow routing in steady state periods (True or False)
case 1: *value = SkipSteadyState; break;
// Analyze rainfall/runoff (True or False)
case 2: *value = IgnoreRainfall; break;
// Analyze RDII (True or False)
case 3: *value = IgnoreRDII; break;
// Analyze snowmelt (True or False)
case 4: *value = IgnoreSnowmelt; break;
// Analyze groundwater (True or False)
case 5: *value = IgnoreGwater; break;
// Analyze flow routing (True or False)
case 6: *value = IgnoreRouting; break;
// Analyze water quality (True or False)
case 7: *value = IgnoreQuality; break;
// Type not available
default: return(ERR_API_OUTBOUNDS);
}
return (0);
}
int DLLEXPORT swmm_getSimulationParam(int type, double *value)
//
// Input: type = analysis type
// Output: Simulation Parameter
// Returns: error code
// Purpose: Get simulation analysis parameter
{
// Check if Open
if(swmm_IsOpenFlag() == FALSE) return(ERR_API_INPUTNOTOPEN);
// Output setting
switch(type)
{
// Routing time step (sec)
case 0: *value = RouteStep; break;
// Minimum variable time step (sec)
case 1: *value = MinRouteStep; break;
// Time step for lengthening (sec)
case 2: *value = LengtheningStep; break;
// Antecedent dry days
case 3: *value = StartDryDays; break;
// Courant time step factor
case 4: *value = CourantFactor; break;
// Minimum nodal surface area
case 5: *value = MinSurfArea; break;
// Minimum conduit slope
case 6: *value = MinSlope; break;
// Runoff continuity error
case 7: *value = RunoffError; break;
// Groundwater continuity error
case 8: *value = GwaterError; break;
// Flow routing error
case 9: *value = FlowError; break;
// Quality routing error
case 10: *value = QualError; break;
// DW routing head tolerance (ft)
case 11: *value = HeadTol; break;
// Tolerance for steady system flow
case 12: *value = SysFlowTol; break;
// Tolerance for steady nodal inflow
case 13: *value = LatFlowTol; break;
// Type not available
default: return(ERR_API_OUTBOUNDS);
}
return (0);
}
int DLLEXPORT swmm_countObjects(int type, int *count)
//
// Input: type = object type (Based on ObjectType enum)
// Output: count = pointer to integer
// Returns: API Error
// Purpose: uses Object Count table to find number of elements of an object
{
if(type >= MAX_OBJ_TYPES)return ERR_API_OUTBOUNDS;
*count = Nobjects[type];
return (0);
}
int DLLEXPORT swmm_getObjectId(int type, int index, char *id)
//
// Input: type = object type (Based on ObjectType enum)
// index = Index of desired ID
// Output: id = pointer to id pass by reference
// Return: API Error
// Purpose: Gets ID for any object
{
//Provide Empty Character Array
strcpy(id,"");
// Check if Open
if(swmm_IsOpenFlag() == FALSE) return(ERR_API_INPUTNOTOPEN);
// Check if object index is within bounds
if (index < 0 || index >= Nobjects[type]) return(ERR_API_OBJECT_INDEX);
switch (type)
{
case GAGE:
strcpy(id,Gage[index].ID); break;
case SUBCATCH:
strcpy(id,Subcatch[index].ID); break;
case NODE:
strcpy(id,Node[index].ID); break;
case LINK:
strcpy(id,Link[index].ID); break;
case POLLUT:
strcpy(id,Pollut[index].ID); break;
case LANDUSE:
strcpy(id,Landuse[index].ID); break;
case TIMEPATTERN:
strcpy(id,Pattern[index].ID); break;
//case CURVE:
//strcpy(id,Curve[index].ID); break;
//case TSERIES:
//strcpy(id,Tseries[index].ID); break;
//case CONTROL:
//strcpy(id,Rules[index].ID); break;
case TRANSECT:
strcpy(id,Transect[index].ID); break;
case AQUIFER:
strcpy(id,Aquifer[index].ID); break;
case UNITHYD:
strcpy(id,UnitHyd[index].ID); break;
case SNOWMELT:
strcpy(id,Snowmelt[index].ID); break;
//case SHAPE:
//strcpy(id,Shape[index].ID); break;
//case LID:
// strcpy(id,LidProcs[index].ID); break;
// Type not available
default: return(ERR_API_OUTBOUNDS);
}
return(0);
}
int DLLEXPORT swmm_getNodeType(int index, int *Ntype)
//
// Input: index = Index of desired ID
// Ntype = Node type (Based on enum NodeType)
// Return: API Error
// Purpose: Gets Node Type
{
// Check if Open
if(swmm_IsOpenFlag() == FALSE) return(ERR_API_INPUTNOTOPEN);
// Check if object index is within bounds
if (index < 0 || index >= Nobjects[NODE]) return(ERR_API_OBJECT_INDEX);
*Ntype = Node[index].type;
return(0);
}
int DLLEXPORT swmm_getLinkType(int index, int *Ltype)
//
// Input: index = Index of desired ID
// Ltype = Link type (Based on enum NodeType)
// Return: API Error
// Purpose: Gets Link Type
{
// Check if Open
if(swmm_IsOpenFlag() == FALSE) return(ERR_API_INPUTNOTOPEN);
// Check if object index is within bounds
if (index < 0 || index >= Nobjects[LINK]) return(ERR_API_OBJECT_INDEX);
*Ltype = Link[index].type;
return(0);
}
int DLLEXPORT swmm_getLinkConnections(int index, int *Node1, int *Node2)
//
// Input: type = object type (Based on ObjectType enum)
// index = Index of desired ID
// Output: Node1 and Node2
// Return: API Error
// Purpose: Gets link Connection ID Indeces
{
// Check if Open
if(swmm_IsOpenFlag() == FALSE) return(ERR_API_INPUTNOTOPEN);
// Check if object index is within bounds
if (index < 0 || index >= Nobjects[LINK]) return(ERR_API_OBJECT_INDEX);
*Node1 = Link[index].node1;
*Node2 = Link[index].node2;
return(0);
}
int DLLEXPORT swmm_getNodeParam(int index, int Param, double *value)
//
// Input: index = Index of desired ID
// param = Parameter desired (Perhaps define enum )
// Output: value = value to be output
// Return: API Error
// Purpose: Gets Node Parameter
{
// Check if Open
if(swmm_IsOpenFlag() == FALSE) return(ERR_API_INPUTNOTOPEN);
// Check if object index is within bounds
if (index < 0 || index >= Nobjects[NODE]) return(ERR_API_OBJECT_INDEX);
switch(Param)
{
// invertElev
case 0: *value = Node[index].invertElev * UCF(LENGTH); break;
// fullDepth
case 1: *value = Node[index].fullDepth * UCF(LENGTH); break;
// surDepth
case 2: *value = Node[index].surDepth * UCF(LENGTH); break;
// pondedArea
case 3: *value = Node[index].pondedArea * UCF(LENGTH) * UCF(LENGTH); break;
// initDepth
case 4: *value = Node[index].initDepth * UCF(LENGTH); break;
// Type not available
default: return(ERR_API_OUTBOUNDS);
}
return(0);
}
int DLLEXPORT swmm_setNodeParam(int index, int Param, double value)
//
// Input: index = Index of desired ID
// param = Parameter desired (Perhaps define enum )
// value = value to be input
// Return: API Error
// Purpose: Sets Node Parameter
{
// Check if Open
if(swmm_IsOpenFlag() == FALSE) return(ERR_API_INPUTNOTOPEN);
// Check if Simulation is Running
if(swmm_IsStartedFlag() == TRUE) return(ERR_API_SIM_NRUNNING);
// Check if object index is within bounds
if (index < 0 || index >= Nobjects[NODE]) return(ERR_API_OBJECT_INDEX);
switch(Param)
{
// invertElev
case 0: Node[index].invertElev = value / UCF(LENGTH); break;
// fullDepth
case 1: Node[index].fullDepth = value / UCF(LENGTH); break;
// surDepth
case 2: Node[index].surDepth = value / UCF(LENGTH); break;
// pondedArea
case 3: Node[index].pondedArea = value / ( UCF(LENGTH) * UCF(LENGTH) ); break;
// initDepth
case 4: Node[index].initDepth = value / UCF(LENGTH); break;
// Type not available
default: return(ERR_API_OUTBOUNDS);
}
// Re-validated a node ******************** BEM 1/20/2017 Probably need to re-validate connecting links
node_validate(index);// incorprate callback here
return(0);
}
// Get Storage
int DLLEXPORT swmm_getStorageParam(int index, int Param, double value)
//
// Input: index = Index of desired ID
// param = Parameter desired (Perhaps define enum )
// value = value to be input
// Return: API Error
// Purpose: Sets Storage Parameter
//
{
int errcode = 0;
*value = 0;
// Check if Open
if(swmm_IsOpenFlag() == FALSE)
{
errcode = ERR_API_INPUTNOTOPEN;
}
// Check if object index is within bounds
else if (index < 0 || index >= Nobjects[Node])
{
errcode = ERR_API_OBJECT_INDEX;
}
else
{
switch(Param)
{
// FUNCTIONAL COEFF
case 0: *value = Storage[index].aCoeff * UCF(LENGTH) * UCF(LENGTH); break;
// FUNCTIONAL EXPON
case 1: *value = Storage[index].aExpon * UCF(LENGTH) * UCF(LENGTH); break;
// FUNCTIONAL CONST
case 2: *value = Storage[index].aConst * UCF(LENGTH) * UCF(LENGTH); break
// STORAGE EXFIL
case 3: *value = Storage[index].exfil * UCF(RATE); break;
// STORAGE EVAP
case 4: *value = Storage[index].fEvap * UCF(RATE); break;
// Type not available
default: errcode = ERR_API_OUTBOUNDS; break;
}
//re-validate storage
storage_validate(index); // incorprate callback here
}
return(0);
}
// Set Storage Parameters
int DLLEXPORT swmm_setStorageParam(int index, int Param, double value)
//
// Input: index = Index of desired ID
// param = Parameter desired (Perhaps define enum )
// value = value to be input
// Return: API Error
// Purpose: Sets Storage Parameter
//
{
int errcode = 0;
*value = 0;
// Check if Open
if(swmm_IsOpenFlag() == FALSE)
{
errcode = ERR_API_INPUTNOTOPEN;
}
// Check if object index is within bounds
else if (index < 0 || index >= Nobjects[Node])
{
errcode = ERR_API_OBJECT_INDEX;
}
else
{
switch(Param)
{
// FUNCTIONAL COEFF
case 0: Storage[index].aCoeff = value / ( UCF(LENGTH) * UCF(LENGTH) ); break;
// FUNCTIONAL EXPON
case 1: Storage[index].aExpon = value / ( UCF(LENGTH) * UCF(LENGTH) ); break;
// FUNCTIONAL CONST
case 2: Storage[index].aConst = value / ( UCF(LENGTH) * UCF(LENGTH) ); break;
// STORAGE EXFIL
case 3: Storage[index].exfil = value / UCF(RATE); break;
// STORAGE EVAP
case 4: Storage[index].fEvap = value / UCF(RATE); break;
// Type not available
default: errcode = ERR_API_OUTBOUNDS; break;
}
//re-validate storage
storage_validate(index); // incorprate callback here
}
return(0);
}
int DLLEXPORT swmm_getLinkParam(int index, int Param, double *value)
//
// Input: index = Index of desired ID
// param = Parameter desired (Perhaps define enum )
// Output: value = value to be output
// Return: API Error
// Purpose: Gets Link Parameter
{
// Check if Open
if(swmm_IsOpenFlag() == FALSE) return(ERR_API_INPUTNOTOPEN);
// Check if object index is within bounds
if (index < 0 || index >= Nobjects[LINK]) return(ERR_API_OBJECT_INDEX);
switch(Param)
{
// offset1
case 0: *value = Link[index].offset1 * UCF(LENGTH); break;
// offset2
case 1: *value = Link[index].offset2 * UCF(LENGTH); break;
// q0
case 2: *value = Link[index].q0 * UCF(FLOW); break;
// qLimit
case 3: *value = Link[index].qLimit * UCF(FLOW); break;
// cLossInlet
case 4: *value = Link[index].cLossInlet; break;
// cLossOutlet
case 5: *value = Link[index].cLossOutlet; break;
// cLossAvg
case 6: *value = Link[index].cLossAvg; break;
// seepRate
//case 7: *value = Link[index].seepRate * UCF(FLOW); break;
// Type not available
default: return(ERR_API_OUTBOUNDS);
}
return(0);
}
int DLLEXPORT swmm_setLinkParam(int index, int Param, double value)
//
// Input: index = Index of desired ID
// param = Parameter desired (Perhaps define enum )
// value = value to be input
// Return: API Error
// Purpose: Gets Link Parameter
{
// Check if Open
if(swmm_IsOpenFlag() == FALSE) return(ERR_API_INPUTNOTOPEN);
// Check if object index is within bounds
if (index < 0 || index >= Nobjects[LINK]) return(ERR_API_OBJECT_INDEX);
switch(Param)
{
// offset1
case 0:
// Check if Simulation is Running
if(swmm_IsStartedFlag() == TRUE) return(ERR_API_SIM_NRUNNING);
Link[index].offset1 = value / UCF(LENGTH); break;
// offset2
case 1:
// Check if Simulation is Running
if(swmm_IsStartedFlag() == TRUE) return(ERR_API_SIM_NRUNNING);
Link[index].offset2 = value / UCF(LENGTH); break;
// q0
case 2:
// Check if Simulation is Running
if(swmm_IsStartedFlag() == TRUE) return(ERR_API_SIM_NRUNNING);
Link[index].q0 = value / UCF(FLOW); break;
// qLimit
case 3: Link[index].qLimit = value / UCF(FLOW); break;
// cLossInlet
case 4: Link[index].cLossInlet; break;
// cLossOutlet
case 5: Link[index].cLossOutlet; break;
// cLossAvg
case 6: Link[index].cLossAvg; break;
// seepRate
//case 7: *value = Link[index].seepRate * UCF(FLOW); break;
// Type not available
default: return(ERR_API_OUTBOUNDS);
}
// re-validated link
link_validate(index);// incorprate callback here
return(0);
}
int DLLEXPORT swmm_getLinkDirection(int index, signed char *value)
//
// Input: index = Index of desired ID
// Output: Link Direction (Only changes is slope < 0)
// Return: API Error
// Purpose: Gets Link Direction
{
// Check if Open
if(swmm_IsOpenFlag() == FALSE) return(ERR_API_INPUTNOTOPEN);
// Check if object index is within bounds
if (index < 0 || index >= Nobjects[LINK]) return(ERR_API_OBJECT_INDEX);
*value = Link[index].direction;
return(0);
}
int DLLEXPORT swmm_getSubcatchParam(int index, int Param, double *value)
//
// Input: index = Index of desired ID
// param = Parameter desired (Perhaps define enum )
// Output: value = value to be output
// Return: API Error
// Purpose: Gets Subcatchment Parameter
{
// Check if Open
if(swmm_IsOpenFlag() == FALSE) return(ERR_API_INPUTNOTOPEN);
// Check if object index is within bounds
if (index < 0 || index >= Nobjects[SUBCATCH]) return(ERR_API_OBJECT_INDEX);
switch(Param)
{
// width
case 0: *value = Subcatch[index].width * UCF(LENGTH); break;
// area
case 1: *value = Subcatch[index].area * UCF(LANDAREA); break;
// fracImperv
case 2: *value = Subcatch[index].fracImperv; break;
// slope
case 3: *value = Subcatch[index].slope; break;
// curbLength
case 4: *value = Subcatch[index].curbLength * UCF(LENGTH); break;
// initBuildup
//case 5: *value = Subcatch[index].initBuildup; break;
// Type not available
default: return(ERR_API_OUTBOUNDS);
}
return(0);
}
int DLLEXPORT swmm_setSubcatchParam(int index, int Param, double value)
//
// Input: index = Index of desired ID
// param = Parameter desired (Perhaps define enum )
// value = value to be output
// Return: API Error
// Purpose: Sets Subcatchment Parameter
{
// Check if Open
if(swmm_IsOpenFlag() == FALSE) return(ERR_API_INPUTNOTOPEN);
// Check if Simulation is Running
if(swmm_IsStartedFlag() == TRUE) return(ERR_API_SIM_NRUNNING);
// Check if object index is within bounds
if (index < 0 || index >= Nobjects[SUBCATCH]) return(ERR_API_OBJECT_INDEX);
switch(Param)
{
// width
case 0: Subcatch[index].width = value / UCF(LENGTH); break;
// area
case 1: Subcatch[index].area = value / UCF(LANDAREA); break;
// fracImperv
case 2: Subcatch[index].fracImperv; break;
// slope
case 3: Subcatch[index].slope; break;
// curbLength
case 4: Subcatch[index].curbLength = value / UCF(LENGTH); break;
// initBuildup
//case 5: *value = Subcatch[index].initBuildup; break;
// Type not available
default: return(ERR_API_OUTBOUNDS);
}
//re-validate subcatchment
subcatch_validate(index); // incorprate callback here
return(0);
}
int DLLEXPORT swmm_getSubcatchOutConnection(int index, int *type, int *Index )
//
// Input: type = object type (Based on ObjectType enum) (Subcatchments can load to Node or another Subcatchment)
// index = Index of desired ID
// Output: Node1 and Node2
// Return: API Error
// Purpose: Gets Subcatchment Connection ID Indeces for either Node or Subcatchment
{
// Check if Open
if(swmm_IsOpenFlag() == FALSE) return(ERR_API_INPUTNOTOPEN);
// Check if object index is within bounds
if (index < 0 || index >= Nobjects[SUBCATCH]) return(ERR_API_OBJECT_INDEX);
if (Subcatch[index].outNode == -1 && Subcatch[index].outSubcatch == -1)
{
*Index = index; // Case of self Loading subcatchment
*type = SUBCATCH;
}
if (Subcatch[index].outNode >= 0)
{
*Index = Subcatch[index].outNode;
*type = NODE;
}
if (Subcatch[index].outSubcatch >= 0)
{
*Index = Subcatch[index].outSubcatch;
*type = SUBCATCH;
}
return(0);
}
//-------------------------------
// Active Simulation Results API
//-------------------------------
int DLLEXPORT swmm_getCurrentDateTimeStr(char *dtimestr)
//
// Output: DateTime String
// Return: API Error
// Purpose: Get the current simulation time
{
// Check if Simulation is Running
if(swmm_IsStartedFlag() == FALSE) return(ERR_API_SIM_NRUNNING);
//Provide Empty Character Array
char theDate[12];
char theTime[9];
char _DTimeStr[22];
DateTime currentTime;
// Fetch Current Time
currentTime = getDateTime(NewRoutingTime);
// Convert To Char
datetime_dateToStr(currentTime, theDate);
datetime_timeToStr(currentTime, theTime);
strcpy(_DTimeStr, theDate);
strcat(_DTimeStr, " ");
strcat(_DTimeStr, theTime);
strcpy(dtimestr, _DTimeStr);
return(0);
}
int DLLEXPORT swmm_getNodeResult(int index, int type, double *result)
//
// Input: index = Index of desired ID
// type = Result Type
// Output: result = result data desired (byref)
// Return: API Error
// Purpose: Gets Node Simulated Value
{
// Check if Simulation is Running
if(swmm_IsStartedFlag() == FALSE) return(ERR_API_SIM_NRUNNING);
// Check if object index is within bounds
if (index < 0 || index >= Nobjects[NODE]) return(ERR_API_OBJECT_INDEX);
switch (type)
{
// Total Inflow
case 0: *result = Node[index].inflow * UCF(FLOW); break;
// Total Outflow
case 1: *result = Node[index].outflow * UCF(FLOW); break;
// Losses (evap + exfiltration loss)
case 2: *result = Node[index].losses * UCF(FLOW); break;
// Current Volume
case 3: *result = Node[index].newVolume * UCF(VOLUME); break;
// overflow
case 4: *result = Node[index].overflow * UCF(FLOW); break;
// Current water depth
case 5: *result = Node[index].newDepth * UCF(LENGTH); break;
// Current water head
case 6: *result = (Node[index].newDepth + Node[index].invertElev) * UCF(LENGTH); break;
// Current Lateral Inflow
case 7: *result = Node[index].newLatFlow * UCF(FLOW); break;
// Type not available
default: return(ERR_API_OUTBOUNDS);
}
return(0);
}
int DLLEXPORT swmm_getLinkResult(int index, int type, double *result)
//
// Input: index = Index of desired ID
// type = Result Type
// Output: result = result data desired (byref)
// Return: API Error
// Purpose: Gets Node Simulated Value
{
// Check if Simulation is Running
if(swmm_IsStartedFlag() == FALSE) return(ERR_API_SIM_NRUNNING);
// Check if object index is within bounds
if (index < 0 || index >= Nobjects[LINK]) return(ERR_API_OBJECT_INDEX);
switch (type)
{
// Current Flow
case 0: *result = Link[index].newFlow * UCF(FLOW) ; break;
// Current Depth
case 1: *result = Link[index].newDepth * UCF(LENGTH); break;
// Current Volume
case 2: *result = Link[index].newVolume * UCF(VOLUME); break;
// Upstream Surface Area
case 3: *result = Link[index].surfArea1 * UCF(LENGTH) * UCF(LENGTH); break;
// Downstream Surface Area
case 4: *result = Link[index].surfArea2 * UCF(LENGTH) * UCF(LENGTH); break;
// Current Setting
case 5: *result = Link[index].setting; break;
// Target Setting
case 6: *result = Link[index].targetSetting; break;
// Froude number
case 7: *result = Link[index].froude; break;
// Type not available
default: return(ERR_API_OUTBOUNDS);
}
return(0);
}
int DLLEXPORT swmm_getSubcatchResult(int index, int type, double *result)
//
// Input: index = Index of desired ID
// type = Result Type
// Output: result = result data desired (byref)
// Return: API Error
// Purpose: Gets Node Simulated Value
{
// Check if Simulation is Running
if(swmm_IsStartedFlag() == FALSE) return(ERR_API_SIM_NRUNNING);
// Check if object index is within bounds
if (index < 0 || index >= Nobjects[SUBCATCH]) return(ERR_API_OBJECT_INDEX);
switch (type)
{
// Current Rainfall
case 0: *result = Subcatch[index].rainfall * UCF(RAINFALL); break;
// Current Evaporation Loss
case 1: *result = Subcatch[index].evapLoss * UCF(EVAPRATE); break;
// Current Infiltration Loss
case 2: *result = Subcatch[index].infilLoss * UCF(RAINFALL); break;
// Subcatchment Runon
case 3: *result = Subcatch[index].runon * UCF(FLOW); break;
// Current Runoff
case 4: *result = Subcatch[index].newRunoff * UCF(FLOW); break;
// Current Snow Depth
case 5: *result = Subcatch[index].newSnowDepth * UCF(RAINDEPTH); break;
// Type not available
default: return(ERR_API_OUTBOUNDS);
}
return(0);
}
int DLLEXPORT swmm_getNodeStats(int index, TNodeStats *nodeStats)
//
// Output: Node Stats Structure (TNodeStats)
// Return: API Error
// Purpose: Gets Node Stats and Converts Units
{
int errorcode = stats_getNodeStat(index, nodeStats);
if (errorcode == 0)
{
// Current Average Depth
nodeStats->avgDepth *= (UCF(LENGTH) / StepCount);
// Current Maximum Depth
nodeStats->maxDepth *= UCF(LENGTH);
// Current Maximum Lateral Inflow
nodeStats->maxLatFlow *= UCF(FLOW);
// Current Maximum Inflow
nodeStats->maxInflow *= UCF(FLOW);
// Cumulative Lateral Inflow
nodeStats->totLatFlow *= UCF(VOLUME);
// Time Courant Critical (hrs)
nodeStats->timeCourantCritical /= 3600.0;
// Cumulative Flooded Volume
nodeStats->volFlooded *= UCF(VOLUME);
// Time Flooded (hrs)
nodeStats->timeFlooded /= 3600.0;
// Current Maximum Overflow
nodeStats->maxOverflow *= UCF(FLOW);
// Current Maximum Ponding Volume
nodeStats->maxPondedVol *= UCF(VOLUME);
// Time Surcharged
nodeStats->timeSurcharged /= 3600.0;
}
return (errorcode);
}
int DLLEXPORT swmm_getStorageStats(int index, TStorageStats *storageStats)
//
// Output: Storage Node Stats Structure (TStorageStats)
// Return: API Error
// Purpose: Gets Storage Node Stats and Converts Units
{
int errorcode = stats_getStorageStat(index, storageStats);
if (errorcode == 0)
{
// Initial Volume
storageStats->initVol *= UCF(VOLUME);
// Current Average Volume
storageStats->avgVol *= (UCF(VOLUME) / StepCount);
// Current Maximum Volume
storageStats->maxVol *= UCF(VOLUME);
// Current Maximum Flow
storageStats->maxFlow *= UCF(FLOW);
// Current Evaporation Volume
storageStats->evapLosses *= UCF(VOLUME);
// Current Exfiltration Volume
storageStats->exfilLosses *= UCF(VOLUME);
}
return (errorcode);
}
int DLLEXPORT swmm_getOutfallStats(int index, TOutfallStats *outfallStats)
//
// Output: Outfall Stats Structure (TOutfallStats)
// Return: API Error
// Purpose: Gets Outfall Node Stats and Converts Units
// Note: Caller is responsible for calling swmm_freeOutfallStats
// to free the pollutants array.
{
int p;
int errorcode = stats_getOutfallStat(index, outfallStats);
if (errorcode == 0)
{
// Current Average Flow
outfallStats->avgFlow *= (UCF(FLOW) / StepCount);
// Current Maximum Flow
outfallStats->maxFlow *= UCF(FLOW);
// Convert Mass Units
if (Nobjects[POLLUT] > 0)
{
for (p = 0; p < Nobjects[POLLUT]; p++)
outfallStats->totalLoad[p] *= (LperFT3 * Pollut[p].mcf);
if (Pollut[p].units == COUNT)
{
outfallStats->totalLoad[p] = LOG10(outfallStats->totalLoad[p]);
}
}
}
return (errorcode);
}
void DLLEXPORT swmm_freeOutfallStats(TOutfallStats *outfallStats)
//
// Return: API Error
// Purpose: Frees Outfall Node Stats and Converts Units
// Note: API user is responsible for calling swmm_freeOutfallStats
// since this function performs a memory allocation.
{
FREE(outfallStats->totalLoad);
}
int DLLEXPORT swmm_getLinkStats(int index, TLinkStats *linkStats)
//
// Output: Link Stats Structure (TLinkStats)
// Return: API Error
// Purpose: Gets Link Stats and Converts Units
{
int errorcode = stats_getLinkStat(index, linkStats);
if (errorcode == 0)
{
// Cumulative Maximum Flowrate
linkStats->maxFlow *= UCF(FLOW);
// Cumulative Maximum Velocity
linkStats->maxVeloc *= UCF(LENGTH);
// Cumulative Maximum Depth
linkStats->maxDepth *= UCF(LENGTH);
// Cumulative Time Normal Flow
linkStats->timeNormalFlow /= 3600.0;
// Cumulative Time Inlet Control
linkStats->timeInletControl /= 3600.0;
// Cumulative Time Surcharged
linkStats->timeSurcharged /= 3600.0;
// Cumulative Time Upstream Full
linkStats->timeFullUpstream /= 3600.0;
// Cumulative Time Downstream Full
linkStats->timeFullDnstream /= 3600.0;
// Cumulative Time Full Flow
linkStats->timeFullFlow /= 3600.0;
// Cumulative Time Capacity limited
linkStats->timeCapacityLimited /= 3600.0;
// Cumulative Time Courant Critical Flow
linkStats->timeCourantCritical /= 3600.0;
}
return (errorcode);