Feature wrapper (#136)

this quite sizable commit does several things, but is primarily
focussed on building a toolkit that can run simultaneous
simulations/analyses within a shared memory space. Versions <=2.1 use a
long list of global variables that prevent multiple instantiations on
linux systems without resorting to compilation tricks (like duplicate
binaries or similar via static linkage). This version uses a single "Project" pointer to encapsulate
the network and analysis data. There are no changes to existing algo
implementations other than to accomodate dereferencing of the passed-in
pointers. A more detailed list of major changes below:

- mirrors all “ENxxxx” function calls with “EN_xxxx” versions (note the
underscore) that take an extra first parameter: a pointer to an
EN_Project struct, which contains all network, hydraulic, quality, and
associated data.
- tweaks some code formatting to make it more readable
- removes some deprecated/commented code that was sufficiently old
- fixes implicit type-cast warnings

* Added ENaddnode and ENaddlink functions

* More memory reallocations

* Added ENInit, ENsetheadcurveindex

* Added ENdeletelink and ENdeletenode

* restored default behavior for float types

* fixed type

* Added docstrings for ENinit

* cleanup change

* moves global rule variables to vars.h

* migrates rule structs to typedefs

for better readability

* char types to proper enums

fixes #93

* Change some variable declarations for compatibility

Changes to keep compatibility with C89 compilers: variables must be
declared at the top of the functions. Remove the use of EN_LinkType in
function call as it is not compatible with ENgetnodetype.

* Moved declaration of idstodelete to top of function

* Updated ENinit function and headers

Updated header files with new functions
Updated def file with new functions
For ENinit changes names of parameters #98
Added enum for headloss formula

* Missed these files in 1a033fc

* migrates char types to enums fixes #93,

supports unified link/node type enums, rather than public/private
redefinitions

* removing links in reverse-index order maintains proper indexing fixes #96

* style

* clarifies curve getter units issue (dox)

closes #95

* fixes link/node confusion in ENsetlinktype

partially reverts a3bce95dc330a5a297634a303d438e2e1bc41cc9

* partial compilation fix

* fixes dox issue

* fixes allocation issues with enums

- updates style in various places
- introduces FlowDirection enum
- use snprintf to prevent overflow

* fixes enum type cast

* updated mac project settings

* Use of _snprintf on Windows and remove DLLEXPORT from mempool.h

snprintf it not compatible on Windows so we use _snprintf
mempool gave starnge compilation errors while removing DLLEXPORT worked.
Not sure why these functions needed to be exposed in the DLL?

* Revert "Use of _snprintf on Windows and remove DLLEXPORT from mempool.h"

This reverts commit 6238f77d47fa0feaabe5836043c006937de433a2.

* use of _snprintf instead of snprintf on Windows and removed DLLEXPORT from mempool.h

Had compilation errors on mempool.h. Removed DLLEXPORT so solve it. Not
sure why there was a need to expose these functions?

* Shift indices for Links in ENaddnode

Need to shift indices for Links not just Pipes since a pump could be
connected directly to a reservoir. Also set the defult base demand to
zero (was 5).

* Set defualts for madatory link properties in ENaddlink and small fix for ENsetheadcurveindex

Relates to #102 and closes #103

* wraps globals into structs, duplicates api functions with objective versions



* parse and serialize Comment field for network elements

related to #47

* adds getter for head/efficiency curve

in EN_getlinkvalue

* adds getter for event node index

… to return the index of the junction (tank) that triggered the event.

* fixes edge case in parsing

… where inp files without demands in [JUNCTIONS] and without any
[DEMAND] categories will fail.

* adds freeing function for project pointer

* removes redundant string literals, fixes overrun issue in error message getter function

* check for hydraulics already closed

* moving error definitions to data file

* deprecates ENR err message getter (unused)

* updates location of errors data file

also begins to expose blind structs to curves and patterns,
anticipating buildout of APIs for those.

* updates CLI output to reflect executable name as invoked

relates to #109

* Feature nrtest (#131)

* Initial commit EPANET testing tools.

* Initial commit for epanet-nrtestsuite

* SWIG wrapper for EPANET outputapi (#118)

* Removed pervious version of outputapi and wrapper

* SWIG wrapper for EPANET outputapi

* Patching cmake build script fixed target for outputapi

* Build failing on deprecated test script

* Minor changes. Responding to review comments.

* Feature nrtest (#121)

* Configured python setup to automatically build nrtest tools.

* Working on build / testing automation

* Adding EPANET 2.0.12 benchmark

* Updated Travis yml to run nrtest

* Fixing InsecurePlatformWarning

* Fixing InsecurePlatformWarning again

* Fixing InsecurePlatformWarning

* Fixing InsecurePlatformWarning

* Fixing InsecurePlatformWarning

* Update .travis.yml

* Update .travis.yml

* Update .travis.yml

* Update .travis.yml

* Working on configuring python environment and building test tools under Travis CI.

* Making gen-config.sh and run-nrtest.sh executable

* Debugging .travis.yml

* Debugging .travis.yml

* Debugging .travis.yml again

* Debugging .travis.yml again

* debugging travis setup

* debugging Travis setup

* debugging Travis setup

* debugging Travis setup

* debugging Travis setup

* debugging Travis setup

* debugging Travis setup

* debugging Travis setup

* debugging Travis setup

* debugging Travis setup

* debugging Travis setup

* Fixing bug with __strncpy_chk destlen < len

* nrtesting clean up

* re-implements fixes from:

5eead5ae40
3c788567a4

* removes extraneous build files, moves cmake and updates travis

* mirror of 9b37035560f9683f1514b439f7586a5c17bca5bf

* Move some variable declarations

* More variable declarations

* Fix TmpDir

* Allocate _defaultModel

* Fix EN_addcurve funcrion

* Fix for inpfile

* Fix writeRuleinInp call

* Set MAXMSG to 79 chars

* Fix for flow direction

* Refactoring testing related python packages and SWIG wrapper bug fix (#139)

* Eliminated epanet-reader package. Removed numpy dependency from epanet-output. Fixed reference counting bug in SWIG wrapper. Added error checking to run_nrtest.sh. Added nrtest package to requirements file.

* changing buildhome directory

* Fixing bug related to preprocessor definition of PI
This commit is contained in:
Sam Hatchett
2018-01-09 16:56:42 -05:00
committed by GitHub
parent 5eead5ae40
commit f97d837231
77 changed files with 37683 additions and 20504 deletions

21
.gitignore vendored
View File

@@ -41,7 +41,6 @@ xcuserdata
*~.nib/
*.swp
*~
*.dat
*.dep
*.xcodeproj/
@@ -62,7 +61,7 @@ xcuserdata
[Dd]ebug/
[Rr]elease/
x64/
build/
#build/
[Bb]in/
[Oo]bj/
@@ -202,3 +201,21 @@ $RECYCLE.BIN/
# WindSDK compiled folders
build/WinSDK/32bit/
build/WinSDK/64bit/
=======
# Python compiler files
*.py[c]
# Python distribution and packaging
dist/
temp/
*.cfg
*.egg-info/
# Eclipse Stuff
.metadata/
.settings/
.project
.cproject
.pydevproject

View File

@@ -1,12 +1,25 @@
language: c
language: python
env:
global:
- EPANET_HOME=`pwd`
- BUILD_HOME=buildproducts
- TEST_HOME=tests/epanet-nrtestsuite
before_install:
- sudo apt-get -qq update
- sudo apt-get install -y swig
install:
- pip install --src build/packages -r tools/requirements.txt
before_script:
- cd build/CMake
- mkdir buildproducts
- cd buildproducts
- mkdir -p $BUILD_HOME
- cd $BUILD_HOME
- cmake ..
script:
- make
- cd ../../../tests
- ./test_networks.sh
- cd $EPANET_HOME
- tools/gen-config.sh $EPANET_HOME/$BUILD_HOME/bin > $TEST_HOME/apps/epanet-$TRAVIS_COMMIT.json
- tools/run-nrtest.sh $TEST_HOME $TRAVIS_COMMIT

55
CMakeLists.txt Normal file
View File

@@ -0,0 +1,55 @@
# CMakeLists.txt - CMake configuration file for EPANET 2.0
#
# CMake is a cross-platform build tool. CMake generates platform native
# makefiles that can be used with your compiler of choice. CMake uses a
# generator concept to represent different build tooling. CMake automatically
# detects the platform it is running on and generates the appropriate makefiles
# for the platform default compiler. Different generators can also be specified.
#
# Note: CMake requires that your platform build system and compiler are
# properly installed. Build using Visual Studio requires msbuild shell.
#
# Example Usage:
# cd build/cmake
# mkdir buildproducts
# cd buildproducts
# cmake ..
# make
#
# Building MSYS on Windows:
# ...
# cmake -G "MSYS Makefiles" ..
# make
#
# Building Visual Studio on Windows:
# ...
# cmake -G "Visual Studio 10 2010" ..
# msbuild /p:Configuration=Release ALL_BUILD.vcxproj
#
# More information:
# cmake --help
#
# CMake is available at https://cmake.org/download/
#
cmake_minimum_required (VERSION 2.6)
SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
SET(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
project(EPANET)
IF(APPLE)
SET(CMAKE_INSTALL_NAME_DIR @executable_path)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
ENDIF(APPLE)
# the library
include_directories(include)
file(GLOB EPANET_SOURCES src/*.c)
add_library(epanet STATIC ${EPANET_SOURCES})
# the standalone executable
include_directories(src)
add_executable(runepanet run/main.c)
target_link_libraries (runepanet LINK_PUBLIC epanet m)

View File

@@ -1,28 +0,0 @@
## cmake .
## make
cmake_minimum_required (VERSION 2.6)
SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
SET(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
project (EPANET)
IF(APPLE)
SET(CMAKE_INSTALL_NAME_DIR @executable_path)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
ENDIF(APPLE)
# the library
include_directories(../../include)
file(GLOB EPANET_SOURCES ../../src/*.c)
add_library(epanet STATIC ${EPANET_SOURCES})
# the standalone executable
include_directories(../../src)
add_executable(runepanet ../../run/main.c)
target_link_libraries (runepanet LINK_PUBLIC epanet m)
# the binary hydraulics file API
include_directories(../../tools/outputapi)
add_library(ENBinaryOut SHARED ../../tools/outputapi/outputapi.c)

View File

@@ -1,109 +0,0 @@
# Linux Makefile for EPANET
# This will build EPANET as a shared object library
# (libepanet2.so) under Linux/Unix, and a standalone
# executable (epanet2).
# The following targets are defined:
# make
# -Builds libepanet2.so, epanet2
# make install
# -Creates shell wrapper runepanet2.sh that executes epanet2.
# The runepanet2.sh wrapper simply exports
# environment variables that help locate the runtime library,
# allowing you to specify your own library locations.
# -Installs epanet2 and runepanet2.sh
# in <prefix>/bin, where <prefix> defaults to ~ (and can be set
# below to something different - see "Install directories")
# -Installs libepanet2.so in <prefix>/lib
# -Installs epanet2.h in <prefix>/include. This is the required
# header file for the EPANET programmer's toolkit, and thus
# <prefix>/include should be on your CPP include search path
# for subsequent use of the toolkit and linking with the
# library libepanet2.so
# make clean
# -Removes object and library files, returning the build directory
# to its pristine state.
# You may wish to change the install path 'prefix',
# or the compiler flags, but these defaults should be fine.
SHELL = /bin/sh
# Target filenames
epanetrootname := epanet2
libname := lib$(epanetrootname).so
exename := $(epanetrootname)
# Shell wrapper
runcmdtemplate = runepanet.sh.template
runcmdname = runepanet2.sh
# Location of EPANET toolkit includes
epanetincludedir = ../../include
# Search path for sources
epanetsrcdir = ../../src
epanetrundir = ../../run
VPATH = $(epanetsrcdir):$(epanetincludedir):$(epanetrundir)
# Install directories
#prefix = /usr/local # GNU standard -- requires superuser rights
prefix =~
#
exec_prefix = $(prefix)
libdir = $(exec_prefix)/lib
bindir = $(exec_prefix)/bin
includedir = $(prefix)/include
datarootdir = $(prefix)/share
docdir = $(datarootdir)/doc/epanet
# Compiler and flags
CC = gcc
CFLAGS = -g -O3 -fPIC -std=c99
CPPFLAGS = -I $(epanetincludedir)
LDFLAGS = -L . -Wl,-rpath,$(libdir) -lm
# Installer
INSTALL = install
INSTALL_PROGRAM = $(INSTALL)
INSTALL_DATA = $(INSTALL) -m 644
# Files for the shared object library
epanet_objs=hash.o hydraul.o inpfile.o input1.o input2.o \
input3.o mempool.o output.o quality.o report.o \
rules.o smatrix.o epanet.o
# Epanet header files
epanet_heads=enumstxt.h funcs.h hash.h mempool.h text.h types.h vars.h
# Epanet main program
epanet_main=main
# Epanet main program header files
epanet_main_heads=epanet2.h
.PHONY: all
all: $(libname) $(exename)
$(libname): $(epanet_objs)
$(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^
$(exename): $(epanet_main).o $(epanet_main_heads)
$(CC) $(CFLAGS) -o $@ $(epanet_main).o -l$(epanetrootname) $(LDFLAGS)
$(epanet_objs): $(epanet_heads)
.PHONY: install
install:
cat $(runcmdtemplate) | sed 's|libdir|$(libdir)|' \
| sed 's|exename|$(bindir)/$(exename)|' \
> $(runcmdname)
$(INSTALL_PROGRAM) -D $(exename) $(bindir)/$(exename)
$(INSTALL_PROGRAM) -D $(libname) $(libdir)/$(libname)
$(INSTALL_DATA) -D $(epanetincludedir)/epanet2.h $(includedir)/epanet2.h
$(INSTALL_PROGRAM) -D $(runcmdname) ~/$(runcmdname)
.PHONY: uninstall
uninstall:
.PHONY: check
check:
.PHONY: clean
clean:
-/bin/rm *.o $(libname) $(exename) $(runcmdname)

View File

@@ -1,111 +0,0 @@
# Linux Makefile for EPANET
# This will build EPANET as a shared object library
# (libepanet_gcc_<Rev>.so) under Linux/Unix, and a standalone
# executable (epanet_gcc_<Rev>).
# The following targets are defined:
# make
# -Builds libepanet_gcc_<Rev>.so, epanet_gcc_<Rev>
# make install
# -Creates shell wrapper runepanet_<Rev>.sh that executes epanet_gcc_<Rev>.exe.
# The runepanet_<Rev>.sh wrapper simply exports
# environment variables that help locate the runtime library,
# allowing you to specify your own library locations.
# -Installs epanet_gcc_<Rev> and runepanet_<Rev>.sh
# in <prefix>/bin, where <prefix> defaults to ~ (and can be set
# below to something different - see "Install directories")
# -Installs libepanet_gcc_<Rev>.so in <prefix>/lib
# -Installs epanet2.h in <prefix>/include. This is the required
# header file for the EPANET programmer's toolkit, and thus
# <prefix>/include should be on your CPP include search path
# for subsequent use of the toolkit and linking with the
# library libepanet_gcc_<Rev>.so
# make clean
# -Removes object and library files, returning the build directory
# to its pristine state.
# You may wish to change the install path 'prefix',
# or the compiler flags, but these defaults should be fine.
SHELL = /bin/sh
# Target filenames
# svnname.sh constructs a name: <prefix><root><Rev><postfix>
# where <Rev> is the atomic revision number of the svn repo.
epanetsvnpath = ../../..
epanetrootname := $(shell ../svnname.sh $(epanetsvnpath) "" epanet_gcc_ "")
libname := lib$(epanetrootname).so
exename := $(epanetrootname)
# Shell wrapper
runcmdtemplate = runepanet.sh.template
runcmdname = $(shell ../svnname.sh $(epanetsvnpath) "" runepanet_ .sh)
# Location of EPANET toolkit includes
epanetincludedir = ../../include
# Search path for sources
epanetsrcdir = ../../src
VPATH = $(epanetsrcdir):$(epanetincludedir)
# Install directories
prefix = ~
exec_prefix = $(prefix)
libdir = $(exec_prefix)/lib
bindir = $(exec_prefix)/bin
includedir = $(prefix)/include
datarootdir = $(prefix)/share
docdir = $(datarootdir)/doc/epanet
# Compiler and flags
CC = gcc
CFLAGS = -g -O3 -fPIC -std=c99
CPPFLAGS = -I $(epanetincludedir)
LDFLAGS = -L . -Wl,-rpath,$(libdir) -lm
# Installer
INSTALL = install
INSTALL_PROGRAM = $(INSTALL)
INSTALL_DATA = $(INSTALL) -m 644
# Files for the shared object library
epanet_objs=hash.o hydraul.o inpfile.o input1.o input2.o \
input3.o mempool.o output.o quality.o report.o \
rules.o smatrix.o
# Epanet header files
epanet_heads=enumstxt.h funcs.h hash.h mempool.h text.h toolkit.h types.h vars.h
# Epanet main program
epanet_main=epanet
# Epanet main program header files
epanet_main_heads=epanet2.h
.PHONY: all
all: $(libname) $(exename)
$(libname): $(epanet_objs)
$(CC) $(CFLAGS) $(CPPFLAGS) -D SOL -c $(epanetsrcdir)/$(epanet_main).c
$(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $(epanet_main).o $^
$(exename): $(libname) $(epanet_main_heads)
$(CC) $(CFLAGS) $(CPPFLAGS) -D CLE -c $(epanetsrcdir)/$(epanet_main).c
$(CC) $(CFLAGS) -o $@ $(epanet_main).o -l$(epanetrootname) $(LDFLAGS)
$(epanet_objs): $(epanet_heads)
.PHONY: install
install:
cat $(runcmdtemplate) | sed 's|libdir|$(libdir)|' \
| sed 's|exename|$(bindir)/$(exename)|' \
> $(runcmdname)
$(INSTALL_PROGRAM) -D $(exename) $(bindir)/$(exename)
$(INSTALL_PROGRAM) -D $(libname) $(libdir)/$(libname)
$(INSTALL_DATA) -D $(epanetincludedir)/epanet2.h $(includedir)/epanet2.h
$(INSTALL_PROGRAM) -D $(runcmdname) $(bindir)/$(runcmdname)
.PHONY: uninstall
uninstall:
.PHONY: check
check:
.PHONY: clean
clean:
-/bin/rm *.o $(libname) $(exename) $(runcmdname)

View File

@@ -1,3 +0,0 @@
#!/bin/sh
export LD_LIBRARY_PATH=libdir:$LD_LIBRARY_PATH
exec exename $*

View File

@@ -1,78 +0,0 @@
# MINGW32 Makefile for EPANET
# This will build EPANET as DLL
# (epanet2.dll) under MINGW32 GCC, and a standalone
# executable (epanet2d.exe).
# The following targets are defined:
# make
# -Builds epanet2.dll, epanet2d.exe
# make install
# -Copy epanet2.dll, epanet2d.exe, epanet2.def to $(prefix)
# make clean
# -Removes object and library files, returning the build directory
# to its pristine state.
# You may wish to change the install path 'prefix',
# or the compiler flags, but these defaults should be fine.
# Target filenames
epanetrootname := epanet2
libname := $(epanetrootname).dll
exename := $(epanetrootname)d.exe
# Location of EPANET toolkit includes
epanetincludedir = ../../include
# Search path for sources
epanetsrcdir = ../../src
# Search path for sources
epanetmainsrcdir = ../../run
VPATH = $(epanetsrcdir):$(epanetincludedir):$(epanetmainsrcdir)
# Install directories
prefix = C:\discoD\EPA\EPAnet_util
execdir = $(prefix)
libdir = $(prefix)
# Compiler and flags
CC = gcc
CFLAGS = -g -O3 -std=c99 -Wno-implicit-function-declaration -D DLL
CPPFLAGS = -I $(epanetincludedir) -I $(epanetsrcdir)
LDFLAGS = -L . -Wl,--kill-at,--enable-stdcall-fixup,-rpath,$(libdir) -lm
# Files for the shared object library
epanet_objs=hash.o hydraul.o inpfile.o input1.o input2.o \
input3.o mempool.o output.o quality.o report.o \
rules.o smatrix.o epanet.o
# Epanet header files
epanet_heads=enumstxt.h funcs.h hash.h mempool.h text.h types.h vars.h epanet2.h
# Epanet main program
epanet_main=main
# Epanet main program header files
epanet_main_heads=epanet2.h
.PHONY: all
all: $(libname) $(exename)
$(libname): $(epanet_objs)
$(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ -Wl,--output-def,$(epanetrootname).def
$(exename): $(epanet_main_heads) $(libname) $(epanet_main).o
$(CC) $(CFLAGS) -o $@ $(epanet_main).o -l$(epanetrootname) $(LDFLAGS)
$(epanet_objs): $(epanet_heads)
.PHONY: clean
clean:
del $(epanet_main).o $(epanet_objs) $(exename) $(libname) $(epanetrootname).def
.PHONY: install
install:
copy $(exename) $(execdir)
copy $(libname) $(libdir)
copy $(epanetrootname).def $(libdir)

View File

@@ -1,773 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
223109E61BA865930030AAE8 /* Net3.inp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 223109E31BA8658A0030AAE8 /* Net3.inp */; };
223109EB1BA869DA0030AAE8 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 22CD9A5D1B27898E00B65E83 /* main.c */; };
223109ED1BA869DA0030AAE8 /* libepanet-static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2255753B17551217009946B1 /* libepanet-static.a */; };
223109EF1BA869DA0030AAE8 /* Net3.inp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 223109E31BA8658A0030AAE8 /* Net3.inp */; };
223109F61BA869F30030AAE8 /* epanet.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F711068369500641384 /* epanet.c */; };
223109F71BA869F30030AAE8 /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F731068369500641384 /* hash.c */; };
223109F81BA869F30030AAE8 /* hydraul.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F751068369500641384 /* hydraul.c */; };
223109F91BA869F30030AAE8 /* inpfile.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F761068369500641384 /* inpfile.c */; };
223109FA1BA869F30030AAE8 /* input1.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F771068369500641384 /* input1.c */; };
223109FB1BA869F30030AAE8 /* input2.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F781068369500641384 /* input2.c */; };
223109FC1BA869F30030AAE8 /* input3.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F791068369500641384 /* input3.c */; };
223109FD1BA869F30030AAE8 /* mempool.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7A1068369500641384 /* mempool.c */; };
223109FE1BA869F30030AAE8 /* output.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7C1068369500641384 /* output.c */; };
223109FF1BA869F30030AAE8 /* quality.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7D1068369500641384 /* quality.c */; };
22310A001BA869F30030AAE8 /* report.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7E1068369500641384 /* report.c */; };
22310A011BA869F30030AAE8 /* rules.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7F1068369500641384 /* rules.c */; };
22310A021BA869F30030AAE8 /* smatrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F801068369500641384 /* smatrix.c */; };
22310A051BA869F30030AAE8 /* epanet2.h in Headers */ = {isa = PBXBuildFile; fileRef = 22322FA9106836B000641384 /* epanet2.h */; };
22322F851068369500641384 /* enumstxt.h in Headers */ = {isa = PBXBuildFile; fileRef = 22322F701068369500641384 /* enumstxt.h */; };
22322F861068369500641384 /* epanet.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F711068369500641384 /* epanet.c */; };
22322F871068369500641384 /* funcs.h in Headers */ = {isa = PBXBuildFile; fileRef = 22322F721068369500641384 /* funcs.h */; };
22322F881068369500641384 /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F731068369500641384 /* hash.c */; };
22322F891068369500641384 /* hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 22322F741068369500641384 /* hash.h */; };
22322F8A1068369500641384 /* hydraul.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F751068369500641384 /* hydraul.c */; };
22322F8B1068369500641384 /* inpfile.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F761068369500641384 /* inpfile.c */; };
22322F8C1068369500641384 /* input1.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F771068369500641384 /* input1.c */; };
22322F8D1068369500641384 /* input2.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F781068369500641384 /* input2.c */; };
22322F8E1068369500641384 /* input3.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F791068369500641384 /* input3.c */; };
22322F8F1068369500641384 /* mempool.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7A1068369500641384 /* mempool.c */; };
22322F901068369500641384 /* mempool.h in Headers */ = {isa = PBXBuildFile; fileRef = 22322F7B1068369500641384 /* mempool.h */; };
22322F911068369500641384 /* output.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7C1068369500641384 /* output.c */; };
22322F921068369500641384 /* quality.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7D1068369500641384 /* quality.c */; };
22322F931068369500641384 /* report.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7E1068369500641384 /* report.c */; };
22322F941068369500641384 /* rules.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7F1068369500641384 /* rules.c */; };
22322F951068369500641384 /* smatrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F801068369500641384 /* smatrix.c */; };
22322F961068369500641384 /* text.h in Headers */ = {isa = PBXBuildFile; fileRef = 22322F811068369500641384 /* text.h */; };
22322F981068369500641384 /* types.h in Headers */ = {isa = PBXBuildFile; fileRef = 22322F831068369500641384 /* types.h */; };
22322F991068369500641384 /* vars.h in Headers */ = {isa = PBXBuildFile; fileRef = 22322F841068369500641384 /* vars.h */; };
22322FAA106836BC00641384 /* epanet2.h in Headers */ = {isa = PBXBuildFile; fileRef = 22322FA9106836B000641384 /* epanet2.h */; settings = {ATTRIBUTES = (Public, ); }; };
2255753F17551234009946B1 /* epanet.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F711068369500641384 /* epanet.c */; };
2255754017551234009946B1 /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F731068369500641384 /* hash.c */; };
2255754117551234009946B1 /* hydraul.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F751068369500641384 /* hydraul.c */; };
2255754217551234009946B1 /* inpfile.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F761068369500641384 /* inpfile.c */; };
2255754317551234009946B1 /* input1.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F771068369500641384 /* input1.c */; };
2255754417551234009946B1 /* input2.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F781068369500641384 /* input2.c */; };
2255754517551234009946B1 /* input3.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F791068369500641384 /* input3.c */; };
2255754617551234009946B1 /* mempool.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7A1068369500641384 /* mempool.c */; };
2255754717551234009946B1 /* output.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7C1068369500641384 /* output.c */; };
2255754817551234009946B1 /* quality.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7D1068369500641384 /* quality.c */; };
2255754917551234009946B1 /* report.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7E1068369500641384 /* report.c */; };
2255754A17551234009946B1 /* rules.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7F1068369500641384 /* rules.c */; };
2255754B17551234009946B1 /* smatrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F801068369500641384 /* smatrix.c */; };
225762C51C068A3900484EC7 /* Net1.inp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 225762C31C068A2A00484EC7 /* Net1.inp */; };
225762C61C068A3B00484EC7 /* Net2.inp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 225762C41C068A2A00484EC7 /* Net2.inp */; };
226537E0179EDEEB00258C60 /* epanet2.h in Headers */ = {isa = PBXBuildFile; fileRef = 22322FA9106836B000641384 /* epanet2.h */; };
22CD9A5E1B27898E00B65E83 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 22CD9A5D1B27898E00B65E83 /* main.c */; };
22CD9A611B278BB900B65E83 /* libepanet-static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2255753B17551217009946B1 /* libepanet-static.a */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
223109E91BA869DA0030AAE8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 2255753A17551217009946B1;
remoteInfo = "epanet-static";
};
22CD9A5F1B278B0400B65E83 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 2255753A17551217009946B1;
remoteInfo = "epanet-static";
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
223109E11BA865690030AAE8 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 6;
files = (
223109E61BA865930030AAE8 /* Net3.inp in CopyFiles */,
225762C51C068A3900484EC7 /* Net1.inp in CopyFiles */,
225762C61C068A3B00484EC7 /* Net2.inp in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
};
223109EE1BA869DA0030AAE8 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 6;
files = (
223109EF1BA869DA0030AAE8 /* Net3.inp in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
223109E31BA8658A0030AAE8 /* Net3.inp */ = {isa = PBXFileReference; lastKnownFileType = text; name = Net3.inp; path = "../../example-networks/Net3.inp"; sourceTree = "<group>"; };
223109F31BA869DA0030AAE8 /* runepanet copy */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "runepanet copy"; sourceTree = BUILT_PRODUCTS_DIR; };
22310A091BA869F30030AAE8 /* libepanet-static copy.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libepanet-static copy.a"; sourceTree = BUILT_PRODUCTS_DIR; };
22322F66106833BB00641384 /* runepanet */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = runepanet; sourceTree = BUILT_PRODUCTS_DIR; };
22322F701068369500641384 /* enumstxt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = enumstxt.h; path = ../../src/enumstxt.h; sourceTree = SOURCE_ROOT; };
22322F711068369500641384 /* epanet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 2; name = epanet.c; path = ../../src/epanet.c; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.c; };
22322F721068369500641384 /* funcs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = funcs.h; path = ../../src/funcs.h; sourceTree = SOURCE_ROOT; };
22322F731068369500641384 /* hash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hash.c; path = ../../src/hash.c; sourceTree = SOURCE_ROOT; };
22322F741068369500641384 /* hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = hash.h; path = ../../src/hash.h; sourceTree = SOURCE_ROOT; };
22322F751068369500641384 /* hydraul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hydraul.c; path = ../../src/hydraul.c; sourceTree = SOURCE_ROOT; };
22322F761068369500641384 /* inpfile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = inpfile.c; path = ../../src/inpfile.c; sourceTree = SOURCE_ROOT; };
22322F771068369500641384 /* input1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = input1.c; path = ../../src/input1.c; sourceTree = SOURCE_ROOT; };
22322F781068369500641384 /* input2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = input2.c; path = ../../src/input2.c; sourceTree = SOURCE_ROOT; };
22322F791068369500641384 /* input3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = input3.c; path = ../../src/input3.c; sourceTree = SOURCE_ROOT; };
22322F7A1068369500641384 /* mempool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mempool.c; path = ../../src/mempool.c; sourceTree = SOURCE_ROOT; };
22322F7B1068369500641384 /* mempool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mempool.h; path = ../../src/mempool.h; sourceTree = SOURCE_ROOT; };
22322F7C1068369500641384 /* output.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = output.c; path = ../../src/output.c; sourceTree = SOURCE_ROOT; };
22322F7D1068369500641384 /* quality.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 2; name = quality.c; path = ../../src/quality.c; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.c; };
22322F7E1068369500641384 /* report.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = report.c; path = ../../src/report.c; sourceTree = SOURCE_ROOT; };
22322F7F1068369500641384 /* rules.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = rules.c; path = ../../src/rules.c; sourceTree = SOURCE_ROOT; };
22322F801068369500641384 /* smatrix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = smatrix.c; path = ../../src/smatrix.c; sourceTree = SOURCE_ROOT; };
22322F811068369500641384 /* text.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = text.h; path = ../../src/text.h; sourceTree = SOURCE_ROOT; };
22322F831068369500641384 /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = types.h; path = ../../src/types.h; sourceTree = SOURCE_ROOT; };
22322F841068369500641384 /* vars.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vars.h; path = ../../src/vars.h; sourceTree = SOURCE_ROOT; };
22322FA9106836B000641384 /* epanet2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 2; name = epanet2.h; path = ../../include/epanet2.h; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
2255753B17551217009946B1 /* libepanet-static.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libepanet-static.a"; sourceTree = BUILT_PRODUCTS_DIR; };
225762C31C068A2A00484EC7 /* Net1.inp */ = {isa = PBXFileReference; lastKnownFileType = text; name = Net1.inp; path = "../../example-networks/Net1.inp"; sourceTree = "<group>"; };
225762C41C068A2A00484EC7 /* Net2.inp */ = {isa = PBXFileReference; lastKnownFileType = text; name = Net2.inp; path = "../../example-networks/Net2.inp"; sourceTree = "<group>"; };
22CD9A5D1B27898E00B65E83 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = main.c; path = ../../run/main.c; sourceTree = "<group>"; };
22E107B21C163E5300689CED /* outputapi.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = outputapi.c; path = ../../tools/outputapi/outputapi.c; sourceTree = "<group>"; };
22E107B31C163E5300689CED /* outputapi.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = outputapi.h; path = ../../tools/outputapi/outputapi.h; sourceTree = "<group>"; };
D2AAC0630554660B00DB518D /* libepanet.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libepanet.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
223109EC1BA869DA0030AAE8 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
223109ED1BA869DA0030AAE8 /* libepanet-static.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
22310A031BA869F30030AAE8 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
22322F64106833BB00641384 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
22CD9A611B278BB900B65E83 /* libepanet-static.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
2255753817551217009946B1 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
D289988505E68E00004EDB86 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
08FB7794FE84155DC02AAC07 /* epanet */ = {
isa = PBXGroup;
children = (
22E107B11C163E3B00689CED /* Output API */,
223109E21BA865790030AAE8 /* sample networks */,
22CD9A5C1B27896200B65E83 /* run epanet */,
22322FA8106836A000641384 /* Include */,
08FB7795FE84155DC02AAC07 /* Source */,
1AB674ADFE9D54B511CA2CBB /* Products */,
);
name = epanet;
sourceTree = "<group>";
};
08FB7795FE84155DC02AAC07 /* Source */ = {
isa = PBXGroup;
children = (
22322F711068369500641384 /* epanet.c */,
22322F751068369500641384 /* hydraul.c */,
22322F701068369500641384 /* enumstxt.h */,
22322F721068369500641384 /* funcs.h */,
22322F731068369500641384 /* hash.c */,
22322F741068369500641384 /* hash.h */,
22322F761068369500641384 /* inpfile.c */,
22322F771068369500641384 /* input1.c */,
22322F781068369500641384 /* input2.c */,
22322F791068369500641384 /* input3.c */,
22322F7A1068369500641384 /* mempool.c */,
22322F7B1068369500641384 /* mempool.h */,
22322F7C1068369500641384 /* output.c */,
22322F7D1068369500641384 /* quality.c */,
22322F7E1068369500641384 /* report.c */,
22322F7F1068369500641384 /* rules.c */,
22322F801068369500641384 /* smatrix.c */,
22322F811068369500641384 /* text.h */,
22322F831068369500641384 /* types.h */,
22322F841068369500641384 /* vars.h */,
);
name = Source;
sourceTree = "<group>";
};
1AB674ADFE9D54B511CA2CBB /* Products */ = {
isa = PBXGroup;
children = (
D2AAC0630554660B00DB518D /* libepanet.dylib */,
22322F66106833BB00641384 /* runepanet */,
2255753B17551217009946B1 /* libepanet-static.a */,
223109F31BA869DA0030AAE8 /* runepanet copy */,
22310A091BA869F30030AAE8 /* libepanet-static copy.a */,
);
name = Products;
sourceTree = "<group>";
};
223109E21BA865790030AAE8 /* sample networks */ = {
isa = PBXGroup;
children = (
223109E31BA8658A0030AAE8 /* Net3.inp */,
225762C31C068A2A00484EC7 /* Net1.inp */,
225762C41C068A2A00484EC7 /* Net2.inp */,
);
name = "sample networks";
sourceTree = "<group>";
};
22322FA8106836A000641384 /* Include */ = {
isa = PBXGroup;
children = (
22322FA9106836B000641384 /* epanet2.h */,
);
name = Include;
sourceTree = "<group>";
};
22CD9A5C1B27896200B65E83 /* run epanet */ = {
isa = PBXGroup;
children = (
22CD9A5D1B27898E00B65E83 /* main.c */,
);
name = "run epanet";
sourceTree = "<group>";
};
22E107B11C163E3B00689CED /* Output API */ = {
isa = PBXGroup;
children = (
22E107B31C163E5300689CED /* outputapi.h */,
22E107B21C163E5300689CED /* outputapi.c */,
);
name = "Output API";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
22310A041BA869F30030AAE8 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
22310A051BA869F30030AAE8 /* epanet2.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
2255753917551217009946B1 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
226537E0179EDEEB00258C60 /* epanet2.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D2AAC0600554660B00DB518D /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
22322FAA106836BC00641384 /* epanet2.h in Headers */,
22322F851068369500641384 /* enumstxt.h in Headers */,
22322F871068369500641384 /* funcs.h in Headers */,
22322F891068369500641384 /* hash.h in Headers */,
22322F901068369500641384 /* mempool.h in Headers */,
22322F961068369500641384 /* text.h in Headers */,
22322F981068369500641384 /* types.h in Headers */,
22322F991068369500641384 /* vars.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
223109E71BA869DA0030AAE8 /* runepanet float-precision */ = {
isa = PBXNativeTarget;
buildConfigurationList = 223109F01BA869DA0030AAE8 /* Build configuration list for PBXNativeTarget "runepanet float-precision" */;
buildPhases = (
223109EA1BA869DA0030AAE8 /* Sources */,
223109EC1BA869DA0030AAE8 /* Frameworks */,
223109EE1BA869DA0030AAE8 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
223109E81BA869DA0030AAE8 /* PBXTargetDependency */,
);
name = "runepanet float-precision";
productName = runepanet;
productReference = 223109F31BA869DA0030AAE8 /* runepanet copy */;
productType = "com.apple.product-type.tool";
};
223109F41BA869F30030AAE8 /* epanet-static float-precision */ = {
isa = PBXNativeTarget;
buildConfigurationList = 22310A061BA869F30030AAE8 /* Build configuration list for PBXNativeTarget "epanet-static float-precision" */;
buildPhases = (
223109F51BA869F30030AAE8 /* Sources */,
22310A031BA869F30030AAE8 /* Frameworks */,
22310A041BA869F30030AAE8 /* Headers */,
);
buildRules = (
);
dependencies = (
);
name = "epanet-static float-precision";
productName = "epanet-static";
productReference = 22310A091BA869F30030AAE8 /* libepanet-static copy.a */;
productType = "com.apple.product-type.library.static";
};
22322F65106833BB00641384 /* runepanet */ = {
isa = PBXNativeTarget;
buildConfigurationList = 22322F6A106833E600641384 /* Build configuration list for PBXNativeTarget "runepanet" */;
buildPhases = (
22322F63106833BB00641384 /* Sources */,
22322F64106833BB00641384 /* Frameworks */,
223109E11BA865690030AAE8 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
22CD9A601B278B0400B65E83 /* PBXTargetDependency */,
);
name = runepanet;
productName = runepanet;
productReference = 22322F66106833BB00641384 /* runepanet */;
productType = "com.apple.product-type.tool";
};
2255753A17551217009946B1 /* epanet-static */ = {
isa = PBXNativeTarget;
buildConfigurationList = 2255753E17551217009946B1 /* Build configuration list for PBXNativeTarget "epanet-static" */;
buildPhases = (
2255753717551217009946B1 /* Sources */,
2255753817551217009946B1 /* Frameworks */,
2255753917551217009946B1 /* Headers */,
);
buildRules = (
);
dependencies = (
);
name = "epanet-static";
productName = "epanet-static";
productReference = 2255753B17551217009946B1 /* libepanet-static.a */;
productType = "com.apple.product-type.library.static";
};
D2AAC0620554660B00DB518D /* epanet */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1DEB914A08733D8E0010E9CD /* Build configuration list for PBXNativeTarget "epanet" */;
buildPhases = (
D2AAC0600554660B00DB518D /* Headers */,
D2AAC0610554660B00DB518D /* Sources */,
D289988505E68E00004EDB86 /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = epanet;
productName = epanet;
productReference = D2AAC0630554660B00DB518D /* libepanet.dylib */;
productType = "com.apple.product-type.library.dynamic";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0630;
};
buildConfigurationList = 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "epanet" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
Japanese,
French,
German,
);
mainGroup = 08FB7794FE84155DC02AAC07 /* epanet */;
projectDirPath = "";
projectRoot = ../../..;
targets = (
D2AAC0620554660B00DB518D /* epanet */,
22322F65106833BB00641384 /* runepanet */,
2255753A17551217009946B1 /* epanet-static */,
223109E71BA869DA0030AAE8 /* runepanet float-precision */,
223109F41BA869F30030AAE8 /* epanet-static float-precision */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
223109EA1BA869DA0030AAE8 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
223109EB1BA869DA0030AAE8 /* main.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
223109F51BA869F30030AAE8 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
223109F61BA869F30030AAE8 /* epanet.c in Sources */,
223109F71BA869F30030AAE8 /* hash.c in Sources */,
223109F81BA869F30030AAE8 /* hydraul.c in Sources */,
223109F91BA869F30030AAE8 /* inpfile.c in Sources */,
223109FA1BA869F30030AAE8 /* input1.c in Sources */,
223109FB1BA869F30030AAE8 /* input2.c in Sources */,
223109FC1BA869F30030AAE8 /* input3.c in Sources */,
223109FD1BA869F30030AAE8 /* mempool.c in Sources */,
223109FE1BA869F30030AAE8 /* output.c in Sources */,
223109FF1BA869F30030AAE8 /* quality.c in Sources */,
22310A001BA869F30030AAE8 /* report.c in Sources */,
22310A011BA869F30030AAE8 /* rules.c in Sources */,
22310A021BA869F30030AAE8 /* smatrix.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
22322F63106833BB00641384 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
22CD9A5E1B27898E00B65E83 /* main.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
2255753717551217009946B1 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
2255753F17551234009946B1 /* epanet.c in Sources */,
2255754017551234009946B1 /* hash.c in Sources */,
2255754117551234009946B1 /* hydraul.c in Sources */,
2255754217551234009946B1 /* inpfile.c in Sources */,
2255754317551234009946B1 /* input1.c in Sources */,
2255754417551234009946B1 /* input2.c in Sources */,
2255754517551234009946B1 /* input3.c in Sources */,
2255754617551234009946B1 /* mempool.c in Sources */,
2255754717551234009946B1 /* output.c in Sources */,
2255754817551234009946B1 /* quality.c in Sources */,
2255754917551234009946B1 /* report.c in Sources */,
2255754A17551234009946B1 /* rules.c in Sources */,
2255754B17551234009946B1 /* smatrix.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D2AAC0610554660B00DB518D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
22322F861068369500641384 /* epanet.c in Sources */,
22322F881068369500641384 /* hash.c in Sources */,
22322F8A1068369500641384 /* hydraul.c in Sources */,
22322F8B1068369500641384 /* inpfile.c in Sources */,
22322F8C1068369500641384 /* input1.c in Sources */,
22322F8D1068369500641384 /* input2.c in Sources */,
22322F8E1068369500641384 /* input3.c in Sources */,
22322F8F1068369500641384 /* mempool.c in Sources */,
22322F911068369500641384 /* output.c in Sources */,
22322F921068369500641384 /* quality.c in Sources */,
22322F931068369500641384 /* report.c in Sources */,
22322F941068369500641384 /* rules.c in Sources */,
22322F951068369500641384 /* smatrix.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
223109E81BA869DA0030AAE8 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 2255753A17551217009946B1 /* epanet-static */;
targetProxy = 223109E91BA869DA0030AAE8 /* PBXContainerItemProxy */;
};
22CD9A601B278B0400B65E83 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 2255753A17551217009946B1 /* epanet-static */;
targetProxy = 22CD9A5F1B278B0400B65E83 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
1DEB914B08733D8E0010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
EXECUTABLE_PREFIX = lib;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = "EN_API_FLOAT_TYPE=double";
PRODUCT_NAME = epanet;
};
name = Debug;
};
1DEB914C08733D8E0010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
EXECUTABLE_PREFIX = lib;
GCC_MODEL_TUNING = G5;
GCC_PREPROCESSOR_DEFINITIONS = "EN_API_FLOAT_TYPE=double";
PRODUCT_NAME = epanet;
};
name = Release;
};
1DEB914F08733D8E0010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_CXX_LIBRARY = "libc++";
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = c89;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = "";
MACOSX_DEPLOYMENT_TARGET = 10.10;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = "";
};
name = Debug;
};
1DEB915008733D8E0010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_CXX_LIBRARY = "libc++";
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = c89;
GCC_NO_COMMON_BLOCKS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = "";
MACOSX_DEPLOYMENT_TARGET = 10.10;
SDKROOT = "";
};
name = Release;
};
223109F11BA869DA0030AAE8 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = "";
INFOPLIST_PREPROCESSOR_DEFINITIONS = "";
PRODUCT_NAME = "runepanet copy";
};
name = Debug;
};
223109F21BA869DA0030AAE8 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
GCC_MODEL_TUNING = G5;
GCC_PREPROCESSOR_DEFINITIONS = "";
INFOPLIST_PREPROCESSOR_DEFINITIONS = "";
PRODUCT_NAME = "runepanet copy";
ZERO_LINK = NO;
};
name = Release;
};
22310A071BA869F30030AAE8 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_WARN_EMPTY_BODY = YES;
COMBINE_HIDPI_IMAGES = YES;
EXECUTABLE_PREFIX = lib;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
PRODUCT_NAME = "epanet-static copy";
};
name = Debug;
};
22310A081BA869F30030AAE8 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_WARN_EMPTY_BODY = YES;
COMBINE_HIDPI_IMAGES = YES;
EXECUTABLE_PREFIX = lib;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
PRODUCT_NAME = "epanet-static copy";
};
name = Release;
};
22322F68106833BC00641384 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = "";
INFOPLIST_PREPROCESSOR_DEFINITIONS = "";
PRODUCT_NAME = runepanet;
SDKROOT = macosx;
};
name = Debug;
};
22322F69106833BC00641384 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
GCC_MODEL_TUNING = G5;
GCC_PREPROCESSOR_DEFINITIONS = "";
INFOPLIST_PREPROCESSOR_DEFINITIONS = "";
PRODUCT_NAME = runepanet;
SDKROOT = macosx;
ZERO_LINK = NO;
};
name = Release;
};
2255753C17551217009946B1 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_WARN_EMPTY_BODY = YES;
COMBINE_HIDPI_IMAGES = YES;
EXECUTABLE_PREFIX = lib;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_PREPROCESSOR_DEFINITIONS = "EN_API_FLOAT_TYPE=double";
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
};
name = Debug;
};
2255753D17551217009946B1 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_WARN_EMPTY_BODY = YES;
COMBINE_HIDPI_IMAGES = YES;
EXECUTABLE_PREFIX = lib;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_PREPROCESSOR_DEFINITIONS = "EN_API_FLOAT_TYPE=double";
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
1DEB914A08733D8E0010E9CD /* Build configuration list for PBXNativeTarget "epanet" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB914B08733D8E0010E9CD /* Debug */,
1DEB914C08733D8E0010E9CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "epanet" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB914F08733D8E0010E9CD /* Debug */,
1DEB915008733D8E0010E9CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
223109F01BA869DA0030AAE8 /* Build configuration list for PBXNativeTarget "runepanet float-precision" */ = {
isa = XCConfigurationList;
buildConfigurations = (
223109F11BA869DA0030AAE8 /* Debug */,
223109F21BA869DA0030AAE8 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
22310A061BA869F30030AAE8 /* Build configuration list for PBXNativeTarget "epanet-static float-precision" */ = {
isa = XCConfigurationList;
buildConfigurations = (
22310A071BA869F30030AAE8 /* Debug */,
22310A081BA869F30030AAE8 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
22322F6A106833E600641384 /* Build configuration list for PBXNativeTarget "runepanet" */ = {
isa = XCConfigurationList;
buildConfigurations = (
22322F68106833BC00641384 /* Debug */,
22322F69106833BC00641384 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
2255753E17551217009946B1 /* Build configuration list for PBXNativeTarget "epanet-static" */ = {
isa = XCConfigurationList;
buildConfigurations = (
2255753C17551217009946B1 /* Debug */,
2255753D17551217009946B1 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
}

View File

@@ -53,7 +53,9 @@ Global Const EN_ENERGY = 13
Global Const EN_LINKQUAL = 14 'ES
Global Const EN_LINKPATTERN = 15
Global Const EN_EFFICIENCY = 16
Global Const EN_PRICEPATTERN = 17
Global Const EN_HEADCURVE = 17
Global Const EN_EFFICIENCYCURVE = 18
Global Const EN_PRICEPATTERN = 19
Global Const EN_DURATION = 0 ' Time parameters
Global Const EN_HYDSTEP = 1
@@ -106,6 +108,10 @@ Global Const EN_MASS = 1
Global Const EN_SETPOINT = 2
Global Const EN_FLOWPACED = 3
Global Const EN_HW = 0 ' Head loss formula
Global Const EN_DW = 1
Global Const EN_CM = 2
Global Const EN_CFS = 0 ' Flow units types
Global Const EN_GPM = 1
Global Const EN_MGD = 2
@@ -247,3 +253,11 @@ Global Const EN_CUSTOM = 2 ' user-defined custom curve
Declare FUnction ENgetfalseaction Lib "epanet2.dll" (ByVal indexRule As Long, ByVal indexAction As Long, indexLink As Long, status As Long, setting As Single) As Long
Declare Function ENsetfalseaction Lib "epanet2.dll" (ByVal indexRule As Long, ByVal indexAction As Long, ByVal indexLink As Long, ByVal status As Long, ByVal setting As Single) As Long
Declare Function ENgetruleID Lib "epanet2.dll" (ByVal indexRule As Long, ByVal id As String) As Long
Declare Function ENinit Lib "epanet2.dll" (ByVal rptFile As String, ByVal binOutFile As String, ByVal UnitsType As Long, ByVal HeadlossFormula As Long) As Long
Declare Function ENsetheadcurveindex Lib "epanet2.dll" (ByVal pumpIndex As Long, ByVal curveIndex As Long) As Long
Declare Function ENsetlinktype Lib "epanet2.dll" (ByVal index As Long, ByVal code As Long) As Long
Declare Function ENaddnode Lib "epanet2.dll" (ByVal id As String, ByVal nodeType As Long) As Long
Declare Function ENaddlink Lib "epanet2.dll" (ByVal id As String, ByVal linkType As Long, ByVal fromNode As String, ByVal toNode As String) As Long
Declare Function ENdeletelink Lib "epanet2.dll" (ByVal nodeIndex As Long) As Long
Declare Function ENdeletenode Lib "epanet2.dll" (ByVal linkIndex As Long) As Long

2268
include/epanet2.h Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -57,7 +57,9 @@ Public Const EN_ENERGY = 13
Public Const EN_LINKQUAL = 14 'ES
Public Const EN_LINKPATTERN = 15
Public Const EN_EFFICIENCY = 16
Public Const EN_PRICEPATTERN = 17
Public Const EN_HEADCURVE = 17
Public Const EN_EFFICIENCYCURVE = 18
Public Const EN_PRICEPATTERN = 19
Public Const EN_DURATION = 0 ' Time parameters
Public Const EN_HYDSTEP = 1
@@ -172,7 +174,7 @@ Public Const EN_CUSTOM = 2 ' user-defined custom curve
Declare Function ENreport Lib "epanet2.dll" () As Int32
Declare Function ENresetreport Lib "epanet2.dll" () As Int32
Declare Function ENsetreport Lib "epanet2.dll" (ByVal S As String) As Int32
Declare Function ENgetcontrol Lib "epanet2.dll" (ByVal Cindex As Int32, ByRef CtlType As Int32, ByRef Lindex As Int32, ByRef Setting As Single, ByRef Nindex As Int32, ByRef Level As Single) As Int32
Declare Function ENgetcount Lib "epanet2.dll" (ByVal Code As Int32, ByRef Value As Int32) As Int32
Declare Function ENgetoption Lib "epanet2.dll" (ByVal Code As Int32, ByRef Value As Single) As Int32
@@ -217,15 +219,15 @@ Public Const EN_CUSTOM = 2 ' user-defined custom curve
Declare Function ENsetoption Lib "epanet2.dll" (ByVal Code As Int32, ByVal Value As Single) As Int32
Declare Function ENsetstatusreport Lib "epanet2.dll" (ByVal Code As Int32) As Int32
Declare Function ENsetqualtype Lib "epanet2.dll" (ByVal QualCode As Int32, ByVal ChemName As String, ByVal ChemUnits As String, ByVal TraceNode As String) As Int32
Declare Function ENaddpattern Lib "epanet2.dll" (ByVal ID As String) As Int32
Declare Function ENgetcurveindex Lib "epanet2.dll" (ByVal ID As String, ByRef Index As Int32) As Int32
Declare Function ENgetcurveid Lib "epanet2.dll" (ByVal Index As Int32, ByVal ID As StringBuilder) As Int32
Declare Function ENgetcurvelen Lib "epanet2.dll" (ByVal Index As Int32, ByRef L As Int32) As Int32
Declare Function ENgetcurvevalue Lib "epanet2.dll" (ByVal Index As Int32, ByVal Pnt As Int32, ByRef X As Single, ByRef Y As Single) As Int32
Declare Function ENgetcurvevalue Lib "epanet2.dll" (ByVal Index As Int32, ByVal Pnt As Int32, ByRef X As Single, ByRef Y As Single) As Int32
Declare Function ENsetcurvevalue Lib "epanet2.dll" (ByVal Index As Int32, ByVal Pnt As Int32, ByVal X As Single, ByVal Y As Single) As Int32
Declare Function ENsetcurve Lib "epanet2.dll" (ByVal Index as Int32, ByRef X as Single, ByRef Y as Single, ByVal N as Int32) as Int32
Declare Function ENsetcurve Lib "epanet2.dll" (ByVal Index as Int32, ByRef X as Single, ByRef Y as Single, ByVal N as Int32) as Int32
Declare Function ENaddcurve Lib "epanet2.dll" (ByVal ID As String) As Int32
Declare Function ENaddcurve Lib "epanet2.dll" (ByVal ID As String) As Long
@@ -244,5 +246,5 @@ Declare Function ENaddcurve Lib "epanet2.dll" (ByVal ID As String) As Long
Declare Function ENgetruleID Lib "epanet2.dll" (ByVal indexRule As Int32, ByVal id As StringBuilder) As Int32
End Module

View File

@@ -2,11 +2,11 @@
#include <string.h>
#include "epanet2.h"
#define MAXMSG 79 /* Max. # characters in message text */
#define MAXMSG 255 /* Max. # characters in message text */
#define MAXWARNCODE 99
/* text copied here, no more need of include "text.h" */
#define FMT01 "\nEPANET Version %d.%d.%d\n"
#define FMT03 "\n Correct syntax is:\n epanet <input file> <output file>\n"
#define FMT03 "\n Correct syntax is:\n %s <input file> <output file>\n"
#define FMT09 "\nEPANET completed.\n"
#define FMT10 "\nEPANET completed. There are warnings."
#define FMT11 "\nEPANET completed. There are errors."
@@ -43,7 +43,7 @@ int main(int argc, char *argv[])
char errmsg[MAXMSG+1]="";
int errcode;
int version;
char s[25];
char s[256];
int major;
int minor;
int patch;
@@ -60,7 +60,8 @@ int main(int argc, char *argv[])
/* Check for proper number of command line arguments */
if (argc < 2) {
writeConsole(FMT03);
sprintf(s, FMT03, argv[0]);
writeConsole(s);
return(1);
}

View File

@@ -1,137 +1,129 @@
/*
***********************************************************************
ENUMSTXT.H -- Text strings for enumerated data types in EPANET
VERSION: 2.00
DATE: 5/8/00
AUTHOR: L. Rossman
US EPA - NRMRL
**********************************************************************
*/
#ifndef ENUMSTXT_H
#define ENUMSTXT_H
char *NodeTxt[] = {t_JUNCTION,
t_RESERVOIR,
t_TANK};
char *LinkTxt[] = {w_CV,
w_PIPE,
w_PUMP,
w_PRV,
w_PSV,
w_PBV,
w_FCV,
w_TCV,
w_GPV};
char *StatTxt[] = {t_XHEAD,
t_TEMPCLOSED,
t_CLOSED,
t_OPEN,
t_ACTIVE,
t_XFLOW,
t_XFCV,
t_XPRESSURE,
t_FILLING,
t_EMPTYING};
char *FormTxt[] = {w_HW,
w_DW,
w_CM};
char *RptFormTxt[] = {t_HW,
t_DW,
t_CM};
char *RptFlowUnitsTxt[] = {u_CFS,
u_GPM,
u_MGD,
u_IMGD,
u_AFD,
u_LPS,
u_LPM,
u_MLD,
u_CMH,
u_CMD};
char *FlowUnitsTxt[] = {w_CFS,
w_GPM,
w_MGD,
w_IMGD,
w_AFD,
w_LPS,
w_LPM,
w_MLD,
w_CMH,
w_CMD};
char *PressUnitsTxt[] = {w_PSI,
w_KPA,
w_METERS};
char *QualTxt[] = {w_NONE,
w_CHEM,
w_AGE,
w_TRACE};
char *SourceTxt[] = {w_CONCEN,
w_MASS,
w_SETPOINT,
w_FLOWPACED};
char *ControlTxt[] = {w_BELOW,
w_ABOVE,
w_TIME,
w_CLOCKTIME};
char *TstatTxt[] = {w_NONE,
w_AVG,
w_MIN,
w_MAX,
w_RANGE};
char *MixTxt[] = {w_MIXED,
w_2COMP,
w_FIFO,
w_LIFO,
NULL};
char *RptFlagTxt[] = {w_NO,
w_YES,
w_FULL};
char *SectTxt[] = {s_TITLE, s_JUNCTIONS, s_RESERVOIRS,
s_TANKS, s_PIPES, s_PUMPS,
s_VALVES, s_CONTROLS, s_RULES,
s_DEMANDS, s_SOURCES, s_EMITTERS,
s_PATTERNS, s_CURVES, s_QUALITY,
s_STATUS, s_ROUGHNESS, s_ENERGY,
s_REACTIONS, s_MIXING, s_REPORT,
s_TIMES, s_OPTIONS, s_COORDS,
s_VERTICES, s_LABELS, s_BACKDROP,
s_TAGS, s_END,
NULL};
char *RptSectTxt[] = {NULL, t_JUNCTION, t_RESERVOIR,
t_TANK, t_PIPE, t_PUMP,
t_VALVE, t_CONTROL, t_RULE,
t_DEMANDFOR,t_SOURCE, t_EMITTER,
t_PATTERN, t_CURVE, t_QUALITY,
t_STATUS, t_ROUGHNESS,t_ENERGY,
t_REACTION, t_MIXING, t_REPORT,
t_TIME, t_OPTION};
char *Fldname[] = {t_ELEV, t_DEMAND, t_HEAD,
t_PRESSURE, t_QUALITY, t_LENGTH,
t_DIAM, t_FLOW, t_VELOCITY,
t_HEADLOSS, t_LINKQUAL, t_LINKSTATUS,
t_SETTING, t_REACTRATE, t_FRICTION,
"", "", "", "", "", "", NULL};
#endif
/*
***********************************************************************
ENUMSTXT.H -- Text strings for enumerated data types in EPANET
VERSION: 2.00
DATE: 5/8/00
AUTHOR: L. Rossman
US EPA - NRMRL
**********************************************************************
*/
#ifndef ENUMSTXT_H
#define ENUMSTXT_H
#include "text.h"
char *NodeTxt[] = {t_JUNCTION,
t_RESERVOIR,
t_TANK};
char *LinkTxt[] = {w_CV,
w_PIPE,
w_PUMP,
w_PRV,
w_PSV,
w_PBV,
w_FCV,
w_TCV,
w_GPV};
char *StatTxt[] = {t_XHEAD,
t_TEMPCLOSED,
t_CLOSED,
t_OPEN,
t_ACTIVE,
t_XFLOW,
t_XFCV,
t_XPRESSURE,
t_FILLING,
t_EMPTYING};
char *FormTxt[] = {w_HW,
w_DW,
w_CM};
char *RptFormTxt[] = {t_HW,
t_DW,
t_CM};
char *RptFlowUnitsTxt[] = {u_CFS,
u_GPM,
u_MGD,
u_IMGD,
u_AFD,
u_LPS,
u_LPM,
u_MLD,
u_CMH,
u_CMD};
char *FlowUnitsTxt[] = {w_CFS,
w_GPM,
w_MGD,
w_IMGD,
w_AFD,
w_LPS,
w_LPM,
w_MLD,
w_CMH,
w_CMD};
char *PressUnitsTxt[] = {w_PSI,
w_KPA,
w_METERS};
char *QualTxt[] = {w_NONE,
w_CHEM,
w_AGE,
w_TRACE};
char *SourceTxt[] = {w_CONCEN,
w_MASS,
w_SETPOINT,
w_FLOWPACED};
char *ControlTxt[] = {w_BELOW,
w_ABOVE,
w_TIME,
w_CLOCKTIME};
char *TstatTxt[] = {w_NONE,
w_AVG,
w_MIN,
w_MAX,
w_RANGE};
char *MixTxt[] = {w_MIXED,
w_2COMP,
w_FIFO,
w_LIFO,
NULL};
char *RptFlagTxt[] = {w_NO,
w_YES,
w_FULL};
char *SectTxt[] = {s_TITLE, s_JUNCTIONS, s_RESERVOIRS,
s_TANKS, s_PIPES, s_PUMPS,
s_VALVES, s_CONTROLS, s_RULES,
s_DEMANDS, s_SOURCES, s_EMITTERS,
s_PATTERNS, s_CURVES, s_QUALITY,
s_STATUS, s_ROUGHNESS, s_ENERGY,
s_REACTIONS, s_MIXING, s_REPORT,
s_TIMES, s_OPTIONS, s_COORDS,
s_VERTICES, s_LABELS, s_BACKDROP,
s_TAGS, s_END,
NULL};
char *Fldname[] = {t_ELEV, t_DEMAND, t_HEAD,
t_PRESSURE, t_QUALITY, t_LENGTH,
t_DIAM, t_FLOW, t_VELOCITY,
t_HEADLOSS, t_LINKQUAL, t_LINKSTATUS,
t_SETTING, t_REACTRATE, t_FRICTION,
"", "", "", "", "", "", NULL};
#endif

8173
src/epanet.c Executable file → Normal file

File diff suppressed because it is too large Load Diff

75
src/errors.dat Normal file
View File

@@ -0,0 +1,75 @@
DAT(0,EN_OK,"ok")
DAT(101,ENERR_INSUF_MEM,"insufficient memory available")
DAT(102,ENERR_NO_NET_DATA,"no network data available")
DAT(103,ENERR_HYD_NOT_INIT,"hydraulics not initialized")
DAT(104,ENERR_NO_HYD,"no hydraulics for water quality analysis")
DAT(105,ENERR_WQ_NOT_INIT,"water quality not initialized")
DAT(106,ENERR_NO_RESULT,"no results saved to report on")
DAT(107,ENERR_HYD_EXT_FILE,"hydraulics supplied from external file")
DAT(108,ENERR_CANT_USE_EXT_FILE,"cannot use external file while hydraulics solver is active")
DAT(109,ENERR_CANT_CHANGE_TIME_PARAM,"cannot change time parameter when solver is active")
DAT(110,ENERR_CANT_SOLVE_HYD,"cannot solve network hydraulic equations")
DAT(120,ENERR_CANT_SOLVE_WQ,"cannot solve water quality transport equations")
DAT(200,ENERR_INP_ERR,"one or more errors in input file")
DAT(201,ENERR_SYNTAX_LINE,"syntax error in following line of section")
DAT(202,ENERR_ILLEGAL_NUM,"function call contains illegal numeric value")
DAT(203,ENERR_UNDEF_NODE,"function call refers to undefined node")
DAT(204,ENERR_UNDEF_LINK,"function call refers to undefined link")
DAT(205,ENERR_UNDEF_PAT,"function call refers to undefined time pattern")
DAT(206,ENERR_UNDEF_CURVE,"function call refers to undefined curve")
DAT(207,ENERR_CANT_CONTROL_CV,"function call attempts to control a CV")
DAT(208,ENERR_SPEC_UNDEF_NODE,"undefined Node")
DAT(209,ENERR_ILLEGAL_VAL_NODE,"illegal value for Node")
DAT(210,ENERR_SPEC_UNDEF_LINK,"specified for undefined Link")
DAT(211,ENERR_ILLEGAL_VAL_LINK,"illegal value for Link")
DAT(212,ENERR_TRACE_NODE,"trace node")
DAT(213,ENERR_ILLEGAL_OPT,"illegal option value in section")
DAT(214,ENERR_TOO_MANY_CHAR,"following line of section contains too many characters")
DAT(215,ENERR_DUPLICATE_ID,"duplicate ID")
DAT(216,ENERR_UNDEF_PUMP,"data specified for undefined Pump")
DAT(217,ENERR_INVALID_DATA_PUMP,"invalid data for Pump")
DAT(219,ENERR_ILLEGAL_CON_TANK,"illegally connected to a tank")
DAT(220,ENERR_ILLEGAL_CON_VALVE,"illegally connected to another valve")
DAT(222,ENERR_SAME_START_END,"same start and end nodes")
DAT(223,ENERR_NOT_ENOUGH_NODES,"not enough nodes in network")
DAT(224,ENERR_NO_TANKS_RES,"no tanks or reservoirs in network")
DAT(225,ENERR_INVALID_LEVELS,"invalid lower/upper levels for Tank")
DAT(226,ENERR_NO_HEAD_CURVE,"no head curve supplied for Pump")
DAT(227,ENERR_INVALID_HEAD_CURVE,"invalid head curve for Pump")
DAT(230,ENERR_X_NONINCREASING,"Curve has nonincreasing x-values")
DAT(233,ENERR_NODE_UNCONNECTED,"Node is unconnected")
DAT(240,ENERR_UNDEF_SOURCE,"undefined source")
DAT(241,ENERR_UNDEF_CONTROL,"refers to undefined control")
DAT(250,ENERR_INVALID_FORMAT,"function call contains invalid format")
DAT(251,ENERR_INVALID_CODE,"function call contains invalid parameter code")
DAT(253,ENERR_NO_DEMAND_CAT,"Function call error - No such demand category index")
DAT(254,ENERR_NO_COORDS,"Function call error - Node have no coordinates")
DAT(255,ENERR_COORDS_NOT_LOADED,"Function call error - Coordinates were not loaded")
DAT(257,ENERR_NO_RULE,"rule does not exist")
DAT(258,ENERR_NO_CONDITION_ACTION,"condition or action index specified in rule does not exist")
DAT(301,ENERR_FILES_ARE_SAME,"identical file names")
DAT(302,ENERR_CANT_OPEN_INP,"cannot open input file")
DAT(303,ENERR_CANT_OPEN_RPT,"cannot open report file")
DAT(304,ENERR_CANT_OPEN_BIN,"cannot open binary output file")
DAT(305,ENERR_CANT_OPEN_HYD,"cannot open hydraulics file")
DAT(306,ENERR_HYD_FILE_NOMATCH,"hydraulics file does not match network data")
DAT(307,ENERR_CANT_READ_HYD,"cannot read hydraulics file")
DAT(308,ENERR_CANT_SAVE_RES,"cannot save results to file")
DAT(309,ENERR_CANT_SAVE_RPT,"cannot save results to report file")
DAT(401,ENERR_QSTEP_NOT_DIVISIBLE,"Qstep is not dividable by Hstep")
DAT(411,ENERR_NO_MEM_ALLOC,"no memory allocated for results")
DAT(412,ENERR_NO_RESULTS_NO_FILE,"no results; binary file hasn't been opened")
DAT(435,ENERR_RUN_TERMINATED,"run terminated; no results in binary file")

View File

@@ -1,288 +1,291 @@
/*
**************************************************************************
FUNCS.H -- Function Prototypes for EPANET Program
VERSION: 2.00
DATE: 5/8/00
9/25/00
10/25/00
12/29/00
3/1/01
2/14/08 (2.00.12)
AUTHOR: L. Rossman
US EPA - NRMRL
**************************************************************************
*/
/*****************************************************************/
/* Most float arguments have been changed to double - 7/3/07 */
/*****************************************************************/
/* ------- EPANET.C --------------------*/
/*
** NOTE: The exportable functions that can be called
** via the DLL are prototyped in TOOLKIT.H.
*/
#ifndef FUNCS_H
#define FUNCS_H
void initpointers(void); /* Initializes pointers */
int allocdata(void); /* Allocates memory */
void freeTmplist(STmplist *); /* Frees items in linked list */
void freeFloatlist(SFloatlist *); /* Frees list of floats */
void freedata(void); /* Frees allocated memory */
int openfiles(char *,char *,char *); /* Opens input & report files */
int openhydfile(void); /* Opens hydraulics file */
int openoutfile(void); /* Opens binary output file */
int strcomp(char *, char *); /* Compares two strings */
char* getTmpName(char* fname); /* Gets temporary file name */ //(2.00.12 - LR)
double interp(int, double *, /* Interpolates a data curve */
double *, double);
int findnode(char *); /* Finds node's index from ID */
int findlink(char *); /* Finds link's index from ID */
char* geterrmsg(int); /* Gets text of error message */
void errmsg(int); /* Reports program error */
void writecon(char *); /* Writes text to console */
void writewin(char *); /* Passes text to calling app */
/* ------- INPUT1.C --------------------*/
int getdata(void); /* Gets network data */
void setdefaults(void); /* Sets default values */
void initreport(void); /* Initializes report options */
void adjustdata(void); /* Adjusts input data */
int inittanks(void); /* Initializes tank levels */
void initunits(void); /* Determines reporting units */
void convertunits(void); /* Converts data to std. units*/
/* -------- INPUT2.C -------------------*/
int netsize(void); /* Determines network size */
int readdata(void); /* Reads in network data */
int newline(int, char *); /* Processes new line of data */
int addnodeID(int, char *); /* Adds node ID to data base */
int addlinkID(int, char *); /* Adds link ID to data base */
int addpattern(char *); /* Adds pattern to data base */
int addcurve(char *); /* Adds curve to data base */
STmplist *findID(char *, STmplist *); /* Locates ID on linked list */
int unlinked(void); /* Checks for unlinked nodes */
int getpumpparams(void); /* Computes pump curve coeffs.*/
int getpatterns(void); /* Gets pattern data from list*/
int getcurves(void); /* Gets curve data from list */
int findmatch(char *,char *[]); /* Finds keyword in line */
int match(char *, char *); /* Checks for word match */
int gettokens(char *); /* Tokenizes input line */
int getfloat(char *, double *); /* Converts string to double */
double hour(char *, char *); /* Converts time to hours */
int setreport(char *); /* Processes reporting command*/
void inperrmsg(int,int,char *); /* Input error message */
/* ---------- INPUT3.C -----------------*/
int juncdata(void); /* Processes junction data */
int tankdata(void); /* Processes tank data */
int pipedata(void); /* Processes pipe data */
int pumpdata(void); /* Processes pump data */
int valvedata(void); /* Processes valve data */
int patterndata(void); /* Processes pattern data */
int curvedata(void); /* Processes curve data */
int coordata(void); /* Processes coordinate data */
int demanddata(void); /* Processes demand data */
int controldata(void); /* Processes simple controls */
int energydata(void); /* Processes energy data */
int sourcedata(void); /* Processes source data */
int emitterdata(void); /* Processes emitter data */
int qualdata(void); /* Processes quality data */
int reactdata(void); /* Processes reaction data */
int mixingdata(void); /* Processes tank mixing data */
int statusdata(void); /* Processes link status data */
int reportdata(void); /* Processes report options */
int timedata(void); /* Processes time options */
int optiondata(void); /* Processes analysis options */
int optionchoice(int); /* Processes option choices */
int optionvalue(int); /* Processes option values */
int getpumpcurve(int); /* Constructs a pump curve */
int powercurve(double, double, double,/* Coeffs. of power pump curve*/
double, double, double *,
double *, double *);
int valvecheck(int, int, int); /* Checks valve placement */
void changestatus(int, char, double); /* Changes status of a link */
/* -------------- RULES.C --------------*/
void initrules(void); /* Initializes rule base */
void addrule(char *); /* Adds rule to rule base */
int allocrules(void); /* Allocates memory for rule */
int ruledata(void); /* Processes rule input data */
int checkrules(long); /* Checks all rules */
void freerules(void); /* Frees rule base memory */
/* ------------- REPORT.C --------------*/
int writereport(void); /* Writes formatted report */
void writelogo(void); /* Writes program logo */
void writesummary(void); /* Writes network summary */
void writehydstat(int,double); /* Writes hydraulic status */
void writeenergy(void); /* Writes energy usage */
int writeresults(void); /* Writes node/link results */
void writeheader(int,int); /* Writes heading on report */
void writeline(char *); /* Writes line to report file */
void writerelerr(int, double); /* Writes convergence error */
void writestatchange(int,char,char); /* Writes link status change */
void writecontrolaction(int, int); /* Writes control action taken*/
void writeruleaction(int, char *); /* Writes rule action taken */
int writehydwarn(int,double); /* Writes hydraulic warnings */
void writehyderr(int); /* Writes hydraulic error msg.*/
int disconnected(void); /* Checks for disconnections */
void marknodes(int, int *, char *); /* Identifies connected nodes */
void getclosedlink(int, char *); /* Finds a disconnecting link */
void writelimits(int,int); /* Writes reporting limits */
int checklimits(double *,int,int); /* Checks variable limits */
void writetime(char *); /* Writes current clock time */
char *clocktime(char *, long); /* Converts time to hrs:min */
char *fillstr(char *, char, int); /* Fills string with character*/
int getnodetype(int); /* Determines node type */
/* --------- HYDRAUL.C -----------------*/
int openhyd(void); /* Opens hydraulics solver */
/*** Updated 3/1/01 ***/
void inithyd(int); /* Re-sets initial conditions */
int runhyd(long *); /* Solves 1-period hydraulics */
int nexthyd(long *); /* Moves to next time period */
void closehyd(void); /* Closes hydraulics solver */
int allocmatrix(void); /* Allocates matrix coeffs. */
void freematrix(void); /* Frees matrix coeffs. */
void initlinkflow(int, char, double); /* Initializes link flow */
void setlinkflow(int, double); /* Sets link flow via headloss*/
void setlinkstatus(int, char, char *, /* Sets link status */
double *);
void setlinksetting(int, double, /* Sets pump/valve setting */
char *, double *);
void resistance(int); /* Computes resistance coeff. */
void demands(void); /* Computes current demands */
int controls(void); /* Controls link settings */
long timestep(void); /* Computes new time step */
void tanktimestep(long *); /* Time till tanks fill/drain */
void controltimestep(long *); /* Time till control action */
void ruletimestep(long *); /* Time till rule action */
void addenergy(long); /* Accumulates energy usage */
void getenergy(int, double *, double *); /* Computes link energy use */
void tanklevels(long); /* Computes new tank levels */
double tankvolume(int,double); /* Finds tank vol. from grade */
double tankgrade(int,double); /* Finds tank grade from vol. */
int netsolve(int *,double *); /* Solves network equations */
int badvalve(int); /* Checks for bad valve */
int valvestatus(void); /* Updates valve status */
int linkstatus(void); /* Updates link status */
char cvstatus(char,double,double); /* Updates CV status */
char pumpstatus(int,double); /* Updates pump status */
char prvstatus(int,char,double, /* Updates PRV status */
double,double);
char psvstatus(int,char,double, /* Updates PSV status */
double,double);
char fcvstatus(int,char,double, /* Updates FCV status */
double);
void tankstatus(int,int,int); /* Checks if tank full/empty */
int pswitch(void); /* Pressure switch controls */
double newflows(void); /* Updates link flows */
void newcoeffs(void); /* Computes matrix coeffs. */
void linkcoeffs(void); /* Computes link coeffs. */
void nodecoeffs(void); /* Computes node coeffs. */
void valvecoeffs(void); /* Computes valve coeffs. */
void pipecoeff(int); /* Computes pipe coeff. */
double DWcoeff(int, double *); /* Computes D-W coeff. */
void pumpcoeff(int); /* Computes pump coeff. */
/*** Updated 10/25/00 ***/
/*** Updated 12/29/00 ***/
void curvecoeff(int,double,double *, /* Computes curve coeffs. */
double *);
void gpvcoeff(int); /* Computes GPV coeff. */
void pbvcoeff(int); /* Computes PBV coeff. */
void tcvcoeff(int); /* Computes TCV coeff. */
void prvcoeff(int,int,int); /* Computes PRV coeff. */
void psvcoeff(int,int,int); /* Computes PSV coeff. */
void fcvcoeff(int,int,int); /* Computes FCV coeff. */
void emittercoeffs(void); /* Computes emitter coeffs. */
double emitflowchange(int); /* Computes new emitter flow */
/* ----------- SMATRIX.C ---------------*/
int createsparse(void); /* Creates sparse matrix */
int allocsparse(void); /* Allocates matrix memory */
void freesparse(void); /* Frees matrix memory */
int buildlists(int); /* Builds adjacency lists */
int paralink(int, int, int); /* Checks for parallel links */
void xparalinks(void); /* Removes parallel links */
void freelists(void); /* Frees adjacency lists */
void countdegree(void); /* Counts links at each node */
int reordernodes(void); /* Finds a node re-ordering */
int mindegree(int, int); /* Finds min. degree node */
int growlist(int); /* Augments adjacency list */
int newlink(Padjlist); /* Adds fill-ins for a node */
int linked(int, int); /* Checks if 2 nodes linked */
int addlink(int, int, int); /* Creates new fill-in */
int storesparse(int); /* Stores sparse matrix */
int ordersparse(int); /* Orders matrix storage */
void transpose(int,int *,int *, /* Transposes sparse matrix */
int *,int *,int *,int *,int *);
int linsolve(int, double *, double *, /* Solution of linear eqns. */
double *); /* via Cholesky factorization */
/* ----------- QUALITY.C ---------------*/
int openqual(void); /* Opens WQ solver system */
void initqual(void); /* Initializes WQ solver */
int runqual(long *); /* Gets current WQ results */
int nextqual(long *); /* Updates WQ by hyd.timestep */
int stepqual(long *); /* Updates WQ by WQ time step */
int closequal(void); /* Closes WQ solver system */
int gethyd(long *, long *); /* Gets next hyd. results */
char setReactflag(void); /* Checks for reactive chem. */
void transport(long); /* Transports mass in network */
void initsegs(void); /* Initializes WQ segments */
void reorientsegs(void); /* Re-orients WQ segments */
void updatesegs(long); /* Updates quality in segments*/
void removesegs(int); /* Removes a WQ segment */
void addseg(int,double,double); /* Adds a WQ segment to pipe */
void accumulate(long); /* Sums mass flow into node */
void updatenodes(long); /* Updates WQ at nodes */
void sourceinput(long); /* Computes source inputs */
void release(long); /* Releases mass from nodes */
void updatetanks(long); /* Updates WQ in tanks */
void updatesourcenodes(long); /* Updates WQ at source nodes */
void tankmix1(int, long); /* Complete mix tank model */
void tankmix2(int, long); /* 2-compartment tank model */
void tankmix3(int, long); /* FIFO tank model */
void tankmix4(int, long); /* LIFO tank model */
double sourcequal(Psource); /* Finds WQ input from source */
double avgqual(int); /* Finds avg. quality in pipe */
void ratecoeffs(void); /* Finds wall react. coeffs. */
double piperate(int); /* Finds wall react. coeff. */
double pipereact(int,double,double,long);/* Reacts water in a pipe */
double tankreact(double,double,double,
long); /* Reacts water in a tank */
double bulkrate(double,double,double); /* Finds bulk reaction rate */
double wallrate(double,double,double,double);/* Finds wall reaction rate */
/* ------------ OUTPUT.C ---------------*/
int savenetdata(void); /* Saves basic data to file */
int savehyd(long *); /* Saves hydraulic solution */
int savehydstep(long *); /* Saves hydraulic timestep */
int saveenergy(void); /* Saves energy usage */
int readhyd(long *); /* Reads hydraulics from file */
int readhydstep(long *); /* Reads time step from file */
int saveoutput(void); /* Saves results to file */
int nodeoutput(int, REAL4 *, double); /* Saves node results to file */
int linkoutput(int, REAL4 *, double); /* Saves link results to file */
int savefinaloutput(void); /* Finishes saving output */
int savetimestat(REAL4 *, char); /* Saves time stats to file */
int savenetreacts(double, double,
double, double); /* Saves react. rates to file */
int saveepilog(void); /* Saves output file epilog */
/* ------------ INPFILE.C --------------*/
int saveinpfile(char *); /* Saves network to text file */
#endif
/*
**************************************************************************
FUNCS.H -- Function Prototypes for EPANET Program
VERSION: 2.00
DATE: 5/8/00
9/25/00
10/25/00
12/29/00
3/1/01
2/14/08 (2.00.12)
AUTHOR: L. Rossman
US EPA - NRMRL
**************************************************************************
*/
/*****************************************************************/
/* Most float arguments have been changed to double - 7/3/07 */
/*****************************************************************/
/* ------- EPANET.C --------------------*/
/*
** NOTE: The exportable functions that can be called
** via the DLL are prototyped in TOOLKIT.H.
*/
#ifndef FUNCS_H
#define FUNCS_H
#include "types.h"
void initpointers(EN_Project *p); /* Initializes pointers */
int allocdata(EN_Project *p); /* Allocates memory */
void freeTmplist(STmplist *); /* Frees items in linked list */
void freeFloatlist(SFloatlist *); /* Frees list of floats */
void freedata(EN_Project *p); /* Frees allocated memory */
int openfiles(EN_Project *p, char *,char *,char *); /* Opens input & report files */
int openhydfile(EN_Project *p); /* Opens hydraulics file */
int openoutfile(EN_Project *p); /* Opens binary output file */
int strcomp(char *, char *); /* Compares two strings */
char* getTmpName(EN_Project *p, char* fname); /* Gets temporary file name */
double interp(int, double *,double *, double); /* Interpolates a data curve */
int findnode(EN_Network *n, char *); /* Finds node's index from ID */
int findlink(EN_Network *n, char *); /* Finds link's index from ID */
int findtank(EN_Network *n, int); /* Find tank index from node index */ // (AH)
int findvalve(EN_Network *n, int); /* Find valve index from node index */ // (AH)
int findpump(EN_Network *n, int); /* Find pump index from node index */ // (AH)
char *geterrmsg(int errcode, char *msg); /* Gets text of error message */
void errmsg(EN_Project *p, int); /* Reports program error */
void writecon(char *); /* Writes text to console */
void writewin(void (*vp)(char *), char *); /* Passes text to calling app */
/* ------- INPUT1.C --------------------*/
int getdata(EN_Project *pr); /* Gets network data */
void setdefaults(EN_Project *pr); /* Sets default values */
void initreport(report_options_t *r); /* Initializes report options */
void adjustdata(EN_Project *pr); /* Adjusts input data */
int inittanks(EN_Project *pr); /* Initializes tank levels */
void initunits(EN_Project *pr); /* Determines reporting units */
void convertunits(EN_Project *pr); /* Converts data to std. units*/
/* -------- INPUT2.C -------------------*/
int netsize(EN_Project *pr); /* Determines network size */
int readdata(EN_Project *pr); /* Reads in network data */
int newline(EN_Project *pr, int, char *); /* Processes new line of data */
int addnodeID(EN_Network *n, int, char *); /* Adds node ID to data base */
int addlinkID(EN_Network *n, int, char *); /* Adds link ID to data base */
int addpattern(parser_data_t *par, char *); /* Adds pattern to data base */
int addcurve(parser_data_t *par, char *); /* Adds curve to data base */
STmplist *findID(char *, STmplist *); /* Locates ID on linked list */
int unlinked(EN_Project *pr); /* Checks for unlinked nodes */
int getpumpparams(EN_Project *pr); /* Computes pump curve coeffs.*/
int getpatterns(EN_Project *pr); /* Gets pattern data from list*/
int getcurves(EN_Project *pr); /* Gets curve data from list */
int findmatch(char *, char *[]); /* Finds keyword in line */
int match(const char *, const char *); /* Checks for word match */
int gettokens(char *s, char** Tok, int maxToks, char *comment); /* Tokenizes input line */
int getfloat(char *, double *); /* Converts string to double */
double hour(char *, char *); /* Converts time to hours */
int setreport(EN_Project *pr, char *); /* Processes reporting command*/
void inperrmsg(EN_Project *pr, int,int,char *); /* Input error message */
/* ---------- INPUT3.C -----------------*/
int juncdata(EN_Project *pr); /* Processes junction data */
int tankdata(EN_Project *pr); /* Processes tank data */
int pipedata(EN_Project *pr); /* Processes pipe data */
int pumpdata(EN_Project *pr); /* Processes pump data */
int valvedata(EN_Project *pr); /* Processes valve data */
int patterndata(EN_Project *pr); /* Processes pattern data */
int curvedata(EN_Project *pr); /* Processes curve data */
int coordata(EN_Project *pr); /* Processes coordinate data */
int demanddata(EN_Project *pr); /* Processes demand data */
int controldata(EN_Project *pr); /* Processes simple controls */
int energydata(EN_Project *pr); /* Processes energy data */
int sourcedata(EN_Project *pr); /* Processes source data */
int emitterdata(EN_Project *pr); /* Processes emitter data */
int qualdata(EN_Project *pr); /* Processes quality data */
int reactdata(EN_Project *pr); /* Processes reaction data */
int mixingdata(EN_Project *pr); /* Processes tank mixing data */
int statusdata(EN_Project *pr); /* Processes link status data */
int reportdata(EN_Project *pr); /* Processes report options */
int timedata(EN_Project *pr); /* Processes time options */
int optiondata(EN_Project *pr); /* Processes analysis options */
int optionchoice(EN_Project *pr, int); /* Processes option choices */
int optionvalue(EN_Project *pr, int); /* Processes option values */
int getpumpcurve(EN_Project *pr, int); /* Constructs a pump curve */
int powercurve(double, double, double,/* Coeffs. of power pump curve*/
double, double, double *,
double *, double *);
int valvecheck(EN_Project *pr, int, int, int); /* Checks valve placement */
void changestatus(EN_Network *net, int, StatType, double); /* Changes status of a link */
/* -------------- RULES.C --------------*/
void initrules(rules_t *rules); /* Initializes rule base */
void addrule(parser_data_t *par, char *); /* Adds rule to rule base */
int allocrules(EN_Project *pr); /* Allocates memory for rule */
int ruledata(EN_Project *pr); /* Processes rule input data */
int checkrules(EN_Project *pr, long); /* Checks all rules */
void freerules(EN_Project *pr); /* Frees rule base memory */
/* ------------- REPORT.C --------------*/
int writereport(EN_Project *pr); /* Writes formatted report */
void writelogo(EN_Project *pr); /* Writes program logo */
void writesummary(EN_Project *pr); /* Writes network summary */
void writehydstat(EN_Project *pr, int,double); /* Writes hydraulic status */
void writeenergy(EN_Project *pr); /* Writes energy usage */
int writeresults(EN_Project *pr); /* Writes node/link results */
void writeheader(EN_Project *pr, int,int); /* Writes heading on report */
void writeline(EN_Project *pr, char *); /* Writes line to report file */
void writerelerr(EN_Project *pr, int, double); /* Writes convergence error */
void writestatchange(EN_Project *pr, int,char,char); /* Writes link status change */
void writecontrolaction(EN_Project *pr, int, int); /* Writes control action taken*/
void writeruleaction(EN_Project *pr, int, char *); /* Writes rule action taken */
int writehydwarn(EN_Project *pr, int,double); /* Writes hydraulic warnings */
void writehyderr(EN_Project *pr, int); /* Writes hydraulic error msg.*/
int disconnected(EN_Project *pr); /* Checks for disconnections */
void marknodes(EN_Project *pr, int, int *, char *); /* Identifies connected nodes */
void getclosedlink(EN_Project *pr, int, char *); /* Finds a disconnecting link */
void writelimits(EN_Project *pr, int,int); /* Writes reporting limits */
int checklimits(report_options_t *rep, double *,int,int); /* Checks variable limits */
void writetime(EN_Project *pr, char *); /* Writes current clock time */
char *clocktime(char *, long); /* Converts time to hrs:min */
char *fillstr(char *, char, int); /* Fills string with character*/
int getnodetype(EN_Network *net, int); /* Determines node type */
/* --------- HYDRAUL.C -----------------*/
int openhyd(EN_Project *pr); /* Opens hydraulics solver */
/*** Updated 3/1/01 ***/
void inithyd(EN_Project *pr, int initFlags); /* Re-sets initial conditions */
int runhyd(EN_Project *pr, long *); /* Solves 1-period hydraulics */
int nexthyd(EN_Project *pr, long *); /* Moves to next time period */
void closehyd(EN_Project *pr); /* Closes hydraulics solver */
int allocmatrix(EN_Project *pr); /* Allocates matrix coeffs. */
void freematrix(EN_Project *pr); /* Frees matrix coeffs. */
void initlinkflow(EN_Project *pr, int, char, double); /* Initializes link flow */
void setlinkflow(EN_Project *pr, int, double); /* Sets link flow via headloss*/
void setlinkstatus(EN_Project *pr, int, char, StatType *, double *); /* Sets link status */
void setlinksetting(EN_Project *pr, int, double, StatType *, double *); /* Sets pump/valve setting */
void resistance(EN_Project *pr, int); /* Computes resistance coeff. */
void demands(EN_Project *pr); /* Computes current demands */
int controls(EN_Project *pr); /* Controls link settings */
long timestep(EN_Project *pr); /* Computes new time step */
int tanktimestep(EN_Project *pr, long *); /* Time till tanks fill/drain */
void controltimestep(EN_Project *pr, long *); /* Time till control action */
void ruletimestep(EN_Project *pr, long *); /* Time till rule action */
void addenergy(EN_Project *pr, long); /* Accumulates energy usage */
void getenergy(EN_Project *pr, int, double *, double *); /* Computes link energy use */
void tanklevels(EN_Project *pr, long); /* Computes new tank levels */
double tankvolume(EN_Project *pr, int,double); /* Finds tank vol. from grade */
double tankgrade(EN_Project *pr, int,double); /* Finds tank grade from vol. */
int netsolve(EN_Project *pr, int *,double *); /* Solves network equations */
int badvalve(EN_Project *pr, int); /* Checks for bad valve */
int valvestatus(EN_Project *pr); /* Updates valve status */
int linkstatus(EN_Project *pr); /* Updates link status */
StatType cvstatus(EN_Project *pr, StatType,double,double); /* Updates CV status */
StatType pumpstatus(EN_Project *pr, int,double); /* Updates pump status */
StatType prvstatus(EN_Project *pr, int,StatType,double,double,double); /* Updates PRV status */
StatType psvstatus(EN_Project *pr, int,StatType,double,double,double); /* Updates PSV status */
StatType fcvstatus(EN_Project *pr, int,StatType,double,double); /* Updates FCV status */
void tankstatus(EN_Project *pr, int,int,int); /* Checks if tank full/empty */
int pswitch(EN_Project *pr); /* Pressure switch controls */
double newflows(EN_Project *pr); /* Updates link flows */
void newcoeffs(EN_Project *pr); /* Computes matrix coeffs. */
void linkcoeffs(EN_Project *pr); /* Computes link coeffs. */
void nodecoeffs(EN_Project *pr); /* Computes node coeffs. */
void valvecoeffs(EN_Project *pr); /* Computes valve coeffs. */
void pipecoeff(EN_Project *pr, int); /* Computes pipe coeff. */
double DWcoeff(EN_Project *pr, int, double *); /* Computes D-W coeff. */
void pumpcoeff(EN_Project *pr, int); /* Computes pump coeff. */
/*** Updated 10/25/00 ***/
/*** Updated 12/29/00 ***/
void curvecoeff(EN_Project *pr, int,double,double *,double *); /* Computes curve coeffs. */
void gpvcoeff(EN_Project *pr, int iLink); /* Computes GPV coeff. */
void pbvcoeff(EN_Project *pr, int iLink); /* Computes PBV coeff. */
void tcvcoeff(EN_Project *pr, int iLink); /* Computes TCV coeff. */
void prvcoeff(EN_Project *pr, int iLink, int n1, int n2); /* Computes PRV coeff. */
void psvcoeff(EN_Project *pr, int iLink, int n1, int n2); /* Computes PSV coeff. */
void fcvcoeff(EN_Project *pr, int iLink, int n1, int n2); /* Computes FCV coeff. */
void emittercoeffs(EN_Project *pr); /* Computes emitter coeffs. */
double emitflowchange(EN_Project *pr, int); /* Computes new emitter flow */
/* ----------- SMATRIX.C ---------------*/
int createsparse(EN_Project *pr); /* Creates sparse matrix */
int allocsparse(EN_Project *pr); /* Allocates matrix memory */
void freesparse(EN_Project *pr); /* Frees matrix memory */
int buildlists(EN_Project *pr, int); /* Builds adjacency lists */
int paralink(EN_Project *pr, int, int, int); /* Checks for parallel links */
void xparalinks(EN_Project *pr); /* Removes parallel links */
void freelists(EN_Project *pr); /* Frees adjacency lists */
void countdegree(EN_Project *pr); /* Counts links at each node */
int reordernodes(EN_Project *pr); /* Finds a node re-ordering */
int mindegree(solver_t *s, int, int); /* Finds min. degree node */
int growlist(EN_Project *pr, int); /* Augments adjacency list */
int newlink(EN_Project *pr, Padjlist); /* Adds fill-ins for a node */
int linked(EN_Network *net, int, int); /* Checks if 2 nodes linked */
int addlink(EN_Network *net, int, int, int); /* Creates new fill-in */
int storesparse(EN_Project *pr, int); /* Stores sparse matrix */
int ordersparse(hydraulics_t *h, int); /* Orders matrix storage */
void transpose(int,int *,int *, /* Transposes sparse matrix */
int *,int *,int *,int *,int *);
int linsolve(solver_t *s, int); /* via Cholesky factorization */
/* ----------- QUALITY.C ---------------*/
int openqual(EN_Project *pr); /* Opens WQ solver system */
void initqual(EN_Project *pr); /* Initializes WQ solver */
int runqual(EN_Project *pr, long *); /* Gets current WQ results */
int nextqual(EN_Project *pr, long *); /* Updates WQ by hyd.timestep */
int stepqual(EN_Project *pr, long *); /* Updates WQ by WQ time step */
int closequal(EN_Project *pr); /* Closes WQ solver system */
int gethyd(EN_Project *pr, long *, long *); /* Gets next hyd. results */
char setReactflag(EN_Project *pr); /* Checks for reactive chem. */
void transport(EN_Project *pr, long); /* Transports mass in network */
void initsegs(EN_Project *pr); /* Initializes WQ segments */
void reorientsegs(EN_Project *pr); /* Re-orients WQ segments */
void updatesegs(EN_Project *pr, long); /* Updates quality in segments*/
void removesegs(EN_Project *pr, int); /* Removes a WQ segment */
void addseg(EN_Project *pr, int,double,double); /* Adds a WQ segment to pipe */
void accumulate(EN_Project *pr, long); /* Sums mass flow into node */
void updatenodes(EN_Project *pr, long); /* Updates WQ at nodes */
void sourceinput(EN_Project *pr, long); /* Computes source inputs */
void release(EN_Project *pr, long); /* Releases mass from nodes */
void updatetanks(EN_Project *pr, long); /* Updates WQ in tanks */
void updatesourcenodes(EN_Project *pr, long); /* Updates WQ at source nodes */
void tankmix1(EN_Project *pr, int, long); /* Complete mix tank model */
void tankmix2(EN_Project *pr, int, long); /* 2-compartment tank model */
void tankmix3(EN_Project *pr, int, long); /* FIFO tank model */
void tankmix4(EN_Project *pr, int, long); /* LIFO tank model */
double sourcequal(EN_Project *pr, Psource); /* Finds WQ input from source */
double avgqual(EN_Project *pr, int); /* Finds avg. quality in pipe */
void ratecoeffs(EN_Project *pr); /* Finds wall react. coeffs. */
double piperate(EN_Project *pr, int); /* Finds wall react. coeff. */
double pipereact(EN_Project *pr, int,double,double,long);/* Reacts water in a pipe */
double tankreact(EN_Project *pr, double,double,double,long); /* Reacts water in a tank */
double bulkrate(EN_Project *pr, double,double,double); /* Finds bulk reaction rate */
double wallrate(EN_Project *pr, double,double,double,double);/* Finds wall reaction rate */
/* ------------ OUTPUT.C ---------------*/
int savenetdata(EN_Project *pr); /* Saves basic data to file */
int savehyd(EN_Project *pr, long *); /* Saves hydraulic solution */
int savehydstep(EN_Project *pr, long *); /* Saves hydraulic timestep */
int saveenergy(EN_Project *pr); /* Saves energy usage */
int readhyd(EN_Project *pr, long *); /* Reads hydraulics from file */
int readhydstep(FILE *hydFile, long *); /* Reads time step from file */
int saveoutput(EN_Project *pr); /* Saves results to file */
int nodeoutput(EN_Project *pr, int, REAL4 *, double); /* Saves node results to file */
int linkoutput(EN_Project *pr, int, REAL4 *, double); /* Saves link results to file */
int savefinaloutput(EN_Project *pr); /* Finishes saving output */
int savetimestat(EN_Project *pr, REAL4 *, HdrType); /* Saves time stats to file */
int savenetreacts(EN_Project *pr, double, double,double, double);
/* Saves react. rates to file */
int saveepilog(EN_Project *pr); /* Saves output file epilog */
/* ------------ INPFILE.C --------------*/
int saveinpfile(EN_Project *pr, char *); /* Saves network to text file */
#endif

View File

@@ -36,6 +36,7 @@ unsigned int _enHash(char *str)
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
}
retHash = hash % ENHASHTABLEMAXSIZE;
return retHash;
}
@@ -72,13 +73,54 @@ int ENHashTableInsert(ENHashTable *ht, char *key, int data)
return(1);
}
int ENHashTableFind(ENHashTable *ht, char *key)
/* Abel Heinsbroek: Added function to update the hash table value for a given key */
int ENHashTableUpdate(ENHashTable *ht, char *key, int new_data)
{
unsigned int i = _enHash(key);
ENHashEntry *entry;
if ( i >= ENHASHTABLEMAXSIZE ) {
return(NOTFOUND);
}
entry = ht[i];
while (entry != NULL)
{
if ( strcmp(entry->key,key) == 0 ) {
entry->data = new_data;
return(1);
}
entry = entry->next;
}
return(NOTFOUND);
}
int ENHashTableDelete(ENHashTable *ht, char *key) {
unsigned int i = _enHash(key);
ENHashEntry *entry;
if ( i >= ENHASHTABLEMAXSIZE ) {
return(NOTFOUND);
}
entry = ht[i];
while (entry != NULL)
{
if (strcmp(entry->key, key) == 0) {
entry->key = "";
return(1);
}
entry = entry->next;
}
return(NOTFOUND);
}
int ENHashTableFind(ENHashTable *ht, char *key)
{
unsigned int i = _enHash(key);
ENHashEntry *entry;
if ( i >= ENHASHTABLEMAXSIZE ) {
return(NOTFOUND);
}
entry = ht[i];
while (entry != NULL)
{

View File

@@ -24,5 +24,7 @@ int ENHashTableInsert(ENHashTable *, char *, int);
int ENHashTableFind(ENHashTable *, char *);
char *ENHashTableFindKey(ENHashTable *, char *);
void ENHashTableFree(ENHashTable *);
int ENHashTableUpdate(ENHashTable *ht, char *key, int new_data);
int ENHashTableDelete(ENHashTable *ht, char *key);
#endif
#endif

File diff suppressed because it is too large Load Diff

1371
src/inpfile.c Executable file → Normal file

File diff suppressed because it is too large Load Diff

1361
src/input1.c Executable file → Normal file

File diff suppressed because it is too large Load Diff

2028
src/input2.c Executable file → Normal file

File diff suppressed because it is too large Load Diff

4090
src/input3.c Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,205 +1,209 @@
/* mempool.c
**
** A simple fast memory allocation package.
**
** By Steve Hill in Graphics Gems III, David Kirk (ed.),
** Academic Press, Boston, MA, 1992
**
** Modified by Lew Rossman, 8/13/94.
**
** AllocInit() - create an alloc pool, returns the old pool handle
** Alloc() - allocate memory
** AllocReset() - reset the current pool
** AllocSetPool() - set the current pool
** AllocFree() - free the memory used by the current pool.
**
*/
#include <stdlib.h>
#ifndef __APPLE__
#include <malloc.h>
#endif
#include "mempool.h"
/*
** ALLOC_BLOCK_SIZE - adjust this size to suit your installation - it
** should be reasonably large otherwise you will be mallocing a lot.
*/
#define ALLOC_BLOCK_SIZE 64000 /*(62*1024)*/
/*
** alloc_hdr_t - Header for each block of memory.
*/
typedef struct alloc_hdr_s
{
struct alloc_hdr_s *next; /* Next Block */
char *block, /* Start of block */
*free, /* Next free in block */
*end; /* block + block size */
} alloc_hdr_t;
/*
** alloc_root_t - Header for the whole pool.
*/
typedef struct alloc_root_s
{
alloc_hdr_t *first, /* First header in pool */
*current; /* Current header */
} alloc_root_t;
/*
** root - Pointer to the current pool.
*/
static alloc_root_t *root;
/*
** AllocHdr()
**
** Private routine to allocate a header and memory block.
*/
static alloc_hdr_t *AllocHdr(void);
static alloc_hdr_t * AllocHdr()
{
alloc_hdr_t *hdr;
char *block;
block = (char *) malloc(ALLOC_BLOCK_SIZE);
hdr = (alloc_hdr_t *) malloc(sizeof(alloc_hdr_t));
if (hdr == NULL || block == NULL) return(NULL);
hdr->block = block;
hdr->free = block;
hdr->next = NULL;
hdr->end = block + ALLOC_BLOCK_SIZE;
return(hdr);
}
/*
** AllocInit()
**
** Create a new memory pool with one block.
** Returns pointer to the new pool.
*/
DLLEXPORT alloc_handle_t * AllocInit()
{
alloc_handle_t *newpool;
root = (alloc_root_t *) malloc(sizeof(alloc_root_t));
if (root == NULL) return(NULL);
if ( (root->first = AllocHdr()) == NULL) return(NULL);
root->current = root->first;
newpool = (alloc_handle_t *) root;
return(newpool);
}
/*
** Alloc()
**
** Use as a direct replacement for malloc(). Allocates
** memory from the current pool.
*/
DLLEXPORT char *Alloc(long size)
{
alloc_hdr_t *hdr = root->current;
char *ptr;
/*
** Align to 4 byte boundary - should be ok for most machines.
** Change this if your machine has weird alignment requirements.
*/
size = (size + 3) & 0xfffffffc;
ptr = hdr->free;
hdr->free += size;
/* Check if the current block is exhausted. */
if (hdr->free >= hdr->end)
{
/* Is the next block already allocated? */
if (hdr->next != NULL)
{
/* re-use block */
hdr->next->free = hdr->next->block;
root->current = hdr->next;
}
else
{
/* extend the pool with a new block */
if ( (hdr->next = AllocHdr()) == NULL) return(NULL);
root->current = hdr->next;
}
/* set ptr to the first location in the next block */
ptr = root->current->free;
root->current->free += size;
}
/* Return pointer to allocated memory. */
return(ptr);
}
/*
** AllocSetPool()
**
** Change the current pool. Return the old pool.
*/
DLLEXPORT alloc_handle_t * AllocSetPool(alloc_handle_t *newpool)
{
alloc_handle_t *old = (alloc_handle_t *) root;
root = (alloc_root_t *) newpool;
return(old);
}
/*
** AllocReset()
**
** Reset the current pool for re-use. No memory is freed,
** so this is very fast.
*/
DLLEXPORT void AllocReset()
{
root->current = root->first;
root->current->free = root->current->block;
}
/*
** AllocFreePool()
**
** Free the memory used by the current pool.
** Don't use where AllocReset() could be used.
*/
DLLEXPORT void AllocFreePool()
{
alloc_hdr_t *tmp,
*hdr = root->first;
while (hdr != NULL)
{
tmp = hdr->next;
free((char *) hdr->block);
free((char *) hdr);
hdr = tmp;
}
free((char *) root);
root = NULL;
}
/* mempool.c
**
** A simple fast memory allocation package.
**
** By Steve Hill in Graphics Gems III, David Kirk (ed.),
** Academic Press, Boston, MA, 1992
**
** Modified by Lew Rossman, 8/13/94.
**
** AllocInit() - create an alloc pool, returns the old pool handle
** Alloc() - allocate memory
** AllocReset() - reset the current pool
** AllocSetPool() - set the current pool
** AllocFree() - free the memory used by the current pool.
**
*/
#include <stdlib.h>
#ifndef __APPLE__
#include <malloc.h>
#endif
#include "mempool.h"
/*
** ALLOC_BLOCK_SIZE - adjust this size to suit your installation - it
** should be reasonably large otherwise you will be mallocing a lot.
*/
#define ALLOC_BLOCK_SIZE 64000 /*(62*1024)*/
/*
** alloc_hdr_t - Header for each block of memory.
*/
typedef struct alloc_hdr_s
{
struct alloc_hdr_s *next; /* Next Block */
char *block, /* Start of block */
*free, /* Next free in block */
*end; /* block + block size */
} alloc_hdr_t;
/*
** alloc_root_t - Header for the whole pool.
*/
typedef struct alloc_root_s
{
alloc_hdr_t *first, /* First header in pool */
*current; /* Current header */
} alloc_root_t;
/*
** root - Pointer to the current pool.
*/
static alloc_root_t *root;
/*
** AllocHdr()
**
** Private routine to allocate a header and memory block.
*/
static alloc_hdr_t *AllocHdr(void);
static alloc_hdr_t * AllocHdr()
{
alloc_hdr_t *hdr;
char *block;
block = (char *) malloc(ALLOC_BLOCK_SIZE);
hdr = (alloc_hdr_t *) malloc(sizeof(alloc_hdr_t));
if (hdr == NULL || block == NULL) return(NULL);
hdr->block = block;
hdr->free = block;
hdr->next = NULL;
hdr->end = block + ALLOC_BLOCK_SIZE;
return(hdr);
}
/*
** AllocInit()
**
** Create a new memory pool with one block.
** Returns pointer to the new pool.
*/
DLLEXPORT alloc_handle_t * AllocInit()
{
alloc_handle_t *newpool;
root = (alloc_root_t *) malloc(sizeof(alloc_root_t));
if (root == NULL) {
return(NULL);
}
if ( (root->first = AllocHdr()) == NULL) {
return(NULL);
}
root->current = root->first;
newpool = (alloc_handle_t *) root;
return(newpool);
}
/*
** Alloc()
**
** Use as a direct replacement for malloc(). Allocates
** memory from the current pool.
*/
DLLEXPORT char *Alloc(long size)
{
alloc_hdr_t *hdr = root->current;
char *ptr;
/*
** Align to 4 byte boundary - should be ok for most machines.
** Change this if your machine has weird alignment requirements.
*/
size = (size + 3) & 0xfffffffc;
ptr = hdr->free;
hdr->free += size;
/* Check if the current block is exhausted. */
if (hdr->free >= hdr->end)
{
/* Is the next block already allocated? */
if (hdr->next != NULL)
{
/* re-use block */
hdr->next->free = hdr->next->block;
root->current = hdr->next;
}
else
{
/* extend the pool with a new block */
if ( (hdr->next = AllocHdr()) == NULL) return(NULL);
root->current = hdr->next;
}
/* set ptr to the first location in the next block */
ptr = root->current->free;
root->current->free += size;
}
/* Return pointer to allocated memory. */
return(ptr);
}
/*
** AllocSetPool()
**
** Change the current pool. Return the old pool.
*/
DLLEXPORT alloc_handle_t * AllocSetPool(alloc_handle_t *newpool)
{
alloc_handle_t *old = (alloc_handle_t *) root;
root = (alloc_root_t *) newpool;
return(old);
}
/*
** AllocReset()
**
** Reset the current pool for re-use. No memory is freed,
** so this is very fast.
*/
DLLEXPORT void AllocReset()
{
root->current = root->first;
root->current->free = root->current->block;
}
/*
** AllocFreePool()
**
** Free the memory used by the current pool.
** Don't use where AllocReset() could be used.
*/
DLLEXPORT void AllocFreePool()
{
alloc_hdr_t *tmp,
*hdr = root->first;
while (hdr != NULL)
{
tmp = hdr->next;
free((char *) hdr->block);
free((char *) hdr);
hdr = tmp;
}
free((char *) root);
root = NULL;
}

View File

@@ -15,7 +15,7 @@
#ifdef __cplusplus
#define DLLEXPORT extern "C" __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllexport) __stdcall
#define DLLEXPORT __declspec(dllexport) __stdcall
#endif
#elif defined(CYGWIN)
#define DLLEXPORT __stdcall
@@ -34,10 +34,10 @@ typedef struct
long dummy;
} alloc_handle_t;
DLLEXPORT alloc_handle_t *AllocInit(void);
DLLEXPORT char *Alloc(long);
DLLEXPORT alloc_handle_t *AllocSetPool(alloc_handle_t *);
DLLEXPORT void AllocReset(void);
DLLEXPORT void AllocFreePool(void);
alloc_handle_t *AllocInit(void);
char *Alloc(long);
alloc_handle_t *AllocSetPool(alloc_handle_t *);
void AllocReset(void);
void AllocFreePool(void);
#endif

1546
src/output.c Executable file → Normal file

File diff suppressed because it is too large Load Diff

3638
src/quality.c Executable file → Normal file

File diff suppressed because it is too large Load Diff

2595
src/report.c Executable file → Normal file

File diff suppressed because it is too large Load Diff

2573
src/rules.c Executable file → Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1020
src/text.h

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,211 +1,16 @@
/*
************************************************************************
Global Variables for EPANET Program
VERSION: 2.00
DATE: 5/8/00
6/24/02
2/14/08 (2.00.12)
AUTHOR: L. Rossman
US EPA - NRMRL
************************************************************************
*/
#ifndef VARS_H
#define VARS_H
#include <stdio.h>
#include "hash.h"
EXTERN FILE *InFile, /* Input file pointer */
*OutFile, /* Output file pointer */
*RptFile, /* Report file pointer */
*HydFile, /* Hydraulics file pointer */
*TmpOutFile; /* Temporary file handle */
EXTERN long HydOffset, /* Hydraulics file byte offset */
OutOffset1, /* 1st output file byte offset */
OutOffset2; /* 2nd output file byte offset */
EXTERN char Msg[MAXMSG+1], /* Text of output message */
InpFname[MAXFNAME+1], /* Input file name */
Rpt1Fname[MAXFNAME+1], /* Primary report file name */
Rpt2Fname[MAXFNAME+1], /* Secondary report file name */
HydFname[MAXFNAME+1], /* Hydraulics file name */
OutFname[MAXFNAME+1], /* Binary output file name */
MapFname[MAXFNAME+1], /* Map file name */
TmpFname[MAXFNAME+1], /* Temporary file name */ //(2.00.12 - LR)
TmpDir[MAXFNAME+1], /* Temporary directory name */ //(2.00.12 - LR)
Title[MAXTITLE][MAXMSG+1], /* Problem title */
ChemName[MAXID+1], /* Name of chemical */
ChemUnits[MAXID+1], /* Units of chemical */
DefPatID[MAXID+1], /* Default demand pattern ID */
/*** Updated 6/24/02 ***/
Atime[13], /* Clock time (hrs:min:sec) */
Outflag, /* Output file flag */ //(2.00.12 - LR)
Hydflag, /* Hydraulics flag */
Qualflag, /* Water quality flag */
Reactflag, /* Reaction indicator */ //(2.00.12 - LR)
Unitsflag, /* Unit system flag */
Flowflag, /* Flow units flag */
Pressflag, /* Pressure units flag */
Formflag, /* Hydraulic formula flag */
Rptflag, /* Report flag */
Summaryflag, /* Report summary flag */
Messageflag, /* Error/warning message flag */
Statflag, /* Status report flag */
Energyflag, /* Energy report flag */
Nodeflag, /* Node report flag */
Linkflag, /* Link report flag */
Tstatflag, /* Time statistics flag */
Warnflag, /* Warning flag */
Openflag, /* Input processed flag */
OpenHflag, /* Hydraul. system opened flag */
SaveHflag, /* Hydraul. results saved flag */
OpenQflag, /* Quality system opened flag */
SaveQflag, /* Quality results saved flag */
Saveflag, /* General purpose save flag */
Coordflag; /* Load coordinates flag */
EXTERN int MaxNodes, /* Node count from input file */
MaxLinks, /* Link count from input file */
MaxJuncs, /* Junction count */
MaxPipes, /* Pipe count */
MaxTanks, /* Tank count */
MaxPumps, /* Pump count */
MaxValves, /* Valve count */
MaxControls, /* Control count */
MaxRules, /* Rule count */
MaxPats, /* Pattern count */
MaxCurves, /* Curve count */
Nnodes, /* Number of network nodes */
Ntanks, /* Number of tanks */
Njuncs, /* Number of junction nodes */
Nlinks, /* Number of network links */
Npipes, /* Number of pipes */
Npumps, /* Number of pumps */
Nvalves, /* Number of valves */
Ncontrols, /* Number of simple controls */
Nrules, /* Number of control rules */
Npats, /* Number of time patterns */
Ncurves, /* Number of data curves */
Nperiods, /* Number of reporting periods */
Ncoeffs, /* Number of non-0 matrix coeffs*/
DefPat, /* Default demand pattern */
Epat, /* Energy cost time pattern */
MaxIter, /* Max. hydraulic trials */
ExtraIter, /* Extra hydraulic trials */
TraceNode, /* Source node for flow tracing */
PageSize, /* Lines/page in output report */
CheckFreq, /* Hydraulics solver parameter */
MaxCheck; /* Hydraulics solver parameter */
EXTERN double Ucf[MAXVAR], /* Unit conversion factors */
Ctol, /* Water quality tolerance */
Htol, /* Hydraulic head tolerance */
Qtol, /* Flow rate tolerance */
RQtol, /* Flow resistance tolerance */
Hexp, /* Exponent in headloss formula */
Qexp, /* Exponent in orifice formula */
Dmult, /* Demand multiplier */
Hacc, /* Hydraulics solution accuracy */
DampLimit, /* Solution damping threshold */ //(2.00.12 - LR)
BulkOrder, /* Bulk flow reaction order */
WallOrder, /* Pipe wall reaction order */
TankOrder, /* Tank reaction order */
Kbulk, /* Global bulk reaction coeff. */
Kwall, /* Global wall reaction coeff. */
Climit, /* Limiting potential quality */
Rfactor, /* Roughness-reaction factor */
Diffus, /* Diffusivity (sq ft/sec) */
Viscos, /* Kin. viscosity (sq ft/sec) */
SpGrav, /* Specific gravity */
Ecost, /* Base energy cost per kwh */
Dcost, /* Energy demand charge/kw/day */
Epump, /* Global pump efficiency */
Emax, /* Peak energy usage */
Dsystem, /* Total system demand */
Wbulk, /* Avg. bulk reaction rate */
Wwall, /* Avg. wall reaction rate */
Wtank, /* Avg. tank reaction rate */
Wsource; /* Avg. mass inflow */
EXTERN long Tstart, /* Starting time of day (sec) */
Hstep, /* Nominal hyd. time step (sec) */
Qstep, /* Quality time step (sec) */
Pstep, /* Time pattern time step (sec) */
Pstart, /* Starting pattern time (sec) */
Rstep, /* Reporting time step (sec) */
Rstart, /* Time when reporting starts */
Rtime, /* Next reporting time */
Htime, /* Current hyd. time (sec) */
Qtime, /* Current quality time (sec) */
Hydstep, /* Actual hydraulic time step */
Rulestep, /* Rule evaluation time step */
Dur; /* Duration of simulation (sec) */
EXTERN SField Field[MAXVAR]; /* Output reporting fields */
/* Array pointers not allocated and freed in same routine */
EXTERN char *LinkStatus, /* Link status */
*OldStat; /* Previous link/tank status */
EXTERN double *NodeDemand, /* Node actual demand */
*NodeQual, /* Node actual quality */
*E, /* Emitter flows */
*LinkSetting, /* Link settings */
*Q, /* Link flows */
*PipeRateCoeff, /* Pipe reaction rate */
*X, /* General purpose array */
*TempQual; /* General purpose array for water quality */
EXTERN double *NodeHead; /* Node heads */
EXTERN double *QTankVolumes;
EXTERN double *QLinkFlow;
EXTERN STmplist *Patlist; /* Temporary time pattern list */
EXTERN STmplist *Curvelist; /* Temporary list of curves */
EXTERN Spattern *Pattern; /* Time patterns */
EXTERN Scurve *Curve; /* Curve data */
EXTERN Scoord *Coord; /* Coordinate data */
EXTERN Snode *Node; /* Node data */
EXTERN Slink *Link; /* Link data */
EXTERN Stank *Tank; /* Tank data */
EXTERN Spump *Pump; /* Pump data */
EXTERN Svalve *Valve; /* Valve data */
EXTERN Scontrol *Control; /* Control data */
EXTERN ENHashTable *NodeHashTable, *LinkHashTable; /* Hash tables for ID labels */
EXTERN Padjlist *Adjlist; /* Node adjacency lists */
EXTERN double _relativeError;
EXTERN int _iterations; /* Info about hydraulic solution */
/*
** NOTE: Hydraulic analysis of the pipe network at a given point in time
** is done by repeatedly solving a linearized version of the
** equations for conservation of flow & energy:
**
** A*H = F
**
** where H = vector of heads (unknowns) at each node,
** F = vector of right-hand side coeffs.
** A = square matrix of coeffs.
** and both A and F are updated at each iteration until there is
** negligible change in pipe flows.
**
** Each row (or column) of A corresponds to a junction in the pipe
** network. Each link (pipe, pump or valve) in the network has a
** non-zero entry in the row-column of A that corresponds to its
** end points. This results in A being symmetric and very sparse.
** The following arrays are used to efficiently manage this sparsity:
*/
EXTERN double *Aii, /* Diagonal coeffs. of A */
*Aij, /* Non-zero, off-diagonal coeffs. of A */
*F; /* Right hand side coeffs. */
EXTERN double *P, /* Inverse headloss derivatives */
*Y; /* Flow correction factors */
EXTERN int *Order, /* Node-to-row of A */
*Row, /* Row-to-node of A */
*Ndx; /* Index of link's coeff. in Aij */
/*
** The following arrays store the positions of the non-zero coeffs.
** of the lower triangular portion of A whose values are stored in Aij:
*/
EXTERN int *XLNZ, /* Start position of each column in NZSUB */
*NZSUB, /* Row index of each coeff. in each column */
*LNZ; /* Position of each coeff. in Aij array */
#endif
/*
************************************************************************
Global Variables for EPANET Program
************************************************************************
*/
#ifndef VARS_H
#define VARS_H
#include <stdio.h>
#include "hash.h"
// this single global variable is used only when the library is called in "legacy mode"
// with the 2.1-style API.
EXTERN EN_Project *_defaultModel;
#endif

9
tests/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
# Ignore app description files generated for nrtest
apps/
# Ignore results generated during nrtest execution
benchmark/
# Except changes to reference benchmark
!benchmark/epanet-2012 # Results for EPANET 2.0.12 MSVC 2010 32-bit

View File

@@ -0,0 +1,7 @@
{
"name" : "epanet",
"version" : "2.0.11a",
"description" : "Windows, MS VC2005 or older, 32 Bit",
"setup_script" : "",
"exe" : "epanet2011a.exe"
}

View File

@@ -0,0 +1,7 @@
{
"name" : "epanet",
"version" : "2.0.12",
"description" : "Windows, MS VC 2010, 32 Bit",
"setup_script" : "",
"exe" : "./epanet2012.exe"
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
{
"duration": 0.87,
"max_memory_MB": 0.0
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
{
"duration": 1.045,
"max_memory_MB": 0.0
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
{
"duration": 0.246,
"max_memory_MB": 0.0
}

View File

@@ -0,0 +1,42 @@
{
"Application": {
"description": "Windows, MS VC 2010, 32 Bit",
"name": "epanet",
"version": "2.0.12"
},
"Tests": [
{
"description": "A simple example of modeling chlorine decay",
"error_msg": null,
"name": "Example 1",
"output_files": {
"example1.out": "epanet allclose",
"example1.rpt": "epanet report"
},
"passed": true,
"version": "1.0"
},
{
"description": "Example of modeling a 55-hour fluoride tracer study.",
"error_msg": null,
"name": "Example 2",
"output_files": {
"example2.out": "epanet allclose",
"example2.rpt": "epanet report"
},
"passed": true,
"version": "1.0"
},
{
"description": "Dual-source system example",
"error_msg": null,
"name": "Example 3",
"output_files": {
"example3.out": "epanet allclose",
"example3.rpt": "epanet report"
},
"passed": true,
"version": "1.0"
}
]
}

View File

@@ -0,0 +1,180 @@
[TITLE]
EPANET Example Network 1
A simple example of modeling chlorine decay. Both bulk and
wall reactions are included.
[JUNCTIONS]
;ID Elev Demand Pattern
10 710 0 ;
11 710 150 ;
12 700 150 ;
13 695 100 ;
21 700 150 ;
22 695 200 ;
23 690 150 ;
31 700 100 ;
32 710 100 ;
[RESERVOIRS]
;ID Head Pattern
9 800 ;
[TANKS]
;ID Elevation InitLevel MinLevel MaxLevel Diameter MinVol VolCurve
2 850 120 100 150 50.5 0 ;
[PIPES]
;ID Node1 Node2 Length Diameter Roughness MinorLoss Status
10 10 11 10530 18 100 0 Open ;
11 11 12 5280 14 100 0 Open ;
12 12 13 5280 10 100 0 Open ;
21 21 22 5280 10 100 0 Open ;
22 22 23 5280 12 100 0 Open ;
31 31 32 5280 6 100 0 Open ;
110 2 12 200 18 100 0 Open ;
111 11 21 5280 10 100 0 Open ;
112 12 22 5280 12 100 0 Open ;
113 13 23 5280 8 100 0 Open ;
121 21 31 5280 8 100 0 Open ;
122 22 32 5280 6 100 0 Open ;
[PUMPS]
;ID Node1 Node2 Parameters
9 9 10 HEAD 1 ;
[VALVES]
;ID Node1 Node2 Diameter Type Setting MinorLoss
[TAGS]
[DEMANDS]
;Junction Demand Pattern Category
[STATUS]
;ID Status/Setting
[PATTERNS]
;ID Multipliers
;Demand Pattern
1 1.0 1.2 1.4 1.6 1.4 1.2
1 1.0 0.8 0.6 0.4 0.6 0.8
[CURVES]
;ID X-Value Y-Value
;PUMP: Pump Curve for Pump 9
1 1500 250
[CONTROLS]
LINK 9 OPEN IF NODE 2 BELOW 110
LINK 9 CLOSED IF NODE 2 ABOVE 140
[RULES]
[ENERGY]
Global Efficiency 75
Global Price 0.0
Demand Charge 0.0
[EMITTERS]
;Junction Coefficient
[QUALITY]
;Node InitQual
10 0.5
11 0.5
12 0.5
13 0.5
21 0.5
22 0.5
23 0.5
31 0.5
32 0.5
9 1.0
2 1.0
[SOURCES]
;Node Type Quality Pattern
[REACTIONS]
;Type Pipe/Tank Coefficient
[REACTIONS]
Order Bulk 1
Order Tank 1
Order Wall 1
Global Bulk -.5
Global Wall -1
Limiting Potential 0.0
Roughness Correlation 0.0
[MIXING]
;Tank Model
[TIMES]
Duration 24:00
Hydraulic Timestep 1:00
Quality Timestep 0:05
Pattern Timestep 2:00
Pattern Start 0:00
Report Timestep 1:00
Report Start 0:00
Start ClockTime 12 am
Statistic None
[REPORT]
Status Yes
Summary No
Nodes All
Links All
[OPTIONS]
Units GPM
Headloss H-W
Specific Gravity 1.0
Viscosity 1.0
Trials 40
Accuracy 0.001
CHECKFREQ 2
MAXCHECK 10
;DAMPLIMIT 0
Unbalanced Continue 10
Pattern 1
Demand Multiplier 1.0
Emitter Exponent 0.5
Quality Chlorine mg/L
Diffusivity 1.0
Tolerance 0.01
[COORDINATES]
;Node X-Coord Y-Coord
10 20.00 70.00
11 30.00 70.00
12 50.00 70.00
13 70.00 70.00
21 30.00 40.00
22 50.00 40.00
23 70.00 40.00
31 30.00 10.00
32 50.00 10.00
9 10.00 70.00
2 50.00 90.00
[VERTICES]
;Link X-Coord Y-Coord
[LABELS]
;X-Coord Y-Coord Label & Anchor Node
6.99 73.63 "Source"
13.48 68.13 "Pump"
43.85 91.21 "Tank"
[BACKDROP]
DIMENSIONS 7.00 6.00 73.00 94.00
UNITS None
FILE
OFFSET 0.00 0.00
[END]

View File

@@ -0,0 +1,17 @@
{
"name": "Example 1",
"version": "1.0",
"description": "A simple example of modeling chlorine decay",
"args": [
"example1.inp",
"example1.rpt",
"example1.out"
],
"input_files": [
"example1.inp"
],
"output_files": {
"example1.rpt": "epanet report",
"example1.out": "epanet allclose"
}
}

View File

@@ -0,0 +1,80 @@
;Measured Fluoride for Net2
;Node Hour MG/L
11 2.50 1.02
11 5.38 0.87
11 8.30 0.70
11 11.75 1.01
11 13.02 0.62
11 14.48 0.26
11 17.43 0.17
11 20.30 0.20
11 23.35 0.90
11 27.00 0.13
11 29.67 0.13
11 33.70 0.54
11 35.40 0.90
11 38.30 0.17
11 41.62 0.10
11 44.42 0.12
11 47.25 0.71
11 51.00 0.13
11 53.27 0.58
19 0.25 1.04
19 2.75 1.04
19 5.70 1.08
19 8.60 1.00
19 12.00 0.81
19 13.25 0.95
19 14.73 1.02
19 17.77 1.01
19 20.52 0.87
19 23.53 0.28
19 27.17 0.98
19 29.87 0.85
19 33.92 0.12
19 35.67 0.17
19 38.48 0.64
19 42.08 0.79
19 44.68 0.87
19 47.50 0.16
19 51.17 0.56
19 53.45 0.70
25 0.58 1.04
3.00 1.00
5.87 1.03
8.80 1.00
12.25 1.02
13.50 0.88
14.97 0.36
18.15 0.91
20.75 0.92
23.73 0.94
27.42 0.19
30.08 0.12
34.12 0.83
35.87 0.82
38.67 0.72
42.40 0.76
44.92 0.78
47.75 0.87
51.50 0.42
53.75 0.48
34 2.67 1.03
5.50 1.04
8.45 0.98
11.87 1.01
13.15 1.02
14.62 1.04
17.60 1.02
20.42 1.02
23.43 1.00
27.08 1.02
29.75 0.94
33.82 0.89
35.53 0.75
38.40 0.80
41.85 0.84
44.55 0.92
47.42 0.91
51.08 0.81
53.37 0.47

View File

@@ -0,0 +1,310 @@
[TITLE]
EPANET Example Network 2
Example of modeling a 55-hour fluoride tracer study.
Measured fluoride data is contained in the file Net2-FL.dat
and should be registered with the project to produce a
Calibration Report (select Calibration Data from the Project
menu).
[JUNCTIONS]
;ID Elev Demand Pattern
1 50 -694.4 2 ;
2 100 8 ;
3 60 14 ;
4 60 8 ;
5 100 8 ;
6 125 5 ;
7 160 4 ;
8 110 9 ;
9 180 14 ;
10 130 5 ;
11 185 34.78 ;
12 210 16 ;
13 210 2 ;
14 200 2 ;
15 190 2 ;
16 150 20 ;
17 180 20 ;
18 100 20 ;
19 150 5 ;
20 170 19 ;
21 150 16 ;
22 200 10 ;
23 230 8 ;
24 190 11 ;
25 230 6 ;
27 130 8 ;
28 110 0 ;
29 110 7 ;
30 130 3 ;
31 190 17 ;
32 110 17 ;
33 180 1.5 ;
34 190 1.5 ;
35 110 0 ;
36 110 1 ;
[RESERVOIRS]
;ID Head Pattern
[TANKS]
;ID Elevation InitLevel MinLevel MaxLevel Diameter MinVol VolCurve
26 235 56.7 50 70 50 0 ;
[PIPES]
;ID Node1 Node2 Length Diameter Roughness MinorLoss Status
1 1 2 2400 12 100 0 Open ;
2 2 5 800 12 100 0 Open ;
3 2 3 1300 8 100 0 Open ;
4 3 4 1200 8 100 0 Open ;
5 4 5 1000 12 100 0 Open ;
6 5 6 1200 12 100 0 Open ;
7 6 7 2700 12 100 0 Open ;
8 7 8 1200 12 140 0 Open ;
9 7 9 400 12 100 0 Open ;
10 8 10 1000 8 140 0 Open ;
11 9 11 700 12 100 0 Open ;
12 11 12 1900 12 100 0 Open ;
13 12 13 600 12 100 0 Open ;
14 13 14 400 12 100 0 Open ;
15 14 15 300 12 100 0 Open ;
16 13 16 1500 8 100 0 Open ;
17 15 17 1500 8 100 0 Open ;
18 16 17 600 8 100 0 Open ;
19 17 18 700 12 100 0 Open ;
20 18 32 350 12 100 0 Open ;
21 16 19 1400 8 100 0 Open ;
22 14 20 1100 12 100 0 Open ;
23 20 21 1300 8 100 0 Open ;
24 21 22 1300 8 100 0 Open ;
25 20 22 1300 8 100 0 Open ;
26 24 23 600 12 100 0 Open ;
27 15 24 250 12 100 0 Open ;
28 23 25 300 12 100 0 Open ;
29 25 26 200 12 100 0 Open ;
30 25 31 600 12 100 0 Open ;
31 31 27 400 8 100 0 Open ;
32 27 29 400 8 100 0 Open ;
34 29 28 700 8 100 0 Open ;
35 22 33 1000 8 100 0 Open ;
36 33 34 400 8 100 0 Open ;
37 32 19 500 8 100 0 Open ;
38 29 35 500 8 100 0 Open ;
39 35 30 1000 8 100 0 Open ;
40 28 35 700 8 100 0 Open ;
41 28 36 300 8 100 0 Open ;
[PUMPS]
;ID Node1 Node2 Parameters
[VALVES]
;ID Node1 Node2 Diameter Type Setting MinorLoss
[TAGS]
[DEMANDS]
;Junction Demand Pattern Category
[STATUS]
;ID Status/Setting
[PATTERNS]
;ID Multipliers
;Demand Pattern
1 1.26 1.04 .97 .97 .89 1.19
1 1.28 .67 .67 1.34 2.46 .97
1 .92 .68 1.43 .61 .31 .78
1 .37 .67 1.26 1.56 1.19 1.26
1 .6 1.1 1.03 .73 .88 1.06
1 .99 1.72 1.12 1.34 1.12 .97
1 1.04 1.15 .91 .61 .68 .46
1 .51 .74 1.12 1.34 1.26 .97
1 .82 1.37 1.03 .81 .88 .81
1 .81
;Pump Station Outflow Pattern
2 .96 .96 .96 .96 .96 .96
2 .62 0 0 0 0 0
2 .8 1 1 1 1 .15
2 0 0 0 0 0 0
2 .55 .92 .92 .92 .92 .9
2 .9 .45 0 0 0 0
2 0 .7 1 1 1 1
2 .2 0 0 0 0 0
2 0 .74 .92 .92 .92 .92
2 .92
;Pump Station Fluoride Pattern
3 .98 1.02 1.05 .99 .64 .46
3 .35 .35 .35 .35 .35 .35
3 .17 .17 .13 .13 .13 .15
3 .15 .15 .15 .15 .15 .15
3 .15 .12 .1 .08 .11 .09
3 .09 .08 .08 .08 .08 .08
3 .08 .09 .07 .07 .09 .09
3 .09 .09 .09 .09 .09 .09
3 .09 .08 .35 .72 .82 .92
3 1
[CURVES]
;ID X-Value Y-Value
[CONTROLS]
[RULES]
[ENERGY]
Global Efficiency 75
Global Price 0.0
Demand Charge 0.0
[EMITTERS]
;Junction Coefficient
[QUALITY]
;Node InitQual
1 1.0
2 1.0
3 1.0
4 1.0
5 1.0
6 1.0
7 1.0
8 1.0
9 1.0
10 1.0
11 1.0
12 1.0
13 1.0
14 1.0
15 1.0
16 1.0
17 1.0
18 1.0
19 1.0
20 1.0
21 1.0
22 1.0
23 1.0
24 1.0
25 1.0
27 1.0
28 1.0
29 1.0
30 1.0
31 1.0
32 1.0
33 1.0
34 1.0
35 1.0
36 1.0
26 1.0
[SOURCES]
;Node Type Quality Pattern
1 CONCEN 1.0 3
[REACTIONS]
;Type Pipe/Tank Coefficient
[REACTIONS]
Order Bulk 1
Order Tank 1
Order Wall 1
Global Bulk 0.0
Global Wall 0.0
Limiting Potential 0.0
Roughness Correlation 0.0
[MIXING]
;Tank Model
[TIMES]
Duration 55:00
Hydraulic Timestep 1:00
Quality Timestep 0:05
Pattern Timestep 1:00
Pattern Start 0:00
Report Timestep 1:00
Report Start 0:00
Start ClockTime 8 am
Statistic None
[REPORT]
Status Yes
Summary No
Nodes All
Links All
[OPTIONS]
Units GPM
Headloss H-W
Specific Gravity 1.0
Viscosity 1.0
Trials 40
Accuracy 0.001
CHECKFREQ 2
MAXCHECK 10
;DAMPLIMIT 0
Unbalanced Continue 10
Pattern 1
Demand Multiplier 1.0
Emitter Exponent 0.5
Quality Fluoride mg/L
Diffusivity 1.0
Tolerance 0.01
[COORDINATES]
;Node X-Coord Y-Coord
1 21.00 4.00
2 19.00 20.00
3 11.00 21.00
4 14.00 28.00
5 19.00 25.00
6 28.00 23.00
7 36.00 39.00
8 38.00 30.00
9 36.00 42.00
10 37.00 23.00
11 37.00 49.00
12 39.00 60.00
13 38.00 64.00
14 38.00 66.00
15 37.00 69.00
16 27.00 65.00
17 27.00 69.00
18 23.00 68.00
19 21.00 59.00
20 45.00 68.00
21 51.00 62.00
22 54.00 69.00
23 35.00 74.00
24 37.00 71.00
25 35.00 76.00
27 39.00 87.00
28 49.00 85.00
29 42.00 86.00
30 47.00 80.00
31 37.00 80.00
32 23.00 64.00
33 56.00 73.00
34 56.00 77.00
35 43.00 81.00
36 53.00 87.00
26 33.00 76.00
[VERTICES]
;Link X-Coord Y-Coord
[LABELS]
;X-Coord Y-Coord Label & Anchor Node
24.00 7.00 "Pump"
24.00 4.00 "Station"
26.76 77.42 "Tank"
[BACKDROP]
DIMENSIONS 8.75 -0.15 58.25 91.15
UNITS None
FILE
OFFSET 0.00 0.00
[END]

View File

@@ -0,0 +1,17 @@
{
"name": "Example 2",
"version": "1.0",
"description": "Example of modeling a 55-hour fluoride tracer study.",
"args": [
"example2.inp",
"example2.rpt",
"example2.out"
],
"input_files": [
"example2.inp"
],
"output_files": {
"example2.rpt": "epanet report",
"example2.out": "epanet allclose"
}
}

View File

@@ -0,0 +1,481 @@
[TITLE]
EPANET Example Network 3
Example showing how the percent of Lake water in a dual-source
system changes over time.
[JUNCTIONS]
;ID Elev Demand Pattern
10 147 0 ;
15 32 1 3 ;
20 129 0 ;
35 12.5 1 4 ;
40 131.9 0 ;
50 116.5 0 ;
60 0 0 ;
601 0 0 ;
61 0 0 ;
101 42 189.95 ;
103 43 133.2 ;
105 28.5 135.37 ;
107 22 54.64 ;
109 20.3 231.4 ;
111 10 141.94 ;
113 2 20.01 ;
115 14 52.1 ;
117 13.6 117.71 ;
119 2 176.13 ;
120 0 0 ;
121 -2 41.63 ;
123 11 1 2 ;
125 11 45.6 ;
127 56 17.66 ;
129 51 0 ;
131 6 42.75 ;
139 31 5.89 ;
141 4 9.85 ;
143 -4.5 6.2 ;
145 1 27.63 ;
147 18.5 8.55 ;
149 16 27.07 ;
151 33.5 144.48 ;
153 66.2 44.17 ;
157 13.1 51.79 ;
159 6 41.32 ;
161 4 15.8 ;
163 5 9.42 ;
164 5 0 ;
166 -2 2.6 ;
167 -5 14.56 ;
169 -5 0 ;
171 -4 39.34 ;
173 -4 0 ;
177 8 58.17 ;
179 8 0 ;
181 8 0 ;
183 11 0 ;
184 16 0 ;
185 16 25.65 ;
187 12.5 0 ;
189 4 107.92 ;
191 25 81.9 ;
193 18 71.31 ;
195 15.5 0 ;
197 23 17.04 ;
199 -2 119.32 ;
201 0.1 44.61 ;
203 2 1 5 ;
204 21 0 ;
205 21 65.36 ;
206 1 0 ;
207 9 69.39 ;
208 16 0 ;
209 -2 0.87 ;
211 7 8.67 ;
213 7 13.94 ;
215 7 92.19 ;
217 6 24.22 ;
219 4 41.32 ;
225 8 22.8 ;
229 10.5 64.18 ;
231 5 16.48 ;
237 14 15.61 ;
239 13 44.61 ;
241 13 0 ;
243 14 4.34 ;
247 18 70.38 ;
249 18 0 ;
251 30 24.16 ;
253 36 54.52 ;
255 27 40.39 ;
257 17 0 ;
259 25 0 ;
261 0 0 ;
263 0 0 ;
265 0 0 ;
267 21 0 ;
269 0 0 ;
271 6 0 ;
273 8 0 ;
275 10 0 ;
[RESERVOIRS]
;ID Head Pattern
River 220.0 ;
Lake 167.0 ;
[TANKS]
;ID Elevation InitLevel MinLevel MaxLevel Diameter MinVol VolCurve
1 131.9 13.1 .1 32.1 85 0 ;
2 116.5 23.5 6.5 40.3 50 0 ;
3 129.0 29.0 4.0 35.5 164 0 ;
[PIPES]
;ID Node1 Node2 Length Diameter Roughness MinorLoss Status
20 3 20 99 99 199 0 Open ;
40 1 40 99 99 199 0 Open ;
50 2 50 99 99 199 0 Open ;
60 River 60 1231 24 140 0 Open ;
101 10 101 14200 18 110 0 Open ;
103 101 103 1350 16 130 0 Open ;
105 101 105 2540 12 130 0 Open ;
107 105 107 1470 12 130 0 Open ;
109 103 109 3940 16 130 0 Open ;
111 109 111 2000 12 130 0 Open ;
112 115 111 1160 12 130 0 Open ;
113 111 113 1680 12 130 0 Open ;
114 115 113 2000 8 130 0 Open ;
115 107 115 1950 8 130 0 Open ;
116 113 193 1660 12 130 0 Open ;
117 263 105 2725 12 130 0 Open ;
119 115 117 2180 12 130 0 Open ;
120 119 120 730 12 130 0 Open ;
121 120 117 1870 12 130 0 Open ;
122 121 120 2050 8 130 0 Open ;
123 121 119 2000 30 141 0 Open ;
125 123 121 1500 30 141 0 Open ;
129 121 125 930 24 130 0 Open ;
131 125 127 3240 24 130 0 Open ;
133 20 127 785 20 130 0 Open ;
135 127 129 900 24 130 0 Open ;
137 129 131 6480 16 130 0 Open ;
145 129 139 2750 8 130 0 Open ;
147 139 141 2050 8 130 0 Open ;
149 143 141 1400 8 130 0 Open ;
151 15 143 1650 8 130 0 Open ;
153 145 141 3510 12 130 0 Open ;
155 147 145 2200 12 130 0 Open ;
159 147 149 880 12 130 0 Open ;
161 149 151 1020 8 130 0 Open ;
163 151 153 1170 12 130 0 Open ;
169 125 153 4560 8 130 0 Open ;
171 119 151 3460 12 130 0 Open ;
173 119 157 2080 30 141 0 Open ;
175 157 159 2910 30 141 0 Open ;
177 159 161 2000 30 141 0 Open ;
179 161 163 430 30 141 0 Open ;
180 163 164 150 14 130 0 Open ;
181 164 166 490 14 130 0 Open ;
183 265 169 590 30 141 0 Open ;
185 167 169 60 8 130 0 Open ;
186 187 204 99.9 8 130 0 Open ;
187 169 171 1270 30 141 0 Open ;
189 171 173 50 30 141 0 Open ;
191 271 171 760 24 130 0 Open ;
193 35 181 30 24 130 0 Open ;
195 181 177 30 12 130 0 Open ;
197 177 179 30 12 130 0 Open ;
199 179 183 210 12 130 0 Open ;
201 40 179 1190 12 130 0 Open ;
202 185 184 99.9 8 130 0 Open ;
203 183 185 510 8 130 0 Open ;
204 184 205 4530. 12 130 0 Open ;
205 204 185 1325. 12 130 0 Open ;
207 189 183 1350 12 130 0 Open ;
209 189 187 500 8 130 0 Open ;
211 169 269 646 12 130 0 Open ;
213 191 187 2560 12 130 0 Open ;
215 267 189 1230 12 130 0 Open ;
217 191 193 520 12 130 0 Open ;
219 193 195 360 12 130 0 Open ;
221 161 195 2300 8 130 0 Open ;
223 197 191 1150 12 130 0 Open ;
225 111 197 2790 12 130 0 Open ;
229 173 199 4000 24 141 0 Open ;
231 199 201 630 24 141 0 Open ;
233 201 203 120 24 130 0 Open ;
235 199 273 725 12 130 0 Open ;
237 205 207 1200 12 130 0 Open ;
238 207 206 450 12 130 0 Open ;
239 275 207 1430 12 130 0 Open ;
240 206 208 510 12 130 0 Open ;
241 208 209 885 12 130 0 Open ;
243 209 211 1210 16 130 0 Open ;
245 211 213 990 16 130 0 Open ;
247 213 215 4285 16 130 0 Open ;
249 215 217 1660 16 130 0 Open ;
251 217 219 2050 14 130 0 Open ;
257 217 225 1560 12 130 0 Open ;
261 213 229 2200 8 130 0 Open ;
263 229 231 1960 12 130 0 Open ;
269 211 237 2080 12 130 0 Open ;
271 237 229 790 8 130 0 Open ;
273 237 239 510 12 130 0 Open ;
275 239 241 35 12 130 0 Open ;
277 241 243 2200 12 130 0 Open ;
281 241 247 445 10 130 0 Open ;
283 239 249 430 12 130 0 Open ;
285 247 249 10 12 130 0 Open ;
287 247 255 1390 10 130 0 Open ;
289 50 255 925 10 130 0 Open ;
291 255 253 1100 10 130 0 Open ;
293 255 251 1100 8 130 0 Open ;
295 249 251 1450 12 130 0 Open ;
297 120 257 645 8 130 0 Open ;
299 257 259 350 8 130 0 Open ;
301 259 263 1400 8 130 0 Open ;
303 257 261 1400 8 130 0 Open ;
305 117 261 645 12 130 0 Open ;
307 261 263 350 12 130 0 Open ;
309 265 267 1580 8 130 0 Open ;
311 193 267 1170 12 130 0 Open ;
313 269 189 646 12 130 0 Open ;
315 181 271 260 24 130 0 Open ;
317 273 275 2230 8 130 0 Open ;
319 273 205 645 12 130 0 Open ;
321 163 265 1200 30 141 0 Open ;
323 201 275 300 12 130 0 Open ;
325 269 271 1290 8 130 0 Open ;
329 61 123 45500 30 140 0 Open ;
330 60 601 1 30 140 0 Closed ;
333 601 61 1 30 140 0 Open ;
[PUMPS]
;ID Node1 Node2 Parameters
10 Lake 10 HEAD 1 ;
335 60 61 HEAD 2 ;
[VALVES]
;ID Node1 Node2 Diameter Type Setting MinorLoss
[TAGS]
[DEMANDS]
;Junction Demand Pattern Category
[STATUS]
;ID Status/Setting
10 Closed
[PATTERNS]
;ID Multipliers
;General Default Demand Pattern
1 1.34 1.94 1.46 1.44 .76 .92
1 .85 1.07 .96 1.1 1.08 1.19
1 1.16 1.08 .96 .83 .79 .74
1 .64 .64 .85 .96 1.24 1.67
;Demand Pattern for Node 123
2 0 0 0 0 0 1219
2 0 0 0 1866 1836 1818
2 1818 1822 1822 1817 1824 1816
2 1833 1817 1830 1814 1840 1859
;Demand Pattern for Node 15
3 620 620 620 620 620 360
3 360 0 0 0 0 360
3 360 360 360 360 0 0
3 0 0 0 0 360 360
;Demand Pattern for Node 35
4 1637 1706 1719 1719 1791 1819
4 1777 1842 1815 1825 1856 1801
4 1819 1733 1664 1620 1613 1620
4 1616 1647 1627 1627 1671 1668
;Demand Pattern for Node 203
5 4439 4531 4511 4582 4531 4582
5 4572 4613 4643 4643 4592 4613
5 4531 4521 4449 4439 4449 4460
5 4439 4419 4368 4399 4470 4480
[CURVES]
;ID X-Value Y-Value
;PUMP: Pump Curve for Pump 10 (Lake Source)
1 0 104.
1 2000. 92.
1 4000. 63.
;PUMP: Pump Curve for Pump 335 (River Source)
2 0 200.
2 8000. 138.
2 14000. 86.
[CONTROLS]
;Lake source operates only part of the day
Link 10 OPEN AT TIME 1
Link 10 CLOSED AT TIME 15
;Pump 335 controlled by level in Tank 1
;When pump is closed, bypass pipe is opened
Link 335 OPEN IF Node 1 BELOW 17.1
Link 335 CLOSED IF Node 1 ABOVE 19.1
Link 330 CLOSED IF Node 1 BELOW 17.1
Link 330 OPEN IF Node 1 ABOVE 19.1
[RULES]
[ENERGY]
Global Efficiency 75
Global Price 0.0
Demand Charge 0.0
[EMITTERS]
;Junction Coefficient
[QUALITY]
;Node InitQual
[SOURCES]
;Node Type Quality Pattern
[REACTIONS]
;Type Pipe/Tank Coefficient
[REACTIONS]
Order Bulk 1
Order Tank 1
Order Wall 1
Global Bulk 0.0
Global Wall 0.0
Limiting Potential 0.0
Roughness Correlation 0.0
[MIXING]
;Tank Model
[TIMES]
Duration 24:00
Hydraulic Timestep 1:00
Quality Timestep 0:05
Pattern Timestep 1:00
Pattern Start 0:00
Report Timestep 1:00
Report Start 0:00
Start ClockTime 12 am
Statistic None
[REPORT]
Status Yes
Summary No
Nodes All
Links All
[OPTIONS]
Units GPM
Headloss H-W
Specific Gravity 1.0
Viscosity 1.0
Trials 40
Accuracy 0.001
CHECKFREQ 2
MAXCHECK 10
;DAMPLIMIT 0
Unbalanced Continue 10
Pattern 1
Demand Multiplier 1.0
Emitter Exponent 0.5
Quality Trace Lake
Diffusivity 1.0
Tolerance 0.01
[COORDINATES]
;Node X-Coord Y-Coord
10 9.00 27.85
15 38.68 23.76
20 29.44 26.91
35 25.46 10.52
40 27.02 9.81
50 33.01 3.01
60 23.90 29.94
601 23.00 29.49
61 23.71 29.03
101 13.81 22.94
103 12.96 21.31
105 16.97 21.28
107 18.45 20.46
109 17.64 18.92
111 20.21 17.53
113 22.04 16.61
115 20.98 19.18
117 21.69 21.28
119 23.70 22.76
120 22.08 23.10
121 23.54 25.50
123 23.37 27.31
125 24.59 25.64
127 29.29 26.40
129 30.32 26.39
131 37.89 29.55
139 33.28 24.54
141 35.68 23.08
143 37.47 21.97
145 33.02 19.29
147 30.24 20.38
149 29.62 20.74
151 28.29 21.39
153 28.13 22.63
157 24.85 20.16
159 23.12 17.50
161 25.10 15.28
163 25.39 14.98
164 25.98 15.14
166 26.48 15.13
167 25.88 12.98
169 25.68 12.74
171 26.65 11.80
173 26.87 11.59
179 25.71 10.40
181 25.72 10.74
183 25.45 10.18
184 25.15 9.52
185 25.01 9.67
187 23.64 11.04
189 24.15 11.37
191 22.10 14.07
193 22.88 14.35
195 23.18 14.72
197 20.97 15.18
199 29.42 8.44
201 30.89 8.57
203 31.14 8.89
204 23.80 10.90
205 29.20 6.46
206 31.66 6.64
207 31.00 6.61
208 32.54 6.81
209 33.76 6.59
211 34.20 5.54
213 35.26 6.16
215 39.95 8.73
217 42.11 8.67
219 44.86 9.32
225 43.53 7.38
229 36.16 3.49
231 38.38 2.54
237 35.37 3.08
239 35.76 2.31
241 35.87 2.11
243 37.04 0.00
247 35.02 2.05
249 35.02 1.81
251 34.15 1.10
253 32.17 1.88
255 33.51 2.45
257 21.17 23.32
259 20.80 23.40
261 20.79 21.45
263 20.32 21.57
265 25.39 13.60
267 23.38 12.95
269 25.03 12.14
271 25.97 11.00
273 29.16 7.38
275 31.07 8.29
River 24.15 31.06
Lake 8.00 27.53
1 27.46 9.84
2 32.99 3.45
3 29.41 27.27
[VERTICES]
;Link X-Coord Y-Coord
[LABELS]
;X-Coord Y-Coord Label & Anchor Node
8.00 29.42 "LAKE"
25.00 31.10 "RIVER"
[BACKDROP]
DIMENSIONS 6.16 -1.55 46.70 32.61
UNITS None
FILE
OFFSET 0.00 0.00
[END]

View File

@@ -0,0 +1,17 @@
{
"name": "Example 3",
"version": "1.0",
"description": "Dual-source system example",
"args": [
"example3.inp",
"example3.rpt",
"example3.out"
],
"input_files": [
"example3.inp"
],
"output_files": {
"example3.rpt": "epanet report",
"example3.out": "epanet allclose"
}
}

27
tools/.gitignore vendored Normal file
View File

@@ -0,0 +1,27 @@
# Python compiler files
*.py[cd]
# Python distribution and packaging
build/
dist/
temp/
*.cfg
*.egg-info/
*.whl
# SWIG generated files
epanet_output_wrap.c
epanet_output.py
# C compiler
*.o
*.dll
*.exe
# Eclipse project files and directories
.metadata/
.settings/
Release/
.project
.cproject
.pydevproject

View File

@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
#
# setup.py
#
# Created: 9/20/2017
# Author: Michael E. Tryby
# US EPA - ORD/NRMRL
#
# Setup up script for en_outputapi python extension
#
# Requires:
# Platform C language compiler
# Python packages: numpy
#
try:
from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext
except ImportError:
from distutils.core import setup, Extension
from distutils.command.build_ext import build_ext
setup(
name = "epanet-output",
version = "1.0",
ext_modules = [
Extension("_epanet_output",
sources = ['src/epanet_output.i', 'src/epanet_output.c', 'src/errormanager.c'],
swig_opts=['-modern'],
language = 'C'
)
],
package_dir = {'':'src'},
py_modules = ['epanet_output'],
install_requires = [
'enum34'
]
)

View File

@@ -0,0 +1,969 @@
//-----------------------------------------------------------------------------
//
// epanet_output.c -- API for reading results from EPANET binary output file
//
// Version: 0.30
// Date 09/06/2017
// 06/17/2016
// 08/05/2014
// 05/21/2014
//
// Author: Michael E. Tryby
// US EPA - ORD/NRMRL
//
// Modified: Maurizio Cingi
// University of Modena
//
// Purpose: Output API provides an interface for retrieving results from an
// EPANET binary output file.
//
// Output data in the binary file are aligned on a 4 byte word size.
// Therefore all values both integers and reals are 32 bits in length.
//
// All values returned by the output API are indexed from 0 to n-1. This
// differs from how node and link elements are indexed by the binary file
// writer found in EPANET. Times correspond to reporting periods are indexed
// from 0 to number of reporting periods minus one. Node and link elements
// are indexed from 0 to nodeCount minus one and 0 to linkCount minus one
// respectively.
//
// The Output API functions provide a convenient way to select "slices" of
// data from the output file. As such they return arrays of data. The API
// functions automatically allocate memory for the array to be returned. The
// caller is responsible for deallocating memory. The function ENR_free() is
// provided to deallocate memory.
//
//-----------------------------------------------------------------------------
#include "epanet_output.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "errormanager.h"
#include "messages.h"
// NOTE: These depend on machine data model and may change when porting
// F_OFF Must be a 8 byte / 64 bit integer for large file support
#ifdef _WIN32 // Windows (32-bit and 64-bit)
#define F_OFF __int64
#else // Other platforms
#define F_OFF off_t
#endif
#define INT4 int // Must be a 4 byte / 32 bit integer type
#define REAL4 float // Must be a 4 byte / 32 bit real type
#define WORDSIZE 4 // Memory alignment 4 byte word size for both int and real
#define MINNREC 14 // Minimum allowable number of records
#define PROLOGUE 884 // Preliminary fixed length section of header
#define MAXID_P1 32 // Max. # characters in ID name
#define NELEMENTTYPES 5 // Number of element types
#define NENERGYRESULTS 6 // Number of energy results
#define NNODERESULTS 4 // number of result fields for nodes
#define NLINKRESULTS 8 // number of result fields for links
#define NREACTRESULTS 4 // number of net reaction results
#define MEMCHECK(x) (((x) == NULL) ? 411 : 0 )
// Typedefs for opaque pointer
typedef struct data_s {
char name[MAXFNAME+1]; // file path/name
FILE* file; // FILE structure pointer
INT4 nodeCount, tankCount, linkCount, pumpCount, valveCount, nPeriods;
F_OFF outputStartPos; // starting file position of output data
F_OFF bytesPerPeriod; // bytes saved per simulation time period
error_handle_t* error_handle;
} data_t;
//-----------------------------------------------------------------------------
// Local functions
//-----------------------------------------------------------------------------
void errorLookup(int errcode, char* errmsg, int length);
int validateFile(ENR_Handle);
float getNodeValue(ENR_Handle, int, int, int);
float getLinkValue(ENR_Handle, int, int, int);
int _fopen(FILE **f, const char *name, const char *mode);
int _fseek(FILE* stream, F_OFF offset, int whence);
F_OFF _ftell(FILE* stream);
float* newFloatArray(int n);
int* newIntArray(int n);
char* newCharArray(int n);
int DLLEXPORT ENR_init(ENR_Handle* dp_handle)
// Purpose: Initialized pointer for the opaque ENR_Handle.
//
// Returns: Error code 0 on success, -1 on failure
//
// Note: The existence of this function has been carefully considered.
// Don't change it.
//
{
int errorcode = 0;
data_t* p_data;
// Allocate memory for private data
p_data = (data_t*)calloc(1, sizeof(data_t));
if (p_data != NULL){
p_data->error_handle = new_errormanager(&errorLookup);
*dp_handle = p_data;
}
else
errorcode = -1;
// TODO: Need to handle errors during initialization better.
return errorcode;
}
int DLLEXPORT ENR_close(ENR_Handle* p_handle)
/*------------------------------------------------------------------------
** Input: *p_handle = pointer to ENR_Handle struct
**
** Returns: Error code 0 on success, -1 on failure
**
** Purpose: Close the output binary file, dellocate ENR_Handle struc
** and nullify pointer to ENR_Handle struct
**
** NOTE: ENR_close must be called before program end
** after calling ENR_close data in ENR_Handle struct are no more
** accessible
**-------------------------------------------------------------------------
*/
{
data_t* p_data;
int errorcode = 0;
p_data = (data_t*)(*p_handle);
if (p_data == NULL || p_data->file == NULL)
errorcode = -1;
else
{
dst_errormanager(p_data->error_handle);
fclose(p_data->file);
free(p_data);
*p_handle = NULL;
}
return errorcode;
}
int DLLEXPORT ENR_open(ENR_Handle p_handle, const char* path)
/*------------------------------------------------------------------------
** Input: path
** Output: p_handle = pointer to ENR_Handle struct
** Returns: warning / error code
** Purpose: Opens the output binary file and reads prologue and epilogue
**
** NOTE: ENR_init must be called before anyother ENR_* functions
**-------------------------------------------------------------------------
*/
{
int err, errorcode = 0;
F_OFF bytecount;
data_t* p_data;
p_data = (data_t*)p_handle;
if (p_data == NULL) return -1;
else
{
strncpy(p_data->name, path, MAXFNAME);
// Attempt to open binary output file for reading only
if ((_fopen(&(p_data->file), path, "rb")) != 0) errorcode = 434;
// Perform checks to insure the file is valid
else if ((err = validateFile(p_data)) != 0) errorcode = err;
// If a warning is encountered read file header
if (errorcode < 400 ) {
// read network size
fseek(p_data->file, 2*WORDSIZE, SEEK_SET);
fread(&(p_data->nodeCount), WORDSIZE, 1, p_data->file);
fread(&(p_data->tankCount), WORDSIZE, 1, p_data->file);
fread(&(p_data->linkCount), WORDSIZE, 1, p_data->file);
fread(&(p_data->pumpCount), WORDSIZE, 1, p_data->file);
fread(&(p_data->valveCount), WORDSIZE, 1, p_data->file);
// Compute positions and offsets for retrieving data
// fixed portion of header + title section + filenames + chem names
bytecount = PROLOGUE;
// node names + link names
bytecount += MAXID_P1*p_data->nodeCount + MAXID_P1*p_data->linkCount;
// network connectivity + tank nodes + tank areas
bytecount += 3*WORDSIZE*p_data->linkCount + 2*WORDSIZE*p_data->tankCount;
// node elevations + link lengths and link diameters
bytecount += WORDSIZE*p_data->nodeCount + 2*WORDSIZE*p_data->linkCount;
// pump energy summary
bytecount += 7*WORDSIZE*p_data->pumpCount + WORDSIZE;
p_data->outputStartPos= bytecount;
p_data->bytesPerPeriod = NNODERESULTS*WORDSIZE*p_data->nodeCount +
NLINKRESULTS*WORDSIZE*p_data->linkCount;
}
}
// If error close the binary file
if (errorcode > 400) {
set_error(p_data->error_handle, errorcode);
ENR_close(&p_handle);
}
return errorcode;
}
int DLLEXPORT ENR_getVersion(ENR_Handle p_handle, int* version)
/*------------------------------------------------------------------------
** Input: p_handle = pointer to ENR_Handle struct
** Output: version Epanet version
** Returns: error code
**
** Purpose: Returns Epanet version that wrote EBOFile
**--------------element codes-------------------------------------------
*/
{
int errorcode = 0;
data_t* p_data;
p_data = (data_t*)p_handle;
if (p_data == NULL) return -1;
else
{
fseek(p_data->file, 1*WORDSIZE, SEEK_SET);
if (fread(version, WORDSIZE, 1, p_data->file) != 1)
errorcode = 436;
}
return set_error(p_data->error_handle, errorcode);
}
int DLLEXPORT ENR_getNetSize(ENR_Handle p_handle, int** elementCount, int* length)
/*------------------------------------------------------------------------
** Input: p_handle = pointer to ENR_Handle struct
** Output: array of element counts (nodes, tanks, links, pumps, valves)
** Returns: error code
** Purpose: Returns an array of count values
**-------------------------------------------------------------------------
*/
{
int errorcode = 0;
int* temp = newIntArray(NELEMENTTYPES);
data_t* p_data;
p_data = (data_t*)p_handle;
if (p_data == NULL) return -1;
else
{
temp[0] = p_data->nodeCount;
temp[1] = p_data->tankCount;
temp[2] = p_data->linkCount;
temp[3] = p_data->pumpCount;
temp[4] = p_data->valveCount;
*elementCount = temp;
*length = NELEMENTTYPES;
}
return set_error(p_data->error_handle, errorcode);
}
int DLLEXPORT ENR_getUnits(ENR_Handle p_handle, ENR_Units code, int* unitFlag)
/*------------------------------------------------------------------------
** Input: p_handle = pointer to ENR_Handle struct
** code
** Output: count
** Returns: unitFlag
** Purpose: Returns pressure or flow unit flag
**--------------pressure unit flags----------------------------------------
** 0 = psi
** 1 = meters
** 2 = kPa
**------------------flow unit flags----------------------------------------
** 0 = cubic feet/second
** 1 = gallons/minute
** 2 = million gallons/day
** 3 = Imperial million gallons/day
** 4 = acre-ft/day
** 5 = liters/second
** 6 = liters/minute
** 7 = megaliters/day
** 8 = cubic meters/hour
** 9 = cubic meters/day
**-------------------------------------------------------------------------
*/
{
int errorcode = 0;
data_t* p_data;
*unitFlag = -1;
p_data = (data_t*)p_handle;
if (p_data == NULL) return -1;
else
{
switch (code)
{
case ENR_flowUnits:
fseek(p_data->file, 9*WORDSIZE, SEEK_SET);
fread(unitFlag, WORDSIZE, 1, p_data->file);
break;
case ENR_pressUnits:
fseek(p_data->file, 10*WORDSIZE, SEEK_SET);
fread(unitFlag, WORDSIZE, 1, p_data->file);
break;
default: errorcode = 421;
}
}
return set_error(p_data->error_handle, errorcode);
}
int DLLEXPORT ENR_getTimes(ENR_Handle p_handle, ENR_Time code, int* time)
/*------------------------------------------------------------------------
** Input: p_handle = pointer to ENR_Handle struct
** code = element code
** Output: time
** Returns: error code
** Purpose: Returns report and simulation time related parameters.
**-------------------------------------------------------------------------
*/
{
int errorcode = 0;
data_t* p_data;
*time = -1;
p_data = (data_t*)p_handle;
if (p_data == NULL) return -1;
else
{
switch (code)
{
case ENR_reportStart:
fseek(p_data->file, 12*WORDSIZE, SEEK_SET);
fread(time, WORDSIZE, 1, p_data->file);
break;
case ENR_reportStep:
fseek(p_data->file, 13*WORDSIZE, SEEK_SET);
fread(time, WORDSIZE, 1, p_data->file);
break;
case ENR_simDuration:
fseek(p_data->file, 14*WORDSIZE, SEEK_SET);
fread(time, WORDSIZE, 1, p_data->file);
break;
case ENR_numPeriods:
*time = p_data->nPeriods;
break;
default:
errorcode = 421;
}
}
return set_error(p_data->error_handle, errorcode);
}
int DLLEXPORT ENR_getElementName(ENR_Handle p_handle, ENR_ElementType type,
int elementIndex, char** name, int* length)
/*------------------------------------------------------------------------
** Input: p_handle = pointer to ENR_Handle struct
** type = ENR_node or ENR_link
** elementIndex from 1 to nodeCount or 1 to linkCount
** Output: name = elementName
** Returns: error code
** Purpose: Retrieves Name of a specified node or link element
** NOTE: 'name' must be able to hold MAXID characters
** TODO: Takes EPANET indexing from 1 to n not 0 to n-1
**-------------------------------------------------------------------------
*/
{
F_OFF offset;
int errorcode = 0;
char* temp;
data_t* p_data;
p_data = (data_t*)p_handle;
if (p_data == NULL) return -1;
/* Allocate memory for name */
else if MEMCHECK(temp = newCharArray(MAXID_P1)) errorcode = 411;
else
{
switch (type)
{
case ENR_node:
if (elementIndex < 1 || elementIndex > p_data->nodeCount)
errorcode = 423;
else offset = PROLOGUE + (elementIndex - 1)*MAXID_P1;
break;
case ENR_link:
if (elementIndex < 1 || elementIndex > p_data->linkCount)
errorcode = 423;
else
offset = PROLOGUE + p_data->nodeCount*MAXID_P1 +
(elementIndex - 1)*MAXID_P1;
break;
default:
errorcode = 421;
}
if (!errorcode)
{
_fseek(p_data->file, offset, SEEK_SET);
fread(temp, 1, MAXID_P1, p_data->file);
*name = temp;
*length = MAXID_P1;
}
}
return set_error(p_data->error_handle, errorcode);
}
int DLLEXPORT ENR_getEnergyUsage(ENR_Handle p_handle, int pumpIndex,
int* linkIndex, float** outValues, int* length)
/*
* Purpose: Returns pump energy usage statistics.
*
* Energy usage statistics:
* 0 = pump utilization
* 1 = avg. efficiency
* 2 = avg. kW/flow
* 3 = avg. kwatts
* 4 = peak kwatts
* 5 = cost/day
*/
{
F_OFF offset;
int errorcode = 0;
float* temp;
data_t* p_data;
p_data = (data_t*)p_handle;
if (p_data == NULL) return -1;
// Check for valid pump index
else if (pumpIndex < 1 || pumpIndex > p_data->pumpCount) errorcode = 423;
// Check memory for outValues
else if MEMCHECK(temp = newFloatArray(NENERGYRESULTS)) errorcode = 411;
else
{
// Position offset to start of pump energy summary
offset = p_data->outputStartPos - (p_data->pumpCount*(WORDSIZE + 6*WORDSIZE) + WORDSIZE);
// Adjust offset by pump index
offset += (pumpIndex - 1)*(WORDSIZE + 6*WORDSIZE);
// Power summary is 1 int and 6 floats for each pump
_fseek(p_data->file, offset, SEEK_SET);
fread(linkIndex, WORDSIZE, 1, p_data->file);
fread(temp, WORDSIZE, 6, p_data->file);
*outValues = temp;
*length = NENERGYRESULTS;
}
return set_error(p_data->error_handle, errorcode);
}
int DLLEXPORT ENR_getNetReacts(ENR_Handle p_handle, float** outValues, int* length)
/*
* Purpose: Returns network wide average reaction rates and average
* source mass inflow:
* 0 = bulk
* 1 = wall
* 2 = tank
* 3 = source
*/
{
F_OFF offset;
int errorcode = 0;
float* temp;
data_t* p_data;
p_data = (data_t*)p_handle;
if (p_data == NULL) return -1;
// Check memory for outValues
else if MEMCHECK(temp = newFloatArray(NREACTRESULTS)) errorcode = 411;
else
{
// Reaction summary is 4 floats located right before epilogue.
// This offset is relative to the end of the file.
offset = - 3*WORDSIZE - 4*WORDSIZE;
_fseek(p_data->file, offset, SEEK_END);
fread(temp, WORDSIZE, 4, p_data->file);
*outValues = temp;
*length = NREACTRESULTS;
}
return set_error(p_data->error_handle, errorcode);
}
void DLLEXPORT ENR_free(void** array)
//
// Purpose: Frees memory allocated by API calls
//
{
if (array != NULL) {
free(*array);
*array = NULL;
}
}
int DLLEXPORT ENR_getNodeSeries(ENR_Handle p_handle, int nodeIndex, ENR_NodeAttribute attr,
int startPeriod, int endPeriod, float** outValueSeries, int* dim)
//
// Purpose: Get time series results for particular attribute. Specify series
// start and length using seriesStart and seriesLength respectively.
//
// NOTE: The node index argument corresponds to the EPANET node index from 1 to
// nnodes. The series returned is indexed from 0 to nperiods - 1.
//
{
int k, length, errorcode = 0;
float* temp;
data_t* p_data;
p_data = (data_t*)p_handle;
if (p_data == NULL) return -1;
else if (nodeIndex < 1 || nodeIndex > p_data->nodeCount) errorcode = 423;
else if (startPeriod < 0 || endPeriod >= p_data->nPeriods ||
endPeriod <= startPeriod) errorcode = 422;
// Check memory for outValues
else if MEMCHECK(temp = newFloatArray(length = endPeriod - startPeriod)) errorcode = 411;
else
{
// loop over and build time series
for (k = 0; k < length; k++)
temp[k] = getNodeValue(p_handle, startPeriod + k,
nodeIndex, attr);
*outValueSeries = temp;
*dim = length;
}
return set_error(p_data->error_handle, errorcode);
}
int DLLEXPORT ENR_getLinkSeries(ENR_Handle p_handle, int linkIndex, ENR_LinkAttribute attr,
int startPeriod, int endPeriod, float** outValueSeries, int* dim)
//
// Purpose: Get time series results for particular attribute. Specify series
// start and length using seriesStart and seriesLength respectively.
//
// NOTE:
// The link index argument corresponds to the EPANET link index from 1 to
// nlinks. The series returned is indexed from 0 to nperiods - 1.
//
{
int k, length, errorcode = 0;
float* temp;
data_t* p_data;
p_data = (data_t*)p_handle;
if (p_data == NULL) return -1;
else if (linkIndex < 1 || linkIndex > p_data->linkCount) errorcode = 423;
else if (startPeriod < 0 || endPeriod >= p_data->nPeriods ||
endPeriod <= startPeriod) errorcode = 422;
// Check memory for outValues
else if MEMCHECK(temp = newFloatArray(length = endPeriod - startPeriod)) errorcode = 411;
else
{
// loop over and build time series
for (k = 0; k < length; k++)
temp[k] = getLinkValue(p_handle, startPeriod + k, linkIndex, attr);
*outValueSeries = temp;
*dim = length;
}
return set_error(p_data->error_handle, errorcode);
}
int DLLEXPORT ENR_getNodeAttribute(ENR_Handle p_handle, int periodIndex,
ENR_NodeAttribute attr, float** outValueArray, int* length)
//
// Purpose:
// For all nodes at given time, get a particular attribute
//
// Returns:
// Error code
// OutValueArray of results is indexed from 0 to nodeCount
//
// Warning:
// Caller must free memory allocated for outValueArray
//
// NOTE:
// The array returned is indexed from 0 to nnodes - 1. So to access
// node values by their EPANET index, the index value must be
// decremented by one.
//
{
F_OFF offset;
int errorcode = 0;
float * temp;
data_t* p_data;
p_data = (data_t*)p_handle;
if (p_data == NULL) return -1;
// if the time index is out of range return an error
else if (periodIndex < 0 || periodIndex >= p_data->nPeriods) errorcode = 422;
// Check memory for outValues
else if MEMCHECK(temp = newFloatArray(p_data->nodeCount)) errorcode = 411;
else
{
// calculate byte offset to start time for series
offset = p_data->outputStartPos + (periodIndex)*p_data->bytesPerPeriod;
// add offset for node and attribute
offset += ((attr - 1)*p_data->nodeCount)*WORDSIZE;
_fseek(p_data->file, offset, SEEK_SET);
fread(temp, WORDSIZE, p_data->nodeCount, p_data->file);
*outValueArray = temp;
*length = p_data->nodeCount;
}
return set_error(p_data->error_handle, errorcode);
}
int DLLEXPORT ENR_getLinkAttribute(ENR_Handle p_handle, int periodIndex,
ENR_LinkAttribute attr, float** outValueArray, int* length)
//
// Purpose:
// For all links at given time, get a particular attribute
//
// Returns:
// Error code
// OutValueArray of results is indexed from 0 to linkCount
//
// Warning:
// Caller must free memory allocated for outValueArray
//
// NOTE:
// The array returned is indexed from 0 to nlinks - 1. So to access
// link values by their EPANET index, the index value must be
// decremented by one.
//
{
F_OFF offset;
int errorcode = 0;
float* temp;
data_t* p_data;
p_data = (data_t*)p_handle;
if (p_data == NULL) return -1;
// if the time index is out of range return an error
else if (periodIndex < 0 || periodIndex >= p_data->nPeriods) errorcode = 422;
// Check memory for outValues
else if MEMCHECK(temp = newFloatArray(p_data->linkCount)) errorcode = 411;
else
{
// calculate byte offset to start time for series
offset = p_data->outputStartPos + (periodIndex)*p_data->bytesPerPeriod
+ (NNODERESULTS*p_data->nodeCount)*WORDSIZE;
// add offset for link and attribute
offset += ((attr - 1)*p_data->linkCount)*WORDSIZE;
_fseek(p_data->file, offset, SEEK_SET);
fread(temp, WORDSIZE, p_data->linkCount, p_data->file);
*outValueArray = temp;
*length = p_data->linkCount;
}
return set_error(p_data->error_handle, errorcode);
}
int DLLEXPORT ENR_getNodeResult(ENR_Handle p_handle, int periodIndex,
int nodeIndex, float** outValueArray, int* length)
//
// Purpose: For a node at given time, get all attributes.
//
// NOTE:
//
{
int j, errorcode = 0;
float* temp;
data_t* p_data;
p_data = (data_t*)p_handle;
if (p_data == NULL) return -1;
else if (periodIndex < 0 || periodIndex >= p_data->nPeriods) errorcode = 422;
else if (nodeIndex < 1 || nodeIndex > p_data->nodeCount) errorcode = 423;
else if MEMCHECK(temp = newFloatArray(NNODERESULTS)) errorcode = 411;
else
{
for (j = 0; j < NNODERESULTS; j++)
temp[j] = getNodeValue(p_handle, periodIndex, nodeIndex, j);
*outValueArray = temp;
*length = NNODERESULTS;
}
return set_error(p_data->error_handle, errorcode);
}
int DLLEXPORT ENR_getLinkResult(ENR_Handle p_handle, int periodIndex,
int linkIndex, float** outValueArray, int* length)
//
// Purpose: For a link at given time, get all attributes
//
{
int j, errorcode = 0;
float* temp;
data_t* p_data;
p_data = (data_t*)p_handle;
if (p_data == NULL) return -1;
else if (periodIndex < 0 || periodIndex >= p_data->nPeriods) errorcode = 422;
else if (linkIndex < 1 || linkIndex > p_data->linkCount) errorcode = 423;
else if MEMCHECK(temp = newFloatArray(NLINKRESULTS)) errorcode = 411;
else
{
for (j = 0; j < NLINKRESULTS; j++)
temp[j] = getLinkValue(p_handle, periodIndex, linkIndex, j);
*outValueArray = temp;
*length = NLINKRESULTS;
}
return set_error(p_data->error_handle, errorcode);
}
void DLLEXPORT ENR_clearError(ENR_Handle p_handle)
{
data_t* p_data;
p_data = (data_t*)p_handle;
clear_error(p_data->error_handle);
}
int DLLEXPORT ENR_checkError(ENR_Handle p_handle, char** msg_buffer)
{
int errorcode = 0;
char *temp = NULL;
data_t* p_data;
p_data = (data_t*)p_handle;
if (p_data == NULL) return -1;
else
{
errorcode = p_data->error_handle->error_status;
if (errorcode)
temp = check_error(p_data->error_handle);
*msg_buffer = temp;
}
return errorcode;
}
void errorLookup(int errcode, char* dest_msg, int dest_len)
//
// Purpose: takes error code returns error message
//
{
const char* msg;
switch (errcode)
{
case 10: msg = WARN10;
break;
case 411: msg = ERR411;
break;
case 412: msg = ERR412;
break;
case 421: msg = ERR421;
break;
case 422: msg = ERR422;
break;
case 423: msg = ERR423;
break;
case 434: msg = ERR434;
break;
case 435: msg = ERR435;
break;
case 436: msg = ERR436;
break;
default: msg = ERRERR;
}
strncpy(dest_msg, msg, MAXMSG);
}
int validateFile(ENR_Handle p_handle)
// Returns:
// Error code: 435, 436
// Warning code: 10
{
INT4 magic1, magic2, hydcode;
int errorcode = 0;
F_OFF filepos;
data_t* p_data;
p_data = (data_t*)p_handle;
// Read magic number from beginning of file
fseek(p_data->file, 0L, SEEK_SET);
fread(&magic1, WORDSIZE, 1, p_data->file);
// Fast forward to end and read file epilogue
fseek(p_data->file, -3*WORDSIZE, SEEK_END);
fread(&(p_data->nPeriods), WORDSIZE, 1, p_data->file);
fread(&hydcode, WORDSIZE, 1, p_data->file);
fread(&magic2, WORDSIZE, 1, p_data->file);
filepos = _ftell(p_data->file);
// Is the file an EPANET binary file?
if (magic1 != magic2) errorcode = 435;
// Does the binary file contain results?
else if (filepos < MINNREC*WORDSIZE || p_data->nPeriods == 0)
errorcode = 436;
// Issue warning if there were problems with the model run.
else if (hydcode != 0) errorcode = 10;
return errorcode;
}
float getNodeValue(ENR_Handle p_handle, int periodIndex, int nodeIndex,
int attr)
//
// Purpose: Retrieves an attribute value at a specified node and time
//
{
F_OFF offset;
REAL4 y;
data_t* p_data;
p_data = (data_t*)p_handle;
// calculate byte offset to start time for series
offset = p_data->outputStartPos + periodIndex*p_data->bytesPerPeriod;
// add byte position for attribute and node
offset += ((attr - 1)*p_data->nodeCount + (nodeIndex - 1))*WORDSIZE;
_fseek(p_data->file, offset, SEEK_SET);
fread(&y, WORDSIZE, 1, p_data->file);
return y;
}
float getLinkValue(ENR_Handle p_handle, int periodIndex, int linkIndex,
int attr)
//
// Purpose: Retrieves an attribute value at a specified link and time
//
{
F_OFF offset;
REAL4 y;
data_t* p_data;
p_data = (data_t*)p_handle;
// Calculate byte offset to start time for series
offset = p_data->outputStartPos + periodIndex*p_data->bytesPerPeriod
+ (NNODERESULTS*p_data->nodeCount)*WORDSIZE;
// add byte position for attribute and link
offset += ((attr - 1)*p_data->linkCount + (linkIndex - 1))*WORDSIZE;
_fseek(p_data->file, offset, SEEK_SET);
fread(&y, WORDSIZE, 1, p_data->file);
return y;
}
int _fopen(FILE **f, const char *name, const char *mode) {
//
// Purpose: Substitute for fopen_s on platforms where it doesn't exist
// Note: fopen_s is part of C++11 standard
//
int ret = 0;
#ifdef _WIN32
ret = (int)fopen_s(f, name, mode);
#else
*f = fopen(name, mode);
if (!*f)
ret = -1;
#endif
return ret;
}
int _fseek(FILE* stream, F_OFF offset, int whence)
//
// Purpose: Selects platform fseek() for large file support
//
{
#ifdef _WIN32 // Windows (32-bit and 64-bit)
#define FSEEK64 _fseeki64
#else // Other platforms
#define FSEEK64 fseeko
#endif
return FSEEK64(stream, offset, whence);
}
F_OFF _ftell(FILE* stream)
//
// Purpose: Selects platform ftell() for large file support
//
{
#ifdef _WIN32 // Windows (32-bit and 64-bit)
#define FTELL64 _ftelli64
#else // Other platforms
#define FTELL64 ftello
#endif
return FTELL64(stream);
}
float* newFloatArray(int n)
//
// Warning: Caller must free memory allocated by this function.
//
{
return (float*) malloc((n)*sizeof(float));
}
int* newIntArray(int n)
//
// Warning: Caller must free memory allocated by this function.
//
{
return (int*) malloc((n)*sizeof(int));
}
char* newCharArray(int n)
//
// Warning: Caller must free memory allocated by this function.
//
{
return (char*) malloc((n)*sizeof(char));
}

View File

@@ -0,0 +1,129 @@
/*
* epanet_output.h - EPANET Output API
*
* Created on: Jun 4, 2014
*
* Author: Michael E. Tryby
* US EPA - ORD/NRMRL
*/
#ifndef EPANET_OUTPUT_H_
#define EPANET_OUTPUT_H_
/* Epanet Results binary file API */
#define MAXFNAME 259 // Max characters in file name
#define MAXID 31 // Max characters in ID name
// This is an opaque pointer to struct. Do not access variables.
typedef void* ENR_Handle;
typedef enum {
ENR_node = 1,
ENR_link = 2
} ENR_ElementType;
typedef enum {
ENR_getSeries = 1,
ENR_getAttribute = 2,
ENR_getResult = 3,
ENR_getReacts = 4,
ENR_getEnergy = 5
} ENR_ApiFunction;
typedef enum {
ENR_flowUnits = 1,
ENR_pressUnits = 2
} ENR_Units;
typedef enum {
ENR_reportStart = 1,
ENR_reportStep = 2,
ENR_simDuration = 3,
ENR_numPeriods = 4
}ENR_Time;
typedef enum {
ENR_demand = 1,
ENR_head = 2,
ENR_pressure = 3,
ENR_quality = 4
} ENR_NodeAttribute;
typedef enum {
ENR_flow = 1,
ENR_velocity = 2,
ENR_headloss = 3,
ENR_avgQuality = 4,
ENR_status = 5,
ENR_setting = 6,
ENR_rxRate = 7,
ENR_frctnFctr = 8
} ENR_LinkAttribute;
#ifdef WINDOWS
#ifdef __cplusplus
#define DLLEXPORT __declspec(dllexport) __cdecl
#else
#define DLLEXPORT __declspec(dllexport) __stdcall
#endif
#else
#define DLLEXPORT
#endif
#ifdef __cplusplus
extern "C" {
#endif
int DLLEXPORT ENR_init(ENR_Handle* p_handle_out);
int DLLEXPORT ENR_open(ENR_Handle p_handle_in, const char* path);
int DLLEXPORT ENR_getVersion(ENR_Handle p_handle_in, int* int_out);
int DLLEXPORT ENR_getNetSize(ENR_Handle p_handle_in, int** int_out, int* int_dim);
int DLLEXPORT ENR_getUnits(ENR_Handle p_handle_in, ENR_Units t_enum, int* int_out);
int DLLEXPORT ENR_getTimes(ENR_Handle p_handle_in, ENR_Time t_enum, int* int_out);
int DLLEXPORT ENR_getElementName(ENR_Handle p_handle_in, ENR_ElementType t_enum,
int elementIndex, char** string_out, int* slen);
int DLLEXPORT ENR_getEnergyUsage(ENR_Handle p_handle_in, int pumpIndex,
int* int_out, float** float_out, int* int_dim);
int DLLEXPORT ENR_getNetReacts(ENR_Handle p_handle_in, float** float_out, int* int_dim);
int DLLEXPORT ENR_getNodeSeries(ENR_Handle p_handle_in, int nodeIndex, ENR_NodeAttribute t_enum,
int startPeriod, int endPeriod, float** outValueSeries, int* dim);
int DLLEXPORT ENR_getLinkSeries(ENR_Handle p_handle_in, int linkIndex, ENR_LinkAttribute t_enum,
int startPeriod, int endPeriod, float** outValueSeries, int* dim);
int DLLEXPORT ENR_getNodeAttribute(ENR_Handle p_handle_in, int periodIndex,
ENR_NodeAttribute t_enum, float** outValueArray, int* dim);
int DLLEXPORT ENR_getLinkAttribute(ENR_Handle p_handle_in, int periodIndex,
ENR_LinkAttribute t_enum, float** outValueArray, int* dim);
int DLLEXPORT ENR_getNodeResult(ENR_Handle p_handle_in, int periodIndex, int nodeIndex,
float** float_out, int* int_dim);
int DLLEXPORT ENR_getLinkResult(ENR_Handle p_handle_in, int periodIndex, int linkIndex,
float** float_out, int* int_dim);
int DLLEXPORT ENR_close(ENR_Handle* p_handle_out);
void DLLEXPORT ENR_free(void** array);
void DLLEXPORT ENR_clearError(ENR_Handle p_handle_in);
int DLLEXPORT ENR_checkError(ENR_Handle p_handle_in, char** msg_buffer);
#ifdef __cplusplus
}
#endif
#endif /* EPANET_OUTPUT_H_ */

View File

@@ -0,0 +1,254 @@
/*
* epanet_output.i - SWIG interface description file for EPANET Output API
*
* Created: 9/20/2017
*
* Author: Michael E. Tryby
* US EPA - ORD/NRMRL
*
*/
%module epanet_output
%{
#include "errormanager.h"
#include "messages.h"
#include "epanet_output.h"
#define SWIG_FILE_WITH_INIT
%}
%include "typemaps.i"
/* DEFINE AND TYPEDEF MUST BE INCLUDED */
#define MAXMSG 53
typedef void* ENR_Handle;
typedef enum {
ENR_node = 1,
ENR_link = 2
} ENR_ElementType;
/*
typedef enum {
ENR_nodeCount = 1,
ENR_tankCount = 2,
ENR_linkCount = 3,
ENR_pumpCount = 4,
ENR_valveCount = 5
} ENR_ElementCount;
*/
typedef enum {
ENR_flowUnits = 1,
ENR_pressUnits = 2
} ENR_Units;
typedef enum {
ENR_reportStart = 1,
ENR_reportStep = 2,
ENR_simDuration = 3,
ENR_numPeriods = 4
}ENR_Time;
typedef enum {
ENR_demand = 1,
ENR_head = 2,
ENR_pressure = 3,
ENR_quality = 4
} ENR_NodeAttribute;
typedef enum {
ENR_flow = 1,
ENR_velocity = 2,
ENR_headloss = 3,
ENR_avgQuality = 4,
ENR_status = 5,
ENR_setting = 6,
ENR_rxRate = 7,
ENR_frctnFctr = 8
} ENR_LinkAttribute;
#ifdef WINDOWS
#ifdef __cplusplus
#define DLLEXPORT __declspec(dllexport) __cdecl
#else
#define DLLEXPORT __declspec(dllexport) __stdcall
#endif
#else
#define DLLEXPORT
#endif
/* TYPEMAPS FOR OPAQUE POINTER */
/* Used for functions that output a new opaque pointer */
%typemap(in, numinputs=0) ENR_Handle* p_handle_out (ENR_Handle retval)
{
/* OUTPUT in */
retval = NULL;
$1 = &retval;
}
/* used for functions that take in an opaque pointer (or NULL)
and return a (possibly) different pointer */
%typemap(argout) ENR_Handle* p_handle_out
{
/* OUTPUT argout */
%append_output(SWIG_NewPointerObj(SWIG_as_voidptr(retval$argnum), $1_descriptor, 0));
}
/* No need for special IN typemap for opaque pointers, it works anyway */
/* TYPEMAP FOR IGNORING INT ERROR CODE RETURN VALUE */
%typemap(out) int {
$result = Py_None;
Py_INCREF($result);
}
/* TYPEMAPS FOR INT ARGUMENT AS RETURN VALUE */
%typemap(in, numinputs=0) int* int_out (int temp) {
$1 = &temp;
}
%typemap(argout) int* int_out {
%append_output(PyInt_FromLong(*$1));
}
/* TYPEMAP FOR MEMORY MANAGEMENT AND ENCODING OF STRINGS */
%typemap(in, numinputs=0)char** string_out (char* temp), int* slen (int temp){
$1 = &temp;
}
%typemap(argout)(char** string_out, int* slen) {
if (*$1) {
PyObject* o;
o = PyUnicode_FromStringAndSize(*$1, *$2);
$result = SWIG_Python_AppendOutput($result, o);
free(*$1);
}
}
/* TYPEMAPS FOR MEMORY MANAGEMNET OF FLOAT ARRAYS */
%typemap(in, numinputs=0)float** float_out (float* temp), int* int_dim (int temp){
$1 = &temp;
}
%typemap(argout) (float** float_out, int* int_dim) {
if (*$1) {
PyObject *o = PyList_New(*$2);
int i;
float* temp = *$1;
for(i=0; i<*$2; i++) {
PyList_SetItem(o, i, PyFloat_FromDouble((double)temp[i]));
}
$result = SWIG_Python_AppendOutput($result, o);
free(*$1);
}
}
/* TYPEMAPS FOR MEMORY MANAGEMENT OF INT ARRAYS */
%typemap(in, numinputs=0)int** int_out (long* temp), int* int_dim (int temp){
$1 = &temp;
}
%typemap(argout) (int** int_out, int* int_dim) {
if (*$1) {
PyObject *o = PyList_New(*$2);
int i;
long* temp = *$1;
for(i=0; i<*$2; i++) {
PyList_SetItem(o, i, PyInt_FromLong(temp[i]));
}
$result = SWIG_Python_AppendOutput($result, o);
free(*$1);
}
}
/* TYPEMAP FOR ENUMERATED TYPES */
%typemap(in) EnumeratedType (int val, int ecode = 0) {
if (PyObject_HasAttrString($input,"value")) {
PyObject* o;
o = PyObject_GetAttrString($input, "value");
ecode = SWIG_AsVal_int(o, &val);
}
else {
SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "$symname" "', argument " "$argnum"" of type '" "$ltype""'");
}
$1 = ($1_type)(val);
}
%apply EnumeratedType {ENR_ElementType, ENR_Units, ENR_Time, ENR_NodeAttribute, ENR_LinkAttribute}
/* RENAME FUNCTIONS PYTHON STYLE */
%rename("%(undercase)s") "";
/* INSERTS CUSTOM EXCEPTION HANDLING IN WRAPPER */
%exception
{
char* err_msg;
ENR_clearError(arg1);
$function
if (ENR_checkError(arg1, &err_msg))
{
PyErr_SetString(PyExc_Exception, err_msg);
SWIG_fail;
}
}
/* INSERT EXCEPTION HANDLING FOR THESE FUNCTIONS */
int DLLEXPORT ENR_open(ENR_Handle p_handle, const char* path);
int DLLEXPORT ENR_getVersion(ENR_Handle p_handle, int* int_out);
int DLLEXPORT ENR_getNetSize(ENR_Handle p_handle, int** int_out, int* int_dim);
int DLLEXPORT ENR_getUnits(ENR_Handle p_handle, ENR_Units t_enum, int* int_out);
int DLLEXPORT ENR_getTimes(ENR_Handle p_handle, ENR_Time t_enum, int* int_out);
int DLLEXPORT ENR_getElementName(ENR_Handle p_handle, ENR_ElementType t_enum,
int elementIndex, char** string_out, int* slen);
int DLLEXPORT ENR_getEnergyUsage(ENR_Handle p_handle, int pumpIndex,
int* int_out, float** float_out, int* int_dim);
int DLLEXPORT ENR_getNetReacts(ENR_Handle p_handle, float** float_out, int* int_dim);
int DLLEXPORT ENR_getNodeAttribute(ENR_Handle p_handle, int periodIndex,
ENR_NodeAttribute t_enum, float** float_out, int* int_dim);
int DLLEXPORT ENR_getLinkAttribute(ENR_Handle p_handle, int periodIndex,
ENR_LinkAttribute t_enum, float** float_out, int* int_dim);
%exception;
/* NO EXCEPTION HANDLING FOR THESE FUNCTIONS */
int DLLEXPORT ENR_init(ENR_Handle* p_handle_out);
int DLLEXPORT ENR_close(ENR_Handle* p_handle_out);
void DLLEXPORT ENR_free(void** array);
void DLLEXPORT ENR_clearError(ENR_Handle p_handle);
int DLLEXPORT ENR_checkError(ENR_Handle p_handle, char** msg_buffer);
/* CODE ADDED DIRECTLY TO SWIGGED INTERFACE MODULE */
%pythoncode%{
import enum
class ElementType(enum.Enum):
NODE = ENR_node
LINK = ENR_link
class Units(enum.Enum):
FLOW_UNIT = ENR_flowUnits
PRESS_UNIT = ENR_pressUnits
class Time(enum.Enum):
REPORT_START = ENR_reportStart
REPORT_STEP = ENR_reportStep
SIM_DURATION = ENR_simDuration
NUM_PERIODS = ENR_numPeriods
class NodeAttribute(enum.Enum):
DEMAND = ENR_demand
HEAD = ENR_head
PRESSURE = ENR_pressure
QUALITY = ENR_quality
class LinkAttribute(enum.Enum):
FLOW = ENR_flow
VELOCITY = ENR_velocity
HEADLOSS = ENR_headloss
AVG_QUALITY = ENR_avgQuality
STATUS = ENR_status
SETTING = ENR_setting
RX_RATE = ENR_rxRate
FRCTN_FCTR = ENR_frctnFctr
%}

View File

@@ -0,0 +1,74 @@
//-----------------------------------------------------------------------------
//
// errormanager.c
//
// Purpose: Provides a simple interface for managing runtime error messages.
//
// Date: 08/25/2017
//
// Author: Michael E. Tryby
// US EPA - ORD/NRMRL
//-----------------------------------------------------------------------------
#include <stdlib.h>
#include <string.h>
#include "errormanager.h"
error_handle_t* new_errormanager(void (*p_error_message)(int, char*, int))
//
// Purpose: Constructs a new error handle.
//
{
error_handle_t* error_handle;
error_handle = (error_handle_t*)calloc(1, sizeof(error_handle_t));
error_handle->p_msg_lookup = p_error_message;
return error_handle;
}
void dst_errormanager(error_handle_t* error_handle)
//
// Purpose: Destroys the error handle.
//
{
free(error_handle);
}
int set_error(error_handle_t* error_handle, int errorcode)
//
// Purpose: Sets an error code in the handle.
//
{
// If the error code is 0 no action is taken and 0 is returned.
// This is a feature not a bug.
if (errorcode)
error_handle->error_status = errorcode;
return errorcode;
}
char* check_error(error_handle_t* error_handle)
//
// Purpose: Returns the error message or NULL.
//
// Note: Caller must free memory allocated by check_error
//
{
char* temp = NULL;
if (error_handle->error_status != 0) {
temp = (char*) calloc(ERR_MAXMSG, sizeof(char));
if (temp)
error_handle->p_msg_lookup(error_handle->error_status, temp, ERR_MAXMSG);
}
return temp;
}
void clear_error(error_handle_t* error_handle)
//
// Purpose: Clears the error from the handle.
//
{
error_handle->error_status = 0;
}

View File

@@ -0,0 +1,27 @@
/*
* errormanager.h
*
* Created on: Aug 25, 2017
*
* Author: Michael E. Tryby
* US EPA - ORD/NRMRL
*/
#ifndef ERRORMANAGER_H_
#define ERRORMANAGER_H_
#define ERR_MAXMSG 256
typedef struct error_s {
int error_status;
void (*p_msg_lookup)(int, char*, int);
} error_handle_t;
error_handle_t* new_errormanager(void (*p_error_message)(int, char*, int));
void dst_errormanager(error_handle_t* error_handle);
int set_error(error_handle_t* error_handle, int errorcode);
char* check_error(error_handle_t* error_handle);
void clear_error(error_handle_t* error_handle);
#endif /* ERRORMANAGER_H_ */

View File

@@ -0,0 +1,29 @@
/*
* messages.h - EPANET
*
* Created on: June 1, 2017
*
* Author: Michael E. Tryby
* US EPA - ORD/NRMRL
*/
#ifndef MESSAGES_H_
#define MESSAGES_H_
/*------------------- Error Messages --------------------*/
#define MAXMSG 53
#define WARN10 "Warning: model run issued warnings"
#define ERR411 "Input Error 411: no memory allocated for results"
#define ERR412 "Input Error 412: binary file hasn't been opened"
#define ERR421 "Input Error 421: invalid parameter code"
#define ERR422 "Input Error 422: reporting period index out of range"
#define ERR423 "Input Error 423: element index out of range"
#define ERR434 "File Error 434: unable to open binary file"
#define ERR435 "File Error 435: invalid binary file type"
#define ERR436 "File Error 436: no results in binary file"
#define ERRERR "Error: An unknown error has occurred"
#endif /* MESSAGES_H_ */

View File

@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
# __init__.py
#
# Created: 11/13/2017
# Author: Michael E. Tryby
# US EPA - ORD/NRMRL
#
import os
DATA_PATH = os.path.abspath(os.path.dirname(__file__))
OUTPUT_FILE_EXAMPLE1 = os.path.join(DATA_PATH, 'net1.out')

Binary file not shown.

View File

@@ -0,0 +1,102 @@
#
# epanet_output_test.py
#
# Created: 11/8/2017
# Author: Michael E. Tryby
# US EPA - ORD/NRMRL
#
# Unit testing for EPANET Output API using pytest.
#
import pytest
import numpy as np
import epanet_output as oapi
from data import OUTPUT_FILE_EXAMPLE1
@pytest.fixture()
def enr_handle(request):
_handle = oapi.enr_init()
oapi.enr_open(_handle, OUTPUT_FILE_EXAMPLE1)
def enr_close():
oapi.enr_close()
request.addfinalizer(enr_close)
return _handle
def test_get_times(enr_handle):
num_periods = oapi.enr_get_times(enr_handle, oapi.Time.NUM_PERIODS)
assert num_periods == 25
# def test_get_size(file_path):
# handle = oapi.enr_init()
# oapi.enr_open(handle, file_path)
#
# size = oapi.enr_get_net_size(handle)
#
# print(size)
#
# handle = oapi.enr_close()
#
# def test_get_names(file_path):
# handle = oapi.enr_init()
# oapi.enr_open(handle, file_path)
#
# name = oapi.enr_get_element_name(handle, oapi.ElementType.NODE, 10)
#
# print(name)
#
# handle = oapi.enr_close()
#
# def test_get_energy(file_path):
# handle = oapi.enr_init()
# oapi.enr_open(handle, file_path)
#
# result = oapi.enr_get_energy_usage(handle, 1)
#
# print(result)
#
# handle = oapi.enr_close()
#
# def test_get_react(file_path):
# handle = oapi.enr_init()
# oapi.enr_open(handle, file_path)
#
# result = oapi.enr_get_net_reacts(handle)
#
# print(result)
#
# handle = oapi.enr_close()
#
def test_get_node_attribute(enr_handle):
ref_array = np.array([ 1., 0.44407997, 0.43766347, 0.42827705, 0.41342604,
0.42804748, 0.44152543, 0.40502965, 0.38635802, 1., 0.96745253])
array = oapi.enr_get_node_attribute(enr_handle, 1, oapi.NodeAttribute.QUALITY)
assert len(array) == 11
assert np.allclose(array, ref_array)
def test_get_link_attribute(enr_handle):
ref_array = np.array([ 1848.58117676, 1220.42736816, 130.11161804,
187.68930054, 119.88839722, 40.46448898, -748.58111572, 478.15377808,
191.73458862, 30.11160851, 140.4644928, 59.53551483, 1848.58117676])
array = oapi.enr_get_link_attribute(enr_handle, 1, oapi.LinkAttribute.FLOW)
assert len(array) == 13
assert np.allclose(array, ref_array)
# if __name__ == "__main__":
#
# file_path = "M:\\net mydocuments\\EPA Projects\\EPAnet Examples\\net1.out"
# test_get_times(file_path)
# test_get_size(file_path)
# test_get_names(file_path)
# test_get_energy(file_path)
# test_get_react(file_path)
# test_get_node_attribute(file_path)
# test_get_link_attribute(file_path)
#

View File

@@ -0,0 +1,251 @@
/*
* test_epanet_output.cpp
*
* Created: 8/4/2017
* Author: Michael E. Tryby
* US EPA - ORD/NRMRL
*
* Unit testing for EPANET Output API using google test.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include "gtest/gtest.h"
#include "../src/epanet_output.h"
#define PROJECT_HOME "C:/Users/mtryby/Workspace/GitRepo/michaeltryby/epanet/"
#define DATA_PATH "tools/epanet-output/test/data/net1.out"
namespace {
TEST(ENR_init, InitTest) {
ENR_Handle p_handle;
int error = ENR_init(&p_handle);
ASSERT_EQ(0, error);
ASSERT_TRUE(p_handle != NULL);
}
TEST(ENR_open, OpenTest) {
std::string path = std::string(PROJECT_HOME) + std::string(DATA_PATH);
ENR_Handle p_handle;
ENR_init(&p_handle);
int error = ENR_open(p_handle, path.c_str());
ASSERT_EQ(0, error);
ENR_close(&p_handle);
}
TEST(ENR_close, CloseTest) {
ENR_Handle p_handle;
int error = ENR_init(&p_handle);
error = ENR_close(&p_handle);
ASSERT_EQ(-1, error);
ASSERT_TRUE(p_handle != NULL);
}
class OutputapiTest : public testing::Test {
protected:
// SetUp for OutputapiTest fixture
virtual void SetUp() {
std::string path = std::string(PROJECT_HOME) + std::string(DATA_PATH);
error = ENR_init(&p_handle);
ENR_clearError(p_handle);
error = ENR_open(p_handle, path.c_str());
}
// TearDown for OutputapiTest fixture
virtual void TearDown() {
ENR_free((void**)&array);
error = ENR_close(&p_handle);
}
int error = 0;
ENR_Handle p_handle = NULL;
float* array = NULL;
int array_dim = 0;
};
TEST_F(OutputapiTest, getNetSizeTest) {
int* i_array = NULL;
// nodes, tanks, links, pumps, valves
int ref_array[5] = {11,2,13,1,0};
error = ENR_getNetSize(p_handle, &i_array, &array_dim);
ASSERT_EQ(0, error);
for (int i = 0; i < array_dim; i++)
EXPECT_EQ(ref_array[i], i_array[i]);
ENR_free((void**)&i_array);
}
TEST_F(OutputapiTest, getElementName) {
char* name = new char[MAXID];
int length, index = 1;
error = ENR_getElementName(p_handle, ENR_node, index, &name, &length);
ASSERT_EQ(0, error);
EXPECT_STREQ("10", name);
delete(name);
}
TEST_F(OutputapiTest, getNodeAttributeTest) {
float ref_array[11] = { 1.0,
0.44407997,
0.43766347,
0.42827705,
0.41342604,
0.42804748,
0.44152543,
0.40502965,
0.38635802,
1.0,
0.96745253 };
error = ENR_getNodeAttribute(p_handle, 1, ENR_quality, &array, &array_dim);
ASSERT_EQ(0, error);
for (int i = 0; i < array_dim; i++)
EXPECT_FLOAT_EQ(ref_array[i], array[i]);
}
TEST_F(OutputapiTest, getLinkAttributeTest) {
float ref_array[13] = { 1848.5812,
1220.4274,
130.11162,
187.6893,
119.8884,
40.464489,
-748.58112,
478.15378,
191.73459,
30.111609,
140.46449,
59.535515,
1848.5812};
error = ENR_getLinkAttribute(p_handle, 1, ENR_flow, &array ,&array_dim);
ASSERT_EQ(0, error);
for (int i = 0; i < array_dim; i++)
EXPECT_FLOAT_EQ(ref_array[i], array[i]);
}
TEST_F(OutputapiTest, getNodeResultTest) {
float ref_array[4] = {0.041142918,
150.0,
987.98358,
120.45029};
error = ENR_getNodeResult(p_handle, 1, 2, &array, &array_dim);
ASSERT_EQ(0, error);
for (int i = 0; i < array_dim; i++)
EXPECT_FLOAT_EQ(ref_array[i], array[i]);
}
TEST_F(OutputapiTest, getLinkResultTest) {
float ref_array[8] = {0.58586824,
1892.2433,
0.0,
-200.71875,
1.0,
3.0,
1.0,
0.0};
error = ENR_getLinkResult(p_handle, 24, 13, &array, &array_dim);
ASSERT_EQ(0, error);
for (int i = 0; i < array_dim; i++)
EXPECT_FLOAT_EQ(ref_array[i], array[i]);
}
TEST_F(OutputapiTest, getNodeSeriesTest){
float ref_array[10] = {119.25731,
120.45029,
121.19854,
122.00622,
122.37414,
122.8122,
122.82034,
122.90379,
123.40434,
123.81807};
error = ENR_getNodeSeries(p_handle, 2, ENR_pressure, 0, 10, &array, &array_dim);
ASSERT_EQ(0, error);
for (int i = 0; i < array_dim; i++)
EXPECT_FLOAT_EQ(ref_array[i], array[i]);
}
TEST_F(OutputapiTest, getLinkSeriesTest) {
float ref_array[10] = {1234.2072,
1220.4274,
1164.4,
1154.8175,
1100.0635,
1094.759,
1041.7854,
1040.7617,
1087.556,
1082.5011};
error = ENR_getLinkSeries(p_handle, 2, ENR_flow, 0, 10, &array, &array_dim);
ASSERT_EQ(0, error);
for (int i = 0; i < array_dim; i++)
EXPECT_FLOAT_EQ(ref_array[i], array[i]);
}
TEST_F(OutputapiTest, getNetReactsTest) {
float ref_array[4] = {18806.59,
85424.438,
115174.05,
238972.66};
error = ENR_getNetReacts(p_handle, &array, &array_dim);
ASSERT_EQ(0, error);
for (int i = 0; i < array_dim; i++)
EXPECT_FLOAT_EQ(ref_array[i], array[i]);
}
TEST_F(OutputapiTest, getEnergyUsageTest) {
float ref_array[6] = {57.712959,
75.0,
880.41583,
96.254318,
96.707115,
0.0};
int linkIdx;
error = ENR_getEnergyUsage(p_handle, 1, &linkIdx, &array, &array_dim);
ASSERT_EQ(0, error);
for (int i = 0; i < array_dim; i++)
EXPECT_FLOAT_EQ(ref_array[i], array[i]);
}
}
GTEST_API_ int main(int argc, char **argv) {
printf("Running main() from gtest_main.cc\n");
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

46
tools/gen-config.sh Executable file
View File

@@ -0,0 +1,46 @@
#! /bin/bash
#
# gen-config.sh - Generates nrtest app configuration file for test executable
#
# Date Created: 10/16/2017
#
# Author: Michael E. Tryby
# US EPA - ORD/NRMRL
#
# Arguments:
# 1 - absolute path to test executable
#
# NOT IMPLEMENTED YET
# 2 - test executable version number
# 3 - build description
#
unameOut="$(uname -s)"
case "${unameOut}" in
Linux*) ;&
Darwin*) abs_build_path=$1
test_cmd="runepanet"
;;
MINGW*) ;&
MSYS*) # Remove leading '/c' from file path for nrtest
abs_build_path="$( echo "$1" | sed -e 's#/c##' )"
test_cmd="runepanet.exe"
;;
*) # Machine unknown
esac
version=""
build_description=""
cat<<EOF
{
"name" : "epanet",
"version" : "${version}",
"description" : "${build_description}",
"setup_script" : "",
"exe" : "${abs_build_path}/${test_cmd}"
}
EOF

136
tools/nrtest-epanet/main.py Normal file
View File

@@ -0,0 +1,136 @@
import numpy as np
import time
import cStringIO
import itertools as it
import epanet_reader as er
def result_compare(path_test, path_ref, comp_args):
isclose = True
close = 0
notclose = 0
equal = 0
total = 0
output = cStringIO.StringIO()
eps = np.finfo(float).eps
start = time.time()
test_reader = er.reader(path_test)
ref_reader = er.reader(path_ref)
for test, ref in it.izip(test_reader, ref_reader):
total += 1
if total%100000 == 0:
print(total)
if test.size != ref.size:
raise ValueError('Inconsistent lengths')
# Skip results if they are zero or equal
if np.array_equal(test, ref):
equal += 1
continue
else:
try:
np.testing.assert_allclose(test, ref, 1.0e-06, 2*eps)
close += 1
except AssertionError as ae:
notclose += 1
output.write(str(ae))
output.write('\n\n')
continue
stop = time.time()
print(output.getvalue())
output.close()
print('equal: %d close: %d notclose: %d total: %d in %f (sec)\n' %
(equal, close, notclose, total, (stop - start)))
if notclose > 0:
print('%d differences found\n' % notclose)
isclose = False
return isclose
from nrtest.testsuite import TestSuite
from nrtest.compare import compare_testsuite, validate_testsuite
def nrtest_compare(path_test, path_ref, (comp_args)):
ts_new = TestSuite.read_benchmark(path_test)
ts_old = TestSuite.read_benchmark(path_ref)
if not validate_testsuite(ts_new) or not validate_testsuite(ts_old):
exit(1)
try:
# logging.info('Found %i tests' % len(ts_new.tests))
compatible = compare_testsuite(ts_new, ts_old, comp_args[0], comp_args[1])
except KeyboardInterrupt:
# logging.warning('Process interrupted by user')
compatible = False
# else:
# logging.info('Finished')
# Non-zero exit code indicates failure
exit(not compatible)
def nrtest_execute(app_path, test_path, output_path):
import logging
import glob
from os import listdir
from os.path import exists, isfile, isdir, join
from nrtest.execute import execute_testsuite, validate_testsuite
# for path in test_path + [app_path]:
# if not exists(path):
# logging.error('Could not find path: "%s"' % path)
test_dirs = glob.glob(test_path)
test_files = [p for p in test_path if isfile(p)]
test_files += [p for d in test_dirs for p in glob.glob(d + '*.json')]
# if p.endswith('.json')]
test_files = list(set(test_files)) # remove duplicates
ts = TestSuite.read_config(app_path, test_files, output_path)
if not validate_testsuite(ts):
exit(1)
try:
logging.info('Found %i tests' % len(test_files))
success = execute_testsuite(ts)
ts.write_manifest()
except KeyboardInterrupt:
logging.warning('Process interrupted by user')
success = False
else:
logging.info('Finished')
# Non-zero exit code indicates failure
exit(not success)
if __name__ == "__main__":
# app_path = "apps\\swmm-5.1.11.json"
# test_path = "tests\\examples\\example1.json"
# output_path = "benchmarks\\test\\"
# nrtest_execute(app_path, test_path, output_path)
# test_path = "C:\\Users\\mtryby\\Workspace\\GitRepo\\Local\\epanet-testsuite\\benchmarks\\v2011a"
# ref_path = "C:\\Users\\mtryby\\Workspace\\GitRepo\\Local\\epanet-testsuite\\benchmarks\\v2012"
# print(nrtest_compare(test_path, ref_path, (0.001, 0.0)))
path_test = "C:\\Users\\mtryby\\Workspace\\GitRepo\\Local\\epanet-testsuite\\benchmarks\\v2011a\\Example_3\\example3.out"
path_ref = "C:\\Users\\mtryby\\Workspace\\GitRepo\\Local\\epanet-testsuite\\benchmarks\\v2012\\Example_3\\example3.out"
result_compare(path_test, path_ref, (0.001, 0.0))

View File

@@ -0,0 +1,121 @@
# -*- coding: utf-8 -*-
#
# __init__.py - nrtest_epanet module
#
# Author: Michael E. Tryby
# US EPA - ORD/NRMRL
#
'''
Numerical regression testing (nrtest) plugin for comparing EPANET binary results
files and EPANET text based report files.
'''
# system imports
import itertools as it
# third party imports
import header_detail_footer as hdf
import numpy as np
# project import
import nrtest_epanet.output_reader as ordr
__author__ = "Michael Tryby"
__copyright__ = "None"
__credits__ = "Colleen Barr, Maurizio Cingi, Mark Gray, David Hall, Bryant McDonnell"
__license__ = "CC0 1.0 Universal"
__version__ = "0.4.0"
__date__ = "September 6, 2017"
__maintainer__ = "Michael Tryby"
__email__ = "tryby.michael@epa.gov"
__status = "Development"
def epanet_allclose_compare(path_test, path_ref, rtol, atol):
'''
Compares results in two EPANET binary files. Using the comparison criteria
described in the numpy assert_allclose documentation.
(test_value - ref_value) <= atol + rtol * abs(ref_value)
Returns true if all of the results in the two binary files meet the
comparison criteria; otherwise, an AssertionError is thrown.
Numpy allclose is quite expensive to evaluate. Test and reference results
are checked to see if they are equal before being compared using the
allclose criteria. This reduces comparison times significantly.
Arguments:
path_test - path to result file being tested
path_ref - path to reference result file
rtol - relative tolerance
atol - absolute tolerance
Returns:
True
Raises:
ValueError()
AssertionError()
...
'''
for (test, ref) in it.izip(ordr.output_generator(path_test),
ordr.output_generator(path_ref)):
if len(test) != len(ref):
raise ValueError('Inconsistent lengths')
# Skip over arrays that are equal
if np.array_equal(test, ref):
continue
else:
np.testing.assert_allclose(test, ref, rtol, atol)
return True
# def epanet_better_compare(path_test, path_ref, rtol, atol):
# '''
# If you don't like assert_allclose you can add another function here.
# '''
# pass
def epanet_report_compare(path_test, path_ref, rtol, atol):
'''
Compares results in two report files ignoring contents of header and footer.
Note: Header is 11 lines with report summary turned off. This test will fail
if the report summary is turned on because a time stamp is being written
immediately after it.
Arguments:
path_test - path to result file being tested
path_ref - path to reference result file
rtol - ignored
atol - ignored
Returns:
True or False
Raises:
HeaderError()
FooterError()
RunTimeError()
...
'''
HEADER = 11
FOOTER = 3
with open(path_test ,'r') as ftest, open(path_ref, 'r') as fref:
for (test_line, ref_line) in it.izip(hdf.parse(ftest, HEADER, FOOTER)[1],
hdf.parse(fref, HEADER, FOOTER)[1]):
if test_line != ref_line:
return False
return True

View File

@@ -0,0 +1,69 @@
# -*- coding: utf-8 -*-
#
# output_reader.py
#
# Date Created: Aug 31, 2016
#
# Author: Michael E. Tryby
# US EPA - ORD/NRMRL
#
'''
The module output_reader provides the class used to implement the output
generator.
'''
# project import
import epanet_output as oapi
def output_generator(path_ref):
'''
The output_generator is designed to iterate over an EPANET binary file and
yield element attributes. It is useful for comparing contents of binary
files for numerical regression testing.
The generator yields a Python list containing element attributes.
Arguments:
path_ref - path to result file
Raises:
Exception()
...
'''
with OutputReader(path_ref) as br:
for period_index in range(0, br.report_periods()):
for element_type in oapi.ElementType:
for attribute in br.elementAttributes[element_type]:
yield br.element_attribute(element_type, period_index, attribute)
class OutputReader():
'''
Provides a minimal API used to implement output_generator.
'''
def __init__(self, filename):
self.filepath = filename
self.handle = None
self.elementAttributes = {oapi.ElementType.NODE: oapi.NodeAttribute,
oapi.ElementType.LINK: oapi.LinkAttribute}
self.getElementAttribute = {oapi.ElementType.NODE: oapi.enr_get_node_attribute,
oapi.ElementType.LINK: oapi.enr_get_link_attribute}
def __enter__(self):
self.handle = oapi.enr_init()
oapi.enr_open(self.handle, self.filepath.encode())
return self
def __exit__(self, type, value, traceback):
self.handle = oapi.enr_close()
def report_periods(self):
return oapi.enr_get_times(self.handle, oapi.Time.NUM_PERIODS)
def element_attribute(self, element_type, time_index, attribute):
return self.getElementAttribute[element_type](self.handle, time_index, attribute)

View File

@@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
#
# setup.py
#
# Created on Aug 30, 2016
# Author: Michael E. Tryby
# US EPA - ORD/NRMRL
#
''' Setup up script for nrtest_epanet package. '''
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
entry_points = {
'nrtest.compare': [
'epanet allclose = nrtest_epanet:epanet_allclose_compare',
'epanet report = nrtest_epanet:epanet_report_compare',
# Add entry point for new comparison functions here
]
}
setup(
name='nrtest-epanet',
version='0.3.0',
description="EPANET extension for nrtest",
author="Michael E. Tryby",
author_email='tryby.michael@epa.gov',
url='https://github.com/USEPA',
packages=['nrtest_epanet',],
entry_points=entry_points,
install_requires=[
'header_detail_footer>=2.3',
'nrtest>=0.2.0',
'numpy>=1.7.0',
'epanet_output>=0.4.0'
],
keywords='nrtest_epanet'
)

View File

@@ -1 +0,0 @@
'''

File diff suppressed because one or more lines are too long

View File

@@ -1,502 +0,0 @@
//-----------------------------------------------------------------------------
//
// outputapi.c -- API for reading results from EPANet binary output file
//
// Version: 0.10
// Date: 08/05/14
// Date: 05/21/14
//
// Author: Michael E. Tryby
// US EPA - NRMRL
//
// Purpose: Output API provides an interface for retrieving results from
// an EPANet binary output file.
//
//-----------------------------------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "outputapi.h"
#define INT4 int
#define REAL4 float
#define RECORDSIZE 4 // number of bytes per file record
#define MEMCHECK(x) (((x) == NULL) ? 411 : 0 )
#define MINNREC 14 // minimum allowable number of records
#define NNODERESULTS 4 // number of result fields for nodes
#define NLINKRESULTS 8 // number of result fields for links
struct ENResultsAPI {
char name[MAXFNAME + 1]; // file path/name
bool isOpened; // current state (CLOSED = 0, OPEN = 1)
FILE *file; // FILE structure pointer
INT4 nodeCount, tankCount, linkCount, pumpCount, valveCount;
INT4 reportStart, reportStep, simDuration, nPeriods;
INT4 flowFlag, pressFlag;
INT4 outputStartPos; // starting file position of output data
INT4 bytesPerPeriod; // bytes saved per simulation time period
};
//-----------------------------------------------------------------------------
// Local functions
//-----------------------------------------------------------------------------
float getNodeValue(ENResultsAPI*, int, int, ENR_NodeAttribute);
float getLinkValue(ENResultsAPI*, int, int, ENR_LinkAttribute);
ENResultsAPI* DLLEXPORT ENR_alloc(void)
{
return malloc(sizeof(struct ENResultsAPI));
}
int DLLEXPORT ENR_open(ENResultsAPI* enrapi, const char* path)
//
// Purpose: Open the output binary file and read epilogue
//
{
int magic1, magic2, errCode, version;
strncpy(enrapi->name, path, MAXFNAME);
enrapi->isOpened = false;
// Attempt to open binary output file for reading only
if ((enrapi->file = fopen(path, "rb")) == NULL)
return 434;
else
enrapi->isOpened = true;
// Fast forward to end and check for minimum number of records
fseek(enrapi->file, 0L, SEEK_END);
if (ftell(enrapi->file) < MINNREC*RECORDSIZE) {
fclose(enrapi->file);
// Error run terminated no results in binary file
return 435;
}
// Fast forward to end and read file epilogue
fseek(enrapi->file, -3*RECORDSIZE, SEEK_END);
fread(&(enrapi->nPeriods), RECORDSIZE, 1, enrapi->file);
fread(&errCode, RECORDSIZE, 1, enrapi->file);
fread(&magic2, RECORDSIZE, 1, enrapi->file);
// Rewind and read magic number from beginning of file
fseek(enrapi->file, 0L, SEEK_SET);
fread(&magic1, RECORDSIZE, 1, enrapi->file);
// Perform error checks
if (magic1 != magic2 || errCode != 0 || enrapi->nPeriods == 0) {
fclose(enrapi->file);
// Error run terminated no results in binary file
return 435;
}
// Otherwise read network size
fread(&version, RECORDSIZE, 1, enrapi->file);
fread(&(enrapi->nodeCount), RECORDSIZE, 1, enrapi->file);
fread(&(enrapi->tankCount), RECORDSIZE, 1, enrapi->file);
fread(&(enrapi->linkCount), RECORDSIZE, 1, enrapi->file);
fread(&(enrapi->pumpCount), RECORDSIZE, 1, enrapi->file);
// Jump ahead and read flow and pressure units
fseek(enrapi->file, 3*RECORDSIZE, SEEK_CUR);
fread(&(enrapi->flowFlag), RECORDSIZE, 1, enrapi->file);
fread(&(enrapi->pressFlag), RECORDSIZE, 1, enrapi->file);
// Jump ahead and read time information
fseek(enrapi->file, RECORDSIZE, SEEK_CUR);
fread(&(enrapi->reportStart), RECORDSIZE, 1, enrapi->file);
fread(&(enrapi->reportStep), RECORDSIZE, 1, enrapi->file);
fread(&(enrapi->simDuration), RECORDSIZE, 1, enrapi->file);
// Compute positions and offsets for retrieving data
enrapi->outputStartPos = 884;
enrapi->outputStartPos += 32*enrapi->nodeCount + 32*enrapi->linkCount;
enrapi->outputStartPos += 12*enrapi->linkCount+ 8*enrapi->tankCount
+ 4*enrapi->nodeCount + 8*enrapi->linkCount;
enrapi->outputStartPos += 28*enrapi->pumpCount + 4;
enrapi->bytesPerPeriod = 16*enrapi->nodeCount + 32*enrapi->linkCount;
return 0;
}
int DLLEXPORT ENR_getNetSize(ENResultsAPI* enrapi, ENR_ElementCount code, int* count)
//
// Purpose: Returns network size
//
{
*count = -1;
if (enrapi->isOpened) {
switch (code)
{
case ENR_nodeCount: *count = enrapi->nodeCount; break;
case ENR_tankCount: *count = enrapi->tankCount; break;
case ENR_linkCount: *count = enrapi->linkCount; break;
case ENR_pumpCount: *count = enrapi->pumpCount; break;
case ENR_valveCount: *count = enrapi->valveCount; break;
default: return 421;
}
return 0;
}
return 412;
}
int DLLEXPORT ENR_getUnits(ENResultsAPI* enrapi, ENR_Unit code, int* unitFlag)
//
// Purpose: Returns pressure and flow units
//
{
*unitFlag = -1;
if (enrapi->isOpened) {
switch (code)
{
case ENR_flowUnits: *unitFlag = enrapi->flowFlag; break;
case ENR_pressUnits: *unitFlag = enrapi->pressFlag; break;
default: return 421;
}
return 0;
}
return 412;
}
int DLLEXPORT ENR_getTimes(ENResultsAPI* enrapi, ENR_Time code, int* time)
//
// Purpose: Returns report and simulation time related parameters.
//
{
*time = -1;
if (enrapi->isOpened) {
switch (code)
{
case ENR_reportStart: *time = enrapi->reportStart; break;
case ENR_reportStep: *time = enrapi->reportStep; break;
case ENR_simDuration: *time = enrapi->simDuration; break;
case ENR_numPeriods: *time = enrapi->nPeriods; break;
default: return 421;
}
return 0;
}
return 412;
}
float* ENR_newOutValueSeries(ENResultsAPI* enrapi, int seriesStart,
int seriesLength, int* length, int* errcode)
//
// Purpose: Allocates memory for outValue Series.
//
// Warning: Caller must free memory allocated by this function using ENR_free().
//
{
int size;
float* array;
if (enrapi->isOpened) {
size = seriesLength - seriesStart;
if (size > enrapi->nPeriods)
size = enrapi->nPeriods;
// Allocate memory for outValues
array = (float*) calloc(size + 1, sizeof(float));
*errcode = (MEMCHECK(array));
*length = size;
return array;
}
*errcode = 412;
return NULL;
}
float* ENR_newOutValueArray(ENResultsAPI* enrapi, ENR_ApiFunction func,
ENR_ElementType type, int* length, int* errcode)
//
// Purpose: Allocates memory for outValue Array.
//
// Warning: Caller must free memory allocated by this function using ENR_free().
//
{
int size;
float* array;
if (enrapi->isOpened) {
switch (func)
{
case ENR_getAttribute:
if (type == ENR_node)
size = enrapi->nodeCount;
else
size = enrapi->linkCount;
break;
case ENR_getResult:
if (type == ENR_node)
size = NNODERESULTS;
else
size = NLINKRESULTS;
break;
default: *errcode = 421;
return NULL;
}
// Allocate memory for outValues
array = (float*) calloc(size, sizeof(float));
*errcode = (MEMCHECK(array));
*length = size;
return array;
}
*errcode = 412;
return NULL;
}
int DLLEXPORT ENR_getNodeSeries(ENResultsAPI* enrapi, int nodeIndex, ENR_NodeAttribute attr,
int seriesStart, int seriesLength, float* outValueSeries, int* length)
//
// What if timeIndex 0? length 0?
//
// Purpose: Get time series results for particular attribute. Specify series
// start and length using seriesStart and seriesLength respectively.
//
{
int k;
if (enrapi->isOpened) {
// Check memory for outValues
if (outValueSeries == NULL) return 411;
// loop over and build time series
for (k = 0; k <= seriesLength; k++)
outValueSeries[k] = getNodeValue(enrapi, seriesStart + 1 + k,
nodeIndex, attr);
return 0;
}
// Error no results to report on binary file not opened
return 412;
}
int DLLEXPORT ENR_getLinkSeries(ENResultsAPI* enrapi, int linkIndex, ENR_LinkAttribute attr,
int seriesStart, int seriesLength, float* outValueSeries)
//
// What if timeIndex 0? length 0?
//
// Purpose: Get time series results for particular attribute. Specify series
// start and length using seriesStart and seriesLength respectively.
//
{
int k;
if (enrapi->isOpened) {
// Check memory for outValues
if (outValueSeries == NULL) return 411;
// loop over and build time series
for (k = 0; k <= seriesLength; k++)
outValueSeries[k] = getLinkValue(enrapi, seriesStart +1 + k,
linkIndex, attr);
return 0;
}
// Error no results to report on binary file not opened
return 412;
}
int DLLEXPORT ENR_getNodeAttribute(ENResultsAPI* enrapi, int timeIndex,
ENR_NodeAttribute attr, float* outValueArray)
//
// Purpose: For all nodes at given time, get a particular attribute
//
{
INT4 offset;
if (enrapi->isOpened) {
// Check memory for outValues
if (outValueArray == NULL) return 411;
// calculate byte offset to start time for series
offset = enrapi->outputStartPos + (timeIndex)*enrapi->bytesPerPeriod;
// add offset for node and attribute
offset += (attr*enrapi->nodeCount)*RECORDSIZE;
fseek(enrapi->file, offset, SEEK_SET);
fread(outValueArray, RECORDSIZE, enrapi->nodeCount, enrapi->file);
return 0;
}
// Error no results to report on binary file not opened
return 412;
}
int DLLEXPORT ENR_getLinkAttribute(ENResultsAPI* enrapi, int timeIndex,
ENR_LinkAttribute attr, float* outValueArray)
//
// Purpose: For all links at given time, get a particular attribute
//
{
INT4 offset;
if (enrapi->isOpened) {
// Check memory for outValues
if (outValueArray == NULL) return 411;
// calculate byte offset to start time for series
offset = enrapi->outputStartPos + (timeIndex)*enrapi->bytesPerPeriod
+ (NNODERESULTS*enrapi->nodeCount)*RECORDSIZE;
// add offset for link and attribute
offset += (attr*enrapi->linkCount)*RECORDSIZE;
fseek(enrapi->file, offset, SEEK_SET);
fread(outValueArray, RECORDSIZE, enrapi->linkCount, enrapi->file);
return 0;
}
// Error no results to report on binary file not opened
return 412;
}
int DLLEXPORT ENR_getNodeResult(ENResultsAPI* enrapi, int timeIndex, int nodeIndex,
float* outValueArray)
//
// Purpose: For a node at given time, get all attributes
//
{
int j;
if (enrapi->isOpened) {
// Check memory for outValues
if (outValueArray == NULL) return 411;
for (j = 0; j < NNODERESULTS; j++)
outValueArray[j] = getNodeValue(enrapi, timeIndex + 1, nodeIndex, j);
return 0;
}
// Error no results to report on binary file not opened
return 412;
}
int DLLEXPORT ENR_getLinkResult(ENResultsAPI* enrapi, int timeIndex, int linkIndex,
float* outValueArray)
//
// Purpose: For a link at given time, get all attributes
//
{
int j;
if (enrapi->isOpened) {
// Check memory for outValues
if (outValueArray == NULL) return 411;
for (j = 0; j < NLINKRESULTS; j++)
outValueArray[j] = getLinkValue(enrapi, timeIndex + 1, linkIndex, j);
return 0;
}
// Error no results to report on binary file not opened
return 412;
}
int DLLEXPORT ENR_free(float* array)
//
// Purpose: frees memory allocated using ENR_newOutValueSeries() or
// ENR_newOutValueArray()
//
{
if (array != NULL)
free(array);
return 0;
}
int DLLEXPORT ENR_close(ENResultsAPI* enrapi)
//
// Purpose: Clean up after and close Output API
//
{
if (enrapi->isOpened) {
fclose(enrapi->file);
free(enrapi);
}
// Error binary file not opened
else return 412;
return 0;
}
int DLLEXPORT ENR_errMessage(int errcode, char* errmsg, int n)
//
// Purpose: takes error code returns error message
//
// Input Error 411: no memory allocated for results
// Input Error 412: no results binary file hasn't been opened
// Input Error 421: invalid parameter code
// File Error 434: unable to open binary output file
// File Error 435: run terminated no results in binary file
{
switch (errcode)
{
case 411: strncpy(errmsg, ERR411, n); break;
case 412: strncpy(errmsg, ERR412, n); break;
case 421: strncpy(errmsg, ERR421, n); break;
case 434: strncpy(errmsg, ERR434, n); break;
case 435: strncpy(errmsg, ERR435, n); break;
default: return 421;
}
return 0;
}
float getNodeValue(ENResultsAPI* enrapi, int timeIndex, int nodeIndex,
ENR_NodeAttribute attr)
//
// Purpose: Retrieves an attribute value at a specified node and time
//
{
REAL4 y;
INT4 offset;
// calculate byte offset to start time for series
offset = enrapi->outputStartPos + (timeIndex - 1)*enrapi->bytesPerPeriod;
// add bytepos for node and attribute
offset += (nodeIndex + attr*enrapi->nodeCount)*RECORDSIZE;
fseek(enrapi->file, offset, SEEK_SET);
fread(&y, RECORDSIZE, 1, enrapi->file);
return y;
}
float getLinkValue(ENResultsAPI* enrapi, int timeIndex, int linkIndex,
ENR_LinkAttribute attr)
//
// Purpose: Retrieves an attribute value at a specified link and time
//
{
REAL4 y;
INT4 offset;
// Calculate byte offset to start time for series
offset = enrapi->outputStartPos + (timeIndex - 1)*enrapi->bytesPerPeriod
+ (NNODERESULTS*enrapi->nodeCount)*RECORDSIZE;
// add bytepos for link and attribute
offset += (linkIndex + attr*enrapi->linkCount)*RECORDSIZE;
fseek(enrapi->file, offset, SEEK_SET);
fread(&y, RECORDSIZE, 1, enrapi->file);
return y;
}

View File

@@ -1,122 +0,0 @@
/*
* outputapi.h
*
* Created on: Jun 4, 2014
* Author: mtryby
*/
#ifndef OUTPUTAPI_H_
#define OUTPUTAPI_H_
#define MAXFNAME 259
/*------------------- Error Messages --------------------*/
#define ERR411 "Input Error 411: no memory allocated for results."
#define ERR412 "Input Error 412: no results; binary file hasn't been opened."
#define ERR421 "Input Error 421: invalid parameter code."
#define ERR434 "File Error 434: unable to open binary output file."
#define ERR435 "File Error 435: run terminated; no results in binary file."
/* Epanet Results binary file API */
typedef struct ENResultsAPI ENResultsAPI; // opaque struct object
typedef enum {
ENR_node = 1,
ENR_link = 2
} ENR_ElementType;
typedef enum {
ENR_getSeries = 1,
ENR_getAttribute = 2,
ENR_getResult = 3
} ENR_ApiFunction;
typedef enum {
ENR_nodeCount = 1,
ENR_tankCount = 2,
ENR_linkCount = 3,
ENR_pumpCount = 4,
ENR_valveCount = 5
} ENR_ElementCount;
typedef enum {
ENR_flowUnits = 1,
ENR_pressUnits = 2
} ENR_Unit;
typedef enum {
ENR_reportStart = 1,
ENR_reportStep = 2,
ENR_simDuration = 3,
ENR_numPeriods = 4
}ENR_Time;
typedef enum {
ENR_demand = 0,
ENR_head = 1,
ENR_pressure = 2,
ENR_quality = 3
} ENR_NodeAttribute;
typedef enum {
ENR_flow = 0,
ENR_velocity = 1,
ENR_headloss = 2,
ENR_avgQuality = 3,
ENR_status = 4,
ENR_setting = 5,
ENR_rxRate = 6,
ENT_frctnFctr = 7
} ENR_LinkAttribute;
#ifdef WINDOWS
#ifdef __cplusplus
#define DLLEXPORT extern "C" __declspec(dllexport) __stdcall
#else
#define DLLEXPORT __declspec(dllexport) __stdcall
#endif
#else
#ifdef __cplusplus
#define DLLEXPORT extern "C"
#else
#define DLLEXPORT
#endif
#endif
ENResultsAPI* DLLEXPORT ENR_alloc(void);
int DLLEXPORT ENR_open(ENResultsAPI* enrapi, const char* path);
int DLLEXPORT ENR_getNetSize(ENResultsAPI* enrapi, ENR_ElementCount code, int* count);
int DLLEXPORT ENR_getUnits(ENResultsAPI* enrapi, ENR_Unit code, int* unitFlag);
float* ENR_newOutValueSeries(ENResultsAPI* enrapi, int seriesStart,
int seriesLength, int* length, int* errcode);
float* ENR_newOutValueArray(ENResultsAPI* enrapi, ENR_ApiFunction func,
ENR_ElementType type, int* length, int* errcode);
int DLLEXPORT ENR_getNodeSeries(ENResultsAPI* enrapi, int nodeIndex, ENR_NodeAttribute attr,
int timeIndex, int length, float* outValueSeries, int* len);
int DLLEXPORT ENR_getLinkSeries(ENResultsAPI* enrapi, int linkIndex, ENR_LinkAttribute attr,
int timeIndex, int length, float* outValueSeries);
int DLLEXPORT ENR_getNodeAttribute(ENResultsAPI* enrapi, int timeIndex,
ENR_NodeAttribute attr, float* outValueArray);
int DLLEXPORT ENT_getLinkAttribute(ENResultsAPI* enrapi, int timeIndex,
ENR_LinkAttribute attr, float* outValueArray);
int DLLEXPORT ENR_getNodeResult(ENResultsAPI* enrapi, int timeIndex, int nodeIndex,
float* outValueArray);
int DLLEXPORT ENR_getLinkResult(ENResultsAPI* enrapi, int timeIndex, int linkIndex,
float* outValueArray);
int DLLEXPORT ENR_free(float *array);
int DLLEXPORT ENR_close(ENResultsAPI* enrapi);
int DLLEXPORT ENR_errMessage(int errcode, char* errmsg, int n);
#endif /* OUTPUTAPI_H_ */

16
tools/requirements.txt Normal file
View File

@@ -0,0 +1,16 @@
#
# requirements.txt
#
# Date Created: 10/10/2017
# Author: Michael E. Tryby
# US EPA ORD/NRMRL
#
# Useful for configuring a python environment to run epanet-nrtestsuite.
#
# command:
# $ pip install --src build/packages -r tools/requirements.txt
#
-e git+https://github.com/OpenWaterAnalytics/nrtest.git@master#egg=nrtest
-e ./tools/epanet-output
-e ./tools/nrtest-epanet

58
tools/run-nrtest.sh Executable file
View File

@@ -0,0 +1,58 @@
#! /bin/bash
#
# run-nrtest.sh - Runs numerical regression test
#
# Date Created: 10/16/2017
#
# Author: Michael E. Tryby
# US EPA - ORD/NRMRL
#
# Arguments:
# 1 - test suite path
# 2 - version/build identifier
#
run-nrtest()
{
return_value=0
test_suite_path=$1
nrtest_execute_cmd="nrtest execute"
test_app_path="apps/epanet-$2.json"
tests="tests/examples"
test_output_path="benchmark/epanet-$2"
nrtest_compare_cmd="nrtest compare"
ref_output_path="benchmark/epanet-2012"
rtol_value=0.1
atol_value=0.0
# change current directory to test_suite
cd ${test_suite_path}
# clean test benchmark results
rm -rf ${test_output_path}
echo INFO: Creating test benchmark
nrtest_command="${nrtest_execute_cmd} ${test_app_path} ${tests} -o ${test_output_path}"
echo INFO: "$nrtest_command"
if ! [ $( $nrtest_command ) ]; then
echo
echo INFO: Comparing test and ref benchmarks
nrtest_command="${nrtest_compare_cmd} ${test_output_path} ${ref_output_path} --rtol ${rtol_value} --atol ${atol_value}"
echo INFO: "$nrtest_command"
return_value=$( $nrtest_command )
else
echo ERROR: Test benchmark creation failed
exit 1
fi
return $return_value
}
run-nrtest $1 $2