Example #1
0
 def __init__(self, inputfile, reportfile=None, outputfile=None):
     self._model = PySWMM(inputfile, reportfile, outputfile)
     self._model.swmm_open()
     self._isOpen = True
     self._advance_seconds = None
     self._isStarted = False
     self._initial_conditions = None
Example #2
0
def test_pyswmm_exception():
    swmmobject = PySWMM(*get_model_files(MODEL_WEIR_SETTING_PATH))
    with pytest.raises(PYSWMMException):
        swmmobject.swmm_open()
        print(swmmobject.fileLoaded)
        swmmobject.swmm_open()
        swmmobject.swmm_close()
Example #3
0
 def __init__(self,
              inputfile,
              reportfile=None,
              outputfile=None,
              swmm_lib_path=None):
     self._model = PySWMM(inputfile, reportfile, outputfile, swmm_lib_path)
     self._model.swmm_open()
     self._isOpen = True
     self._advance_seconds = None
     self._isStarted = False
     self._callbacks = {
         "before_start": None,
         "before_step": None,
         "after_step": None,
         "before_end": None,
         "after_end": None,
         "after_close": None
     }
Example #4
0
 def __init__(self,
              inputfile,
              reportfile=None,
              outputfile=None,
              swmm_lib_path=None):
     self._model = PySWMM(inputfile, reportfile, outputfile, swmm_lib_path)
     self._model.swmm_open()
     self._isOpen = True
     self._advance_seconds = None
     self._isStarted = False
     self._callbacks = {
         "before_start": None,
         "before_step": None,
         "after_step": None,
         "before_end": None,
         "after_end": None,
         "after_close": None
     }
