SWMM-Docs  5.2.0.dev5
Stormwater Management Model
toolkitAPI.c
Go to the documentation of this file.
1 
11 #define _CRT_SECURE_NO_DEPRECATE
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <math.h>
17 
18 #include "headers.h"
19 #include "swmm5.h" // declaration of exportable functions
20 #include "toolkitAPI.h"
21 #include "hash.h"
22 
23 // Function Declarations for API
24 int massbal_getRoutingFlowTotal(SM_RoutingTotals *routingTot);
25 int massbal_getRunoffTotal(SM_RunoffTotals *runoffTot);
26 double massbal_getTotalArea(void);
27 int massbal_getNodeTotalInflow(int index, double *value);
28 
29 int stats_getNodeStat(int index, SM_NodeStats *nodeStats);
30 int stats_getStorageStat(int index, SM_StorageStats *storageStats);
31 int stats_getOutfallStat(int index, SM_OutfallStats *outfallStats);
32 int stats_getLinkStat(int index, SM_LinkStats *linkStats);
33 int stats_getPumpStat(int index, SM_PumpStats *pumpStats);
34 TSubcatchStats *stats_getSubcatchStat(int index);
35 
36 // Utilty Function Declarations
37 double* newDoubleArray(int n);
38 
39 //-----------------------------------------------------------------------------
40 // Extended API Functions
41 //-----------------------------------------------------------------------------
42 void DLLEXPORT swmm_getAPIError(int errcode, char *s)
48 {
49  char *errmsg = error_getMsg(errcode);
50  strcpy(s, errmsg);
51 }
52 
53 
54 int DLLEXPORT swmm_project_findObject(int type, char *id, int *index)
55 {
56  int errorcode = 0;
57 
58  int idx = project_findObject(type, id);
59 
60  if (idx == -1) {
61  index = NULL;
62  errorcode = ERR_API_OBJECT_INDEX;
63  } else
64  *index = idx;
65 
66  return errorcode;
67 }
68 
69 int DLLEXPORT swmm_getSimulationDateTime(int timetype, int *year, int *month, int *day,
70  int *hour, int *minute, int *second)
76 {
77  int errcode = 0;
78  *year = 1900;
79  *month = 1;
80  *day = 1;
81  *hour = 0;
82  *minute = 0;
83  *second = 0;
84 
85  // Check if Open
86  if (swmm_IsOpenFlag() == FALSE)
87  {
88  errcode = ERR_API_INPUTNOTOPEN;
89  }
90  else
91  {
92  DateTime _dtime;
93  switch (timetype)
94  {
95  //StartDateTime (globals.h)
96  case SM_STARTDATE: _dtime = StartDateTime; break;
97  //EndDateTime (globals.h)
98  case SM_ENDDATE: _dtime = EndDateTime; break;
99  //ReportStart (globals.h)
100  case SM_REPORTDATE: _dtime = ReportStart; break;
101  default: return(ERR_API_OUTBOUNDS);
102  }
103  datetime_decodeDate(_dtime, year, month, day);
104  datetime_decodeTime(_dtime, hour, minute, second);
105  }
106 
107  return (errcode);
108 }
109 
110 int DLLEXPORT swmm_setSimulationDateTime(int timetype, char *dtimestr)
116 {
117  int errcode = 0;
118 
119  char theDate[10];
120  char theTime[9];
121 
122  // Check if Open
123  if(swmm_IsOpenFlag() == FALSE)
124  {
125  errcode = ERR_API_INPUTNOTOPEN;
126  }
127  // Check if Simulation is Running
128  else if(swmm_IsStartedFlag() == TRUE)
129  {
130  errcode = ERR_API_SIM_NRUNNING;
131  }
132  else
133  {
134  strncpy(theDate, dtimestr, 10);
135  strncpy(theTime, dtimestr+11, 9);
136 
137  switch(timetype)
138  {
139  //StartDateTime (globals.h)
140  case SM_STARTDATE:
141  project_readOption("START_DATE", theDate);
142  project_readOption("START_TIME", theTime);
143  StartDateTime = StartDate + StartTime;
144  TotalDuration = floor((EndDateTime - StartDateTime) * SECperDAY);
145  // --- convert total duration to milliseconds
146  TotalDuration *= 1000.0;
147  break;
148  //EndDateTime (globals.h)
149  case SM_ENDDATE:
150  project_readOption("END_DATE", theDate);
151  project_readOption("END_TIME", theTime);
152  EndDateTime = EndDate + EndTime;
153  TotalDuration = floor((EndDateTime - StartDateTime) * SECperDAY);
154  // --- convert total duration to milliseconds
155  TotalDuration *= 1000.0;
156  break;
157  //ReportStart (globals.h)
158  case SM_REPORTDATE:
159  project_readOption("REPORT_START_DATE", theDate);
160  project_readOption("REPORT_START_TIME", theTime);
161  ReportStart = ReportStartDate + ReportStartTime;
162  break;
163  default: errcode = ERR_API_OUTBOUNDS; break;
164  }
165  }
166 
167  return (errcode);
168 }
169 
170 int DLLEXPORT swmm_getSimulationUnit(int type, int *value)
176 {
177  int errcode = 0;
178  *value = 0;
179  // Check if Open
180  if(swmm_IsOpenFlag() == FALSE)
181  {
182  errcode = ERR_API_INPUTNOTOPEN;
183  }
184  else
185  {
186  switch(type)
187  {
188  // System Unit (enum.h UnitsType)
189  case SM_SYSTEMUNIT: *value = UnitSystem; break;
190  // Flow Unit (enum.h FlowUnitsType)
191  case SM_FLOWUNIT: *value = FlowUnits; break;
192  // Concentration Unit
193  //case 2: *value = UnitSystem; break;
194  // Type not available
195  default: errcode = ERR_API_OUTBOUNDS; break;
196  }
197  }
198 
199  return (errcode);
200 }
201 
202 int DLLEXPORT swmm_getSimulationAnalysisSetting(int type, int *value)
208 {
209  int errcode = 0;
210  *value = 0;
211  // Check if Open
212  if(swmm_IsOpenFlag() == FALSE)
213  {
214  errcode = ERR_API_INPUTNOTOPEN;
215  }
216  else
217  {
218  switch(type)
219  {
220  // No ponding at nodes (True or False)
221  case SM_ALLOWPOND: *value = AllowPonding; break;
222  // Do flow routing in steady state periods (True or False)
223  case SM_SKIPSTEADY: *value = SkipSteadyState; break;
224  // Analyze rainfall/runoff (True or False)
225  case SM_IGNORERAIN: *value = IgnoreRainfall; break;
226  // Analyze RDII (True or False)
227  case SM_IGNORERDII: *value = IgnoreRDII; break;
228  // Analyze snowmelt (True or False)
229  case SM_IGNORESNOW: *value = IgnoreSnowmelt; break;
230  // Analyze groundwater (True or False)
231  case SM_IGNOREGW: *value = IgnoreGwater; break;
232  // Analyze flow routing (True or False)
233  case SM_IGNOREROUTE: *value = IgnoreRouting; break;
234  // Analyze water quality (True or False)
235  case SM_IGNORERQUAL: *value = IgnoreQuality; break;
236  // Type not available
237  default: errcode = ERR_API_OUTBOUNDS; break;
238  }
239  }
240  return (errcode);
241 }
242 
243 int DLLEXPORT swmm_getSimulationParam(int type, double *value)
249 {
250  int errcode = 0;
251  *value = 0;
252  // Check if Open
253  if(swmm_IsOpenFlag() == FALSE)
254  {
255  errcode = ERR_API_INPUTNOTOPEN;
256  }
257  // Output setting
258  else
259  {
260  switch(type)
261  {
262  // Routing time step (sec)
263  case SM_ROUTESTEP: *value = RouteStep; break;
264  // Minimum variable time step (sec)
265  case SM_MINROUTESTEP: *value = MinRouteStep; break;
266  // Time step for lengthening (sec)
267  case SM_LENGTHSTEP: *value = LengtheningStep; break;
268  // Antecedent dry days
269  case SM_STARTDRYDAYS: *value = StartDryDays; break;
270  // Courant time step factor
271  case SM_COURANTFACTOR: *value = CourantFactor; break;
272  // Minimum nodal surface area
273  case SM_MINSURFAREA: *value = MinSurfArea; break;
274  // Minimum conduit slope
275  case SM_MINSLOPE: *value = MinSlope; break;
276  // Runoff continuity error
277  case SM_RUNOFFERROR: *value = RunoffError; break;
278  // Groundwater continuity error
279  case SM_GWERROR: *value = GwaterError; break;
280  // Flow routing error
281  case SM_FLOWERROR: *value = FlowError; break;
282  // Quality routing error
283  case SM_QUALERROR: *value = QualError; break;
284  // DW routing head tolerance (ft)
285  case SM_HEADTOL: *value = HeadTol; break;
286  // Tolerance for steady system flow
287  case SM_SYSFLOWTOL: *value = SysFlowTol; break;
288  // Tolerance for steady nodal inflow
289  case SM_LATFLOWTOL: *value = LatFlowTol; break;
290  // Type not available
291  default: errcode = ERR_API_OUTBOUNDS; break;
292  }
293  }
294  return (errcode);
295 }
296 
297 int DLLEXPORT swmm_countObjects(int type, int *count)
303 {
304  *count = 0;
305  if(type >= MAX_OBJ_TYPES)return ERR_API_OUTBOUNDS;
306  *count = Nobjects[type];
307  return (0);
308 }
309 
310 int DLLEXPORT swmm_getObjectIndex(SM_ObjectType type, char *id, int *index)
317 {
318  int error = 0;
319 
320  // Check if Open
321  if(swmm_IsOpenFlag() == TRUE)
322  *index = project_findObject(type, id);
323  else
324  error = ERR_API_INPUTNOTOPEN;
325 
326  return error;
327 }
328 
329 int DLLEXPORT swmm_getObjectId(int type, int index, char *id)
336 {
337  int errcode = 0;
338  TLidProc* lidProc;
339  //Provide Empty Character Array
340  strcpy(id,"");
341 
342  // Check if Open
343  if(swmm_IsOpenFlag() == FALSE)
344  {
345  errcode = ERR_API_INPUTNOTOPEN;
346  }
347  // Check if object index is within bounds
348  else if (index < 0 || index >= Nobjects[type])
349  {
350  errcode = ERR_API_OBJECT_INDEX;
351  }
352  else
353  {
354  switch (type)
355  {
356  case SM_GAGE:
357  strcpy(id,Gage[index].ID); break;
358  case SM_SUBCATCH:
359  strcpy(id,Subcatch[index].ID); break;
360  case SM_NODE:
361  strcpy(id,Node[index].ID); break;
362  case SM_LINK:
363  strcpy(id,Link[index].ID); break;
364  case SM_POLLUT:
365  strcpy(id,Pollut[index].ID); break;
366  case SM_LANDUSE:
367  strcpy(id,Landuse[index].ID); break;
368  case SM_TIMEPATTERN:
369  strcpy(id,Pattern[index].ID); break;
370  case SM_CURVE:
371  strcpy(id,Curve[index].ID); break;
372  case SM_TSERIES:
373  strcpy(id,Tseries[index].ID); break;
374  //case SM_CONTROL:
375  //strcpy(id,Rules[index].ID); break;
376  case SM_TRANSECT:
377  strcpy(id,Transect[index].ID); break;
378  case SM_AQUIFER:
379  strcpy(id,Aquifer[index].ID); break;
380  case SM_UNITHYD:
381  strcpy(id,UnitHyd[index].ID); break;
382  case SM_SNOWMELT:
383  strcpy(id,Snowmelt[index].ID); break;
384  //case SM_SHAPE:
385  //strcpy(id,Shape[index].ID); break;
386  case SM_LID:
387  lidProc = lid_getLidProc(index);
388  if (lidProc != NULL)
389  {
390  strcpy(id,lidProc->ID);
391  }
392  break;
393  default: errcode = ERR_API_OUTBOUNDS; break;
394  }
395  }
396  return(errcode);
397 }
398 
399 int DLLEXPORT swmm_getNodeType(int index, int *Ntype)
405 {
406  int errcode = 0;
407  *Ntype = -1;
408  // Check if Open
409  if(swmm_IsOpenFlag() == FALSE)
410  {
411  errcode = ERR_API_INPUTNOTOPEN;
412  }
413  // Check if object index is within bounds
414  else if (index < 0 || index >= Nobjects[NODE])
415  {
416  errcode = ERR_API_OBJECT_INDEX;
417  }
418  else *Ntype = Node[index].type;
419 
420  return(errcode);
421 }
422 
423 int DLLEXPORT swmm_getLinkType(int index, int *Ltype)
429 {
430  int errcode = 0;
431  *Ltype = -1;
432  // Check if Open
433  if(swmm_IsOpenFlag() == FALSE)
434  {
435  errcode = ERR_API_INPUTNOTOPEN;
436  }
437  // Check if object index is within bounds
438  else if (index < 0 || index >= Nobjects[LINK])
439  {
440  errcode = ERR_API_OBJECT_INDEX;
441  }
442  else *Ltype = Link[index].type;
443 
444  return(errcode);
445 }
446 
447 int DLLEXPORT swmm_getLinkConnections(int index, int *Node1, int *Node2)
453 {
454  int errcode = 0;
455  *Node1 = -1;
456  *Node2 = -1;
457  // Check if Open
458  if(swmm_IsOpenFlag() == FALSE)
459  {
460  errcode = ERR_API_INPUTNOTOPEN;
461  }
462  // Check if object index is within bounds
463  else if (index < 0 || index >= Nobjects[LINK])
464  {
465  errcode = ERR_API_OBJECT_INDEX;
466  }
467  else
468  {
469  *Node1 = Link[index].node1;
470  *Node2 = Link[index].node2;
471  }
472  return(errcode);
473 }
474 
475 int DLLEXPORT swmm_getLinkDirection(int index, signed char *value)
481 {
482  int errcode = 0;
483  *value = 0;
484  // Check if Open
485  if(swmm_IsOpenFlag() == FALSE)
486  {
487  errcode = ERR_API_INPUTNOTOPEN;
488  }
489  // Check if object index is within bounds
490  else if (index < 0 || index >= Nobjects[LINK])
491  {
492  errcode = ERR_API_OBJECT_INDEX;
493  }
494  else
495  {
496  *value = Link[index].direction;
497  }
498  return(errcode);
499 }
500 
501 int DLLEXPORT swmm_getNodeParam(int index, int Param, double *value)
508 {
509  int errcode = 0;
510  *value = 0;
511  // Check if Open
512  if(swmm_IsOpenFlag() == FALSE)
513  {
514  errcode = ERR_API_INPUTNOTOPEN;
515  }
516  // Check if object index is within bounds
517  else if (index < 0 || index >= Nobjects[NODE])
518  {
519  errcode = ERR_API_OBJECT_INDEX;
520  }
521  else
522  {
523  switch(Param)
524  {
525  case SM_INVERTEL:
526  *value = Node[index].invertElev * UCF(LENGTH); break;
527  case SM_FULLDEPTH:
528  *value = Node[index].fullDepth * UCF(LENGTH); break;
529  case SM_SURCHDEPTH:
530  *value = Node[index].surDepth * UCF(LENGTH); break;
531  case SM_PONDAREA:
532  *value = Node[index].pondedArea * UCF(LENGTH) * UCF(LENGTH); break;
533  case SM_INITDEPTH:
534  *value = Node[index].initDepth * UCF(LENGTH); break;
535  default: errcode = ERR_API_OUTBOUNDS; break;
536  }
537  }
538  return(errcode);
539 }
540 
541 int DLLEXPORT swmm_setNodeParam(int index, int Param, double value)
548 {
549  int errcode = 0;
550  // Check if Open
551  if(swmm_IsOpenFlag() == FALSE)
552  {
553  errcode = ERR_API_INPUTNOTOPEN;
554  }
555  // Check if Simulation is Running
556  else if(swmm_IsStartedFlag() == TRUE)
557  {
558  errcode = ERR_API_SIM_NRUNNING;
559  }
560  // Check if object index is within bounds
561  else if (index < 0 || index >= Nobjects[NODE])
562  {
563  errcode = ERR_API_OBJECT_INDEX;
564  }
565  else
566  {
567  switch(Param)
568  {
569  case SM_INVERTEL:
570  Node[index].invertElev = value / UCF(LENGTH); break;
571  case SM_FULLDEPTH:
572  Node[index].fullDepth = value / UCF(LENGTH); break;
573  case SM_SURCHDEPTH:
574  Node[index].surDepth = value / UCF(LENGTH); break;
575  case SM_PONDAREA:
576  Node[index].pondedArea = value / ( UCF(LENGTH) * UCF(LENGTH) ); break;
577  case SM_INITDEPTH:
578  Node[index].initDepth = value / UCF(LENGTH); break;
579  default: errcode = ERR_API_OUTBOUNDS; break;
580  }
581  }
582  // Re-validated a node BEM 1/20/2017 Probably need to re-validate connecting links
583  //node_validate(index)
584  return(errcode);
585 }
586 
587 int DLLEXPORT swmm_getLinkParam(int index, int Param, double *value)
594 {
595  int errcode = 0;
596  *value = 0;
597  // Check if Open
598  if(swmm_IsOpenFlag() == FALSE)
599  {
600  errcode = ERR_API_INPUTNOTOPEN;
601  }
602  // Check if object index is within bounds
603  else if (index < 0 || index >= Nobjects[LINK])
604  {
605  errcode = ERR_API_OBJECT_INDEX;
606  }
607  else
608  {
609  switch(Param)
610  {
611  case SM_OFFSET1:
612  *value = Link[index].offset1 * UCF(LENGTH); break;
613  case SM_OFFSET2:
614  *value = Link[index].offset2 * UCF(LENGTH); break;
615  case SM_INITFLOW:
616  *value = Link[index].q0 * UCF(FLOW); break;
617  case SM_FLOWLIMIT:
618  *value = Link[index].qLimit * UCF(FLOW); break;
619  case SM_INLETLOSS:
620  *value = Link[index].cLossInlet; break;
621  case SM_OUTLETLOSS:
622  *value = Link[index].cLossOutlet; break;
623  case SM_AVELOSS:
624  *value = Link[index].cLossAvg; break;
625  default: errcode = ERR_API_OUTBOUNDS; break;
626  }
627  }
628  return(errcode);
629 }
630 
631 int DLLEXPORT swmm_setLinkParam(int index, int Param, double value)
638 {
639  int errcode = 0;
640  // Check if Open
641  if(swmm_IsOpenFlag() == FALSE)
642  {
643  errcode = ERR_API_INPUTNOTOPEN;
644  }
645  // Check if object index is within bounds
646  else if (index < 0 || index >= Nobjects[LINK])
647  {
648  errcode = ERR_API_OBJECT_INDEX;
649  }
650  else
651  {
652  switch(Param)
653  {
654  // offset1
655  case SM_OFFSET1:
656  // Check if Simulation is Running
657  if(swmm_IsStartedFlag() == TRUE)
658  {
659  errcode = ERR_API_SIM_NRUNNING; break;
660  }
661  Link[index].offset1 = value / UCF(LENGTH); break;
662  case SM_OFFSET2:
663  // Check if Simulation is Running
664  if(swmm_IsStartedFlag() == TRUE)
665  {
666  errcode = ERR_API_SIM_NRUNNING; break;
667  }
668  Link[index].offset2 = value / UCF(LENGTH); break;
669  case SM_INITFLOW:
670  Link[index].q0 = value / UCF(FLOW); break;
671  case SM_FLOWLIMIT:
672  Link[index].qLimit = value / UCF(FLOW); break;
673  case SM_INLETLOSS:
674  Link[index].cLossInlet = value; break;
675  case SM_OUTLETLOSS:
676  Link[index].cLossOutlet = value; break;
677  case SM_AVELOSS:
678  Link[index].cLossAvg = value; break;
679  default: errcode = ERR_API_OUTBOUNDS; break;
680  }
681  // re-validated link
682  //link_validate(index);
683  }
684 
685  return(errcode);
686 }
687 
688 
689 int DLLEXPORT swmm_getSubcatchParam(int index, int Param, double *value)
696 {
697  int errcode = 0;
698  *value = 0;
699  // Check if Open
700  if(swmm_IsOpenFlag() == FALSE)
701  {
702  errcode = ERR_API_INPUTNOTOPEN;
703  }
704  // Check if object index is within bounds
705  else if (index < 0 || index >= Nobjects[SUBCATCH])
706  {
707  errcode = ERR_API_OBJECT_INDEX;
708  }
709  else
710  {
711  switch(Param)
712  {
713  case SM_WIDTH:
714  *value = Subcatch[index].width * UCF(LENGTH); break;
715  case SM_AREA:
716  *value = Subcatch[index].area * UCF(LANDAREA); break;
717  case SM_FRACIMPERV:
718  *value = Subcatch[index].fracImperv; break;
719  case SM_SLOPE:
720  *value = Subcatch[index].slope; break;
721  case SM_CURBLEN:
722  *value = Subcatch[index].curbLength * UCF(LENGTH); break;
723  default: errcode = ERR_API_OUTBOUNDS; break;
724  }
725  }
726  return(errcode);
727 }
728 
729 int DLLEXPORT swmm_setSubcatchParam(int index, int Param, double value)
736 {
737  int errcode = 0;
738  // Check if Open
739  if(swmm_IsOpenFlag() == FALSE)
740  {
741  errcode = ERR_API_INPUTNOTOPEN;
742  }
743  // Check if Simulation is Running
744  else if(swmm_IsStartedFlag() == TRUE)
745  {
746  errcode = ERR_API_SIM_NRUNNING;
747  }
748  // Check if object index is within bounds
749  else if (index < 0 || index >= Nobjects[SUBCATCH])
750  {
751  errcode = ERR_API_OBJECT_INDEX;
752  }
753  else
754  {
755  switch(Param)
756  {
757  case SM_WIDTH:
758  Subcatch[index].width = value / UCF(LENGTH); break;
759  case SM_AREA:
760  Subcatch[index].area = value / UCF(LANDAREA); break;
761  case SM_FRACIMPERV:
762  break; //Subcatch[index].fracImperv; break;
763  // Cannot Open Function just yet. Need
764  // to adjust some internal functions to
765  // ensure parameters are recalculated
766  // = MIN(value, 100.0) / 100.0; break;
767  case SM_SLOPE:
768  Subcatch[index].slope = value; break;
769  case SM_CURBLEN:
770  Subcatch[index].curbLength = value / UCF(LENGTH); break;
771  default: errcode = ERR_API_OUTBOUNDS; break;
772  }
773  //re-validate subcatchment
774  subcatch_validate(index); // incorprate callback here
775  }
776 
777  return(errcode);
778 }
779 
780 int DLLEXPORT swmm_getSubcatchOutConnection(int index, int *type, int *out_index)
788 {
789  int errcode = 0;
790  *type = -1;
791  *out_index = -1;
792  // Check if Open
793  if(swmm_IsOpenFlag() == FALSE)
794  {
795  errcode = ERR_API_INPUTNOTOPEN;
796  }
797  // Check if object index is within bounds
798  else if (index < 0 || index >= Nobjects[SUBCATCH])
799  {
800  errcode = ERR_API_OBJECT_INDEX;
801  }
802  else
803  {
804  if (Subcatch[index].outNode == -1 && Subcatch[index].outSubcatch == -1)
805  {
806  *out_index = index; // Case of self Loading subcatchment
807  *type = SUBCATCH;
808  }
809  if (Subcatch[index].outNode >= 0)
810  {
811  *out_index = Subcatch[index].outNode;
812  *type = NODE;
813  }
814  if (Subcatch[index].outSubcatch >= 0)
815  {
816  *out_index = Subcatch[index].outSubcatch;
817  *type = SUBCATCH;
818  }
819  }
820  return(errcode);
821 }
822 
823 
824 int DLLEXPORT swmm_getLidUCount(int index, int *value)
825 // Input: index = Index of desired subcatchment
826 // Output: int = number of lid units for subcatchment
827 // Return: number of lid units for subcatchment
828 // Purpose: count number of lid units for subcatchment
829 {
830  int errcode = 0;
831 
832  // Check if Open
833  if(swmm_IsOpenFlag() == FALSE)
834  {
835  errcode = ERR_API_INPUTNOTOPEN;
836  }
837  // Check if subcatchment index is within bounds
838  else if(index < 0 || index >= Nobjects[SUBCATCH])
839  {
840  errcode = ERR_API_OBJECT_INDEX;
841  }
842  else
843  {
844  *value = lid_getLidUnitCount(index);
845  }
846 
847  return (errcode);
848 }
849 
850 
851 int DLLEXPORT swmm_getLidUParam(int index, int lidIndex, int param, double *value)
852 //
853 // Input: index = Index of desired subcatchment
854 // lidIndex = Index of desired lid unit (subcatchment allow for multiple lid units)
855 // param = Parameter desired (Based on enum SM_LidUProperty)
856 // Output: value = value to be output
857 // Return: API Error
858 // Purpose: Gets Lid Unit Parameter
859 {
860  int errcode = 0;
861  TLidUnit* lidUnit;
862 
863  // Check if Open
864  if(swmm_IsOpenFlag() == FALSE)
865  {
866  errcode = ERR_API_INPUTNOTOPEN;
867  }
868  // Check if subcatchment index is within bounds
869  else if(index < 0 || index >= Nobjects[SUBCATCH])
870  {
871  errcode = ERR_API_OBJECT_INDEX;
872  }
873  else
874  {
875  lidUnit = lid_getLidUnit(index, lidIndex, &errcode);
876 
877  // There are no Lid Units defined for the subcatchments
878  if(lidUnit)
879  {
880  switch(param)
881  {
882  case SM_UNITAREA:
883  *value = lidUnit->area * SQR(UCF(LENGTH));
884  break;
885  case SM_FWIDTH:
886  *value = lidUnit->fullWidth * UCF(LENGTH); break;
887  case SM_BWIDTH:
888  *value = lidUnit->botWidth * UCF(LENGTH); break;
889  case SM_INITSAT:
890  *value = lidUnit->initSat * 100; break;
891  case SM_FROMIMPERV:
892  *value = lidUnit->fromImperv * 100; break;
893  case SM_FROMPERV:
894  *value = lidUnit->fromPerv * 100; break;
895  default:
896  errcode = ERR_API_OUTBOUNDS; break;
897  }
898  }
899  }
900 
901  return(errcode);
902 }
903 
904 
905 int DLLEXPORT swmm_setLidUParam(int index, int lidIndex, int Param, double value)
906 //
907 // Input: index = Index of desired subcatchment
908 // lidIndex = Index of desired lid unit (subcatchment allow for multiple lid units)
909 // param = Parameter desired (Based on enum SM_LidUProperty)
910 // value = replacement
911 // Return: API Error
912 // Purpose: Gets Lid Unit Parameter
913 {
914  int errcode = 0;
915  TLidUnit* lidUnit;
916 
917  // Check if Open
918  if(swmm_IsOpenFlag() == FALSE)
919  {
920  errcode = ERR_API_INPUTNOTOPEN;
921  }
922  // Check if subcatchment index is within bounds
923  else if(index < 0 || index >= Nobjects[SUBCATCH])
924  {
925  errcode = ERR_API_OBJECT_INDEX;
926  }
927  // Check if model is running
928  else if(swmm_IsStartedFlag() == TRUE)
929  {
930  errcode = ERR_API_SIM_NRUNNING;
931  }
932  else
933  {
934  lidUnit = lid_getLidUnit(index, lidIndex, &errcode);
935 
936  // There are no Lid Units defined for the subcatchments
937  if(lidUnit)
938  {
939  switch(Param)
940  {
941  case SM_UNITAREA:
942  lidUnit->area = value / SQR(UCF(LENGTH));
943  break;
944  case SM_FWIDTH:
945  lidUnit->fullWidth = value / UCF(LENGTH); break;
946  //case SM_BWIDTH:
947  // lidUnit->botWidth = value / UCF(LENGTH); break;
948  case SM_INITSAT:
949  lidUnit->initSat = value / 100; break;
950  case SM_FROMIMPERV:
951  lidUnit->fromImperv = value / 100; break;
952  case SM_FROMPERV:
953  lidUnit->fromPerv = value / 100; break;
954  default:
955  errcode = ERR_API_OUTBOUNDS; break;
956  }
957  }
958  }
959 
960  if(errcode == ERR_NONE)
961  {
962  lid_validateLidGroup(index);
963  lid_updateLidGroup(index);
964  }
965 
966  return(errcode);
967 }
968 
969 
970 int DLLEXPORT swmm_getLidUOption(int index, int lidIndex, int param, int *value)
971 //
972 // Input: index = Index of desired subcatchment
973 // lidIndex = Index of desired lid unit (subcatchment allow for multiple lid units)
974 // param = Parameter desired (Based on enum SM_LidUOption)
975 // Output: value = value to be output
976 // Return: API Error
977 // Purpose: Gets Lid Unit Option Parameter
978 {
979  int errcode = 0;
980  TLidUnit* lidUnit;
981 
982  // Check if Open
983  if(swmm_IsOpenFlag() == FALSE)
984  {
985  errcode = ERR_API_INPUTNOTOPEN;
986  }
987  // Check if subcatchment index is within bounds
988  else if(index < 0 || index >= Nobjects[SUBCATCH])
989  {
990  errcode = ERR_API_OBJECT_INDEX;
991  }
992  else
993  {
994  lidUnit = lid_getLidUnit(index, lidIndex, &errcode);
995 
996  // There are no Lid Units defined for the subcatchments
997  if(lidUnit)
998  {
999 
1000  switch(param)
1001  {
1002  case SM_INDEX:
1003  *value = lidUnit->lidIndex; break;
1004  case SM_NUMBER:
1005  *value = lidUnit->number; break;
1006  case SM_TOPERV:
1007  *value = lidUnit->toPerv; break;
1008  case SM_DRAINSUB:
1009  *value = lidUnit->drainSubcatch; break;
1010  case SM_DRAINNODE:
1011  *value = lidUnit->drainNode; break;
1012  default:
1013  errcode = ERR_API_OUTBOUNDS; break;
1014  }
1015  }
1016  }
1017 
1018  return(errcode);
1019 }
1020 
1021 
1022 int DLLEXPORT swmm_setLidUOption(int index, int lidIndex, int param, int value)
1023 //
1024 // Input: index = Index of desired subcatchment
1025 // lidIndex = Index of desired lid unit (subcatchment allow for multiple lid units)
1026 // param = Parameter desired (Based on enum SM_LidUOption)
1027 // value = replacement value
1028 // Return: API Error
1029 // Purpose: Sets Lid Unit Option
1030 {
1031  int errcode = 0;
1032  TLidUnit* lidUnit;
1033 
1034  // Check if Open
1035  if(swmm_IsOpenFlag() == FALSE)
1036  {
1037  errcode = ERR_API_INPUTNOTOPEN;
1038  }
1039  // Check if subcatchment index is within bounds
1040  else if(index < 0 || index >= Nobjects[SUBCATCH])
1041  {
1042  errcode = ERR_API_OBJECT_INDEX;
1043  }
1044  // Check if model is running
1045  else if(swmm_IsStartedFlag() == TRUE)
1046  {
1047  errcode = ERR_API_SIM_NRUNNING;
1048  }
1049  else
1050  {
1051  lidUnit = lid_getLidUnit(index, lidIndex, &errcode);
1052 
1053  // There are no Lid Units defined for the subcatchments
1054  if(lidUnit)
1055  {
1056  switch(param)
1057  {
1058  case SM_INDEX:
1059  lidUnit->lidIndex = value; break;
1060  case SM_NUMBER:
1061  lidUnit->number = value;
1062  break;
1063  case SM_TOPERV:
1064  lidUnit->toPerv = (value > 0.0); break;
1065  case SM_DRAINSUB:
1066  lidUnit->drainSubcatch = value;
1067  lidUnit->drainNode = -1;
1068  break;
1069  case SM_DRAINNODE:
1070  lidUnit->drainNode = value;
1071  lidUnit->drainSubcatch = -1;
1072  break;
1073  default:
1074  errcode = ERR_API_OUTBOUNDS; break;
1075  }
1076  }
1077  }
1078 
1079  if(errcode == ERR_NONE)
1080  {
1081  lid_validateLidGroup(index);
1082  lid_updateLidGroup(index);
1083  }
1084 
1085  return(errcode);
1086 }
1087 
1088 
1089 int DLLEXPORT swmm_getLidCOverflow(int lidControlIndex, char *condition)
1090 //
1091 // Input: lidControlIndex = Index of desired lid control
1092 // Output: condition = value to be output
1093 // Return: API Error
1094 // Purpose: Get Lid Control Surface Immediate Overflow Condition
1095 {
1096  int errcode = 0;
1097  TLidProc* lidProc;
1098 
1099  // Check if Open
1100  if(swmm_IsOpenFlag() == FALSE)
1101  {
1102  errcode = ERR_API_INPUTNOTOPEN;
1103  }
1104  // Check if subcatchment index is within bounds
1105  else if(lidControlIndex < 0 || lidControlIndex >= Nobjects[LID])
1106  {
1107  errcode = ERR_API_OBJECT_INDEX;
1108  }
1109  else
1110  {
1111  lidProc = lid_getLidProc(lidControlIndex);
1112  if (lidProc != NULL)
1113  {
1114  *condition = lidProc->surface.canOverflow;
1115 
1116  }
1117  }
1118  return(errcode);
1119 }
1120 
1121 int DLLEXPORT swmm_getLidCParam(int lidControlIndex, int layerIndex, int param, double *value)
1122 //
1123 // Input: lidControlIndex = Index of desired lid control
1124 // layerIndex = Index of desired lid control layer (Based on enum SM_LidLayers)
1125 // param = Parameter desired (Based on enum SM_LidLayersProperty)
1126 // Output: value = value to be output
1127 // Return: API Error
1128 // Purpose: Gets Lid Control Layer Parameter
1129 {
1130  int errcode = 0;
1131  TLidProc* lidProc;
1132 
1133  // Check if Open
1134  if(swmm_IsOpenFlag() == FALSE)
1135  {
1136  errcode = ERR_API_INPUTNOTOPEN;
1137  }
1138  // Check if subcatchment index is within bounds
1139  else if(lidControlIndex < 0 || lidControlIndex >= Nobjects[LID])
1140  {
1141  errcode = ERR_API_OBJECT_INDEX;
1142  }
1143  else
1144  {
1145  lidProc = lid_getLidProc(lidControlIndex);
1146 
1147  switch(layerIndex)
1148  {
1149  case SM_SURFACE:
1150  switch(param)
1151  {
1152  case SM_THICKNESS:
1153  *value = lidProc->surface.thickness * UCF(RAINDEPTH); break;
1154  case SM_VOIDFRAC:
1155  *value = 1 - lidProc->surface.voidFrac; break;
1156  case SM_ROUGHNESS:
1157  *value = lidProc->surface.roughness; break;
1158  case SM_SURFSLOPE:
1159  *value = lidProc->surface.surfSlope * 100; break;
1160  case SM_SIDESLOPE:
1161  *value = lidProc->surface.sideSlope; break;
1162  case SM_ALPHA:
1163  *value = lidProc->surface.alpha; break;
1164  default:
1165  errcode = ERR_API_OUTBOUNDS; break;
1166  }
1167  break;
1168  case SM_SOIL:
1169  switch(param)
1170  {
1171  case SM_THICKNESS:
1172  *value = lidProc->soil.thickness * UCF(RAINDEPTH); break;
1173  case SM_POROSITY:
1174  *value = lidProc->soil.porosity; break;
1175  case SM_FIELDCAP:
1176  *value = lidProc->soil.fieldCap; break;
1177  case SM_WILTPOINT:
1178  *value = lidProc->soil.wiltPoint; break;
1179  case SM_KSAT:
1180  *value = lidProc->soil.kSat * UCF(RAINFALL); break;
1181  case SM_KSLOPE:
1182  *value = lidProc->soil.kSlope; break;
1183  case SM_SUCTION:
1184  *value = lidProc->soil.suction * UCF(RAINDEPTH); break;
1185  default:
1186  errcode = ERR_API_OUTBOUNDS; break;
1187  }
1188  break;
1189  case SM_STOR:
1190  switch(param)
1191  {
1192  case SM_THICKNESS:
1193  *value = lidProc->storage.thickness * UCF(RAINDEPTH); break;
1194  case SM_VOIDFRAC:
1195  if (lidProc->storage.voidFrac < 1)
1196  {
1197  *value = lidProc->storage.voidFrac / (1 - lidProc->storage.voidFrac);
1198  }
1199  else
1200  {
1201  *value = lidProc->storage.voidFrac;
1202  }
1203  break;
1204  case SM_KSAT:
1205  *value = lidProc->storage.kSat * UCF(RAINFALL); break;
1206  case SM_CLOGFACTOR:
1207  if (lidProc->storage.thickness > 0.0)
1208  {
1209  *value = lidProc->storage.clogFactor /
1210  (lidProc->storage.thickness *
1211  lidProc->storage.voidFrac);
1212  }
1213  else
1214  {
1215  *value = lidProc->pavement.clogFactor;
1216  }
1217  break;
1218  default:
1219  errcode = ERR_API_OUTBOUNDS; break;
1220  }
1221  break;
1222  case SM_PAVE:
1223  switch(param)
1224  {
1225  case SM_THICKNESS:
1226  *value = lidProc->pavement.thickness * UCF(RAINDEPTH); break;
1227  case SM_VOIDFRAC:
1228  if (lidProc->pavement.voidFrac < 1)
1229  {
1230  *value = lidProc->pavement.voidFrac / (1 - lidProc->pavement.voidFrac);
1231  }
1232  else
1233  {
1234  *value = lidProc->pavement.voidFrac;
1235  }
1236  break;
1237  case SM_IMPERVFRAC:
1238  *value = lidProc->pavement.impervFrac; break;
1239  case SM_KSAT:
1240  *value = lidProc->pavement.kSat * UCF(RAINFALL); break;
1241  case SM_CLOGFACTOR:
1242  if (lidProc->pavement.thickness > 0.0)
1243  {
1244  *value = lidProc->pavement.clogFactor /
1245  (lidProc->pavement.thickness *
1246  lidProc->pavement.voidFrac *
1247  (1 - lidProc->pavement.impervFrac));
1248  }
1249  else
1250  {
1251  *value = lidProc->pavement.clogFactor;
1252  }
1253  break;
1254  case SM_REGENDAYS:
1255  *value = lidProc->pavement.regenDays; break;
1256  case SM_REGENDEGREE:
1257  *value = lidProc->pavement.regenDegree; break;
1258  default:
1259  errcode = ERR_API_OUTBOUNDS; break;
1260  }
1261  break;
1262  case SM_DRAIN:
1263  switch(param)
1264  {
1265  case SM_COEFF:
1266  *value = lidProc->drain.coeff; break;
1267  case SM_EXPON:
1268  *value = lidProc->drain.expon; break;
1269  case SM_OFFSET:
1270  *value = lidProc->drain.offset * UCF(RAINDEPTH); break;
1271  case SM_DELAY:
1272  *value = lidProc->drain.delay / 3600; break;
1273  case SM_HOPEN:
1274  *value = lidProc->drain.hOpen * UCF(RAINDEPTH); break;
1275  case SM_HCLOSE:
1276  *value = lidProc->drain.hClose * UCF(RAINDEPTH); break;
1277  default:
1278  errcode = ERR_API_OUTBOUNDS; break;
1279  }
1280  break;
1281  case SM_DRAINMAT:
1282  switch(param)
1283  {
1284  case SM_THICKNESS:
1285  *value = lidProc->drainMat.thickness * UCF(RAINDEPTH); break;
1286  case SM_VOIDFRAC:
1287  *value = lidProc->drainMat.voidFrac; break;
1288  case SM_ROUGHNESS:
1289  *value = lidProc->drainMat.roughness; break;
1290  case SM_ALPHA:
1291  *value = lidProc->drainMat.alpha; break;
1292  default:
1293  errcode = ERR_API_OUTBOUNDS; break;
1294  }
1295  break;
1296  default:
1297  errcode = ERR_API_OUTBOUNDS; break;
1298  }
1299  }
1300  return(errcode);
1301 }
1302 
1303 
1304 int DLLEXPORT swmm_setLidCParam(int lidControlIndex, int layerIndex, int param, double value)
1305 //
1306 // Input: lidControlIndex = Index of desired lid control
1307 // layerIndex = Index of desired lid control layer (Based on enum SM_LidLayers)
1308 // param = Parameter desired (Based on enum SM_LidLayersProperty)
1309 // value = replacement value
1310 // Return: API Error
1311 // Purpose: Sets Lid Control Layer Parameter
1312 {
1313  int errcode = 0;
1314  TLidProc* lidProc;
1315 
1316  // Check if Open
1317  if(swmm_IsOpenFlag() == FALSE)
1318  {
1319  errcode = ERR_API_INPUTNOTOPEN;
1320  }
1321  // Check if subcatchment index is within bounds
1322  else if(lidControlIndex < 0 || lidControlIndex >= Nobjects[LID])
1323  {
1324  errcode = ERR_API_OBJECT_INDEX;
1325  }
1326  else
1327  {
1328  lidProc = lid_getLidProc(lidControlIndex);
1329 
1330  switch(layerIndex)
1331  {
1332  case SM_SURFACE:
1333  switch(param)
1334  {
1335  case SM_THICKNESS:
1336  lidProc->surface.thickness = value / UCF(RAINDEPTH); break;
1337  case SM_VOIDFRAC:
1338  lidProc->surface.voidFrac = 1 - value; break;
1339  case SM_ROUGHNESS:
1340  lidProc->surface.roughness = value; break;
1341  case SM_SURFSLOPE:
1342  lidProc->surface.surfSlope = value / 100; break;
1343  case SM_SIDESLOPE:
1344  lidProc->surface.sideSlope = value; break;
1345  //case SM_ALPHA:
1346  // lidProc->surface.alpha = value; break;
1347  default:
1348  errcode = ERR_API_OUTBOUNDS; break;
1349  }
1350  break;
1351  case SM_SOIL:
1352  switch(param)
1353  {
1354  case SM_THICKNESS:
1355  lidProc->soil.thickness = value / UCF(RAINDEPTH); break;
1356  case SM_POROSITY:
1357  lidProc->soil.porosity = value; break;
1358  case SM_FIELDCAP:
1359  lidProc->soil.fieldCap = value; break;
1360  case SM_WILTPOINT:
1361  lidProc->soil.wiltPoint = value; break;
1362  case SM_KSAT:
1363  lidProc->soil.kSat = value / UCF(RAINFALL); break;
1364  case SM_KSLOPE:
1365  lidProc->soil.kSlope = value; break;
1366  case SM_SUCTION:
1367  lidProc->soil.suction = value / UCF(RAINDEPTH); break;
1368  default:
1369  errcode = ERR_API_OUTBOUNDS; break;
1370  }
1371  break;
1372  case SM_STOR:
1373  switch(param)
1374  {
1375  case SM_THICKNESS:
1376  if (lidProc->storage.thickness > 0)
1377  {
1378  lidProc->storage.clogFactor /= lidProc->storage.thickness;
1379  lidProc->storage.thickness = value / UCF(RAINDEPTH);
1380  lidProc->storage.clogFactor *= lidProc->storage.thickness;
1381  }
1382  else
1383  {
1384  lidProc->storage.thickness = value / UCF(RAINDEPTH);
1385  }
1386  break;
1387  case SM_VOIDFRAC:
1388  if (lidProc->storage.voidFrac > 0)
1389  {
1390  lidProc->storage.clogFactor /= lidProc->storage.voidFrac;
1391  lidProc->storage.voidFrac = value / (value + 1);
1392  lidProc->storage.clogFactor *= lidProc->storage.voidFrac;
1393  }
1394  else
1395  {
1396  lidProc->storage.voidFrac = value / (value + 1);
1397  }
1398 
1399  break;
1400  case SM_KSAT:
1401  lidProc->storage.kSat = value / UCF(RAINFALL); break;
1402  case SM_CLOGFACTOR:
1403  lidProc->storage.clogFactor = value *
1404  lidProc->storage.thickness *
1405  lidProc->storage.voidFrac;
1406  break;
1407  default:
1408  errcode = ERR_API_OUTBOUNDS; break;
1409  }
1410  break;
1411  case SM_PAVE:
1412  switch(param)
1413  {
1414  case SM_THICKNESS:
1415  if (lidProc->pavement.thickness > 0)
1416  {
1417  lidProc->pavement.clogFactor /= lidProc->pavement.thickness;
1418  lidProc->pavement.thickness = value / UCF(RAINDEPTH);
1419  lidProc->pavement.clogFactor *= lidProc->pavement.thickness;
1420  }
1421  else
1422  {
1423  lidProc->pavement.thickness = value / UCF(RAINDEPTH);
1424  }
1425  break;
1426  case SM_VOIDFRAC:
1427  if (lidProc->pavement.voidFrac > 0)
1428  {
1429  lidProc->pavement.clogFactor /= lidProc->pavement.voidFrac;
1430  lidProc->pavement.voidFrac = value / (value + 1);
1431  lidProc->pavement.clogFactor *= lidProc->pavement.voidFrac;
1432  }
1433  else
1434  {
1435  lidProc->pavement.voidFrac = value / (value + 1);
1436  }
1437  break;
1438  case SM_IMPERVFRAC:
1439  if (lidProc->pavement.impervFrac > 0)
1440  {
1441  lidProc->pavement.clogFactor /= (1 - lidProc->pavement.impervFrac);
1442  lidProc->pavement.impervFrac = value;
1443  lidProc->pavement.clogFactor *= (1 - lidProc->pavement.impervFrac);
1444  }
1445  else
1446  {
1447  lidProc->pavement.impervFrac = value;
1448  }
1449  break;
1450  case SM_KSAT:
1451  lidProc->pavement.kSat = value / UCF(RAINFALL); break;
1452  case SM_CLOGFACTOR:
1453  lidProc->pavement.clogFactor = value *
1454  lidProc->pavement.thickness *
1455  lidProc->pavement.voidFrac *
1456  (1.0 - lidProc->pavement.impervFrac);
1457  break;
1458  case SM_REGENDAYS:
1459  lidProc->pavement.regenDays = value; break;
1460  case SM_REGENDEGREE:
1461  lidProc->pavement.regenDegree = value; break;
1462  default:
1463  errcode = ERR_API_OUTBOUNDS; break;
1464  }
1465  break;
1466  case SM_DRAIN:
1467  switch(param)
1468  {
1469  case SM_COEFF:
1470  lidProc->drain.coeff = value; break;
1471  case SM_EXPON:
1472  lidProc->drain.expon = value; break;
1473  case SM_OFFSET:
1474  lidProc->drain.offset = value / UCF(RAINDEPTH); break;
1475  case SM_DELAY:
1476  lidProc->drain.delay = value * 3600; break;
1477  case SM_HOPEN:
1478  lidProc->drain.hOpen = value / UCF(RAINDEPTH); break;
1479  case SM_HCLOSE:
1480  lidProc->drain.hClose = value / UCF(RAINDEPTH); break;
1481  default:
1482  errcode = ERR_API_OUTBOUNDS; break;
1483  }
1484  break;
1485  case SM_DRAINMAT:
1486  switch(param)
1487  {
1488  case SM_THICKNESS:
1489  lidProc->drainMat.thickness = value / UCF(RAINDEPTH); break;
1490  case SM_VOIDFRAC:
1491  lidProc->drainMat.voidFrac = value; break;
1492  case SM_ROUGHNESS:
1493  lidProc->drainMat.roughness = value; break;
1494  //case SM_ALPHA:
1495  // lidProc->drainMat.alpha = value; break;
1496  default:
1497  errcode = ERR_API_OUTBOUNDS; break;
1498  }
1499  break;
1500  default:
1501  errcode = ERR_API_OUTBOUNDS; break;
1502  }
1503 
1504  }
1505  if(errcode == ERR_NONE)
1506  {
1507  lid_validateLidProc(lidControlIndex);
1508  lid_updateAllLidUnit(lidControlIndex);
1509  }
1510  return(errcode);
1511 }
1512 
1513 //-------------------------------
1514 // Active Simulation Results API
1515 //-------------------------------
1516 
1517 int DLLEXPORT swmm_getCurrentDateTimeStr(char *dtimestr)
1522 {
1523  //strcpy(dtimestr,"");
1524  //Provide Empty Character Array
1525  char theDate[12];
1526  char theTime[9];
1527  char _DTimeStr[22];
1528  DateTime currentTime;
1529 
1530  // Check if Simulation is Running
1531  if(swmm_IsStartedFlag() == FALSE) return(ERR_API_SIM_NRUNNING);
1532 
1533  // Fetch Current Time
1534  currentTime = getDateTime(NewRoutingTime);
1535 
1536  // Convert To Char
1537  datetime_dateToStr(currentTime, theDate);
1538  datetime_timeToStr(currentTime, theTime);
1539 
1540  strcpy(_DTimeStr, theDate);
1541  strcat(_DTimeStr, " ");
1542  strcat(_DTimeStr, theTime);
1543 
1544  strcpy(dtimestr, _DTimeStr);
1545  return(0);
1546 }
1547 
1548 
1549 int DLLEXPORT swmm_getNodeResult(int index, int type, double *result)
1556 {
1557  int errcode = 0;
1558  *result = 0;
1559 
1560  // Check if Open
1561  if(swmm_IsOpenFlag() == FALSE)
1562  {
1563  errcode = ERR_API_INPUTNOTOPEN;
1564  }
1565  // Check if object index is within bounds
1566  else if (index < 0 || index >= Nobjects[NODE])
1567  {
1568  errcode = ERR_API_OBJECT_INDEX;
1569  }
1570  else
1571  {
1572  switch (type)
1573  {
1574  case SM_TOTALINFLOW:
1575  *result = Node[index].inflow * UCF(FLOW); break;
1576  case SM_TOTALOUTFLOW:
1577  *result = Node[index].outflow * UCF(FLOW); break;
1578  case SM_LOSSES:
1579  *result = Node[index].losses * UCF(FLOW); break;
1580  case SM_NODEVOL:
1581  *result = Node[index].newVolume * UCF(VOLUME); break;
1582  case SM_NODEFLOOD:
1583  *result = Node[index].overflow * UCF(FLOW); break;
1584  case SM_NODEDEPTH:
1585  *result = Node[index].newDepth * UCF(LENGTH); break;
1586  case SM_NODEHEAD:
1587  *result = (Node[index].newDepth
1588  + Node[index].invertElev) * UCF(LENGTH); break;
1589  case SM_LATINFLOW:
1590  *result = Node[index].newLatFlow * UCF(FLOW); break;
1591  default: errcode = ERR_API_OUTBOUNDS; break;
1592  }
1593  }
1594  return(errcode);
1595 }
1596 
1597 int DLLEXPORT swmm_getLinkResult(int index, int type, double *result)
1604 {
1605  int errcode = 0;
1606  *result = 0;
1607 
1608  // Check if Open
1609  if(swmm_IsOpenFlag() == FALSE)
1610  {
1611  errcode = ERR_API_INPUTNOTOPEN;
1612  }
1613  // Check if object index is within bounds
1614  else if (index < 0 || index >= Nobjects[LINK])
1615  {
1616  errcode = ERR_API_OBJECT_INDEX;
1617  }
1618  else
1619  {
1620  switch (type)
1621  {
1622  case SM_LINKFLOW:
1623  *result = Link[index].newFlow * UCF(FLOW) ; break;
1624  case SM_LINKDEPTH:
1625  *result = Link[index].newDepth * UCF(LENGTH); break;
1626  case SM_LINKVOL:
1627  *result = Link[index].newVolume * UCF(VOLUME); break;
1628  case SM_USSURFAREA:
1629  *result = Link[index].surfArea1 * UCF(LENGTH) * UCF(LENGTH); break;
1630  case SM_DSSURFAREA:
1631  *result = Link[index].surfArea2 * UCF(LENGTH) * UCF(LENGTH); break;
1632  case SM_SETTING:
1633  *result = Link[index].setting; break;
1634  case SM_TARGETSETTING:
1635  *result = Link[index].targetSetting; break;
1636  case SM_FROUDE:
1637  *result = Link[index].froude; break;
1638  default: errcode = ERR_API_OUTBOUNDS; break;
1639  }
1640  }
1641  return(errcode);
1642 }
1643 
1644 int DLLEXPORT swmm_getSubcatchResult(int index, int type, double *result)
1651 {
1652  int errcode = 0;
1653  *result = 0;
1654 
1655  // Check if Open
1656  if(swmm_IsOpenFlag() == FALSE)
1657  {
1658  errcode = ERR_API_INPUTNOTOPEN;
1659  }
1660  // Check if object index is within bounds
1661  else if (index < 0 || index >= Nobjects[SUBCATCH])
1662  {
1663  errcode = ERR_API_OBJECT_INDEX;
1664  }
1665  else
1666  {
1667  switch (type)
1668  {
1669  case SM_SUBCRAIN:
1670  *result = Subcatch[index].rainfall * UCF(RAINFALL); break;
1671  case SM_SUBCEVAP:
1672  *result = Subcatch[index].evapLoss * UCF(EVAPRATE); break;
1673  case SM_SUBCINFIL:
1674  *result = Subcatch[index].infilLoss * UCF(RAINFALL); break;
1675  case SM_SUBCRUNON:
1676  *result = Subcatch[index].runon * UCF(FLOW); break;
1677  case SM_SUBCRUNOFF:
1678  *result = Subcatch[index].newRunoff * UCF(FLOW); break;
1679  case SM_SUBCSNOW:
1680  *result = Subcatch[index].newSnowDepth * UCF(RAINDEPTH); break;
1681  default: errcode = ERR_API_OUTBOUNDS; break;
1682  }
1683  }
1684  return(errcode);
1685 }
1686 
1687 int DLLEXPORT swmm_getSubcatchPollut(int index, int type, double **PollutArray)
1694 {
1695  int p;
1696  int errcode = 0;
1697  double a;
1698  double* result;
1699 
1700  // Check if Open
1701  if(swmm_IsOpenFlag() == FALSE)
1702  {
1703  errcode = ERR_API_INPUTNOTOPEN;
1704  }
1705  // Check if object index is within bounds
1706  else if (index < 0 || index >= Nobjects[SUBCATCH])
1707  {
1708  errcode = ERR_API_OBJECT_INDEX;
1709  }
1710  else if (MEMCHECK(result = newDoubleArray(Nobjects[POLLUT])))
1711  {
1712  errcode = ERR_MEMORY;
1713  }
1714 
1715  else
1716  {
1717  switch (type)
1718  {
1719  case SM_BUILDUP:
1720  {
1721  a = Subcatch[index].area;
1722  for (p = 0; p < Nobjects[POLLUT]; p++)
1723  {
1724  result[p] = Subcatch[index].surfaceBuildup[p] /
1725  (a * UCF(LANDAREA));
1726  } *PollutArray = result;
1727  } break;
1728  case SM_CPONDED:
1729  {
1730  for (p = 0; p < Nobjects[POLLUT]; p++)
1731  {
1732  result[p] = Subcatch[index].concPonded[p] / LperFT3;
1733  } *PollutArray = result;
1734  } break;
1735  default: errcode = ERR_API_OUTBOUNDS; break;
1736  }
1737  }
1738  return(errcode);
1739 }
1740 
1741 int DLLEXPORT swmm_getGagePrecip(int index, double **GageArray)
1747 {
1748  int errcode = 0;
1749  double rainfall = 0;
1750  double snowfall = 0;
1751  double total = 0;
1752  double* temp;
1753 
1754  // Check if Open
1755  if(swmm_IsOpenFlag() == FALSE)
1756  {
1757  errcode = ERR_API_INPUTNOTOPEN;
1758  }
1759  // Check if object index is within bounds
1760  else if (index < 0 || index >= Nobjects[GAGE])
1761  {
1762  errcode = ERR_API_OBJECT_INDEX;
1763  }
1764  else if (MEMCHECK(temp = newDoubleArray(3)))
1765  {
1766  errcode = ERR_MEMORY;
1767  }
1768  // Read the rainfall value
1769  else
1770  {
1771  total = gage_getPrecip(index, &rainfall, &snowfall);
1772  temp[0] = total * UCF(RAINFALL);
1773  temp[1] = rainfall * UCF(RAINFALL);
1774  temp[2] = snowfall * UCF(RAINFALL);
1775  *GageArray = temp;
1776  }
1777  return(errcode);
1778 }
1779 
1780 int DLLEXPORT swmm_getNodeStats(int index, SM_NodeStats *nodeStats)
1785 {
1786  int errorcode = stats_getNodeStat(index, nodeStats);
1787 
1788  if (errorcode == 0)
1789  {
1790  // Current Average Depth
1791  nodeStats->avgDepth *= (UCF(LENGTH) / (double)StepCount);
1792  // Current Maximum Depth
1793  nodeStats->maxDepth *= UCF(LENGTH);
1794  // Current Maximum Lateral Inflow
1795  nodeStats->maxLatFlow *= UCF(FLOW);
1796  // Current Maximum Inflow
1797  nodeStats->maxInflow *= UCF(FLOW);
1798  // Cumulative Lateral Inflow
1799  nodeStats->totLatFlow *= UCF(VOLUME);
1800  // Time Courant Critical (hrs)
1801  nodeStats->timeCourantCritical /= 3600.0;
1802  // Cumulative Flooded Volume
1803  nodeStats->volFlooded *= UCF(VOLUME);
1804  // Time Flooded (hrs)
1805  nodeStats->timeFlooded /= 3600.0;
1806  // Current Maximum Overflow
1807  nodeStats->maxOverflow *= UCF(FLOW);
1808  // Current Maximum Ponding Volume
1809  nodeStats->maxPondedVol *= UCF(VOLUME);
1810  // Time Surcharged
1811  nodeStats->timeSurcharged /= 3600.0;
1812  }
1813  return (errorcode);
1814 }
1815 
1816 int DLLEXPORT swmm_getNodeTotalInflow(int index, double *value)
1822 {
1823  //*value = 0;
1824  int errorcode = massbal_getNodeTotalInflow(index, value);
1825 
1826  if (errorcode == 0)
1827  {
1828  *value *= UCF(VOLUME);
1829  }
1830 
1831  return(errorcode);
1832 }
1833 
1834 int DLLEXPORT swmm_getStorageStats(int index, SM_StorageStats *storageStats)
1839 {
1840  int errorcode = stats_getStorageStat(index, storageStats);
1841 
1842  if (errorcode == 0)
1843  {
1844  // Initial Volume
1845  storageStats->initVol *= UCF(VOLUME);
1846  // Current Average Volume
1847  storageStats->avgVol *= (UCF(VOLUME) / (double)StepCount);
1848  // Current Maximum Volume
1849  storageStats->maxVol *= UCF(VOLUME);
1850  // Current Maximum Flow
1851  storageStats->maxFlow *= UCF(FLOW);
1852  // Current Evaporation Volume
1853  storageStats->evapLosses *= UCF(VOLUME);
1854  // Current Exfiltration Volume
1855  storageStats->exfilLosses *= UCF(VOLUME);
1856  }
1857 
1858  return (errorcode);
1859 }
1860 
1861 int DLLEXPORT swmm_getOutfallStats(int index, SM_OutfallStats *outfallStats)
1868 {
1869  int p;
1870  int errorcode = stats_getOutfallStat(index, outfallStats);
1871 
1872  if (errorcode == 0)
1873  {
1874  // Current Average Flow
1875  if ( outfallStats->totalPeriods > 0 )
1876  {
1877  outfallStats->avgFlow *= (UCF(FLOW) / (double)outfallStats->totalPeriods);
1878  }
1879  else
1880  {
1881  outfallStats->avgFlow *= 0.0;
1882  }
1883  // Current Maximum Flow
1884  outfallStats->maxFlow *= UCF(FLOW);
1885  // Convert Mass Units
1886  if (Nobjects[POLLUT] > 0)
1887  {
1888  for (p = 0; p < Nobjects[POLLUT]; p++)
1889  outfallStats->totalLoad[p] *= (LperFT3 * Pollut[p].mcf);
1890  if (Pollut[p].units == COUNT)
1891  {
1892  outfallStats->totalLoad[p] = LOG10(outfallStats->totalLoad[p]);
1893  }
1894  }
1895  }
1896 
1897  return (errorcode);
1898 }
1899 
1900 void DLLEXPORT swmm_freeOutfallStats(SM_OutfallStats *outfallStats)
1906 {
1907  FREE(outfallStats->totalLoad);
1908 }
1909 
1910 
1911 
1912 int DLLEXPORT swmm_getLinkStats(int index, SM_LinkStats *linkStats)
1917 {
1918  int errorcode = stats_getLinkStat(index, linkStats);
1919 
1920  if (errorcode == 0)
1921  {
1922  // Cumulative Maximum Flowrate
1923  linkStats->maxFlow *= UCF(FLOW);
1924  // Cumulative Maximum Velocity
1925  linkStats->maxVeloc *= UCF(LENGTH);
1926  // Cumulative Maximum Depth
1927  linkStats->maxDepth *= UCF(LENGTH);
1928  // Cumulative Time Normal Flow
1929  linkStats->timeNormalFlow /= 3600.0;
1930  // Cumulative Time Inlet Control
1931  linkStats->timeInletControl /= 3600.0;
1932  // Cumulative Time Surcharged
1933  linkStats->timeSurcharged /= 3600.0;
1934  // Cumulative Time Upstream Full
1935  linkStats->timeFullUpstream /= 3600.0;
1936  // Cumulative Time Downstream Full
1937  linkStats->timeFullDnstream /= 3600.0;
1938  // Cumulative Time Full Flow
1939  linkStats->timeFullFlow /= 3600.0;
1940  // Cumulative Time Capacity limited
1941  linkStats->timeCapacityLimited /= 3600.0;
1942  // Cumulative Time Courant Critical Flow
1943  linkStats->timeCourantCritical /= 3600.0;
1944  }
1945 
1946  return (errorcode);
1947 }
1948 
1949 
1950 int DLLEXPORT swmm_getPumpStats(int index, SM_PumpStats *pumpStats)
1955 {
1956  int errorcode = stats_getPumpStat(index, pumpStats);
1957 
1958  if (errorcode == 0)
1959  {
1960  // Cumulative Minimum Flow
1961  pumpStats->minFlow *= UCF(FLOW);
1962  // Cumulative Average Flow
1963  if (pumpStats->totalPeriods > 0)
1964  {
1965  pumpStats->avgFlow *= (UCF(FLOW) / (double)pumpStats->totalPeriods);
1966  }
1967  else
1968  {
1969  pumpStats->avgFlow *= 0.0;
1970  }
1971  // Cumulative Maximum Flow
1972  pumpStats->maxFlow *= UCF(FLOW);
1973  // Cumulative Pumping Volume
1974  pumpStats->volume *= UCF(VOLUME);
1975  }
1976 
1977  return (errorcode);
1978 }
1979 
1980 
1981 int DLLEXPORT swmm_getSubcatchStats(int index, SM_SubcatchStats **subcatchStats)
1986 {
1987  int errorcode = 0;
1988  double a;
1989  TSubcatchStats *tmp = (TSubcatchStats *)calloc(1, sizeof(TSubcatchStats));
1990 
1991  // Check if Open
1992  if (swmm_IsOpenFlag() == FALSE)
1993  {
1994  errorcode = ERR_API_INPUTNOTOPEN;
1995  }
1996 
1997  // Check if Simulation is Running
1998  else if (swmm_IsStartedFlag() == FALSE)
1999  {
2000  errorcode = ERR_API_SIM_NRUNNING;
2001  }
2002 
2003  // Check if object index is within bounds
2004  else if (index < 0 || index >= Nobjects[SUBCATCH])
2005  {
2006  errorcode = ERR_API_OBJECT_INDEX;
2007  }
2008  // Copy Structure
2009  else
2010  {
2011  memcpy(tmp, stats_getSubcatchStat(index), sizeof(TSubcatchStats));
2012  *subcatchStats = (SM_SubcatchStats *)tmp;
2013 
2014  a = Subcatch[index].area;
2015 
2016  // Cumulative Runon Volume
2017  (*subcatchStats)->runon *= UCF(VOLUME);
2018  // Cumulative Infiltration Volume
2019  (*subcatchStats)->infil *= UCF(VOLUME);
2020  // Cumulative Runoff Volume
2021  (*subcatchStats)->runoff *= UCF(VOLUME);
2022  // Maximum Runoff Rate
2023  (*subcatchStats)->maxFlow *= UCF(FLOW);
2024  // Cumulative Rainfall Depth
2025  (*subcatchStats)->precip *= (UCF(RAINDEPTH) / a);
2026  // Cumulative Evaporation Volume
2027  (*subcatchStats)->evap *= UCF(VOLUME);
2028  }
2029 
2030  return (errorcode);
2031 }
2032 
2033 
2039 {
2040  int errorcode = massbal_getRoutingFlowTotal(routingTot);
2041 
2042  if (errorcode == 0)
2043  {
2044  // Cumulative Dry Weather Inflow Volume
2045  routingTot->dwInflow *= UCF(VOLUME);
2046  // Cumulative Wet Weather Inflow Volume
2047  routingTot->wwInflow *= UCF(VOLUME);
2048  // Cumulative Groundwater Inflow Volume
2049  routingTot->gwInflow *= UCF(VOLUME);
2050  // Cumulative I&I Inflow Volume
2051  routingTot->iiInflow *= UCF(VOLUME);
2052  // Cumulative External Inflow Volume
2053  routingTot->exInflow *= UCF(VOLUME);
2054  // Cumulative Flooding Volume
2055  routingTot->flooding *= UCF(VOLUME);
2056  // Cumulative Outflow Volume
2057  routingTot->outflow *= UCF(VOLUME);
2058  // Cumulative Evaporation Loss
2059  routingTot->evapLoss *= UCF(VOLUME);
2060  // Cumulative Seepage Loss
2061  routingTot->seepLoss *= UCF(VOLUME);
2062  // Continuity Error
2063  routingTot->pctError *= 100;
2064  }
2065 
2066  return(errorcode);
2067 }
2068 
2074 {
2075  int errorcode = massbal_getRunoffTotal(runoffTot);
2076 
2077  if (errorcode == 0)
2078  {
2079  double TotalArea = massbal_getTotalArea();
2080  // Cumulative Rainfall Depth
2081  runoffTot->rainfall *= (UCF(RAINDEPTH) / TotalArea);
2082  // Cumulative Evaporation Volume
2083  runoffTot->evap *= UCF(VOLUME);
2084  // Cumulative Infiltration Volume
2085  runoffTot->infil *= UCF(VOLUME);
2086  // Cumulative Runoff Volume
2087  runoffTot->runoff *= UCF(VOLUME);
2088  // Cumulative Runon Volume
2089  runoffTot->runon *= UCF(VOLUME);
2090  // Cumulative Drain Volume
2091  runoffTot->drains *= UCF(VOLUME);
2092  // Cumulative Snow Removed Volume
2093  runoffTot->snowRemoved *= (UCF(RAINDEPTH) / TotalArea);
2094  // Initial Storage Volume
2095  runoffTot->initStorage *= (UCF(RAINDEPTH) / TotalArea);
2096  // Final Storage Volume
2097  runoffTot->finalStorage *= (UCF(RAINDEPTH) / TotalArea);
2098  // Initial Snow Cover Volume
2099  runoffTot->initSnowCover *= (UCF(RAINDEPTH) / TotalArea);
2100  // Final Snow Cover Volume
2101  runoffTot->finalSnowCover *= (UCF(RAINDEPTH) / TotalArea);
2102  // Continuity Error
2103  runoffTot->pctError *= 100;
2104  }
2105 
2106  return(errorcode);
2107 }
2108 
2109 int DLLEXPORT swmm_getLidUFluxRates(int index, int lidIndex, int layerIndex, double *result)
2110 //
2111 // Input: index = Index of desired subcatchment
2112 // lidIndex = Index of desired lid control (subcatchment allow for multiple lids)
2113 // layerIndex = Index of desired lid layer (default is surface)
2114 // Output: result = result data desired (byref)
2115 // Return: API Error
2116 // Purpose: Gets Lid Unit Water Balance Simulated Value at Current Time
2117 {
2118  int errcode = 0;
2119  TLidUnit* lidUnit;
2120 
2121  // Check if Open
2122  if (swmm_IsOpenFlag() == FALSE)
2123  {
2124  errcode = ERR_API_INPUTNOTOPEN;
2125  }
2126  // Check if object index is within bounds
2127  else if (index < 0 || index >= Nobjects[SUBCATCH])
2128  {
2129  errcode = ERR_API_OBJECT_INDEX;
2130  }
2131  else
2132  {
2133  lidUnit = lid_getLidUnit(index, lidIndex, &errcode);
2134 
2135  // There are no Lid Units defined for the subcatchments
2136  if (lidUnit)
2137  {
2138  switch (layerIndex)
2139  {
2140  case SM_SURFACE:
2141  *result = lidUnit->oldFluxRates[SM_SURFACE] * UCF(LENGTH); break;
2142  case SM_SOIL:
2143  *result = lidUnit->oldFluxRates[SM_SOIL] * UCF(LENGTH); break;
2144  case SM_STORAGE:
2145  *result = lidUnit->oldFluxRates[SM_STORAGE] * UCF(LENGTH); break;
2146  case SM_PAVE:
2147  *result = lidUnit->oldFluxRates[SM_PAVE] * UCF(LENGTH); break;
2148  default:
2149  errcode = ERR_API_OUTBOUNDS; break;
2150  }
2151  }
2152  else
2153  {
2154  errcode = ERR_API_UNDEFINED_LID;
2155  }
2156  }
2157  return(errcode);
2158 }
2159 
2160 int DLLEXPORT swmm_getLidGResult(int index, int type, double *result)
2161 //
2162 // Input: index = index of desired subcatchment
2163 // type = type of result data desired
2164 // Output: result = result data desired
2165 // Return: API Error
2166 // Purpose: Gets Lid Group Data at Current Time
2167 {
2168  int errcode = 0;
2169  TLidGroup lidGroup;
2170 
2171  // Check if Open
2172  if (swmm_IsOpenFlag() == FALSE)
2173  {
2174  errcode = ERR_API_INPUTNOTOPEN;
2175  }
2176  // Check if object index is within bounds
2177  else if (index < 0 || index >= Nobjects[SUBCATCH])
2178  {
2179  errcode = ERR_API_OBJECT_INDEX;
2180  }
2181  else
2182  {
2183  lidGroup = lid_getLidGroup(index);
2184 
2185  if (lidGroup)
2186  {
2187  switch (type)
2188  {
2189  case SM_PERVAREA:
2190  *result = lidGroup->pervArea * SQR(UCF(LENGTH)); break;
2191  case SM_FLOWTOPERV:
2192  *result = lidGroup->flowToPerv * UCF(FLOW); break;
2193  case SM_OLDDRAINFLOW:
2194  *result = lidGroup->oldDrainFlow * UCF(FLOW); break;
2195  case SM_NEWDRAINFLOW:
2196  *result = lidGroup->newDrainFlow * UCF(FLOW); break;
2197  default:
2198  errcode = ERR_API_OUTBOUNDS; break;
2199  }
2200  }
2201  else
2202  {
2203  errcode = ERR_API_UNDEFINED_LID;
2204  }
2205  }
2206  return(errcode);
2207 }
2208 
2209 int DLLEXPORT swmm_getLidUResult(int index, int lidIndex, int type, double *result)
2210 //
2211 // Input: index = Index of desired subcatchment
2212 // lidIndex = Index of desired lid control (subcatchment allow for multiple lids)
2213 // Output: result = result data desired (byref)
2214 // Return: API Error
2215 // Purpose: Gets Lid Unit Water Balance Simulated Value at Current Time
2216 {
2217  int errcode = 0;
2218  TLidUnit* lidUnit;
2219  double Tstep = 0;
2220 
2221  // Check if Open
2222  if (swmm_IsOpenFlag() == FALSE)
2223  {
2224  errcode = ERR_API_INPUTNOTOPEN;
2225  }
2226  // Check if object index is within bounds
2227  else if (index < 0 || index >= Nobjects[SUBCATCH])
2228  {
2229  errcode = ERR_API_OBJECT_INDEX;
2230  }
2231  else
2232  {
2233  lidUnit = lid_getLidUnit(index, lidIndex, &errcode);
2234 
2235  // There are no Lid Units defined for the subcatchments
2236  if (lidUnit)
2237  {
2238  switch (type)
2239  {
2240  case SM_INFLOW:
2241  *result = lidUnit->waterBalance.inflow * UCF(RAINDEPTH); break;
2242  case SM_EVAP:
2243  *result = lidUnit->waterBalance.evap * UCF(RAINDEPTH); break;
2244  case SM_INFIL:
2245  *result = lidUnit->waterBalance.infil * UCF(RAINDEPTH); break;
2246  case SM_SURFFLOW:
2247  *result = lidUnit->waterBalance.surfFlow * UCF(RAINDEPTH); break;
2248  case SM_DRAINFLOW:
2249  *result = lidUnit->waterBalance.drainFlow * UCF(RAINDEPTH); break;
2250  case SM_INITVOL:
2251  *result = lidUnit->waterBalance.initVol * UCF(RAINDEPTH); break;
2252  case SM_FINALVOL:
2253  *result = lidUnit->waterBalance.finalVol * UCF(RAINDEPTH); break;
2254  case SM_SURFDEPTH:
2255  *result = lidUnit->surfaceDepth * UCF(RAINDEPTH); break;
2256  case SM_PAVEDEPTH:
2257  *result = lidUnit->paveDepth * UCF(RAINDEPTH); break;
2258  case SM_SOILMOIST:
2259  *result = lidUnit->soilMoisture; break;
2260  case SM_STORDEPTH:
2261  *result = lidUnit->storageDepth * UCF(RAINDEPTH); break;
2262  case SM_DRYTIME:
2263  *result = lidUnit->dryTime; break;
2264  case SM_OLDDRAINFLOW:
2265  *result = lidUnit->oldDrainFlow * UCF(FLOW); break;
2266  case SM_NEWDRAINFLOW:
2267  *result = lidUnit->newDrainFlow * UCF(FLOW); break;
2268  case SM_EVAPRATE:
2269  *result = lidUnit->waterRate.evap * UCF(RAINFALL); break;
2270  case SM_NATIVEINFIL:
2271  *result = lidUnit->waterRate.maxNativeInfil * UCF(RAINFALL); break;
2272  case SM_SURFINFLOW:
2273  *result = lidUnit->waterRate.surfaceInflow * UCF(RAINFALL); break;
2274  case SM_SURFINFIL:
2275  *result = lidUnit->waterRate.surfaceInfil * UCF(RAINFALL); break;
2276  case SM_SURFEVAP:
2277  *result = lidUnit->waterRate.surfaceEvap * UCF(RAINFALL); break;
2278  case SM_SURFOUTFLOW:
2279  *result = lidUnit->waterRate.surfaceOutflow * UCF(RAINFALL); break;
2280  case SM_PAVEEVAP:
2281  *result = lidUnit->waterRate.paveEvap * UCF(RAINFALL); break;
2282  case SM_PAVEPERC:
2283  *result = lidUnit->waterRate.pavePerc * UCF(RAINFALL); break;
2284  case SM_SOILEVAP:
2285  *result = lidUnit->waterRate.soilEvap * UCF(RAINFALL); break;
2286  case SM_SOILPERC:
2287  *result = lidUnit->waterRate.soilPerc * UCF(RAINFALL); break;
2288  case SM_STORAGEINFLOW:
2289  *result = lidUnit->waterRate.storageInflow * UCF(RAINFALL); break;
2290  case SM_STORAGEEXFIL:
2291  *result = lidUnit->waterRate.storageExfil * UCF(RAINFALL); break;
2292  case SM_STORAGEEVAP:
2293  *result = lidUnit->waterRate.storageEvap * UCF(RAINFALL); break;
2294  case SM_STORAGEDRAIN:
2295  *result = lidUnit->waterRate.storageDrain * UCF(RAINFALL); break;
2296  default:
2297  errcode = ERR_API_OUTBOUNDS; break;
2298  }
2299  }
2300  else
2301  {
2302  errcode = ERR_API_UNDEFINED_LID;
2303  }
2304  }
2305  return(errcode);
2306 }
2307 
2308 //-------------------------------
2309 // Setters API
2310 //-------------------------------
2311 
2312 int DLLEXPORT swmm_setLinkSetting(int index, double setting)
2318 {
2319  DateTime currentTime;
2320  int errcode = 0;
2321  char _rule_[11] = "ToolkitAPI";
2322 
2323  // Check if Open
2324  if (swmm_IsOpenFlag() == FALSE)
2325  {
2326  errcode = ERR_API_INPUTNOTOPEN;
2327  }
2328  // Check if object index is within bounds
2329  else if (index < 0 || index >= Nobjects[LINK])
2330  {
2331  errcode = ERR_API_OBJECT_INDEX;
2332  }
2333  else
2334  {
2335  // --- check that new setting lies within feasible limits
2336  if (setting < 0.0) setting = 0.0;
2337  if (Link[index].type != PUMP && setting > 1.0) setting = 1.0;
2338 
2339  Link[index].targetSetting = setting;
2340 
2341  // Use internal function to apply the new setting
2342  link_setSetting(index, 0.0);
2343 
2344  // Add control action to RPT file if desired flagged
2345  if (RptFlags.controls)
2346  {
2347  currentTime = getDateTime(NewRoutingTime);
2348  report_writeControlAction(currentTime, Link[index].ID, setting, _rule_);
2349  }
2350  }
2351  return(errcode);
2352 }
2353 
2354 
2355 int DLLEXPORT swmm_setNodeInflow(int index, double flowrate)
2361 {
2362  int errcode = 0;
2363 
2364  // Check if Open
2365  if (swmm_IsOpenFlag() == FALSE)
2366  {
2367  errcode = ERR_API_INPUTNOTOPEN;
2368  }
2369  // Check if object index is within bounds
2370  else if (index < 0 || index >= Nobjects[NODE])
2371  {
2372  errcode = ERR_API_OBJECT_INDEX;
2373  }
2374  else
2375  {
2376  // Check to see if node has an assigned inflow object
2377  TExtInflow* inflow;
2378 
2379  // --- check if an external inflow object for this constituent already exists
2380  inflow = Node[index].extInflow;
2381  while (inflow)
2382  {
2383  if (inflow->param == -1) break;
2384  inflow = inflow->next;
2385  }
2386 
2387  if (!inflow)
2388  {
2389  int param = -1; // FLOW (-1) or Pollutant Index
2390  int type = FLOW_INFLOW;// Type of inflow (FLOW)
2391  int tSeries = -1; // No Time Series
2392  int basePat = -1; // No Base Pattern
2393  double cf = 1.0; // Unit Convert (Converted during validation)
2394  double sf = 1.0; // Scaling Factor
2395  double baseline = 0.0; // Baseline Inflow Rate
2396 
2397  // Initializes Inflow Object
2398  errcode = inflow_setExtInflow(index, param, type, tSeries,
2399  basePat, cf, baseline, sf);
2400 
2401  // Get The Inflow Object
2402  if ( errcode == 0 )
2403  {
2404  inflow = Node[index].extInflow;
2405  }
2406  }
2407  // Assign new flow rate
2408  if ( errcode == 0 )
2409  {
2410  inflow -> extIfaceInflow = flowrate;
2411  }
2412  }
2413  return(errcode);
2414 }
2415 
2416 int DLLEXPORT swmm_setOutfallStage(int index, double stage)
2422 {
2423  int errcode = 0;
2424  // Check if Open
2425  if (swmm_IsOpenFlag() == FALSE)
2426  {
2427  errcode = ERR_API_INPUTNOTOPEN;
2428  }
2429  // Check if object index is within bounds
2430  else if ( index < 0 || index >= Nobjects[NODE] )
2431  {
2432  errcode = ERR_API_OBJECT_INDEX;
2433  }
2434  else if ( Node[index].type != OUTFALL )
2435  {
2436  errcode = ERR_API_WRONG_TYPE;
2437  }
2438  else
2439  {
2440  int k = Node[index].subIndex;
2441  if ( Outfall[k].type != STAGED_OUTFALL )
2442  {
2443  // Change Boundary Conditions Setting Type
2444  Outfall[k].type = STAGED_OUTFALL;
2445  }
2446  Outfall[k].outfallStage = stage / UCF(LENGTH);
2447  }
2448  return(errcode);
2449 }
2450 
2451 int DLLEXPORT swmm_setGagePrecip(int index, double total_precip)
2457 {
2458  int errcode = 0;
2459  // Check if Open
2460  if(swmm_IsOpenFlag() == FALSE)
2461  {
2462  errcode = ERR_API_INPUTNOTOPEN;
2463  }
2464  // Check if object index is within bounds
2465  else if (index < 0 || index >= Nobjects[GAGE])
2466  {
2467  errcode = ERR_API_OBJECT_INDEX;
2468  }
2469  // Set the Rainfall rate
2470  else
2471  {
2472  if (Gage[index].dataSource != RAIN_API)
2473  {
2474  Gage[index].dataSource = RAIN_API;
2475  }
2476  if (Gage[index].isUsed == FALSE)
2477  {
2478  Gage[index].isUsed = TRUE;
2479  }
2480  if (Gage[index].coGage != -1)
2481  {
2482  Gage[index].coGage = -1;
2483  }
2484  Gage[index].externalRain = total_precip;
2485  }
2486  return(errcode);
2487 }
2488 
2489 //-------------------------------
2490 // Utility Functions
2491 //-------------------------------
2492 
2493 double* newDoubleArray(int n)
2497 {
2498  return (double*) malloc((n)*sizeof(double));
2499 }
2500 
2501 
2502 void DLLEXPORT freeArray(void** array)
2506 {
2507  if (array != NULL) {
2508  FREE(*array);
2509  *array = NULL;
2510  }
2511 }
void DLLEXPORT freeArray(void **array)
Helper function to free memory array allocated in SWMM.
Definition: toolkitAPI.c:2502
int DLLEXPORT swmm_getObjectId(int type, int index, char *id)
Gets Object ID.
Definition: toolkitAPI.c:329
int DLLEXPORT swmm_setLidUOption(int index, int lidIndex, int param, int value)
Set the lid option for a specified lid unit on a specified subcatchment.
Definition: toolkitAPI.c:1022
double volume
Definition: toolkitAPI.h:441
Prototypes for SWMM5 functions exported to swmm5.dll.
int DLLEXPORT swmm_getLinkResult(int index, int type, double *result)
Get a result value for specified link.
Definition: toolkitAPI.c:1597
int DLLEXPORT swmm_setGagePrecip(int index, double total_precip)
Set a total precipitation intensity to the gage.
Definition: toolkitAPI.c:2451
double finalSnowCover
Definition: toolkitAPI.h:564
int DLLEXPORT swmm_getGagePrecip(int index, double **GageArray)
Get precipitation rates for a gage.
Definition: toolkitAPI.c:1741
int totalPeriods
Definition: toolkitAPI.h:446
double maxFlow
Definition: toolkitAPI.h:440
int DLLEXPORT swmm_setLinkSetting(int index, double setting)
Set a link setting (pump, orifice, or weir). Setting for an orifice and a weir should be [0,...
Definition: toolkitAPI.c:2312
int DLLEXPORT swmm_getLidCOverflow(int lidControlIndex, char *condition)
Get the lid control surface immediate overflow condition.
Definition: toolkitAPI.c:1089
int DLLEXPORT swmm_getSubcatchStats(int index, SM_SubcatchStats **subcatchStats)
Get subcatchment statistics.
Definition: toolkitAPI.c:1981
Node stats structure.
Definition: toolkitAPI.h:281
int DLLEXPORT swmm_getNodeResult(int index, int type, double *result)
Get a result value for specified node.
Definition: toolkitAPI.c:1549
int DLLEXPORT swmm_getStorageStats(int index, SM_StorageStats *storageStats)
Get a storage statistics.
Definition: toolkitAPI.c:1834
int DLLEXPORT swmm_getSubcatchResult(int index, int type, double *result)
Get a result value for specified subcatchment.
Definition: toolkitAPI.c:1644
int DLLEXPORT swmm_getLidUCount(int index, int *value)
Get the number of lid units on a subcatchment.
Definition: toolkitAPI.c:824
int DLLEXPORT swmm_getSubcatchPollut(int index, int type, double **PollutArray)
Gets pollutant values for a specified subcatchment.
Definition: toolkitAPI.c:1687
int DLLEXPORT swmm_setSimulationDateTime(int timetype, char *dtimestr)
Set simulation datetime information.
Definition: toolkitAPI.c:110
int DLLEXPORT swmm_getNodeStats(int index, SM_NodeStats *nodeStats)
Get a node statistics.
Definition: toolkitAPI.c:1780
Pump Statistics.
Definition: toolkitAPI.h:435
double initSnowCover
Definition: toolkitAPI.h:563
int DLLEXPORT swmm_getNodeParam(int index, int Param, double *value)
Get a property value for specified node.
Definition: toolkitAPI.c:501
int DLLEXPORT swmm_setNodeParam(int index, int Param, double value)
Set a property value for specified node.
Definition: toolkitAPI.c:541
void DLLEXPORT swmm_getAPIError(int errcode, char *s)
Get the text of an error code.
Definition: toolkitAPI.c:42
Subcatchment Statistics.
Definition: toolkitAPI.h:465
double avgFlow
Definition: toolkitAPI.h:439
int DLLEXPORT swmm_getPumpStats(int index, SM_PumpStats *pumpStats)
Get pump statistics.
Definition: toolkitAPI.c:1950
int DLLEXPORT swmm_countObjects(int type, int *count)
Gets Object Count.
Definition: toolkitAPI.c:297
System runoff stats structure.
Definition: toolkitAPI.h:553
int DLLEXPORT swmm_getSimulationAnalysisSetting(int type, int *value)
Gets Simulation Analysis Setting.
Definition: toolkitAPI.c:202
Storage Statatistics.
Definition: toolkitAPI.h:318
int DLLEXPORT swmm_getSystemRunoffStats(SM_RunoffTotals *runoffTot)
Get system runoff statistics.
Definition: toolkitAPI.c:2069
int DLLEXPORT swmm_getSubcatchParam(int index, int Param, double *value)
Get a property value for specified subcatchment.
Definition: toolkitAPI.c:689
int DLLEXPORT swmm_getSimulationParam(int type, double *value)
Gets Simulation Analysis Setting.
Definition: toolkitAPI.c:243
int DLLEXPORT swmm_setLidUParam(int index, int lidIndex, int Param, double value)
Set a property value for a specified lid unit on a specified subcatchment.
Definition: toolkitAPI.c:905
double finalStorage
Definition: toolkitAPI.h:562
double minFlow
Definition: toolkitAPI.h:438
int DLLEXPORT swmm_getNodeType(int index, int *Ntype)
Get the type of node with specified index.
Definition: toolkitAPI.c:399
double snowRemoved
Definition: toolkitAPI.h:565
Outfall Statatistics.
Definition: toolkitAPI.h:341
int DLLEXPORT swmm_getSubcatchOutConnection(int index, int *type, int *out_index)
Get the Subcatchment connection. Subcatchments can load to a node, another subcatchment,...
Definition: toolkitAPI.c:780
int DLLEXPORT swmm_getLinkType(int index, int *Ltype)
Get the type of link with specified index.
Definition: toolkitAPI.c:423
int DLLEXPORT swmm_setLinkParam(int index, int Param, double value)
Set a property value for specified link.
Definition: toolkitAPI.c:631
int DLLEXPORT swmm_setLidCParam(int lidControlIndex, int layerIndex, int param, double value)
Set a property value for specified lid control.
Definition: toolkitAPI.c:1304
int DLLEXPORT swmm_setNodeInflow(int index, double flowrate)
Set an inflow rate to a node. The inflow rate is held constant until the caller changes it.
Definition: toolkitAPI.c:2355
int DLLEXPORT swmm_getSimulationDateTime(int timetype, int *year, int *month, int *day, int *hour, int *minute, int *second)
Get the current simulation datetime information.
Definition: toolkitAPI.c:69
int DLLEXPORT swmm_getObjectIndex(SM_ObjectType type, char *id, int *index)
Gets Object Index.
Definition: toolkitAPI.c:310
int DLLEXPORT swmm_getLinkConnections(int index, int *Node1, int *Node2)
Get the link Connection Node Indeces. If the conduit has a negative slope, the dynamic wave solver wi...
Definition: toolkitAPI.c:447
int DLLEXPORT swmm_setSubcatchParam(int index, int Param, double value)
Set a property value for specified subcatchment.
Definition: toolkitAPI.c:729
int DLLEXPORT swmm_getSystemRoutingStats(SM_RoutingTotals *routingTot)
Get system routing statistics.
Definition: toolkitAPI.c:2034
int DLLEXPORT swmm_getLidCParam(int lidControlIndex, int layerIndex, int param, double *value)
Get a property value for specified lid control.
Definition: toolkitAPI.c:1121
double evapLosses
Definition: toolkitAPI.h:324
System Flow Routing Statistics.
Definition: toolkitAPI.h:505
int DLLEXPORT swmm_getLidUParam(int index, int lidIndex, int param, double *value)
Get a property value for a specified lid unit on a specified subcatchment.
Definition: toolkitAPI.c:851
int DLLEXPORT swmm_getCurrentDateTimeStr(char *dtimestr)
Get the simulation current datetime as a string.
Definition: toolkitAPI.c:1517
double exfilLosses
Definition: toolkitAPI.h:325
int DLLEXPORT swmm_getLinkStats(int index, SM_LinkStats *linkStats)
Get link statistics.
Definition: toolkitAPI.c:1912
double * newDoubleArray(int n)
Definition: toolkitAPI.c:2493
int DLLEXPORT swmm_getLidUResult(int index, int lidIndex, int type, double *result)
Get the lid unit of a specified subcatchment result at current time.
Definition: toolkitAPI.c:2209
int DLLEXPORT swmm_setOutfallStage(int index, double stage)
Set outfall stage.
Definition: toolkitAPI.c:2416
void DLLEXPORT swmm_freeOutfallStats(SM_OutfallStats *outfallStats)
Free outfall statistics structure.
Definition: toolkitAPI.c:1900
int DLLEXPORT swmm_getSimulationUnit(int type, int *value)
Gets Simulation Unit.
Definition: toolkitAPI.c:170
int DLLEXPORT swmm_getLidUOption(int index, int lidIndex, int param, int *value)
Get the lid option for a specified lid unit on a specified subcatchment.
Definition: toolkitAPI.c:970
int DLLEXPORT swmm_getOutfallStats(int index, SM_OutfallStats *outfallStats)
Get outfall statistics.
Definition: toolkitAPI.c:1861
double initStorage
Definition: toolkitAPI.h:561
int DLLEXPORT swmm_getLidUFluxRates(int index, int lidIndex, int layerIndex, double *result)
Get the lid unit water balance simulated value at current time.
Definition: toolkitAPI.c:2109
int DLLEXPORT swmm_project_findObject(int type, char *id, int *index)
Finds the index of an object given its ID.
Definition: toolkitAPI.c:54
SM_ObjectType
Object type codes.
Definition: toolkitAPI.h:33
Exportable Functions for Toolkit API.
int DLLEXPORT swmm_getNodeTotalInflow(int index, double *value)
Get the cumulative inflow for a node.
Definition: toolkitAPI.c:1816
int DLLEXPORT swmm_getLidGResult(int index, int type, double *result)
Get the lid group of a specified subcatchment result at current time.
Definition: toolkitAPI.c:2160
double * totalLoad
Definition: toolkitAPI.h:345
int DLLEXPORT swmm_getLinkDirection(int index, signed char *value)
Get the link flow direction (see swmm_getLinkType() for notes.
Definition: toolkitAPI.c:475
int DLLEXPORT swmm_getLinkParam(int index, int Param, double *value)
Get a property value for specified link.
Definition: toolkitAPI.c:587