Source code for wntr.sim.epanet
"""The EPANET simulator.
"""
from wntr.sim.core import WaterNetworkSimulator
from wntr.network.io import write_inpfile
import wntr.epanet.io
import warnings
import logging
logger = logging.getLogger(__name__)
try:
import wntr.epanet.toolkit
except ImportError as e:
print('{}'.format(e))
logger.critical('%s',e)
raise ImportError('Error importing epanet toolkit while running epanet simulator. '
'Make sure libepanet is installed and added to path.')
[docs]
class EpanetSimulator(WaterNetworkSimulator):
"""
Fast EPANET simulator class.
Use the EPANET DLL to run an INP file as-is, and read the results from the
binary output file. Multiple water quality simulations are still possible
using the WQ keyword in the run_sim function. Hydraulics will be stored and
saved to a file. This file will not be deleted by default, nor will any
binary files be deleted.
The reason this is considered a "fast" simulator is due to the fact that there
is no looping within Python. The "ENsolveH" and "ENsolveQ" toolkit
functions are used instead.
.. note::
WNTR now includes access to both the EPANET 2.0.12 and EPANET 2.2 toolkit libraries.
By default, version 2.2 will be used.
Parameters
----------
wn : WaterNetworkModel
Water network model
reader : wntr.epanet.io.BinFile derived object
Defaults to None, which will create a new wntr.epanet.io.BinFile object with
the results_types specified as an init option. Otherwise, a fully
result_types : dict
Defaults to None, or all results. Otherwise, is a keyword dictionary to pass to
the reader to specify what results should be saved.
.. seealso::
wntr.epanet.io.BinFile
"""
[docs]
def __init__(self, wn, reader=None, result_types=None):
WaterNetworkSimulator.__init__(self, wn)
self.reader = reader
self.prep_time_before_main_loop = 0.0
if self.reader is None:
self.reader = wntr.epanet.io.BinFile(result_types=result_types)
[docs]
def run_sim(self, file_prefix='temp', save_hyd=False, use_hyd=False, hydfile=None,
version=2.2, convergence_error=False):
"""
Run the EPANET simulator.
Runs the EPANET simulator through the compiled toolkit DLL. Can use/save hydraulics
to allow for separate WQ runs.
.. note::
By default, WNTR now uses the EPANET 2.2 toolkit as the engine for the EpanetSimulator.
To force usage of the older EPANET 2.0 toolkit, use the ``version`` command line option.
Note that if the demand_model option is set to PDD, then a warning will be issued, as
EPANET 2.0 does not support such analysis.
Parameters
----------
file_prefix : str
Default prefix is "temp". All files (.inp, .bin/.out, .hyd, .rpt) use this prefix
use_hyd : bool
Will load hydraulics from ``file_prefix + '.hyd'`` or from file specified in `hydfile_name`
save_hyd : bool
Will save hydraulics to ``file_prefix + '.hyd'`` or to file specified in `hydfile_name`
hydfile : str
Optionally specify a filename for the hydraulics file other than the `file_prefix`
version : float, {2.0, **2.2**}
Optionally change the version of the EPANET toolkit libraries. Valid choices are
either 2.2 (the default if no argument provided) or 2.0.
convergence_error: bool (optional)
If convergence_error is True, an error will be raised if the
simulation does not converge. If convergence_error is False, partial results are returned,
a warning will be issued, and results.error_code will be set to 0
if the simulation does not converge. Default = False.
"""
if isinstance(version, str):
version = float(version)
inpfile = file_prefix + '.inp'
write_inpfile(self._wn, inpfile, units=self._wn.options.hydraulic.inpfile_units, version=version)
enData = wntr.epanet.toolkit.ENepanet(version=version)
rptfile = file_prefix + '.rpt'
outfile = file_prefix + '.bin'
if hydfile is None:
hydfile = file_prefix + '.hyd'
enData.ENopen(inpfile, rptfile, outfile)
if use_hyd:
enData.ENusehydfile(hydfile)
logger.debug('Loaded hydraulics')
else:
enData.ENsolveH()
logger.debug('Solved hydraulics')
if save_hyd:
enData.ENsavehydfile(hydfile)
logger.debug('Saved hydraulics')
enData.ENsolveQ()
logger.debug('Solved quality')
enData.ENreport()
logger.debug('Ran quality')
enData.ENclose()
logger.debug('Completed run')
#os.sys.stderr.write('Finished Closing\n')
results = self.reader.read(outfile, convergence_error, self._wn.options.hydraulic.headloss=='D-W')
return results