Example #5
0
class Simulation(object):
    """
    Base class for a SWMM Simulation.

    The model object provides several options to run a simulation.
    User can specified SWMM library path. Uses default lib if not provided.

    Initialize the Simulation class.

    :param str inpfile: Name of SWMM input file (default '')
    :param str rptfile: Report file to generate (default None)
    :param str binfile: Optional binary output file (default None)
    :param str swmm_lib_path: User-specified SWMM library path (default None).

    Examples:

    Intialize a simulation and iterate through a simulation. This
    approach requires some clean up.

    >>> from pyswmm import Simulation
    >>>
    >>> sim = Simulation('tests/data/TestModel1_weirSetting.inp')
    >>> for step in sim:
    ...     pass
    >>>
    >>> sim.report()
    >>> sim.close()

    Intialize using with statement.  This automatically cleans up
    after a simulation

    >>> from pyswmm import Simulation
    >>>
    >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
    ...     for step in sim:
    ...         pass
    ...     sim.report()

    Initialize the simulation and execute. This style does not allow
    the user to interact with the simulation. However, this approach
    tends to be the fastest.

    >>> from pyswmm import Simulation
    >>>
    >>> sim = Simulation('tests/data/TestModel1_weirSetting.inp')
    >>> sim.execute()
    """
    def __init__(self,
                 inputfile,
                 reportfile=None,
                 outputfile=None,
                 swmm_lib_path=None):
        self._model = PySWMM(inputfile, reportfile, outputfile, swmm_lib_path)
        self._model.swmm_open()
        self._isOpen = True
        self._advance_seconds = None
        self._isStarted = False
        self._callbacks = {
            "before_start": None,
            "before_step": None,
            "after_step": None,
            "before_end": None,
            "after_end": None,
            "after_close": None
        }

    def __enter__(self):
        """
        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     for step in sim:
        ...         print(sim.current_time)
        ...     sim.report()
        >>>
        >>> 2015-11-01 14:00:30
        >>> 2015-11-01 14:01:00
        >>> 2015-11-01 14:01:30
        >>> 2015-11-01 14:02:00
        """
        return self

    def __iter__(self):
        """Iterator over Simulation"""
        return self

    def start(self):
        """Start Simulation"""
        if not self._isStarted:
            # Set Model Initial Conditions
            # (This Will be Deprecated with Time)
            if hasattr(self, "_initial_conditions"):
                self._initial_conditions()
            # Execute Callback Hooks Before Simulation
            self._execute_callback(self.before_start())
            self._model.swmm_start(True)
            self._isStarted = True

    def __next__(self):
        """Next"""
        # Start Simulation
        self.start()
        # Execute Callback Hooks Before Simulation Step
        self._execute_callback(self.before_step())
        # Simulation Step Amount
        if self._advance_seconds is None:
            time = self._model.swmm_step()
        else:
            time = self._model.swmm_stride(self._advance_seconds)
        # Execute Callback Hooks After Simulation Step
        self._execute_callback(self.after_step())
        if time <= 0.0:
            self._execute_callback(self.before_end())
            raise StopIteration
        return self._model

    next = __next__  # Python 2

    def __exit__(self, *a):
        """close"""
        if self._isStarted:
            self._model.swmm_end()
            self._isStarted = False
            # Execute Callback Hooks After Simulation End
            self._execute_callback(self.after_end())
        if self._isOpen:
            self._model.swmm_close()
            self._isOpen = False
            # Execute Callback Hooks After Simulation Closes
            self._execute_callback(self.after_close())

    @staticmethod
    def _is_callback(callable_object):
        """Checks if arugment is a function/method."""
        if not callable(callable_object):
            error_msg = 'Requires Callable Object, not {}'.format(
                type(callable_object))
            raise (PYSWMMException(error_msg))
        else:
            return True

    def _execute_callback(self, callback):
        """Runs the callback."""
        if callback:
            try:
                callback()
            except PYSWMMException:
                error_msg = "Callback Failed"
                raise PYSWMMException((error_msg))

    def initial_conditions(self, init_conditions):
        """
        Intial Conditions for Hydraulics and Hydrology can be set
        from within the api by setting a function to the
        initial_conditions property.

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('./TestModel1_weirSetting.inp') as sim:
        ...     nodeJ1 = Nodes(sim)["J1"]
        ...
        ...     def init_conditions():
        ...         nodeJ1.initial_depth = 4
        ...
        ...     sim.initial_conditions(init_conditions)
        ...
        ...     for step in sim:
        ...         pass
        ...     sim.report()

        """
        if self._is_callback(init_conditions):
            self._initial_conditions = init_conditions

    def before_start(self):
        """Get Before Start Callback.

        :return: Callbacks
        """
        return self._callbacks["before_start"]

    def add_before_start(self, callback):
        """
        Add callback function/method/object to execute before
        the simlation starts. Needs to be callable.

        :param func callback: Callable Object

        >>> from pyswmm import Simulation
        >>>
        >>> def test_callback():
        ...     print("CALLBACK - Executed")
        >>>
        >>> with Simulation('./TestModel1_weirSetting.inp') as sim:
        ...
        ...     sim.before_start(test_callback) #<- pass function handle.
        ...     print("Waiting to Start")
        ...     for ind, step in enumerate(sim):
        ...         print("Step {}".format(ind))
        ...     print("Complete!")
        ... print("Closed")
        >>>
        >>> "Waiting to Start"
        >>> "CALLBACK - Executed"
        >>> "Step 0"
        >>> "Step 1"
        >>> ...
        >>> "Complete!"
        >>> "Closed"
        """
        if self._is_callback(callback):
            self._callbacks["before_start"] = callback

    def before_step(self):
        """Get Before Step Callback.

        :return: Callbacks
        """
        return self._callbacks["before_step"]

    def add_before_step(self, callback):
        """
        Add callback function/method/object to execute before
        a simlation step. Needs to be callable.

        :param func callback: Callable Object

        (See self.add_before_start() for more details)
        """
        if self._is_callback(callback):
            self._callbacks["before_step"] = callback

    def after_step(self):
        """Get After Step Callback.

        :return: Callbacks
        """
        return self._callbacks["after_step"]

    def add_after_step(self, callback):
        """
        Add callback function/method/object to execute after
        a simlation step. Needs to be callable.

        :param func callback: Callable Object

        (See self.add_before_start() for more details)
        """
        if self._is_callback(callback):
            self._callbacks["after_step"] = callback

    def before_end(self):
        """Get Before End Callback.

        :return: Callbacks
        """
        return self._callbacks["before_end"]

    def add_before_end(self, callback):
        """
        Add callback function/method/object to execute after
        the simulation ends. Needs to be callable.

        :param func callback: Callable Object

        (See self.add_before_start() for more details)
        """
        if self._is_callback(callback):
            self._callbacks["before_end"] = callback

    def after_end(self):
        """Get After End Callback.

        :return: Callbacks
        """
        return self._callbacks["after_end"]

    def add_after_end(self, callback):
        """
        Add callback function/method/object to execute after
        the simulation ends. Needs to be callable.

        :param func callback: Callable Object

        (See self.add_before_start() for more details)
        """
        if self._is_callback(callback):
            self._callbacks["after_end"] = callback

    def after_close(self):
        """Get After Close Callback.

        :return: Callbacks
        """
        return self._callbacks["after_close"]

    def add_after_close(self, callback):
        """
        Add callback function/method/object to execute after
        the simulation is closed. Needs to be callable.

        :param func callback: Callable Object

        (See self.add_before_start() for more details)
        """
        if self._is_callback(callback):
            self._callbacks["after_close"] = callback

    def step_advance(self, advance_seconds):
        """
        Advances the model by X number of seconds instead of
        intervening at every routing step.  This does not change
        the routing step for the simulation; only lets python take
        back control after each advance period.

        :param int advance_seconds: Seconds to Advance simulation

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     sim.step_advance(300)
        ...     for step in sim:
        ...         print(step.current_time)
        ...         # or here! sim.step_advance(newvalue)
        ...     sim.report()
        >>>
        >>> 2015-11-01 14:00:30
        >>> 2015-11-01 14:01:00
        >>> 2015-11-01 14:01:30
        >>> 2015-11-01 14:02:00
        """
        self._advance_seconds = advance_seconds

    def report(self):
        """
        Writes to report file after simulation.

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     for step in sim:
        ...         pass
        ...     sim.report()
        """
        self._model.swmm_report()

    def close(self):
        """
        Intialize a simulation and iterate through a simulation. This
        approach requires some clean up.

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> sim = Simulation('./TestModel1_weirSetting.inp')
        >>> for step in sim:
        ...     pass
        >>>
        >>> sim.report()
        >>> sim.close()
        """
        self.__exit__()

    def execute(self):
        """
        Open an input file, run SWMM, then close the file.

        Examples:

        >>> sim = PYSWMM(r'\\test.inp')
        >>> sim.execute()
        """
        self._model.swmmExec()

    @property
    def engine_version(self):
        """
        Retrieves the SWMM Engine Version.

        :return: Engine Version
        :rtype: StrictVersion

        Examples:

        >>> sim = PYSWMM(r'\\test.inp')
        >>> sim.engine_version
        StrictVersion("5.1.13")
        """
        return self._model.swmm_getVersion()

    @property
    def runoff_error(self):
        """
        Retrieves the Runoff Mass Balance Error.

        :return: Runoff Mass Balance Error
        :rtype: float

        Examples:

        >>> sim = PYSWMM(r'\\test.inp')
        >>> sim.execute()
        >>> sim.runoff_error
        0.01
        """
        return self._model.swmm_getMassBalErr()[0]

    @property
    def flow_routing_error(self):
        """
        Retrieves the Flow Routing Mass Balance Error.

        :return: Flow Routing Mass Balance Error
        :rtype: float

        Examples:

        >>> sim = PYSWMM(r'\\test.inp')
        >>> sim.execute()
        >>> sim.flow_routing_error
        0.01
        """
        return self._model.swmm_getMassBalErr()[1]

    @property
    def quality_error(self):
        """
        Retrieves the Quality Routing Mass Balance Error.

        :return: Quality Routing Mass Balance Error
        :rtype: float

        Examples:

        >>> sim = PYSWMM(r'\\test.inp')
        >>> sim.execute()
        >>> sim.quality_error
        0.01
        """
        return self._model.swmm_getMassBalErr()[2]

    @property
    def start_time(self):
        """Get/set Simulation start time.

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     print sim.start_time
        ...     sim.start_time = datetime(2015,5,10,15,15,1)
        >>>
        >>> datetime.datetime(2015,5,10,15,15,1)
        """
        return self._model.getSimulationDateTime(
            SimulationTime.StartDateTime.value)

    @start_time.setter
    def start_time(self, dtimeval):
        """Set simulation Start time"""
        self._model.setSimulationDateTime(SimulationTime.StartDateTime.value,
                                          dtimeval)

    @property
    def end_time(self):
        """Get/set Simulation end time.

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     print sim.end_time
        ...     sim.end_time = datetime(2016,5,10,15,15,1)
        >>>
        >>> datetime.datetime(2016,5,10,15,15,1)
        """
        return self._model.getSimulationDateTime(
            SimulationTime.EndDateTime.value)

    @end_time.setter
    def end_time(self, dtimeval):
        """Set simulation End time."""
        self._model.setSimulationDateTime(SimulationTime.EndDateTime.value,
                                          dtimeval)

    @property
    def report_start(self):
        """Get/set Simulation report start time.

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     print sim.report_start
        ...     sim.report_start = datetime(2015,5,10,15,15,1)
        >>>
        >>> datetime.datetime(2015,5,10,15,15,1)
        """
        return self._model.getSimulationDateTime(
            SimulationTime.ReportStart.value)

    @report_start.setter
    def report_start(self, dtimeval):
        """Set simulation report start time."""
        self._model.setSimulationDateTime(SimulationTime.ReportStart.value,
                                          dtimeval)

    @property
    def flow_units(self):
        """
        Get Simulation Units (CFS, GPM, MGD, CMS, LPS, MLD).

        :return: Flow Unit
        :rtype: str

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     print sim.flow_units
        >>>
        >>> CFS
        """
        return self._model.getSimUnit(SimulationUnits.FlowUnits.value)

    @property
    def system_units(self):
        """Get system units (US, SI).

        :return: System Unit
        :rtype: str

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     print sim.system_units
        >>>
        >>> US
        """
        return self._model.getSimUnit(SimulationUnits.UnitSystem.value)

    @property
    def current_time(self):
        """Get Simulation Current Time.

        :return: Current Simulation Time
        :rtype: Datetime

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     for step in sim:
        ...         print(sim.current_time)
        ...     sim.report()
        >>>
        >>> 2015-11-01 14:00:30
        >>> 2015-11-01 14:01:00
        >>> 2015-11-01 14:01:30
        >>> 2015-11-01 14:02:00
        """
        return self._model.getCurrentSimulationTime()

    @property
    def percent_complete(self):
        """Get Simulation Percent Complete.

        :return: Current Percent Complete
        :rtype: Datetime

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     for step in sim:
        ...         print(sim.percent_complete)
        ...     sim.report()
        >>>
        >>> 0.01
        >>> 0.25
        >>> 0.50
        >>> 0.75
        """
        dt = self.current_time - self.start_time
        total_time = self.end_time - self.start_time
        return float(dt.total_seconds()) / total_time.total_seconds()
