Skip to content

Commit eadb99d

Browse files
committed
Merge pull request #1 from mauriziocingi/lavoro
up to date
2 parents 6e2c499 + e4b4785 commit eadb99d

1 file changed

Lines changed: 178 additions & 39 deletions

File tree

epamodule.py

Lines changed: 178 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,7 @@
11
#!/usr/bin/env python
22
"""Python EpanetToolkit interface
33
4-
not yet implemented:
5-
- ENgetqualtype
6-
- ENsetqualtype
7-
- ENstepQ
8-
9-
- ENresetreport
10-
- ENsetreport
11-
- ENsetstatusreport
12-
- ENwriteline
13-
14-
- ENsavehydfile
15-
- ENusehydfile
16-
17-
added functions:
18-
+ ENsimtime"""
4+
added function ENsimtime"""
195

206
import ctypes
217
import platform
@@ -24,11 +10,22 @@
2410
_plat= platform.system()
2511
if _plat=='Linux':
2612
_lib = ctypes.CDLL("libepanet.so.2")
27-
elif _plat=='Windows':
28-
_lib = ctypes.windll.epanet2
13+
elif _plat=='Windows':
14+
try:
15+
# if epanet2.dll compiled with __cdecl (as in OpenWaterAnalytics)
16+
_lib = ctypes.CDLL("epanet2.dll")
17+
_lib.ENgetversion(ctypes.byref(ctypes.c_int()))
18+
except ValueError:
19+
# if epanet2.dll compiled with __stdcall (as in EPA original DLL)
20+
try:
21+
_lib = ctypes.windll.epanet2
22+
_lib.ENgetversion(ctypes.byref(ctypes.c_int()))
23+
except ValueError:
24+
raise Exception("epanet2.dll not suitable")
25+
2926
else:
3027
Exception('Platform '+ _plat +' unsupported (not yet)')
31-
28+
3229

3330
_current_simulation_time= ctypes.c_long()
3431

@@ -39,19 +36,24 @@
3936

4037

4138

42-
def ENepanet(nomeinp, nomerpt='report.txt', nomebin='', vfunc=None):
39+
def ENepanet(nomeinp, nomerpt='', nomebin='', vfunc=None):
4340
"""Runs a complete EPANET simulation.
4441
4542
Arguments:
4643
nomeinp: name of the input file
4744
nomerpt: name of an output report file
4845
nomebin: name of an optional binary output file
4946
vfunc : pointer to a user-supplied function which accepts a character string as its argument."""
50-
ierr= _lib.ENepanet(ctypes.c_char_p(nomeinp), ctypes.c_char_p(nomerpt), ctypes.c_char_p(nomebin), vfunc)
47+
if vfunc is not None:
48+
CFUNC = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_char_p)
49+
callback= CFUNC(vfunc)
50+
else:
51+
callback= None
52+
ierr= _lib.ENepanet(ctypes.c_char_p(nomeinp), ctypes.c_char_p(nomerpt), ctypes.c_char_p(nomebin), callback)
5153
if ierr!=0: raise ENtoolkitError(ierr)
5254

5355

54-
def ENopen(nomeinp, nomerpt='report.txt', nomebin=''):
56+
def ENopen(nomeinp, nomerpt='', nomebin=''):
5557
"""Opens the Toolkit to analyze a particular distribution system
5658
5759
Arguments:
@@ -300,6 +302,24 @@ def ENgettimeparam(paramcode):
300302
ierr= _lib.ENgettimeparam(paramcode, ctypes.byref(j))
301303
if ierr!=0: raise ENtoolkitError(ierr)
302304
return j.value
305+
306+
def ENgetqualtype(qualcode):
307+
"""Retrieves the type of water quality analysis called for
308+
returns qualcode: Water quality analysis codes are as follows:
309+
EN_NONE 0 No quality analysis
310+
EN_CHEM 1 Chemical analysis
311+
EN_AGE 2 Water age analysis
312+
EN_TRACE 3 Source tracing
313+
tracenode: index of node traced in a source tracing
314+
analysis (value will be 0 when qualcode
315+
is not EN_TRACE)"""
316+
qualcode= ctypes.c_int()
317+
tracenode= ctypes.c_int()
318+
ierr= _lib.ENgetqualtype(ctypes.byref(qualcode),
319+
ctypes.byref(tracenode))
320+
if ierr!=0: raise ENtoolkitError(ierr)
321+
return qualcode.value, tracenode.value
322+
303323