Example #6
0
class Simulation(object):
    """
    Base class for a SWMM Simulation.

    The model object provides several options to run a simulation.

    Examples:

    Intialize a simulation and iterate through a simulation. This
    approach requires some clean up.

    >>> from pyswmm import Simulation
    >>>
    >>> sim = Simulation('./TestModel1_weirSetting.inp')
    >>> for step in sim:
    ...     pass
    >>>
    >>> sim.report()
    >>> sim.close()

    Intialize using with statement.  This automatically cleans up
    after a simulation

    >>> from pyswmm import Simulation
    >>>
    >>> with Simulation('./TestModel1_weirSetting.inp') as sim:
    ...     for step in sim:
    ...         pass
    ...     sim.report()

    Initialize the simulation and execute. This style does not allow
    the user to interact with the simulation. However, this approach
    tends to be the fastest.

    >>> from pyswmm import Simulation
    >>>
    >>> sim = Simulation('./TestModel1_weirSetting.inp')
    >>> sim.execute()
    """

    def __init__(self, inputfile, reportfile=None, outputfile=None):
        self._model = PySWMM(inputfile, reportfile, outputfile)
        self._model.swmm_open()
        self._advance_seconds = None
        self._isStarted = False

    def __enter__(self):
        """
        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('../test/TestModel1_weirSetting.inp') as sim:
        ...     for step in sim:
        ...         print(sim.current_time)
        ...     sim.report()
        >>>
        >>> 2015-11-01 14:00:30
        >>> 2015-11-01 14:01:00
        >>> 2015-11-01 14:01:30
        >>> 2015-11-01 14:02:00
        """
        return self

    def __iter__(self):
        """Iterator over Simulation"""
        return self

    def next(self):
        """Next"""
        # Start Simulation
        if not self._isStarted:
            self._model.swmm_start(True)
            self._isStarted = True

        # Simulation Step Amount
        if self._advance_seconds is None:
            time = self._model.swmm_step()
        else:
            time = self._model.swmm_stride(self._advance_seconds)

        if time <= 0.0:
            self._model.swmm_end()
            raise StopIteration
        return self._model

    def __exit__(self, *a):
        """close"""
        self._model.swmm_end()
        self._model.swmm_close()

    def step_advance(self, advance_seconds):
        """
        Advances the model by X number of seconds instead of
        intervening at every routing step.  This does not change
        the routing step for the simulation; only lets python take
        back control after each advance period.

        :param int advance_seconds: Seconds to Advance simulation

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('../test/TestModel1_weirSetting.inp') as sim:
        ...     sim.step_advance(300)
        ...     for step in sim:
        ...         print(step.current_time)
        ...         # or here! sim.step_advance(newvalue)
        ...     sim.report()
        >>>
        >>> 2015-11-01 14:00:30
        >>> 2015-11-01 14:01:00
        >>> 2015-11-01 14:01:30
        >>> 2015-11-01 14:02:00
        """
        self._advance_seconds = advance_seconds

    def report(self):
        """
        Writes to report file after simulation

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('../test/TestModel1_weirSetting.inp') as sim:
        ...     for step in sim:
        ...         pass
        ...     sim.report()
        """
        self._model.swmm_report()

    def close(self):
        """
        Intialize a simulation and iterate through a simulation. This
        approach requires some clean up.

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> sim = Simulation('./TestModel1_weirSetting.inp')
        >>> for step in sim:
        ...     pass
        >>>
        >>> sim.report()
        >>> sim.close()
        """
        self.__exit__()

    def execute(self):
        """
        Open an input file, run SWMM, then close the file.

        Examples:

        >>> sim = PYSWMM(r'\\test.inp')
        >>> sim.execute()
        """
        self._model.swmmExec()

    @property
    def start_time(self):
        """Get/set Simulation start time

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('../test/TestModel1_weirSetting.inp') as sim:
        ...     print sim.start_time
        ...     sim.start_time = datetime(2015,5,10,15,15,1)
        >>>
        >>> datetime.datetime(2015,5,10,15,15,1)
        """
        return self._model.getSimulationDateTime(
            SimulationTime.StartDateTime.value)

    @start_time.setter
    def start_time(self, dtimeval):
        """Set simulation Start time"""
        self._model.setSimulationDateTime(SimulationTime.StartDateTime.value,
                                          dtimeval)

    @property
    def end_time(self):
        """Get/set Simulation end time

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('../test/TestModel1_weirSetting.inp') as sim:
        ...     print sim.end_time
        ...     sim.end_time = datetime(2016,5,10,15,15,1)
        >>>
        >>> datetime.datetime(2016,5,10,15,15,1)
        """
        return self._model.getSimulationDateTime(
            SimulationTime.EndDateTime.value)

    @end_time.setter
    def end_time(self, dtimeval):
        """Set simulation End time"""
        self._model.setSimulationDateTime(SimulationTime.EndDateTime.value,
                                          dtimeval)

    @property
    def report_start(self):
        """Get/set Simulation report start time

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('../test/TestModel1_weirSetting.inp') as sim:
        ...     print sim.report_start
        ...     sim.report_start = datetime(2015,5,10,15,15,1)
        >>>
        >>> datetime.datetime(2015,5,10,15,15,1)
        """
        return self._model.getSimulationDateTime(
            SimulationTime.ReportStart.value)

    @report_start.setter
    def report_start(self, dtimeval):
        """Set simulation report start time"""
        self._model.setSimulationDateTime(SimulationTime.ReportStart.value,
                                          dtimeval)

    @property
    def flow_units(self):
        """
        Get Simulation Units (CFS, GPM, MGD, CMS, LPS, MLD).

        :return: Flow Unit
        :rtype: str

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('../test/TestModel1_weirSetting.inp') as sim:
        ...     print sim.flow_units
        >>>
        >>> CFS
        """
        return self._model.getSimUnit(SimulationUnits.FlowUnits.value)

    @property
    def system_units(self):
        """Get system units (US, SI).

        :return: System Unit
        :rtype: str

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('../test/TestModel1_weirSetting.inp') as sim:
        ...     print sim.system_units
        >>>
        >>> US
        """
        return self._model.getSimUnit(SimulationUnits.UnitSystem.value)

    @property
    def current_time(self):
        """Get Simulation Current Time.

        :return: Current Simulation Time
        :rtype: Datetime

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('../test/TestModel1_weirSetting.inp') as sim:
        ...     for step in sim:
        ...         print(sim.current_time)
        ...     sim.report()
        >>>
        >>> 2015-11-01 14:00:30
        >>> 2015-11-01 14:01:00
        >>> 2015-11-01 14:01:30
        >>> 2015-11-01 14:02:00
        """
        return self._model.getCurrentSimualationTime()
Example #7
0
def test_error_rpt_out():
    swmmobject = PySWMM(MODEL_WEIR_SETTING_PATH)
    swmmobject.swmm_open()
Example #8
0
def test_nodes_1():
    swmmobject = PySWMM(MODEL_WEIR_SETTING_PATH)
    swmmobject.swmm_open()
    node = Node(swmmobject, "J1")
    print(node.invert_elevation)
Example #9
0
def test_plot_weir_setting():
    swmmobject = PySWMM(*get_model_files(MODEL_WEIR_SETTING_PATH))
    swmmobject.swmm_open()
    swmmobject.swmm_start(True)

    fig = plt.figure()
    ax = fig.add_subplot(221)
    ax.set_ylabel('Flow Rate')
    line, = ax.plot([], [], label='C3')
    ax.grid()
    ax.legend()

    ax2 = fig.add_subplot(223, sharex=ax)
    ax2.set_ylabel('Setting')
    line2, = ax2.plot([], [], label='C3')
    ax2.grid()

    xdata, ydata = [], []
    ydata2 = []

    ax3 = fig.add_subplot(2, 2, (2, 4))
    arr_lena = read_png(IMAGE_WEIR_SETTING_PATH)
    imagebox = OffsetImage(arr_lena, zoom=0.45)
    ab = AnnotationBbox(
        imagebox,
        (0.5, 0.5),
        xybox=(0.5, 0.5),
        xycoords='data',
        boxcoords="offset points",
        pad=0.0,
    )
    ax3.add_artist(ab)
    ax3.axis('off')

    def data_gen(t=0):
        i = 0
        while (True):
            time = swmmobject.swmm_stride(300)
            i += 1
            if i == 80:
                swmmobject.setLinkSetting('C3', 0.9)
            elif i == 90:
                swmmobject.setLinkSetting('C3', 0.8)
            elif i == 100:
                swmmobject.setLinkSetting('C3', 0.7)
            elif i == 110:
                swmmobject.setLinkSetting('C3', 0.6)
            elif i == 120:
                swmmobject.setLinkSetting('C3', 0.5)
            elif i == 130:
                swmmobject.setLinkSetting('C3', 0.4)
            elif i == 140:
                swmmobject.setLinkSetting('C3', 0.3)
            elif i == 150:
                swmmobject.setLinkSetting('C3', 0.2)
            elif i == 160:
                swmmobject.setLinkSetting('C3', 0.1)
            elif i == 170:
                swmmobject.setLinkSetting('C3', 0.0)
            elif i == 220:
                swmmobject.setLinkSetting('C3', 1.0)

            if i > 0 and time == 0.0:
                break

            if i > 0 and time > 0:
                yield time

    def run(t):
        xdata.append(t)
        new_y = swmmobject.getLinkResult('C3', tka.LinkResults.newFlow)
        ydata.append(new_y)

        new_y2 = swmmobject.getLinkResult('C3', tka.LinkResults.setting)
        ydata2.append(new_y2)

        xmin, xmax = ax.get_xlim()
        ymin, ymax = ax.get_ylim()
        ymin2, ymax2 = ax2.get_ylim()

        # ax
        if new_y > ymax:
            ax.set_ylim(-0.1, 1.5 * ymax)

        if t >= xmax:
            ax.set_xlim(xmin, 1.5 * xmax)
            ax.figure.canvas.draw()
        line.set_data(xdata, ydata)

        # ax1
        if new_y2 > ymax2:
            ax2.set_ylim(-0.1, 1.2 * ymax2)
        line2.set_data(xdata, ydata2)

    ani = animation.FuncAnimation(fig,
                                  run,
                                  data_gen,
                                  blit=False,
                                  repeat=False,
                                  save_count=800,
                                  interval=10)

    show_fig = False
    if show_fig:
        plt.show()
    else:
        movie_path = os.path.join(DATA_PATH, "weir_setting.mp4")
        print(movie_path, ani)
        # ani.save(movie_path, fps=20, dpi=170, bitrate=50000)

    plt.close()

    swmmobject.swmm_end()
    swmmobject.swmm_close()
    print("Check Passed")
Example #10
0
def test_plot_node_inflows():
    swmmobject = PySWMM(*get_model_files(MODEL_NODE_INFLOWS_PATH))
    swmmobject.swmm_open()
    swmmobject.swmm_start()

    fig = plt.figure()
    ax = fig.add_subplot(2, 3, (1, 2))
    ax.set_ylabel('Flow Rate')
    line, = ax.plot([], [], label='C3')
    ax.grid()
    ax.legend()

    ax2 = fig.add_subplot(2, 3, (4, 5), sharex=ax)
    ax2.set_ylabel('Toolkit API\nInflow')
    line2, = ax2.plot([], [], label='J1')
    ax2.grid()

    xdata, ydata = [], []
    ydata2 = []

    ax3 = fig.add_subplot(2, 3, (3, 6))

    arr_lena = read_png(IMAGE_NODE_INFLOWS_PATH)
    imagebox = OffsetImage(arr_lena, zoom=0.67)
    ab = AnnotationBbox(
        imagebox,
        (0.5, 0.5),
        xybox=(0.5, 0.5),
        xycoords='data',
        boxcoords="offset points",
        pad=0.0,
    )

    ax3.add_artist(ab)
    ax3.axis('off')

    def data_gen(t=0):
        i = 0
        while (True):
            if i >= 80:
                swmmobject.setNodeInflow('J1', random.randint(1, 5))
            time = swmmobject.swmm_stride(1500)
            i += 1

            if i > 0 and time == 0.0:
                break
            if i > 0 and time > 0:
                yield time

    def run(t):
        xdata.append(t)
        new_y = swmmobject.getLinkResult('C2', tka.LinkResults.newFlow)
        ydata.append(new_y)

        new_y2 = swmmobject.getNodeResult('J1', tka.NodeResults.newLatFlow)
        ydata2.append(new_y2)

        xmin, xmax = ax.get_xlim()
        ymin, ymax = ax.get_ylim()
        ymin2, ymax2 = ax2.get_ylim()

        # ax
        if new_y > ymax:
            ax.set_ylim(-0.1, 1.5 * ymax)
        if t >= xmax:
            ax.set_xlim(xmin, 1.5 * xmax)
            ax.figure.canvas.draw()
        line.set_data(xdata, ydata)

        # ax1
        if new_y2 > ymax2:
            ax2.set_ylim(-0.1, 1.2 * ymax2)
        line2.set_data(xdata, ydata2)

    ani = animation.FuncAnimation(
        fig,
        run,
        data_gen,
        blit=False,
        repeat=False,
        save_count=800,
        interval=10,
    )

    show_figure = False
    if show_figure:
        plt.show()
    else:
        movie_path = os.path.join(DATA_PATH, "node_inflows.mp4")
        print(movie_path, ani)
        # ani.save(movie_path, fps=20, dpi=170, bitrate=50000)
    plt.close()

    swmmobject.swmm_end()
    swmmobject.swmm_report()
    swmmobject.swmm_close()
    print("Check Passed")
Example #11
0
def test_warning():
    swmmobject = PySWMM(*get_model_files(MODEL_WEIR_SETTING_PATH))
    swmmobject.swmm_open()
    swmmobject.getLinkResult('C2', 0)
    swmmobject.swmm_close()
# Simulation Time Steps

episode_count = 198
timesteps = episode_count * 576