304324

305325
#-------Retrieving other network information--------
@@ -308,7 +328,7 @@ def ENgetcontrol(cindex, ctype, lindex, setting, nindex, level ):
308328
Arguments:
309329
cindex: control statement index
310330
ctype: control type code EN_LOWLEVEL (Low Level Control)
311-
EN_HILEVEL (High Level Control)
331+
EN_HILEVEL (High Level Control)
312332
EN_TIMER (Timer Control)
313333
EN_TIMEOFDAY (Time-of-Day Control)
314334
lindex: index of link being controlled
@@ -415,7 +435,9 @@ def ENsetlinkvalue(index, paramcode, value):
415435
a simulation is being run (within the ENrunH - ENnextH loop).
416436
417437
value:parameter value"""
418-
ierr= _lib.ENsetlinkvalue(ctypes.c_int(index), ctypes.c_int(paramcode), ctypes.c_float(value))
438+
ierr= _lib.ENsetlinkvalue(ctypes.c_int(index),
439+
ctypes.c_int(paramcode),
440+
ctypes.c_float(value))
419441
if ierr!=0: raise ENtoolkitError(ierr)
420442

421443

@@ -449,13 +471,25 @@ def ENsetpatternvalue( index, period, value):
449471
period: period within time pattern
450472
value: multiplier factor for the period"""
451473
#int ENsetpatternvalue( int index, int period, float value )
452-
ierr= _lib.ENsetpatternvalue( ctypes.c_int(index), ctypes.c_int(period), ctypes.c_float(value) )
474+
ierr= _lib.ENsetpatternvalue( ctypes.c_int(index),
475+
ctypes.c_int(period),
476+
ctypes.c_float(value) )
453477
if ierr!=0: raise ENtoolkitError(ierr)
454478

455479

456480

457-
458-
481+
def ENsetqualtype(qualcode, chemname, chemunits, tracenode):
482+
"""Sets the type of water quality analysis called for.
483+
Arguments:
484+
qualcode: water quality analysis code
485+
chemname: name of the chemical being analyzed
486+
chemunits: units that the chemical is measured in
487+
tracenode: ID of node traced in a source tracing analysis """
488+
ierr= _lib.ENsetqualtype( ctypes.c_int(qualcode),
489+
ctypes.c_char_p(chemname),
490+
ctypes.c_char_p(chemunits),
491+
ctypes.c_char_p(tracenode))
492+
if ierr!=0: raise ENtoolkitError(ierr)
459493

460494

461495
def ENsettimeparam(paramcode, timevalue):
@@ -496,14 +530,23 @@ def ENsetoption( optioncode, value):
496530
if ierr!=0: raise ENtoolkitError(ierr)
497531

498532

533+
#----- Saving and using hydraulic analysis results files -------
534+
def ENsavehydfile(fname):
535+
"""Saves the current contents of the binary hydraulics file to a file."""
536+
ierr= _lib.ENsavehydfile(ctypes.c_char_p(fname))
537+
if ierr!=0: raise ENtoolkitError(ierr)
499538

539+
def ENusehydfile(fname):
540+
"""Uses the contents of the specified file as the current binary hydraulics file"""
541+
ierr= _lib.ENusehydfile(ctypes.c_char_p(fname))
542+
if ierr!=0: raise ENtoolkitError(ierr)
500543

501544

502545

503546
#----------Running a hydraulic analysis --------------------------
504547
def ENsolveH():
505-
"""Runs a complete hydraulic simulation with results for all time periods written to the
506-
binary Hydraulics file."""
548+
"""Runs a complete hydraulic simulation with results
549+
for all time periods written to the binary Hydraulics file."""
507550
ierr= _lib.ENsolveH()
508551
if ierr!=0: raise ENtoolkitError(ierr)
509552

@@ -514,7 +557,8 @@ def ENopenH():
514557

515558