epi_start = 0
epi_end = 1
epsilon_value = np.linspace(epi_start, epi_end, timesteps + 10)

episode_timer = 0

while episode_timer < episode_count:

    #run SWMM
    swmm_model = PySWMM('test.inp', 'test.rpt', 'test.out')
    swmm_model.swmm_open()
    swmm_model.swmm_start()
    n1 = "Tank_LaoDongLu"
    n2 = "Tank_ChengXi"
    p1 = "Pump_LaoDongLu1"
    p2 = "Pump_LaoDongLu2"
    p3 = "Pump_LaoDongLu3"
    p4 = "Pump_ChengXi1"
    p5 = "Pump_ChengXi2"
    p6 = "Pump_ChengXi3"
    p7 = "Pump_ChengXi4"
    node = [n1, n2]
    pump = [p1, p2, p3, p4, p5, p6, p7]

    for i in node_controlled:
Example #13
0
def test_set_current_time():
    swmmobject = PySWMM(*get_model_files(MODEL_WEIR_SETTING_PATH))
    swmmobject.swmm_open()

    print(swmmobject.getSimulationDateTime(0))
    print(swmmobject.getSimulationDateTime(0) - timedelta(days=10))
    swmmobject.setSimulationDateTime(
        0,
        swmmobject.getSimulationDateTime(0) - timedelta(days=10), )
    print(swmmobject.getSimulationDateTime(0))

    print(swmmobject.getSimulationDateTime(1))
    print(swmmobject.getSimulationDateTime(1) - timedelta(days=10))
    swmmobject.setSimulationDateTime(
        1,
        swmmobject.getSimulationDateTime(1) - timedelta(days=10), )
    print(swmmobject.getSimulationDateTime(1))

    print(swmmobject.getSimulationDateTime(2))
    print(swmmobject.getSimulationDateTime(2) - timedelta(days=10))
    swmmobject.setSimulationDateTime(
        2,
        swmmobject.getSimulationDateTime(2) - timedelta(days=10), )
    print(swmmobject.getSimulationDateTime(2))

    swmmobject.swmm_start()

    i = 0
    while (True):
        time = swmmobject.swmm_stride(600)
        i += 1
        print(swmmobject.getCurrentSimualationTime())
        print(type(swmmobject.getCurrentSimualationTime()))

        if (time <= 0.0):
            break

        if i % 144 == 0:
            print(i)

    swmmobject.swmm_end()
    swmmobject.swmm_close()
Example #14
0
def test_current_time():
    swmmobject = PySWMM(*get_model_files(MODEL_WEIR_SETTING_PATH))
    swmmobject.swmm_open()
    date = swmmobject.getSimulationDateTime(0)
    print(date)
    swmmobject.swmm_start()

    i = 0
    while (True):
        time = swmmobject.swmm_stride(600)
        print(time)
        i += 1
        current_time = swmmobject.getCurrentSimualationTime()
        print(current_time)
        print(type(swmmobject.getCurrentSimualationTime()))

        if (time <= 0.0):
            break
        if i % 144 == 0:
            print(i)

    swmmobject.swmm_end()
    swmmobject.swmm_report()
    swmmobject.swmm_close()
Example #15
0
def test_nodes_1():
    ''' pytest pyswmm/tests/test_nodes.py -k `test_nodes_1` '''
    swmmobject = PySWMM(MODEL_WEIR_SETTING_PATH)
    swmmobject.swmm_open()
    node = Node(swmmobject, "J1")
    assert(node.invert_elevation == 20.728)
Example #16
0
episode_timer = 0

while episode_timer < episode_count:
    """
    i=random.randint(1,3)
    """

    i = 1
    sim_num = i

    #run SWMM
    rain = rain_generation(i)

    swmm_model = PySWMM(r'../model/test' + str(i) + '.inp',
                        r'../model/test' + str(i) + '.rpt',
                        r'../model/test' + str(i) + '.out')
    swmm_model.swmm_open()
    swmm_model.swmm_start()
    n1 = "Tank_LaoDongLu"
    n2 = "Tank_ChengXi"
    p1 = "Pump_LaoDongLu1"
    p2 = "Pump_LaoDongLu2"
    p3 = "Pump_LaoDongLu3"
    p4 = "Pump_ChengXi1"
    p5 = "Pump_ChengXi2"
    p6 = "Pump_ChengXi3"
    p7 = "Pump_ChengXi4"
    node = [n1, n2]
    pump = [p1, p2, p3, p4, p5, p6, p7]
Example #17
0
class Simulation(object):
    """
    Base class for a SWMM Simulation.

    The model object provides several options to run a simulation.

    Examples:

    Intialize a simulation and iterate through a simulation. This
    approach requires some clean up.

    >>> from pyswmm import Simulation
    >>>
    >>> sim = Simulation('./TestModel1_weirSetting.inp')
    >>> for step in sim:
    ...     pass
    >>>
    >>> sim.report()
    >>> sim.close()

    Intialize using with statement.  This automatically cleans up
    after a simulation

    >>> from pyswmm import Simulation
    >>>
    >>> with Simulation('./TestModel1_weirSetting.inp') as sim:
    ...     for step in sim:
    ...         pass
    ...     sim.report()

    Initialize the simulation and execute. This style does not allow
    the user to interact with the simulation. However, this approach
    tends to be the fastest.

    >>> from pyswmm import Simulation
    >>>
    >>> sim = Simulation('./TestModel1_weirSetting.inp')
    >>> sim.execute()
    """
    def __init__(self, inputfile, reportfile=None, outputfile=None):
        self._model = PySWMM(inputfile, reportfile, outputfile)
        self._model.swmm_open()
        self._isOpen = True
        self._advance_seconds = None
        self._isStarted = False
        self._initial_conditions = None

    def __enter__(self):
        """
        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('../test/TestModel1_weirSetting.inp') as sim:
        ...     for step in sim:
        ...         print(sim.current_time)
        ...     sim.report()
        >>>
        >>> 2015-11-01 14:00:30
        >>> 2015-11-01 14:01:00
        >>> 2015-11-01 14:01:30
        >>> 2015-11-01 14:02:00
        """
        return self

    def __iter__(self):
        """Iterator over Simulation"""
        return self

    def start(self):
        """Start Simulation"""
        if not self._isStarted:
            # Set Model Initial Conditions
            if self._initial_conditions:
                self._initial_conditions()
            self._model.swmm_start(True)
            self._isStarted = True

    def __next__(self):
        """Next"""
        # Start Simulation
        self.start()

        # Simulation Step Amount
        if self._advance_seconds is None:
            time = self._model.swmm_step()
        else:
            time = self._model.swmm_stride(self._advance_seconds)

        if time <= 0.0:
            self._model.swmm_end()
            self._isStarted = False
            raise StopIteration
        return self._model

    next = __next__  # Python 2

    def __exit__(self, *a):
        """close"""
        if self._isStarted:
            self._model.swmm_end()
            self._isStarted = False
        if self._isOpen:
            self._model.swmm_close()
            self._isOpen = False

    def initial_conditions(self, init_conditions):
        """
        Intial Conditions for Hydraulics and Hydrology can be set
        from within the api by setting a function to the
        initial_conditions property.

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('./TestModel1_weirSetting.inp') as sim:
        ...     nodeJ1 = Nodes(sim)["J1"]
        ...
        ...     def init_conditions():
        ...         nodeJ1.initial_depth = 4
        ...
        ...     sim.initial_conditions(init_conditions)
        ...
        ...     for step in sim:
        ...         pass
        ...     sim.report()

        """
        if hasattr(init_conditions, '__call__'):
            self._initial_conditions = init_conditions
        else:
            error_msg = 'Requires Type Function, not {}'.format(
                type(init_conditions))
            raise (PYSWMMException(error_msg))

    def step_advance(self, advance_seconds):
        """
        Advances the model by X number of seconds instead of
        intervening at every routing step.  This does not change
        the routing step for the simulation; only lets python take
        back control after each advance period.

        :param int advance_seconds: Seconds to Advance simulation

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('../test/TestModel1_weirSetting.inp') as sim:
        ...     sim.step_advance(300)
        ...     for step in sim:
        ...         print(step.current_time)
        ...         # or here! sim.step_advance(newvalue)
        ...     sim.report()
        >>>
        >>> 2015-11-01 14:00:30
        >>> 2015-11-01 14:01:00
        >>> 2015-11-01 14:01:30
        >>> 2015-11-01 14:02:00
        """
        self._advance_seconds = advance_seconds

    def report(self):
        """
        Writes to report file after simulation.

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('../test/TestModel1_weirSetting.inp') as sim:
        ...     for step in sim:
        ...         pass
        ...     sim.report()
        """
        self._model.swmm_report()

    def close(self):
        """
        Intialize a simulation and iterate through a simulation. This
        approach requires some clean up.

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> sim = Simulation('./TestModel1_weirSetting.inp')
        >>> for step in sim:
        ...     pass
        >>>
        >>> sim.report()
        >>> sim.close()
        """
        self.__exit__()

    def execute(self):
        """
        Open an input file, run SWMM, then close the file.

        Examples:

        >>> sim = PYSWMM(r'\\test.inp')
        >>> sim.execute()
        """
        self._model.swmmExec()

    @property
    def engine_version(self):
        """
        Retrieves the SWMM Engine Version.

        :return: Engine Version
        :rtype: StrictVersion

        Examples:

        >>> sim = PYSWMM(r'\\test.inp')
        >>> sim.engine_version
        StrictVersion("5.1.13")
        """
        return self._model.swmm_getVersion()

    @property
    def runoff_error(self):
        """
        Retrieves the Runoff Mass Balance Error.

        :return: Runoff Mass Balance Error
        :rtype: float

        Examples:

        >>> sim = PYSWMM(r'\\test.inp')
        >>> sim.execute()
        >>> sim.runoff_error
        0.01
        """
        return self._model.swmm_getMassBalErr()[0]

    @property
    def flow_routing_error(self):
        """
        Retrieves the Flow Routing Mass Balance Error.

        :return: Flow Routing Mass Balance Error
        :rtype: float

        Examples:

        >>> sim = PYSWMM(r'\\test.inp')
        >>> sim.execute()
        >>> sim.flow_routing_error
        0.01
        """
        return self._model.swmm_getMassBalErr()[1]

    @property
    def quality_error(self):
        """
        Retrieves the Quality Routing Mass Balance Error.

        :return: Quality Routing Mass Balance Error
        :rtype: float

        Examples:

        >>> sim = PYSWMM(r'\\test.inp')
        >>> sim.execute()
        >>> sim.quality_error
        0.01
        """
        return self._model.swmm_getMassBalErr()[2]

    @property
    def start_time(self):
        """Get/set Simulation start time.

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('../test/TestModel1_weirSetting.inp') as sim:
        ...     print sim.start_time
        ...     sim.start_time = datetime(2015,5,10,15,15,1)
        >>>
        >>> datetime.datetime(2015,5,10,15,15,1)
        """
        return self._model.getSimulationDateTime(
            SimulationTime.StartDateTime.value)

    @start_time.setter
    def start_time(self, dtimeval):
        """Set simulation Start time"""
        self._model.setSimulationDateTime(SimulationTime.StartDateTime.value,
                                          dtimeval)

    @property
    def end_time(self):
        """Get/set Simulation end time.

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('../test/TestModel1_weirSetting.inp') as sim:
        ...     print sim.end_time
        ...     sim.end_time = datetime(2016,5,10,15,15,1)
        >>>
        >>> datetime.datetime(2016,5,10,15,15,1)
        """
        return self._model.getSimulationDateTime(
            SimulationTime.EndDateTime.value)

    @end_time.setter
    def end_time(self, dtimeval):
        """Set simulation End time."""
        self._model.setSimulationDateTime(SimulationTime.EndDateTime.value,
                                          dtimeval)

    @property
    def report_start(self):
        """Get/set Simulation report start time.

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('../test/TestModel1_weirSetting.inp') as sim:
        ...     print sim.report_start
        ...     sim.report_start = datetime(2015,5,10,15,15,1)
        >>>
        >>> datetime.datetime(2015,5,10,15,15,1)
        """
        return self._model.getSimulationDateTime(
            SimulationTime.ReportStart.value)

    @report_start.setter
    def report_start(self, dtimeval):
        """Set simulation report start time."""
        self._model.setSimulationDateTime(SimulationTime.ReportStart.value,
                                          dtimeval)

    @property
    def flow_units(self):
        """
        Get Simulation Units (CFS, GPM, MGD, CMS, LPS, MLD).

        :return: Flow Unit
        :rtype: str

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('../test/TestModel1_weirSetting.inp') as sim:
        ...     print sim.flow_units
        >>>
        >>> CFS
        """
        return self._model.getSimUnit(SimulationUnits.FlowUnits.value)

    @property
    def system_units(self):
        """Get system units (US, SI).

        :return: System Unit
        :rtype: str

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('../test/TestModel1_weirSetting.inp') as sim:
        ...     print sim.system_units
        >>>
        >>> US
        """
        return self._model.getSimUnit(SimulationUnits.UnitSystem.value)

    @property
    def current_time(self):
        """Get Simulation Current Time.

        :return: Current Simulation Time
        :rtype: Datetime

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('../test/TestModel1_weirSetting.inp') as sim:
        ...     for step in sim:
        ...         print(sim.current_time)
        ...     sim.report()
        >>>
        >>> 2015-11-01 14:00:30
        >>> 2015-11-01 14:01:00
        >>> 2015-11-01 14:01:30
        >>> 2015-11-01 14:02:00
        """
        return self._model.getCurrentSimulationTime()

    @property
    def percent_complete(self):
        """Get Simulation Percent Complete.

        :return: Current Percent Complete
        :rtype: Datetime

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('../test/TestModel1_weirSetting.inp') as sim:
        ...     for step in sim:
        ...         print(sim.percent_complete)
        ...     sim.report()
        >>>
        >>> 0.01
        >>> 0.25
        >>> 0.50
        >>> 0.75
        """
        dt = self.current_time - self.start_time
        total_time = self.end_time - self.start_time
        return float(dt.total_seconds()) / total_time.total_seconds()