516559
def ENinitH(flag=None):
517-
"""Initializes storage tank levels, link status and settings, and the simulation clock time prior
560+
"""Initializes storage tank levels, link status and settings,
561+
and the simulation clock time prior
518562
to running a hydraulic analysis.
519563
520564
flag EN_NOSAVE [+EN_SAVE] [+EN_INITFLOW] """
@@ -523,7 +567,8 @@ def ENinitH(flag=None):
523567

524568

525569
def ENrunH():
526-
"""Runs a single period hydraulic analysis, retrieving the current simulation clock time t"""
570+
"""Runs a single period hydraulic analysis,
571+
retrieving the current simulation clock time t"""
527572
ierr= _lib.ENrunH(ctypes.byref(_current_simulation_time))
528573
if ierr>=100:
529574
raise ENtoolkitError(ierr)
@@ -553,7 +598,8 @@ def ENcloseH():
553598

554599
#----------Running a quality analysis --------------------------
555600
def ENsolveQ():
556-
"""Runs a complete water quality simulation with results at uniform reporting intervals written to EPANET's binary Output file."""
601+
"""Runs a complete water quality simulation with results
602+
at uniform reporting intervals written to EPANET's binary Output file."""
557603
ierr= _lib.ENsolveQ()
558604
if ierr!=0: raise ENtoolkitError(ierr)
559605

@@ -564,29 +610,43 @@ def ENopenQ():
564610

565611