Example #18
0
def test_nodes_4():
    swmmobject = PySWMM(*get_model_files(MODEL_WEIR_SETTING_PATH))
    swmmobject.swmm_open()

    print(swmmobject.getNodeParam('J2', tka.NodeParams.invertElev))
    swmmobject.setNodeParam('J2', tka.NodeParams.invertElev, 19)
    print(swmmobject.getNodeParam('J2', tka.NodeParams.invertElev))

    print(swmmobject.getLinkParam('C1:C2', tka.LinkParams.offset1))
    swmmobject.setLinkParam('C1:C2', tka.LinkParams.offset1, 19)
    print(swmmobject.getLinkParam('C1:C2', tka.LinkParams.offset1))

    print(swmmobject.getSubcatchParam('S2', tka.SubcParams.area))
    swmmobject.setSubcatchParam('S2', tka.SubcParams.area, 19)
    print(swmmobject.getSubcatchParam('S2', tka.SubcParams.area))

    swmmobject.swmm_start()
    i = 0
    while (True):
        time = swmmobject.swmm_stride(600)
        i += 1

        if (time <= 0.0):
            break

        if i % 144 == 0:
            print(i)

        swmmobject.setLinkParam('C1:C2', tka.LinkParams.qLimit, 0.25)

    swmmobject.swmm_end()
    swmmobject.swmm_close()
    print("swmm_step() Check Passed")
Example #19
0
class Simulation(object):
    """
    Base class for a SWMM Simulation.

    The model object provides several options to run a simulation.
    User can specified SWMM library path. Uses default lib if not provided.

    Initialize the Simulation class.

    :param str inpfile: Name of SWMM input file (default '')
    :param str rptfile: Report file to generate (default None)
    :param str binfile: Optional binary output file (default None)
    :param str swmm_lib_path: User-specified SWMM library path (default None).

    Examples:

    Intialize a simulation and iterate through a simulation. This
    approach requires some clean up.

    >>> from pyswmm import Simulation
    >>>
    >>> sim = Simulation('tests/data/TestModel1_weirSetting.inp')
    >>> for step in sim:
    ...     pass
    >>>
    >>> sim.report()
    >>> sim.close()

    Intialize using with statement.  This automatically cleans up
    after a simulation

    >>> from pyswmm import Simulation
    >>>
    >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
    ...     for step in sim:
    ...         pass
    ...     sim.report()

    Initialize the simulation and execute. This style does not allow
    the user to interact with the simulation. However, this approach
    tends to be the fastest.

    >>> from pyswmm import Simulation
    >>>
    >>> sim = Simulation('tests/data/TestModel1_weirSetting.inp')
    >>> sim.execute()
    """

    def __init__(self,
                 inputfile,
                 reportfile=None,
                 outputfile=None,
                 swmm_lib_path=None):
        self._model = PySWMM(inputfile, reportfile, outputfile, swmm_lib_path)
        self._model.swmm_open()
        self._isOpen = True
        self._advance_seconds = None
        self._isStarted = False
        self._callbacks = {
            "before_start": None,
            "before_step": None,
            "after_step": None,
            "before_end": None,
            "after_end": None,
            "after_close": None
        }

    def __enter__(self):
        """
        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     for step in sim:
        ...         print(sim.current_time)
        ...     sim.report()
        >>>
        >>> 2015-11-01 14:00:30
        >>> 2015-11-01 14:01:00
        >>> 2015-11-01 14:01:30
        >>> 2015-11-01 14:02:00
        """
        return self

    def __iter__(self):
        """Iterator over Simulation"""
        return self

    def start(self):
        """Start Simulation"""
        if not self._isStarted:
            # Set Model Initial Conditions
            # (This Will be Deprecated with Time)
            if hasattr(self, "_initial_conditions"):
                self._initial_conditions()
            # Execute Callback Hooks Before Simulation
            self._execute_callback(self.before_start())
            self._model.swmm_start(True)
            self._isStarted = True

    def __next__(self):
        """Next"""
        # Start Simulation
        self.start()
        # Execute Callback Hooks Before Simulation Step
        self._execute_callback(self.before_step())
        # Simulation Step Amount
        if self._advance_seconds is None:
            time = self._model.swmm_step()
        else:
            time = self._model.swmm_stride(self._advance_seconds)
        # Execute Callback Hooks After Simulation Step
        self._execute_callback(self.after_step())
        if time <= 0.0:
            self._execute_callback(self.before_end())
            raise StopIteration
        return self._model

    next = __next__  # Python 2

    def __exit__(self, *a):
        """close"""
        if self._isStarted:
            self._model.swmm_end()
            self._isStarted = False
            # Execute Callback Hooks After Simulation End
            self._execute_callback(self.after_end())
        if self._isOpen:
            self._model.swmm_close()
            self._isOpen = False
            # Execute Callback Hooks After Simulation Closes
            self._execute_callback(self.after_close())

    @staticmethod
    def _is_callback(callable_object):
        """Checks if arugment is a function/method."""
        if not callable(callable_object):
            error_msg = 'Requires Callable Object, not {}'.format(
                type(callable_object))
            raise (PYSWMMException(error_msg))
        else:
            return True

    def _execute_callback(self, callback):
        """Runs the callback."""
        if callback:
            try:
                callback()
            except PYSWMMException:
                error_msg = "Callback Failed"
                raise PYSWMMException((error_msg))

    def initial_conditions(self, init_conditions):
        """
        Intial Conditions for Hydraulics and Hydrology can be set
        from within the api by setting a function to the
        initial_conditions property.

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('./TestModel1_weirSetting.inp') as sim:
        ...     nodeJ1 = Nodes(sim)["J1"]
        ...
        ...     def init_conditions():
        ...         nodeJ1.initial_depth = 4
        ...
        ...     sim.initial_conditions(init_conditions)
        ...
        ...     for step in sim:
        ...         pass
        ...     sim.report()

        """
        if self._is_callback(init_conditions):
            self._initial_conditions = init_conditions

    def before_start(self):
        """Get Before Start Callback.

        :return: Callbacks
        """
        return self._callbacks["before_start"]

    def add_before_start(self, callback):
        """
        Add callback function/method/object to execute before
        the simlation starts. Needs to be callable.

        :param func callback: Callable Object

        >>> from pyswmm import Simulation
        >>>
        >>> def test_callback():
        ...     print("CALLBACK - Executed")
        >>>
        >>> with Simulation('./TestModel1_weirSetting.inp') as sim:
        ...
        ...     sim.before_start(test_callback) #<- pass function handle.
        ...     print("Waiting to Start")
        ...     for ind, step in enumerate(sim):
        ...         print("Step {}".format(ind))
        ...     print("Complete!")
        ... print("Closed")
        >>>
        >>> "Waiting to Start"
        >>> "CALLBACK - Executed"
        >>> "Step 0"
        >>> "Step 1"
        >>> ...
        >>> "Complete!"
        >>> "Closed"
        """
        if self._is_callback(callback):
            self._callbacks["before_start"] = callback

    def before_step(self):
        """Get Before Step Callback.

        :return: Callbacks
        """
        return self._callbacks["before_step"]

    def add_before_step(self, callback):
        """
        Add callback function/method/object to execute before
        a simlation step. Needs to be callable.

        :param func callback: Callable Object

        (See self.add_before_start() for more details)
        """
        if self._is_callback(callback):
            self._callbacks["before_step"] = callback

    def after_step(self):
        """Get After Step Callback.

        :return: Callbacks
        """
        return self._callbacks["after_step"]

    def add_after_step(self, callback):
        """
        Add callback function/method/object to execute after
        a simlation step. Needs to be callable.

        :param func callback: Callable Object

        (See self.add_before_start() for more details)
        """
        if self._is_callback(callback):
            self._callbacks["after_step"] = callback

    def before_end(self):
        """Get Before End Callback.

        :return: Callbacks
        """
        return self._callbacks["before_end"]

    def add_before_end(self, callback):
        """
        Add callback function/method/object to execute after
        the simulation ends. Needs to be callable.

        :param func callback: Callable Object

        (See self.add_before_start() for more details)
        """
        if self._is_callback(callback):
            self._callbacks["before_end"] = callback

    def after_end(self):
        """Get After End Callback.

        :return: Callbacks
        """
        return self._callbacks["after_end"]

    def add_after_end(self, callback):
        """
        Add callback function/method/object to execute after
        the simulation ends. Needs to be callable.

        :param func callback: Callable Object

        (See self.add_before_start() for more details)
        """
        if self._is_callback(callback):
            self._callbacks["after_end"] = callback

    def after_close(self):
        """Get After Close Callback.

        :return: Callbacks
        """
        return self._callbacks["after_close"]

    def add_after_close(self, callback):
        """
        Add callback function/method/object to execute after
        the simulation is closed. Needs to be callable.

        :param func callback: Callable Object

        (See self.add_before_start() for more details)
        """
        if self._is_callback(callback):
            self._callbacks["after_close"] = callback

    def step_advance(self, advance_seconds):
        """
        Advances the model by X number of seconds instead of
        intervening at every routing step.  This does not change
        the routing step for the simulation; only lets python take
        back control after each advance period.

        :param int advance_seconds: Seconds to Advance simulation

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     sim.step_advance(300)
        ...     for step in sim:
        ...         print(step.current_time)
        ...         # or here! sim.step_advance(newvalue)
        ...     sim.report()
        >>>
        >>> 2015-11-01 14:00:30
        >>> 2015-11-01 14:01:00
        >>> 2015-11-01 14:01:30
        >>> 2015-11-01 14:02:00
        """
        self._advance_seconds = advance_seconds

    def report(self):
        """
        Writes to report file after simulation.

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     for step in sim:
        ...         pass
        ...     sim.report()
        """
        self._model.swmm_report()

    def close(self):
        """
        Intialize a simulation and iterate through a simulation. This
        approach requires some clean up.

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> sim = Simulation('./TestModel1_weirSetting.inp')
        >>> for step in sim:
        ...     pass
        >>>
        >>> sim.report()
        >>> sim.close()
        """
        self.__exit__()

    def execute(self):
        """
        Open an input file, run SWMM, then close the file.

        Examples:

        >>> sim = PYSWMM(r'\\test.inp')
        >>> sim.execute()
        """
        self._model.swmmExec()

    @property
    def engine_version(self):
        """
        Retrieves the SWMM Engine Version.

        :return: Engine Version
        :rtype: StrictVersion

        Examples:

        >>> sim = PYSWMM(r'\\test.inp')
        >>> sim.engine_version
        StrictVersion("5.1.13")
        """
        return self._model.swmm_getVersion()

    @property
    def runoff_error(self):
        """
        Retrieves the Runoff Mass Balance Error.

        :return: Runoff Mass Balance Error
        :rtype: float

        Examples:

        >>> sim = PYSWMM(r'\\test.inp')
        >>> sim.execute()
        >>> sim.runoff_error
        0.01
        """
        return self._model.swmm_getMassBalErr()[0]

    @property
    def flow_routing_error(self):
        """
        Retrieves the Flow Routing Mass Balance Error.

        :return: Flow Routing Mass Balance Error
        :rtype: float

        Examples:

        >>> sim = PYSWMM(r'\\test.inp')
        >>> sim.execute()
        >>> sim.flow_routing_error
        0.01
        """
        return self._model.swmm_getMassBalErr()[1]

    @property
    def quality_error(self):
        """
        Retrieves the Quality Routing Mass Balance Error.

        :return: Quality Routing Mass Balance Error
        :rtype: float

        Examples:

        >>> sim = PYSWMM(r'\\test.inp')
        >>> sim.execute()
        >>> sim.quality_error
        0.01
        """
        return self._model.swmm_getMassBalErr()[2]

    @property
    def start_time(self):
        """Get/set Simulation start time.

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     print sim.start_time
        ...     sim.start_time = datetime(2015,5,10,15,15,1)
        >>>
        >>> datetime.datetime(2015,5,10,15,15,1)
        """
        return self._model.getSimulationDateTime(
            SimulationTime.StartDateTime.value)

    @start_time.setter
    def start_time(self, dtimeval):
        """Set simulation Start time"""
        self._model.setSimulationDateTime(SimulationTime.StartDateTime.value,
                                          dtimeval)

    @property
    def end_time(self):
        """Get/set Simulation end time.

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     print sim.end_time
        ...     sim.end_time = datetime(2016,5,10,15,15,1)
        >>>
        >>> datetime.datetime(2016,5,10,15,15,1)
        """
        return self._model.getSimulationDateTime(
            SimulationTime.EndDateTime.value)

    @end_time.setter
    def end_time(self, dtimeval):
        """Set simulation End time."""
        self._model.setSimulationDateTime(SimulationTime.EndDateTime.value,
                                          dtimeval)

    @property
    def report_start(self):
        """Get/set Simulation report start time.

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     print sim.report_start
        ...     sim.report_start = datetime(2015,5,10,15,15,1)
        >>>
        >>> datetime.datetime(2015,5,10,15,15,1)
        """
        return self._model.getSimulationDateTime(
            SimulationTime.ReportStart.value)

    @report_start.setter
    def report_start(self, dtimeval):
        """Set simulation report start time."""
        self._model.setSimulationDateTime(SimulationTime.ReportStart.value,
                                          dtimeval)

    @property
    def flow_units(self):
        """
        Get Simulation Units (CFS, GPM, MGD, CMS, LPS, MLD).

        :return: Flow Unit
        :rtype: str

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     print sim.flow_units
        >>>
        >>> CFS
        """
        return self._model.getSimUnit(SimulationUnits.FlowUnits.value)

    @property
    def system_units(self):
        """Get system units (US, SI).

        :return: System Unit
        :rtype: str

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     print sim.system_units
        >>>
        >>> US
        """
        return self._model.getSimUnit(SimulationUnits.UnitSystem.value)

    @property
    def current_time(self):
        """Get Simulation Current Time.

        :return: Current Simulation Time
        :rtype: Datetime

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     for step in sim:
        ...         print(sim.current_time)
        ...     sim.report()
        >>>
        >>> 2015-11-01 14:00:30
        >>> 2015-11-01 14:01:00
        >>> 2015-11-01 14:01:30
        >>> 2015-11-01 14:02:00
        """
        return self._model.getCurrentSimulationTime()

    @property
    def percent_complete(self):
        """Get Simulation Percent Complete.

        :return: Current Percent Complete
        :rtype: Datetime

        Examples:

        >>> from pyswmm import Simulation
        >>>
        >>> with Simulation('tests/data/TestModel1_weirSetting.inp') as sim:
        ...     for step in sim:
        ...         print(sim.percent_complete)
        ...     sim.report()
        >>>
        >>> 0.01
        >>> 0.25
        >>> 0.50
        >>> 0.75
        """
        dt = self.current_time - self.start_time
        total_time = self.end_time - self.start_time
        return float(dt.total_seconds()) / total_time.total_seconds()