566612
def ENinitQ(flag=None):
567-
"""Initializes water quality and the simulation clock time prior to running a water quality analysis.
613+
"""Initializes water quality and the simulation clock
614+
time prior to running a water quality analysis.
568615
569616
flag EN_NOSAVE | EN_SAVE """
570617
ierr= _lib.ENinitQ(flag)
571618
if ierr!=0: raise ENtoolkitError(ierr)
572619

573620
def ENrunQ():
574-
"""Makes available the hydraulic and water quality results that occur at the start of the next time period of a water quality analysis, where the start of the period is returned in t."""
621+
"""Makes available the hydraulic and water quality results
622+
that occur at the start of the next time period of a water quality analysis,
623+
where the start of the period is returned in t."""
575624
ierr= _lib.ENrunQ(ctypes.byref(_current_simulation_time))
576625
if ierr>=100:
577626
raise ENtoolkitError(ierr)
578627
elif ierr>0:
579628
return ENgeterror(ierr)
580629

581630
def ENnextQ():
582-
"""Advances the water quality simulation to the start of the next hydraulic time period."""
631+
"""Advances the water quality simulation
632+
to the start of the next hydraulic time period."""
583633
_deltat= ctypes.c_long()
584634
ierr= _lib.ENnextQ(ctypes.byref(_deltat))
585635
if ierr!=0: raise ENtoolkitError(ierr)
586636
return _deltat.value
637+
638+
639+
def ENstepQ():
640+
"""Advances the water quality simulation one water quality time step.
641+
The time remaining in the overall simulation is returned in tleft."""
642+
tleft= ctypes.c_long()
643+
ierr= _lib.ENnextQ(ctypes.byref(tleft))
644+
if ierr!=0: raise ENtoolkitError(ierr)
645+
return tleft.value
587646

588647
def ENcloseQ():
589-
"""Closes the water quality analysis system, freeing all allocated memory."""
648+
"""Closes the water quality analysis system,
649+
freeing all allocated memory."""
590650
ierr= _lib.ENcloseQ()
591651
if ierr!=0: raise ENtoolkitError(ierr)
592652
#--------------------------------------------
@@ -596,30 +656,65 @@ def ENcloseQ():
596656

597657

598658
def ENsaveH():
599-
"""Transfers results of a hydraulic simulation from the binary Hydraulics file to the binary
600-
Output file, where results are only reported at uniform reporting intervals."""
659+
"""Transfers results of a hydraulic simulation
660+
from the binary Hydraulics file to the binary
661+
Output file, where results are only reported at
662+
uniform reporting intervals."""
601663
ierr= _lib.ENsaveH()
602664
if ierr!=0: raise ENtoolkitError(ierr)
603665

604666

605667
def ENsaveinpfile(fname):
606-
"""Writes all current network input data to a file using the format of an EPANET input file."""
668+
"""Writes all current network input data to a file
669+
using the format of an EPANET input file."""
607670
ierr= _lib.ENsaveinpfile( ctypes.c_char_p(fname))
608671
if ierr!=0: raise ENtoolkitError(ierr)
609672

610673

611674
def ENreport():
612-
"""Writes a formatted text report on simulation results to the Report file."""
675+
"""Writes a formatted text report on simulation results
676+
to the Report file."""
613677
ierr= _lib.ENreport()
614678
if ierr!=0: raise ENtoolkitError(ierr)
615679

680+
def ENresetreport():
681+
"""Clears any report formatting commands
682+
683+
that either appeared in the [REPORT] section of the
684+
EPANET Input file or were issued with the
685+
ENsetreport function"""
686+
ierr= _lib.ENresetreport()
687+
if ierr!=0: raise ENtoolkitError(ierr)
688+
689+
def ENsetreport(command):
690+
"""Issues a report formatting command.
691+
692+
Formatting commands are the same as used in the
693+
[REPORT] section of the EPANET Input file."""
694+
ierr= _lib.ENsetreport(ctypes.c_char_p(command))
695+
if ierr!=0: raise ENtoolkitError(ierr)
696+
697+
def ENsetstatusreport(statuslevel):
698+
"""Sets the level of hydraulic status reporting.
699+
700+
statuslevel: level of status reporting
701+
0 - no status reporting
702+
1 - normal reporting
703+
2 - full status reporting"""
704+
ierr= _lib.ENsetstatusreport(ctypes.c_int(statuslevel))
705+
if ierr!=0: raise ENtoolkitError(ierr)
616706

617707
def ENgeterror(errcode):
618708
"""Retrieves the text of the message associated with a particular error or warning code."""
619709
errmsg= ctypes.create_string_buffer(_err_max_char)
620710
_lib.ENgeterror( errcode,ctypes.byref(errmsg), _err_max_char )
621711
return errmsg.value
622712

713+
def ENwriteline(line ):
714+
"""Writes a line of text to the EPANET report file."""
715+
ierr= _lib.ENwriteline(ctypes.c_char_p(line ))
716+
if ierr!=0: raise ENtoolkitError(ierr)
717+
623718

624719
class ENtoolkitError(Exception):
625720
def __init__(self, ierr):
@@ -630,6 +725,50 @@ def __init__(self, ierr):
630725
self.message='ENtoolkit Undocumented Error '+str(ierr)+': look at text.h in epanet sources'
631726
def __str__(self):
632727
return self.message
728+
729+
730+
#------ functions added from OpenWaterAnalytics ----------------------------------
731+
# functions not present in original Epanet2 toolkit from US EPA
732+
# it may change in future versions
733+
#----------------------------------------------------------------------------------
734+
if hasattr(_lib,"ENgetcurve"):
735+
def ENgetcurve(curveIndex):
736+
curveid = ctypes.create_string_buffer(_max_label_len)
737+
nValues = ctypes.c_int()
738+
xValues= ctypes.POINTER(ctypes.c_float)()
739+
yValues= ctypes.POINTER(ctypes.c_float)()
740+
ierr= _lib.ENgetcurve(curveIndex,
741+
ctypes.byref(curveid),
742+
ctypes.byref(nValues),
743+
ctypes.byref(xValues),
744+
ctypes.byref(yValues)
745+
)
746+
# strange behavior of ENgetcurve: it returns also curveID
747+
# better split in two distinct functions ....
748+
if ierr!=0: raise ENtoolkitError(ierr)
749+
curve= []
750+
for i in range(nValues.value):
751+
curve.append( (xValues[i],yValues[i]) )
752+
return curve
753+
754+
def ENgetcurveid(curveIndex):
755+
curveid = ctypes.create_string_buffer(_max_label_len)
756+
nValues = ctypes.c_int()
757+
xValues= ctypes.POINTER(ctypes.c_float)()
758+
yValues= ctypes.POINTER(ctypes.c_float)()
759+
ierr= _lib.ENgetcurve(curveIndex,
760+
ctypes.byref(curveid),
761+
ctypes.byref(nValues),
762+
ctypes.byref(xValues),
763+
ctypes.byref(yValues)
764+
)
765+
# strange behavior of ENgetcurve: it returns also curveID
766+
# better split in two distinct functions ....
767+
if ierr!=0: raise ENtoolkitError(ierr)
768+
return curveid.value
769+
770+
#-----end of functions added from OpenWaterAnalytics ----------------------------------
771+
633772

634773
EN_ELEVATION = 0 # /* Node parameters */
635774
EN_BASEDEMAND = 1

0 commit comments

Comments
 (0)