diff --git a/epanet/epanet.py b/epanet/epanet.py
index 82863d5..eefd3f6 100644
--- a/epanet/epanet.py
+++ b/epanet/epanet.py
@@ -8,18 +8,19 @@ from datetime import datetime
import subprocess
import logging
from typing import Any
-sys.path.append("..")
+
+sys.path.append("..")
from api import project
from api import inp_out
def _verify_platform():
_platform = platform.system()
- if _platform != "Windows":
- raise Exception(f'Platform {_platform} unsupported (not yet)')
+ if _platform not in ["Windows", "Linux"]:
+ raise Exception(f"Platform {_platform} unsupported (not yet)")
-
-if __name__ == '__main__':
+
+if __name__ == "__main__":
_verify_platform()
@@ -27,201 +28,260 @@ class Output:
def __init__(self, path: str) -> None:
self._path = path
- self._lib = ctypes.CDLL(os.path.join(os.getcwd(), 'epanet', 'epanet-output.dll'))
+ if platform.system() == "Windows":
+ self._lib = ctypes.CDLL(
+ os.path.join(os.getcwd(), "epanet", "epanet-output.dll")
+ )
+ else:
+ self._lib = ctypes.CDLL(
+ os.path.join(os.getcwd(), "epanet", "linux", "libepanet-output.so")
+ )
self._handle = ctypes.c_void_p()
self._check(self._lib.ENR_init(ctypes.byref(self._handle)))
- self._check(self._lib.ENR_open(self._handle, ctypes.c_char_p(self._path.encode())))
-
+ self._check(
+ self._lib.ENR_open(self._handle, ctypes.c_char_p(self._path.encode()))
+ )
def __del__(self):
# throw exception in destructor ? :)
self._check(self._lib.ENR_close(ctypes.byref(self._handle)))
-
def _check(self, result):
if result != 0 and result != 10:
msg = ctypes.c_char_p()
code = self._lib.ENR_checkError(self._handle, ctypes.byref(msg))
assert code == result
- error = f'Failed to read project [{self._path}] output, message [{msg.value.decode()}]'
+ error = f"Failed to read project [{self._path}] output, message [{msg.value.decode()}]"
self._lib.ENR_free(ctypes.byref(msg))
raise Exception(error)
-
def version(self) -> int:
v = ctypes.c_int()
self._check(self._lib.ENR_getVersion(self._handle, ctypes.byref(v)))
return v.value
-
def net_size(self) -> dict[str, int]:
element_count = ctypes.POINTER(ctypes.c_int)()
length = ctypes.c_int()
- self._check(self._lib.ENR_getNetSize(self._handle, ctypes.byref(element_count), ctypes.byref(length)))
+ self._check(
+ self._lib.ENR_getNetSize(
+ self._handle, ctypes.byref(element_count), ctypes.byref(length)
+ )
+ )
assert length.value == 5
- category = ['node', 'tank', 'link', 'pump', 'valve']
+ category = ["node", "tank", "link", "pump", "valve"]
sizes = {}
for i in range(length.value):
sizes[category[i]] = element_count[i]
self._lib.ENR_free(ctypes.byref(element_count))
return sizes
-
def units(self) -> dict[str, str]:
- f_us = ['CFS', 'GPM', 'MGD', 'IMGD', 'AFD', 'LPS', 'LPM', 'MLD', 'CMH', 'CMD']
- p_us = ['PSI', 'MTR', 'KPA']
- q_us = ['NONE', 'MGL', 'UGL', 'HOURS', 'PRCNT']
+ f_us = ["CFS", "GPM", "MGD", "IMGD", "AFD", "LPS", "LPM", "MLD", "CMH", "CMD"]
+ p_us = ["PSI", "MTR", "KPA"]
+ q_us = ["NONE", "MGL", "UGL", "HOURS", "PRCNT"]
f, p, q = ctypes.c_int(1), ctypes.c_int(2), ctypes.c_int(3)
f_u, p_u, q_u = ctypes.c_int(), ctypes.c_int(), ctypes.c_int()
self._check(self._lib.ENR_getUnits(self._handle, f, ctypes.byref(f_u)))
self._check(self._lib.ENR_getUnits(self._handle, p, ctypes.byref(p_u)))
self._check(self._lib.ENR_getUnits(self._handle, q, ctypes.byref(q_u)))
- return { 'flow': f_us[f_u.value], 'pressure': p_us[p_u.value], 'quality': q_us[q_u.value] }
-
+ return {
+ "flow": f_us[f_u.value],
+ "pressure": p_us[p_u.value],
+ "quality": q_us[q_u.value],
+ }
def times(self) -> dict[str, int]:
ts = []
for i in range(1, 5):
t = ctypes.c_int(1)
- self._check(self._lib.ENR_getTimes(self._handle, ctypes.c_int(i), ctypes.byref(t)))
+ self._check(
+ self._lib.ENR_getTimes(self._handle, ctypes.c_int(i), ctypes.byref(t))
+ )
ts.append(t.value)
d = {}
- category = ['report_start', 'report_step', 'sim_duration', 'num_periods']
+ category = ["report_start", "report_step", "sim_duration", "num_periods"]
for i in range(4):
d[category[i]] = ts[i]
return d
-
def element_name(self) -> dict[str, list[str]]:
sizes = self.net_size()
node_type = ctypes.c_int(1)
nodes = []
- for i in range(1, sizes['node'] + 1):
+ for i in range(1, sizes["node"] + 1):
name = ctypes.c_char_p()
name_len = ctypes.c_int()
- self._check(self._lib.ENR_getElementName(self._handle, node_type, ctypes.c_int(i), ctypes.byref(name), ctypes.byref(name_len)))
+ self._check(
+ self._lib.ENR_getElementName(
+ self._handle,
+ node_type,
+ ctypes.c_int(i),
+ ctypes.byref(name),
+ ctypes.byref(name_len),
+ )
+ )
nodes.append(name.value.decode())
self._lib.ENR_free(ctypes.byref(name))
-
+
link_type = ctypes.c_int(2)
links = []
- for i in range(1, sizes['link'] + 1):
+ for i in range(1, sizes["link"] + 1):
name = ctypes.c_char_p()
name_len = ctypes.c_int()
- self._check(self._lib.ENR_getElementName(self._handle, link_type, ctypes.c_int(i), ctypes.byref(name), ctypes.byref(name_len)))
+ self._check(
+ self._lib.ENR_getElementName(
+ self._handle,
+ link_type,
+ ctypes.c_int(i),
+ ctypes.byref(name),
+ ctypes.byref(name_len),
+ )
+ )
links.append(name.value.decode())
self._lib.ENR_free(ctypes.byref(name))
- return { 'nodes' : nodes, 'links': links }
-
+ return {"nodes": nodes, "links": links}
def energy_usage(self) -> list[dict[str, Any]]:
- size = self.net_size()['pump']
+ size = self.net_size()["pump"]
usages = []
- category = ['utilization', 'avg.efficiency', 'avg.kW/flow', 'avg.kwatts', 'max.kwatts', 'cost/day' ]
- links = self.element_name()['links']
+ category = [
+ "utilization",
+ "avg.efficiency",
+ "avg.kW/flow",
+ "avg.kwatts",
+ "max.kwatts",
+ "cost/day",
+ ]
+ links = self.element_name()["links"]
for i in range(1, size + 1):
index = ctypes.c_int()
values = ctypes.POINTER(ctypes.c_float)()
length = ctypes.c_int()
- self._check(self._lib.ENR_getEnergyUsage(self._handle, ctypes.c_int(i), ctypes.byref(index), ctypes.byref(values), ctypes.byref(length)))
+ self._check(
+ self._lib.ENR_getEnergyUsage(
+ self._handle,
+ ctypes.c_int(i),
+ ctypes.byref(index),
+ ctypes.byref(values),
+ ctypes.byref(length),
+ )
+ )
assert length.value == 6
- d = { 'pump' : links[index.value - 1] }
+ d = {"pump": links[index.value - 1]}
for j in range(length.value):
- d |= { category[j] : values[j] }
+ d |= {category[j]: values[j]}
usages.append(d)
self._lib.ENR_free(ctypes.byref(values))
return usages
-
def reactions(self) -> dict[str, float]:
values = ctypes.POINTER(ctypes.c_float)()
length = ctypes.c_int()
- self._check(self._lib.ENR_getNetReacts(self._handle, ctypes.byref(values), ctypes.byref(length)))
+ self._check(
+ self._lib.ENR_getNetReacts(
+ self._handle, ctypes.byref(values), ctypes.byref(length)
+ )
+ )
assert length.value == 4
- category = ['bulk', 'wall', 'tank', 'source']
+ category = ["bulk", "wall", "tank", "source"]
d = {}
for i in range(4):
d[category[i]] = values[i]
self._lib.ENR_free(ctypes.byref(values))
return d
-
def node_results(self) -> list[dict[str, Any]]:
- size = self.net_size()['node']
- num_periods = self.times()['num_periods']
- nodes = self.element_name()['nodes']
- category = ['demand', 'head', 'pressure', 'quality']
+ size = self.net_size()["node"]
+ num_periods = self.times()["num_periods"]
+ nodes = self.element_name()["nodes"]
+ category = ["demand", "head", "pressure", "quality"]
ds = []
for i in range(1, size + 1):
- d = { 'node' : nodes[i - 1], 'result' : [] }
+ d = {"node": nodes[i - 1], "result": []}
for j in range(num_periods):
values = ctypes.POINTER(ctypes.c_float)()
length = ctypes.c_int()
- self._check(self._lib.ENR_getNodeResult(self._handle, j, i, ctypes.byref(values), ctypes.byref(length)))
+ self._check(
+ self._lib.ENR_getNodeResult(
+ self._handle, j, i, ctypes.byref(values), ctypes.byref(length)
+ )
+ )
assert length.value == len(category)
attributes = {}
for k in range(length.value):
attributes[category[k]] = values[k]
- d['result'].append(attributes)
+ d["result"].append(attributes)
self._lib.ENR_free(ctypes.byref(values))
ds.append(d)
return ds
-
def link_results(self) -> list[dict[str, Any]]:
- size = self.net_size()['link']
- num_periods = self.times()['num_periods']
- links = self.element_name()['links']
- category = ['flow', 'velocity', 'headloss', 'quality', 'status', 'setting', 'reaction', 'friction']
+ size = self.net_size()["link"]
+ num_periods = self.times()["num_periods"]
+ links = self.element_name()["links"]
+ category = [
+ "flow",
+ "velocity",
+ "headloss",
+ "quality",
+ "status",
+ "setting",
+ "reaction",
+ "friction",
+ ]
ds = []
for i in range(1, size + 1):
- d = { 'link' : links[i - 1], 'result' : [] }
+ d = {"link": links[i - 1], "result": []}
for j in range(num_periods):
values = ctypes.POINTER(ctypes.c_float)()
length = ctypes.c_int()
- self._check(self._lib.ENR_getLinkResult(self._handle, j, i, ctypes.byref(values), ctypes.byref(length)))
+ self._check(
+ self._lib.ENR_getLinkResult(
+ self._handle, j, i, ctypes.byref(values), ctypes.byref(length)
+ )
+ )
assert length.value == len(category)
attributes = {}
for k in range(length.value):
- if category[k] == 'status':
+ if category[k] == "status":
if values[k] == 2.0:
- attributes[category[k]] = 'CLOSED'
+ attributes[category[k]] = "CLOSED"
else:
- attributes[category[k]] = 'OPEN'
+ attributes[category[k]] = "OPEN"
continue
attributes[category[k]] = values[k]
- d['result'].append(attributes)
+ d["result"].append(attributes)
self._lib.ENR_free(ctypes.byref(values))
ds.append(d)
return ds
-
def dump(self) -> dict[str, Any]:
data = {}
- data |= { 'version' : self.version() }
- data |= { 'net_size' : self.net_size() }
- data |= { 'units' : self.units() }
- data |= { 'times' : self.times() }
- data |= { 'element_name' : self.element_name() }
- data |= { 'energy_usage' : self.energy_usage() }
- data |= { 'reactions' : self.reactions() }
- data |= { 'node_results' : self.node_results() }
- data |= { 'link_results' : self.link_results() }
+ data |= {"version": self.version()}
+ data |= {"net_size": self.net_size()}
+ data |= {"units": self.units()}
+ data |= {"times": self.times()}
+ data |= {"element_name": self.element_name()}
+ data |= {"energy_usage": self.energy_usage()}
+ data |= {"reactions": self.reactions()}
+ data |= {"node_results": self.node_results()}
+ data |= {"link_results": self.link_results()}
return data
def _dump_output(path: str) -> dict[str, Any]:
opt = Output(path)
data = opt.dump()
- with open(path + '.json', 'w') as f:
+ with open(path + ".json", "w") as f:
json.dump(data, f)
return data
@@ -232,90 +292,106 @@ def dump_output(path: str) -> str:
def dump_report(path: str) -> str:
- return open(path, 'r').read()
+ return open(path, "r").read()
def dump_output_binary(path: str) -> str:
- with open(path, 'rb') as f:
+ with open(path, "rb") as f:
data = f.read()
bast64_data = base64.b64encode(data)
- return str(bast64_data, 'utf-8')
+ return str(bast64_data, "utf-8")
-#DingZQ, 2025-02-04, 返回dict[str, Any]
+
+# DingZQ, 2025-02-04, 返回dict[str, Any]
def run_project_return_dict(name: str, readable_output: bool = False) -> dict[str, Any]:
if not project.have_project(name):
- raise Exception(f'Not found project [{name}]')
+ raise Exception(f"Not found project [{name}]")
dir = os.path.abspath(os.getcwd())
- db_inp = os.path.join(os.path.join(dir, 'db_inp'), name + '.db.inp')
- inp_out.dump_inp(name, db_inp, '2')
+ db_inp = os.path.join(os.path.join(dir, "db_inp"), name + ".db.inp")
+ inp_out.dump_inp(name, db_inp, "2")
- input = name + '.db'
- exe = os.path.join(os.path.join(dir, 'epanet'), 'runepanet.exe')
- inp = os.path.join(os.path.join(dir, 'db_inp'), input + '.inp')
- rpt = os.path.join(os.path.join(dir, 'temp'), input + '.rpt')
- opt = os.path.join(os.path.join(dir, 'temp'), input + '.opt')
- command = f'{exe} {inp} {rpt} {opt}'
+ input = name + ".db"
+ if platform.system() == "Windows":
+ exe = os.path.join(os.path.join(dir, "epanet"), "runepanet.exe")
+ else:
+ exe = os.path.join(os.path.join(dir, "epanet"), "linux", "runepanet")
+ inp = os.path.join(os.path.join(dir, "db_inp"), input + ".inp")
+ rpt = os.path.join(os.path.join(dir, "temp"), input + ".rpt")
+ opt = os.path.join(os.path.join(dir, "temp"), input + ".opt")
+ command = f"{exe} {inp} {rpt} {opt}"
+
+ if platform.system() != "Windows":
+ if not os.access(exe, os.X_OK):
+ os.chmod(exe, 0o755)
data = {}
result = os.system(command)
if result != 0:
- data['simulation_result'] = 'failed'
+ data["simulation_result"] = "failed"
else:
- data['simulation_result'] = 'successful'
+ data["simulation_result"] = "successful"
if readable_output:
- data ['output'] = _dump_output(opt)
+ data["output"] = _dump_output(opt)
else:
- data['output'] = dump_output_binary(opt)
+ data["output"] = dump_output_binary(opt)
- data['report'] = dump_report(rpt)
+ data["report"] = dump_report(rpt)
return data
+
# original code
def run_project(name: str, readable_output: bool = False) -> str:
if not project.have_project(name):
- raise Exception(f'Not found project [{name}]')
+ raise Exception(f"Not found project [{name}]")
dir = os.path.abspath(os.getcwd())
- db_inp = os.path.join(os.path.join(dir, 'db_inp'), name + '.db.inp')
- inp_out.dump_inp(name, db_inp, '2')
+ db_inp = os.path.join(os.path.join(dir, "db_inp"), name + ".db.inp")
+ inp_out.dump_inp(name, db_inp, "2")
- input = name + '.db'
- exe = os.path.join(os.path.join(dir, 'epanet'), 'runepanet.exe')
- inp = os.path.join(os.path.join(dir, 'db_inp'), input + '.inp')
- rpt = os.path.join(os.path.join(dir, 'temp'), input + '.rpt')
- opt = os.path.join(os.path.join(dir, 'temp'), input + '.opt')
+ input = name + ".db"
+ if platform.system() == "Windows":
+ exe = os.path.join(os.path.join(dir, "epanet"), "runepanet.exe")
+ else:
+ exe = os.path.join(os.path.join(dir, "epanet"), "linux", "runepanet")
+ inp = os.path.join(os.path.join(dir, "db_inp"), input + ".inp")
+ rpt = os.path.join(os.path.join(dir, "temp"), input + ".rpt")
+ opt = os.path.join(os.path.join(dir, "temp"), input + ".opt")
- command = f'{exe} {inp} {rpt} {opt}'
+ command = f"{exe} {inp} {rpt} {opt}"
logging.info(f"Run simulation at {datetime.now()}")
logging.info(command)
+ if platform.system() != "Windows":
+ if not os.access(exe, os.X_OK):
+ os.chmod(exe, 0o755)
+
data = {}
# DingZQ, 2025-06-02, 使用subprocess.Popen捕获输出到全局日志, 原来的代码是这么写的
result = os.system(command)
- #logging.info(f"Simulation result: {result}")
+ # logging.info(f"Simulation result: {result}")
if result != 0:
- data['simulation_result'] = 'failed'
+ data["simulation_result"] = "failed"
- logging.error('simulation failed')
+ logging.error("simulation failed")
else:
- data['simulation_result'] = 'successful'
- logging.info('simulation successful')
+ data["simulation_result"] = "successful"
+ logging.info("simulation successful")
if readable_output:
data |= _dump_output(opt)
else:
- data['output'] = dump_output_binary(opt)
+ data["output"] = dump_output_binary(opt)
- data['report'] = dump_report(rpt)
- #logging.info(f"Report: {data['report']}")
+ data["report"] = dump_report(rpt)
+ # logging.info(f"Report: {data['report']}")
return json.dumps(data)
@@ -323,22 +399,29 @@ def run_project(name: str, readable_output: bool = False) -> str:
def run_inp(name: str) -> str:
dir = os.path.abspath(os.getcwd())
- exe = os.path.join(os.path.join(dir, 'epanet'), 'runepanet.exe')
- inp = os.path.join(os.path.join(dir, 'inp'), name + '.inp')
- rpt = os.path.join(os.path.join(dir, 'temp'), name + '.rpt')
- opt = os.path.join(os.path.join(dir, 'temp'), name + '.opt')
- command = f'{exe} {inp} {rpt} {opt}'
+ if platform.system() == "Windows":
+ exe = os.path.join(os.path.join(dir, "epanet"), "runepanet.exe")
+ else:
+ exe = os.path.join(os.path.join(dir, "epanet"), "linux", "runepanet")
+ inp = os.path.join(os.path.join(dir, "inp"), name + ".inp")
+ rpt = os.path.join(os.path.join(dir, "temp"), name + ".rpt")
+ opt = os.path.join(os.path.join(dir, "temp"), name + ".opt")
+ command = f"{exe} {inp} {rpt} {opt}"
+
+ if platform.system() != "Windows":
+ if not os.access(exe, os.X_OK):
+ os.chmod(exe, 0o755)
data = {}
result = os.system(command)
if result != 0:
- data['simulation_result'] = 'failed'
+ data["simulation_result"] = "failed"
else:
- data['simulation_result'] = 'successful'
+ data["simulation_result"] = "successful"
# data |= _dump_output(opt)
- data['output'] = dump_output_binary(opt)
+ data["output"] = dump_output_binary(opt)
- data['report'] = dump_report(rpt)
+ data["report"] = dump_report(rpt)
return json.dumps(data)
diff --git a/epanet/linux/epanet2.h b/epanet/linux/epanet2.h
new file mode 100644
index 0000000..042d6c6
--- /dev/null
+++ b/epanet/linux/epanet2.h
@@ -0,0 +1,464 @@
+/*
+ ******************************************************************************
+ Project: OWA EPANET
+ Version: 2.3
+ Module: epanet2.h
+ Description: declarations of the legacy style EPANET 2 API functions
+ Authors: see AUTHORS
+ Copyright: see AUTHORS
+ License: see LICENSE
+ Last Updated: 02/14/2025
+ ******************************************************************************
+ */
+
+/*
+This module contains declarations of the legacy style EPANET API functions, with
+version 2.2 updates, that apply only to single threaded applications. A second
+set of thread safe API functions that allows one to run concurrent analyses on
+multiple EPANET projects can be found in the epanet2_2.h header file. The two
+APIs share the same function names and arguments with the difference being that
+the thread safe functions use the prefix "EN_" and include an extra argument that
+represents the EPANET project being analyzed. To avoid unnecessary repetition,
+only the thread safe API functions have been documented. To see a description of
+a legacy style API function declared here please refer to its complementary named
+function in epanet2_2.h.
+*/
+
+#ifndef EPANET2_H
+#define EPANET2_H
+
+// The legacy style EPANET API can be compiled with support for either single
+// precision or double precision floating point arguments, with the default
+// being single precision. To compile for double precision one must #define
+// EN_API_FLOAT_TYPE as double both here and in any client code that uses the
+// API.
+#ifndef EN_API_FLOAT_TYPE
+ #define EN_API_FLOAT_TYPE float
+#endif
+
+#ifndef DLLEXPORT
+ #ifdef _WIN32
+ #ifdef epanet2_EXPORTS
+ #define DLLEXPORT __declspec(dllexport) __stdcall
+ #else
+ #define DLLEXPORT __declspec(dllimport) __stdcall
+ #endif
+ #elif defined(__CYGWIN__)
+ #define DLLEXPORT __stdcall
+ #else
+ #define DLLEXPORT
+ #endif
+#endif
+
+#include "epanet2_enums.h"
+
+// --- Declare the EPANET toolkit functions
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/********************************************************************
+
+ Project Functions
+
+********************************************************************/
+
+ int DLLEXPORT ENepanet(const char *inpFile, const char *rptFile,
+ const char *outFile, void (*pviewprog) (char *));
+
+ int DLLEXPORT ENinit(const char *rptFile, const char *outFile,
+ int unitsType, int headlossType);
+
+ int DLLEXPORT ENopen(const char *inpFile, const char *rptFile,
+ const char *outFile);
+
+ int DLLEXPORT ENopenX(const char *inpFile, const char *rptFile,
+ const char *outFile);
+
+ int DLLEXPORT ENgettitle(char *line1, char *line2, char *line3);
+
+ int DLLEXPORT ENsettitle(const char *line1, const char *line2, const char *line3);
+
+ int DLLEXPORT ENgetcomment(int object, int index, char *comment);
+
+ int DLLEXPORT ENsetcomment(int object, int index, const char *comment);
+
+ int DLLEXPORT ENgettag(int object, int index, char *tag);
+
+ int DLLEXPORT ENsettag(int object, int index, const char *tag);
+
+ int DLLEXPORT ENgetcount(int object, int *count);
+
+ int DLLEXPORT ENsaveinpfile(const char *filename);
+
+ int DLLEXPORT ENclose();
+
+/********************************************************************
+
+ Hydraulic Analysis Functions
+
+********************************************************************/
+
+ int DLLEXPORT ENsolveH();
+
+ int DLLEXPORT ENsaveH();
+
+ int DLLEXPORT ENopenH();
+
+ int DLLEXPORT ENinitH(int initFlag);
+
+ int DLLEXPORT ENrunH(long *currentTime);
+
+ int DLLEXPORT ENnextH(long *tStep);
+
+ int DLLEXPORT ENcloseH();
+
+ int DLLEXPORT ENsavehydfile(const char *filename);
+
+ int DLLEXPORT ENusehydfile(const char *filename);
+
+/********************************************************************
+
+ Water Quality Analysis Functions
+
+********************************************************************/
+
+ int DLLEXPORT ENsolveQ();
+
+ int DLLEXPORT ENopenQ();
+
+ int DLLEXPORT ENinitQ(int saveFlag);
+
+ int DLLEXPORT ENrunQ(long *currentTime);
+
+ int DLLEXPORT ENnextQ(long *tStep);
+
+ int DLLEXPORT ENstepQ(long *timeLeft);
+
+ int DLLEXPORT ENcloseQ();
+
+/********************************************************************
+
+ Reporting Functions
+
+********************************************************************/
+
+ int DLLEXPORT ENwriteline(const char *line);
+
+ int DLLEXPORT ENreport();
+
+ int DLLEXPORT ENcopyreport(const char *filename);
+
+ int DLLEXPORT ENclearreport();
+
+ int DLLEXPORT ENresetreport();
+
+ int DLLEXPORT ENsetreport(const char *format);
+
+ int DLLEXPORT ENsetstatusreport(int level);
+
+ int DLLEXPORT ENgetversion(int *version);
+
+ int DLLEXPORT ENgeterror(int errcode, char *errmsg, int maxLen);
+
+ int DLLEXPORT ENgetstatistic(int type, EN_API_FLOAT_TYPE* value);
+
+ int DLLEXPORT ENgetresultindex(int type, int index, int *value);
+
+ int DLLEXPORT ENtimetonextevent(int *eventType, long *duration, int *elementIndex);
+
+ int DLLEXPORT ENsetreportcallback(void (*callback)(void *userData, void *EN_projectHandle, const char*));
+
+ int DLLEXPORT ENsetreportcallbackuserdata(void *userData);
+
+
+/********************************************************************
+
+ Analysis Options Functions
+
+********************************************************************/
+
+ int DLLEXPORT ENgetoption(int option, EN_API_FLOAT_TYPE *value);
+
+ int DLLEXPORT ENsetoption(int option, EN_API_FLOAT_TYPE value);
+
+ int DLLEXPORT ENgetflowunits(int *units);
+
+ int DLLEXPORT ENsetflowunits(int units);
+
+ int DLLEXPORT ENgettimeparam(int param, long *value);
+
+ int DLLEXPORT ENsettimeparam(int param, long value);
+
+ int DLLEXPORT ENgetqualinfo(int *qualType, char *chemName, char *chemUnits,
+ int *traceNode);
+
+ int DLLEXPORT ENgetqualtype(int *qualType, int *traceNode);
+
+ int DLLEXPORT ENsetqualtype(int qualType, const char *chemName,
+ const char *chemUnits, const char *traceNode);
+
+/********************************************************************
+
+ Node Functions
+
+********************************************************************/
+
+ int DLLEXPORT ENaddnode(const char *id, int nodeType, int *index);
+
+ int DLLEXPORT ENdeletenode(int index, int actionCode);
+
+ int DLLEXPORT ENgetnodeindex(const char *id, int *index);
+
+ int DLLEXPORT ENgetnodeid(int index, char *id);
+
+ int DLLEXPORT ENsetnodeid(int index, const char *newid);
+
+ int DLLEXPORT ENgetnodetype(int index, int *nodeType);
+
+ int DLLEXPORT ENgetnodevalue(int index, int property, EN_API_FLOAT_TYPE *value);
+
+ int DLLEXPORT ENgetnodevalues(int property, EN_API_FLOAT_TYPE *value);
+
+ int DLLEXPORT ENsetnodevalue(int index, int property, EN_API_FLOAT_TYPE value);
+
+ int DLLEXPORT ENsetjuncdata(int index, EN_API_FLOAT_TYPE elev,
+ EN_API_FLOAT_TYPE dmnd, const char *dmndpat);
+
+ int DLLEXPORT ENsettankdata(int index, EN_API_FLOAT_TYPE elev,
+ EN_API_FLOAT_TYPE initlvl, EN_API_FLOAT_TYPE minlvl,
+ EN_API_FLOAT_TYPE maxlvl, EN_API_FLOAT_TYPE diam,
+ EN_API_FLOAT_TYPE minvol, const char *volcurve);
+
+ int DLLEXPORT ENgetcoord(int index, double *x, double *y);
+
+ int DLLEXPORT ENsetcoord(int index, double x, double y);
+
+/********************************************************************
+
+ Nodal Demand Functions
+
+********************************************************************/
+
+ int DLLEXPORT ENgetdemandmodel(int *model, EN_API_FLOAT_TYPE *pmin,
+ EN_API_FLOAT_TYPE *preq, EN_API_FLOAT_TYPE *pexp);
+
+ int DLLEXPORT ENsetdemandmodel(int model, EN_API_FLOAT_TYPE pmin,
+ EN_API_FLOAT_TYPE preq, EN_API_FLOAT_TYPE pexp);
+
+ int DLLEXPORT ENadddemand(int nodeIndex, EN_API_FLOAT_TYPE baseDemand,
+ const char *demandPattern, const char *demandName);
+
+ int DLLEXPORT ENdeletedemand(int nodeIndex, int demandIndex);
+
+ int DLLEXPORT ENgetnumdemands(int nodeIndex, int *numDemands);
+
+ int DLLEXPORT ENgetdemandindex(int nodeIndex, const char *demandName,
+ int *demandIndex);
+
+ int DLLEXPORT ENgetbasedemand(int nodeIndex, int demandIndex,
+ EN_API_FLOAT_TYPE *baseDemand);
+
+ int DLLEXPORT ENsetbasedemand(int nodeIndex, int demandIndex,
+ EN_API_FLOAT_TYPE baseDemand);
+
+ int DLLEXPORT ENgetdemandpattern(int nodeIndex, int demandIndex, int *patIndex);
+
+ int DLLEXPORT ENsetdemandpattern(int nodeIndex, int demandIndex, int patIndex);
+
+ int DLLEXPORT ENgetdemandname(int nodeIndex, int demandIndex, char *demandName);
+
+ int DLLEXPORT ENsetdemandname(int nodeIndex, int demandIndex, const char *demandName);
+
+/********************************************************************
+
+ Link Functions
+
+********************************************************************/
+
+ int DLLEXPORT ENaddlink(const char *id, int linkType, const char *fromNode,
+ const char *toNode, int *index);
+
+ int DLLEXPORT ENdeletelink(int index, int actionCode);
+
+ int DLLEXPORT ENgetlinkindex(const char *id, int *index);
+
+ int DLLEXPORT ENgetlinkid(int index, char *id);
+
+ int DLLEXPORT ENsetlinkid(int index, const char *newid);
+
+ int DLLEXPORT ENgetlinktype(int index, int *linkType);
+
+ int DLLEXPORT ENsetlinktype(int *index, int linkType, int actionCode);
+
+ int DLLEXPORT ENgetlinknodes(int index, int *node1, int *node2);
+
+ int DLLEXPORT ENsetlinknodes(int index, int node1, int node2);
+
+ int DLLEXPORT ENgetlinkvalue(int index, int property, EN_API_FLOAT_TYPE *value);
+
+ int DLLEXPORT ENgetlinkvalues(int property, EN_API_FLOAT_TYPE *value);
+
+ int DLLEXPORT ENsetlinkvalue(int index, int property, EN_API_FLOAT_TYPE value);
+
+ int DLLEXPORT ENsetpipedata(int index, EN_API_FLOAT_TYPE length,
+ EN_API_FLOAT_TYPE diam, EN_API_FLOAT_TYPE rough,
+ EN_API_FLOAT_TYPE mloss);
+
+ int DLLEXPORT ENgetvertexcount(int index, int *count);
+
+ int DLLEXPORT ENgetvertex(int index, int vertex, double *x, double *y);
+
+ int DLLEXPORT ENsetvertex(int index, int vertex, double x, double y);
+
+ int DLLEXPORT ENsetvertices(int index, double *x, double *y, int count);
+
+/********************************************************************
+
+ Pump Functions
+
+********************************************************************/
+
+ int DLLEXPORT ENgetpumptype(int linkIndex, int *pumpType);
+
+ int DLLEXPORT ENgetheadcurveindex(int linkIndex, int *curveIndex);
+
+ int DLLEXPORT ENsetheadcurveindex(int linkIndex, int curveIndex);
+
+/********************************************************************
+
+ Time Pattern Functions
+
+********************************************************************/
+
+ int DLLEXPORT ENaddpattern(const char *id);
+
+ int DLLEXPORT ENdeletepattern(int index);
+
+ int DLLEXPORT ENgetpatternindex(const char *id, int *index);
+
+ int DLLEXPORT ENgetpatternid(int index, char *id);
+
+ int DLLEXPORT ENsetpatternid(int index, const char *id);
+
+ int DLLEXPORT ENgetpatternlen(int index, int *len);
+
+ int DLLEXPORT ENgetpatternvalue(int index, int period, EN_API_FLOAT_TYPE *value);
+
+ int DLLEXPORT ENsetpatternvalue(int index, int period, EN_API_FLOAT_TYPE value);
+
+ int DLLEXPORT ENgetaveragepatternvalue(int index, EN_API_FLOAT_TYPE *value);
+
+ int DLLEXPORT ENsetpattern(int index, EN_API_FLOAT_TYPE *values, int len);
+
+ int DLLEXPORT ENloadpatternfile(const char *filename, const char *id);
+
+/********************************************************************
+
+ Data Curve Functions
+
+********************************************************************/
+
+ int DLLEXPORT ENaddcurve(const char *id);
+
+ int DLLEXPORT ENdeletecurve(int index);
+
+ int DLLEXPORT ENgetcurveindex(const char *id, int *index);
+
+ int DLLEXPORT ENgetcurveid(int index, char *id);
+
+ int DLLEXPORT ENsetcurveid(int index, const char *id);
+
+ int DLLEXPORT ENgetcurvelen(int index, int *len);
+
+ int DLLEXPORT ENgetcurvetype(int index, int *type);
+
+ int DLLEXPORT ENsetcurvetype(int index, int type);
+
+ int DLLEXPORT ENgetcurvevalue(int curveIndex, int pointIndex,
+ EN_API_FLOAT_TYPE *x, EN_API_FLOAT_TYPE *y);
+
+ int DLLEXPORT ENsetcurvevalue(int curveIndex, int pointIndex,
+ EN_API_FLOAT_TYPE x, EN_API_FLOAT_TYPE y);
+
+ int DLLEXPORT ENgetcurve(int index, char* id, int *nPoints,
+ EN_API_FLOAT_TYPE *xValues, EN_API_FLOAT_TYPE *yValues);
+
+ int DLLEXPORT ENsetcurve(int index, EN_API_FLOAT_TYPE *xValues,
+ EN_API_FLOAT_TYPE *yValues, int nPoints);
+
+/********************************************************************
+
+ Simple Controls Functions
+
+********************************************************************/
+
+ int DLLEXPORT ENaddcontrol(int type, int linkIndex, EN_API_FLOAT_TYPE setting,
+ int nodeIndex, EN_API_FLOAT_TYPE level, int *index);
+
+ int DLLEXPORT ENdeletecontrol(int index);
+
+ int DLLEXPORT ENgetcontrol(int index, int *type, int *linkIndex,
+ EN_API_FLOAT_TYPE *setting, int *nodeIndex, EN_API_FLOAT_TYPE *level);
+
+ int DLLEXPORT ENsetcontrol(int index, int type, int linkIndex,
+ EN_API_FLOAT_TYPE setting, int nodeIndex, EN_API_FLOAT_TYPE level);
+
+ int DLLEXPORT ENgetcontrolenabled(int index, int *out_enabled);
+
+ int DLLEXPORT ENsetcontrolenabled(int index, int enabled);
+
+/********************************************************************
+
+ Rule-Based Controls Functions
+
+********************************************************************/
+
+ int DLLEXPORT ENaddrule(char *rule);
+
+ int DLLEXPORT ENdeleterule(int index);
+
+ int DLLEXPORT ENgetrule(int index, int *nPremises, int *nThenActions,
+ int *nElseActions, EN_API_FLOAT_TYPE *priority);
+
+ int DLLEXPORT ENgetruleID(int index, char* id);
+
+ int DLLEXPORT ENgetpremise(int ruleIndex, int premiseIndex, int *logop,
+ int *object, int *objIndex, int *variable,
+ int *relop, int *status, EN_API_FLOAT_TYPE *value);
+
+ int DLLEXPORT ENsetpremise(int ruleIndex, int premiseIndex, int logop,
+ int object, int objIndex, int variable, int relop,
+ int status, EN_API_FLOAT_TYPE value);
+
+ int DLLEXPORT ENsetpremiseindex(int ruleIndex, int premiseIndex, int objIndex);
+
+ int DLLEXPORT ENsetpremisestatus(int ruleIndex, int premiseIndex, int status);
+
+ int DLLEXPORT ENsetpremisevalue(int ruleIndex, int premiseIndex,
+ EN_API_FLOAT_TYPE value);
+
+ int DLLEXPORT ENgetthenaction(int ruleIndex, int actionIndex, int *linkIndex,
+ int *status, EN_API_FLOAT_TYPE *setting);
+
+ int DLLEXPORT ENsetthenaction(int ruleIndex, int actionIndex, int linkIndex,
+ int status, EN_API_FLOAT_TYPE setting);
+
+ int DLLEXPORT ENgetelseaction(int ruleIndex, int actionIndex, int *linkIndex,
+ int *status, EN_API_FLOAT_TYPE *setting);
+
+ int DLLEXPORT ENsetelseaction(int ruleIndex, int actionIndex, int linkIndex,
+ int status, EN_API_FLOAT_TYPE setting);
+
+ int DLLEXPORT ENsetrulepriority(int index, EN_API_FLOAT_TYPE priority);
+
+ int DLLEXPORT ENgetruleenabled(int index, int *out_enabled);
+
+ int DLLEXPORT ENsetruleenabled(int index, int enabled);
+
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif //EPANET2_H
diff --git a/epanet/linux/epanet2.pas b/epanet/linux/epanet2.pas
new file mode 100644
index 0000000..0e7ba66
--- /dev/null
+++ b/epanet/linux/epanet2.pas
@@ -0,0 +1,486 @@
+unit epanet2;
+
+{ Declarations of imported procedures from the EPANET PROGRAMMERs TOOLKIT }
+{ (EPANET2.DLL) }
+
+{Last updated on 04/23/2025}
+
+interface
+
+const
+
+{ These are codes used by the DLL functions }
+ EN_MAXID = 31; { Max. # characters in ID name }
+ EN_MAXMSG = 255; { Max. # characters in strings }
+ EN_MISSING = -1.0E10;
+ EN_SET_CLOSED = -1.0E10;
+ EN_SET_OPEN = 1.0E10;
+
+ EN_ELEVATION = 0; { Node parameters }
+ EN_BASEDEMAND = 1;
+ EN_PATTERN = 2;
+ EN_EMITTER = 3;
+ EN_INITQUAL = 4;
+ EN_SOURCEQUAL = 5;
+ EN_SOURCEPAT = 6;
+ EN_SOURCETYPE = 7;
+ EN_TANKLEVEL = 8;
+ EN_DEMAND = 9;
+ EN_HEAD = 10;
+ EN_PRESSURE = 11;
+ EN_QUALITY = 12;
+ EN_SOURCEMASS = 13;
+ EN_INITVOLUME = 14;
+ EN_MIXMODEL = 15;
+ EN_MIXZONEVOL = 16;
+ EN_TANKDIAM = 17;
+ EN_MINVOLUME = 18;
+ EN_VOLCURVE = 19;
+ EN_MINLEVEL = 20;
+ EN_MAXLEVEL = 21;
+ EN_MIXFRACTION = 22;
+ EN_TANK_KBULK = 23;
+ EN_TANKVOLUME = 24;
+ EN_MAXVOLUME = 25;
+ EN_CANOVERFLOW = 26;
+ EN_DEMANDDEFICIT = 27;
+ EN_NODE_INCONTROL = 28;
+ EN_EMITTERFLOW = 29;
+ EN_LEAKAGEFLOW = 30;
+ EN_DEMANDFLOW = 31;
+ EN_FULLDEMAND = 32;
+
+ EN_DIAMETER = 0; { Link parameters }
+ EN_LENGTH = 1;
+ EN_ROUGHNESS = 2;
+ EN_MINORLOSS = 3;
+ EN_INITSTATUS = 4;
+ EN_INITSETTING = 5;
+ EN_KBULK = 6;
+ EN_KWALL = 7;
+ EN_FLOW = 8;
+ EN_VELOCITY = 9;
+ EN_HEADLOSS = 10;
+ EN_STATUS = 11;
+ EN_SETTING = 12;
+ EN_ENERGY = 13;
+ EN_LINKQUAL = 14;
+ EN_LINKPATTERN = 15;
+ EN_PUMP_STATE = 16;
+ EN_PUMP_EFFIC = 17;
+ EN_PUMP_POWER = 18;
+ EN_PUMP_HCURVE = 19;
+ EN_PUMP_ECURVE = 20;
+ EN_PUMP_ECOST = 21;
+ EN_PUMP_EPAT = 22;
+ EN_LINK_INCONTROL = 23;
+ EN_GPV_CURVE = 24;
+ EN_PCV_CURVE = 25;
+ EN_LEAK_AREA = 26;
+ EN_LEAK_EXPAN = 27;
+ EN_LINK_LEAKAGE = 28;
+ EN_VALVE_TYPE = 29;
+
+ EN_DURATION = 0; { Time parameters }
+ EN_HYDSTEP = 1;
+ EN_QUALSTEP = 2;
+ EN_PATTERNSTEP = 3;
+ EN_PATTERNSTART = 4;
+ EN_REPORTSTEP = 5;
+ EN_REPORTSTART = 6;
+ EN_RULESTEP = 7;
+ EN_STATISTIC = 8;
+ EN_PERIODS = 9;
+ EN_STARTTIME = 10;
+ EN_HTIME = 11;
+ EN_QTIME = 12;
+ EN_HALTFLAG = 13;
+ EN_NEXTEVENT = 14;
+ EN_NEXTEVENTTANK = 15;
+
+ EN_ITERATIONS = 0; { Analysis statistics }
+ EN_RELATIVEERROR = 1;
+ EN_MAXHEADERROR = 2;
+ EN_MAXFLOWCHANGE = 3;
+ EN_MASSBALANCE = 4;
+ EN_DEFICIENTNODES = 5;
+ EN_DEMANDREDUCTION = 6;
+ EN_LEAKAGELOSS = 7;
+
+ EN_NODE = 0; { Component Types }
+ EN_LINK = 1;
+ EN_TIMEPAT = 2;
+ EN_CURVE = 3;
+ EN_CONTROL = 4;
+ EN_RULE = 5;
+
+ EN_NODECOUNT = 0; { Component counts }
+ EN_TANKCOUNT = 1;
+ EN_LINKCOUNT = 2;
+ EN_PATCOUNT = 3;
+ EN_CURVECOUNT = 4;
+ EN_CONTROLCOUNT = 5;
+ EN_RULECOUNT = 6;
+
+ EN_JUNCTION = 0; { Node types }
+ EN_RESERVOIR = 1;
+ EN_TANK = 2;
+
+ EN_CVPIPE = 0; { Link types }
+ EN_PIPE = 1;
+ EN_PUMP = 2;
+ EN_PRV = 3;
+ EN_PSV = 4;
+ EN_PBV = 5;
+ EN_FCV = 6;
+ EN_TCV = 7;
+ EN_GPV = 8;
+ EN_PCV = 9;
+
+ EN_CLOSED = 0; { Link status types }
+ EN_OPEN = 1;
+
+ EN_PUMP_XHEAD = 0; { Pump state types }
+ EN_PUMP_CLOSED = 2;
+ EN_PUMP_OPEN = 3;
+ EN_PUMP_XFLOW = 5;
+
+ EN_NONE = 0; { Quality analysis types }
+ EN_CHEM = 1;
+ EN_AGE = 2;
+ EN_TRACE = 3;
+
+ EN_CONCEN = 0; { Source quality types }
+ EN_MASS = 1;
+ EN_SETPOINT = 2;
+ EN_FLOWPACED = 3;
+
+ EN_HW = 0; { Head loss formulas }
+ EN_DW = 1;
+ EN_CM = 2;
+
+ EN_CFS = 0; { Flow units types }
+ EN_GPM = 1;
+ EN_MGD = 2;
+ EN_IMGD = 3;
+ EN_AFD = 4;
+ EN_LPS = 5;
+ EN_LPM = 6;
+ EN_MLD = 7;
+ EN_CMH = 8;
+ EN_CMD = 9;
+ EN_CMS = 10;
+
+ EN_PSI = 0; { Pressure units types }
+ EN_KPA = 1;
+ EN_METERS = 2;
+ EN_BAR = 3;
+ EN_FEET = 4;
+
+ EN_DDA = 0; { Demand model types }
+ EN_PDA = 1;
+
+ EN_TRIALS = 0; { Option types }
+ EN_ACCURACY = 1;
+ EN_TOLERANCE = 2;
+ EN_EMITEXPON = 3;
+ EN_DEMANDMULT = 4;
+ EN_HEADERROR = 5;
+ EN_FLOWCHANGE = 6;
+ EN_HEADLOSSFORM = 7;
+ EN_GLOBALEFFIC = 8;
+ EN_GLOBALPRICE = 9;
+ EN_GLOBALPATTERN = 10;
+ EN_DEMANDCHARGE = 11;
+ EN_SP_GRAVITY = 12;
+ EN_SP_VISCOS = 13;
+ EN_EXTRA_ITER = 14;
+ EN_CHECKFREQ = 15;
+ EN_MAXCHECK = 16;
+ EN_DAMPLIMIT = 17;
+ EN_SP_DIFFUS = 18;
+ EN_BULKORDER = 19;
+ EN_WALLORDER = 20;
+ EN_TANKORDER = 21;
+ EN_CONCENLIMIT = 22;
+ EN_DEMANDPATTERN = 23;
+ EN_EMITBACKFLOW = 24;
+ EN_PRESS_UNITS = 25;
+ EN_STATUS_REPORT = 26;
+
+ EN_LOWLEVEL = 0; { Control types }
+ EN_HILEVEL = 1;
+ EN_TIMER = 2;
+ EN_TIMEOFDAY = 3;
+
+ EN_SERIES = 0; { Report statistic types }
+ EN_AVERAGE = 1;
+ EN_MINIMUM = 2;
+ EN_MAXIMUM = 3;
+ EN_RANGE = 4;
+
+ EN_MIX1 = 0; { Tank mixing models }
+ EN_MIX2 = 1;
+ EN_FIFO = 2;
+ EN_LIFO = 3;
+
+ EN_NOSAVE = 0; { Hydraulics flags }
+ EN_SAVE = 1;
+ EN_INITFLOW = 10;
+ EN_SAVE_AND_INIT = 11;
+
+ EN_CONST_HP = 0; { Pump curve types }
+ EN_POWER_FUNC = 1;
+ EN_CUSTOM = 2;
+ EN_NOCURVE = 3;
+
+ EN_VOLUME_CURVE = 0; { Curve types }
+ EN_PUMP_CURVE = 1;
+ EN_EFFIC_CURVE = 2;
+ EN_HLOSS_CURVE = 3;
+ EN_GENERIC_CURVE = 4;
+ EN_VALVE_CURVE = 5;
+
+ EN_UNCONDITIONAL = 0; { Deletion action codes }
+ EN_CONDITIONAL = 1;
+
+ EN_NO_REPORT = 0; { Status reporting levels }
+ EN_NORMAL_REPORT = 1;
+ EN_FULL_REPORT = 2;
+
+ EN_R_NODE = 6; { Rule-based control objects }
+ EN_R_LINK = 7;
+ EN_R_SYSTEM = 8;
+
+ EN_R_DEMAND = 0; { Rule-based control variables }
+ EN_R_HEAD = 1;
+ EN_R_GRADE = 2;
+ EN_R_LEVEL = 3;
+ EN_R_PRESSURE = 4;
+ EN_R_FLOW = 5;
+ EN_R_STATUS = 6;
+ EN_R_SETTING = 7;
+ EN_R_POWER = 8;
+ EN_R_TIME = 9;
+ EN_R_CLOCKTIME = 10;
+ EN_R_FILLTIME = 11;
+ EN_R_DRAINTIME = 12;
+
+ EN_R_EQ = 0; { Rule-based control operators }
+ EN_R_NE = 1;
+ EN_R_LE = 2;
+ EN_R_GE = 3;
+ EN_R_LT = 4;
+ EN_R_GT = 5;
+ EN_R_IS = 6;
+ EN_R_NOT = 7;
+ EN_R_BELOW = 8;
+ EN_R_ABOVE = 9;
+
+ EN_R_IS_OPEN = 1; { Rule-based control link status }
+ EN_R_IS_CLOSED = 2;
+ EN_R_IS_ACTIVE = 3;
+
+ EN_FALSE = 0; { boolean false }
+ EN_TRUE = 1; { boolean true }
+
+
+{$MACRO ON}
+
+{$ifdef MSWINDOWS}
+ EpanetLib = 'epanet2.dll';
+ {$DEFINE cdecl := stdcall}
+{$endif}
+
+{$ifdef UNIX}
+ {$ifdef DARWIN}
+ EpanetLib = 'libepanet2.dylib';
+ {$linklib libepanet2}
+ {$else}
+ EpanetLib = 'libepanet2.so';
+ {$endif}
+{$endif}
+
+{$ifdef UNIX}
+ {$DEFINE TimeType:=Int64}
+{$else}
+ {$DEFINE TimeType:=Integer}
+{$endif}
+
+{Project Functions}
+ function ENepanet(F1: PAnsiChar; F2: PAnsiChar; F3: PAnsiChar; F4: Pointer): Integer; cdecl; external EpanetLib;
+ function ENinit(F2: PAnsiChar; F3: PAnsiChar; UnitsType: Integer; HeadlossType: Integer): Integer; cdecl; external EpanetLib;
+ function ENopen(F1: PAnsiChar; F2: PAnsiChar; F3: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENopenX(F1: PAnsiChar; F2: PAnsiChar; F3: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENgetcount(Code: Integer; var Count: Integer): Integer; cdecl; external EpanetLib;
+ function ENgettitle(Line1: PAnsiChar; Line2: PAnsiChar; Line3: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENsettitle(Line1: PAnsiChar; Line2: PAnsiChar; Line3: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENgetcomment(ObjType: Integer; Index: Integer; Comment: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENsetcomment(ObjType: Integer; Index: Integer; Comment: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENgettag(ObjType: Integer; Index: Integer; Tag: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENsettag(ObjType: Integer; Index: Integer; Tag: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENsaveinpfile(F: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENclose: Integer; cdecl; external EpanetLib;
+
+{Hydraulic Functions}
+ function ENsolveH: Integer; cdecl; external EpanetLib;
+ function ENsaveH: Integer; cdecl; external EpanetLib;
+ function ENopenH: Integer; cdecl; external EpanetLib;
+ function ENinitH(SaveFlag: Integer): Integer; cdecl; external EpanetLib;
+ function ENrunH(var T: TimeType): Integer; cdecl; external EpanetLib;
+ function ENnextH(var Tstep: TimeType): Integer; cdecl; external EpanetLib;
+ function ENcloseH: Integer; cdecl; external EpanetLib;
+ function ENsavehydfile(F: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENusehydfile(F: PAnsiChar): Integer; cdecl; external EpanetLib;
+
+{Quality Functions}
+ function ENsolveQ: Integer; cdecl; external EpanetLib;
+ function ENopenQ: Integer; cdecl; external EpanetLib;
+ function ENinitQ(SaveFlag: Integer): Integer; cdecl; external EpanetLib;
+ function ENrunQ(var T: TimeType): Integer; cdecl; external EpanetLib;
+ function ENnextQ(var Tstep: TimeType): Integer; cdecl; external EpanetLib;
+ function ENstepQ(var Tleft: TimeType): Integer; cdecl; external EpanetLib;
+ function ENcloseQ: Integer; cdecl; external EpanetLib;
+
+{Reporting Functions}
+ function ENwriteline(S: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENreport: Integer; cdecl; external EpanetLib;
+ function ENcopyreport(F: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENclearreport: Integer; cdecl; external EpanetLib;
+ function ENresetreport: Integer; cdecl; external EpanetLib;
+ function ENsetreport(S: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENsetstatusreport(Code: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetversion(var Version: Integer): Integer; cdecl; external EpanetLib;
+ function ENgeterror(Errcode: Integer; Errmsg: PAnsiChar; MaxLen: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetstatistic(StatType: Integer; var Value: Single): Integer; cdecl; external EpanetLib;
+ function ENgetresultindex(Code: Integer; Index: Integer; var Value: Integer): Integer; cdecl; external EpanetLib;
+ function ENtimetonextevent(var EventType: Integer; var Duration: TimeType; var ElementIndex: Integer): Integer; cdecl; external EpanetLib;
+
+{Analysis Options Functions}
+ function ENgetoption(Code: Integer; var Value: Single): Integer; cdecl; external EpanetLib;
+ function ENsetoption(Code: Integer; Value: Single): Integer; cdecl; external EpanetLib;
+ function ENgetflowunits(var Code: Integer): Integer; cdecl; external EpanetLib;
+ function ENsetflowunits(Code: Integer): Integer; cdecl; external EpanetLib;
+ function ENgettimeparam(Code: Integer; var Value: TimeType): Integer; cdecl; external EpanetLib;
+ function ENsettimeparam(Code: Integer; Value: TimeType): Integer; cdecl; external EpanetLib;
+ function ENgetqualinfo(var QualType: Integer; ChemName: PAnsiChar; ChemUnits: PAnsiChar; var TraceNode: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetqualtype(var QualCode: Integer; var TraceNode: Integer): Integer; cdecl; external EpanetLib;
+ function ENsetqualtype(QualCode: Integer; ChemName: PAnsiChar; ChemUnits: PAnsiChar; TraceNodeID: PAnsiChar): Integer; cdecl; external EpanetLib;
+
+{Node Functions}
+ function ENaddnode(ID: PAnsiChar; NodeType: Integer; var Index: Integer): Integer; cdecl; external EpanetLib;
+ function ENdeletenode(Index: Integer; ActionCode: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetnodeindex(ID: PAnsiChar; var Index: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetnodeid(Index: Integer; ID: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENsetnodeid(Index: Integer; NewID: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENgetnodetype(Index: Integer; var Code: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetnodevalue(Index: Integer; Code: Integer; var Value: Single): Integer; cdecl; external EpanetLib;
+ function ENsetnodevalue(Index: Integer; Code: Integer; Value: Single): Integer; cdecl; external EpanetLib;
+ function ENsetjuncdata(Index: Integer; Elev: Single; Dmnd: Single; DmndPat: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENsettankdata(Index: Integer; Elev, InitLvl, MinLvl, MaxLvl, Diam, MinVol: Single; VolCurve: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENgetcoord(Index: Integer; var X: Double; var Y: Double): Integer; cdecl; external EpanetLib;
+ function ENsetcoord(Index: Integer; X: Double; Y: Double): Integer; cdecl; external EpanetLib;
+ function ENgetnodevalues(Code: Integer; var X: array of Single): Integer; cdecl; external EpanetLib;
+
+{Demand Functions}
+ function ENgetdemandmodel(var Model: Integer; var Pmin: Single; var Preq: Single; var Pexp: Single): Integer; cdecl; external EpanetLib;
+ function ENsetdemandmodel(Model: Integer; Pmin: Single; Preq: Single; Pexp: Single): Integer; cdecl; external EpanetLib;
+ function ENgetnumdemands(NodeIndex: Integer; var NumDemands: Integer): Integer; cdecl; external EpanetLib;
+ function ENadddemand(NodeIndex: Integer; BaseDemand: Single; PatName: PAnsiChar; DemandName: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENdeletedemand(NodeIndex: Integer; DemandIndex: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetdemandindex(NodeIndex: Integer; DemandName: PAnsiChar; var DemandIndex: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetbasedemand(NodeIndex: Integer; DemandIndex: Integer; var BaseDemand: Single): Integer; cdecl; external EpanetLib;
+ function ENsetbasedemand(NodeIndex: Integer; DemandIndex: Integer; BaseDemand: Single): Integer; cdecl; external EpanetLib;
+ function ENgetdemandpattern(NodeIndex: Integer; DemandIndex: Integer; var PatIndex: Integer): Integer; cdecl; external EpanetLib;
+ function ENsetdemandpattern(NodeIndex: Integer; DemandIndex: Integer; PatIndex: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetdemandname(NodeIndex: Integer; DemandIndex: Integer; DemandName: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENsetdemandname(NodeIndex: Integer; DemandIndex: Integer; DemandName: PAnsiChar): Integer; cdecl; external EpanetLib;
+
+{Link Functions}
+ function ENaddlink(ID: PAnsiChar; LinkType: Integer; FromNode: PAnsiChar; ToNode: PAnsiChar; var Index: Integer): Integer; cdecl; external EpanetLib;
+ function ENdeletelink(Index: Integer; ActionCode: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetlinkindex(ID: PAnsiChar; var Index: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetlinkid(Index: Integer; ID: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENsetlinkid(Index: Integer; ID: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENgetlinktype(Index: Integer; var Code: Integer): Integer; cdecl; external EpanetLib;
+ function ENsetlinktype(var Index: Integer; LinkType: Integer; ActionCode: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetlinknodes(Index: Integer; var Node1: Integer; var Node2: Integer): Integer; cdecl; external EpanetLib;
+ function ENsetlinknodes(Index: Integer; Node1: Integer; Node2: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetlinkvalue(Index: Integer; Code: Integer; var Value: Single): Integer; cdecl; external EpanetLib;
+ function ENsetlinkvalue(Index: Integer; Code: Integer; Value: Single): Integer; cdecl; external EpanetLib;
+ function ENsetpipedata(Index: Integer; Length: Single; Diam: Single; Rough: Single; Mloss:Single): Integer; cdecl; external EpanetLib;
+ function ENgetlinkvalues(Code: Integer; var X: array of Single): Integer; cdecl; external EpanetLib;
+
+ function ENgetvertexcount(Index: Integer; var Count: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetvertex(Index: Integer; Vertex: Integer; var X: Double; var Y: Double): Integer; cdecl; external EpanetLib;
+ function ENsetvertex(Index: Integer; Vertex: Integer; X: Double; Y: Double): Integer; cdecl; external EpanetLib;
+ function ENsetvertices(Index: Integer; var X: Double; var Y: Double; Count: Integer): Integer; cdecl; external EpanetLib;
+
+{Pump Functions}
+ function ENgetpumptype(LinkIndex: Integer; var PumpType: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetheadcurveindex(LinkIndex: Integer; var CurveIndex: Integer): Integer; cdecl; external EpanetLib;
+ function ENsetheadcurveindex(LinkIndex: Integer; CurveIndex: Integer): Integer; cdecl; external EpanetLib;
+
+{Pattern Functions}
+ function ENaddpattern(ID: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENdeletepattern(Index: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetpatternindex(ID: PAnsiChar; var Index: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetpatternid(Index: Integer; ID: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENsetpatternid(Index: Integer; ID: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENgetpatternlen(Index: Integer; var Len: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetpatternvalue(Index: Integer; Period: Integer; var Value: Single): Integer; cdecl; external EpanetLib;
+ function ENsetpatternvalue(Index: Integer; Period: Integer; Value: Single): Integer; cdecl; external EpanetLib;
+ function ENgetaveragepatternvalue(Index: Integer; var Value: Single): Integer; cdecl; external EpanetLib;
+ function ENsetpattern(Index: Integer; var F: Single; N: Integer): Integer; cdecl; external EpanetLib;
+
+{Curve Functions}
+ function ENaddcurve(ID: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENdeletecurve(Index: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetcurveindex(ID: PAnsiChar; var Index: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetcurveid(Index: Integer; ID: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENsetcurveid(Index: Integer; ID: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENgetcurvelen(Index: Integer; var Len: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetcurvetype(Index: Integer; var CurveType: Integer): Integer; cdecl; external EpanetLib;
+ function ENsetcurvetype(Index: Integer; CurveType: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetcurvevalue(CurveIndex: Integer; PointIndex: Integer; var X: Single; var Y: Single): Integer; cdecl; external EpanetLib;
+ function ENsetcurvevalue(CurveIndex: Integer; PointIndex: Integer; X: Single; Y: Single): Integer; cdecl; external EpanetLib;
+ function ENgetcurve(Index: Integer; ID: PAnsiChar; var N: Integer; var X: Single; var Y: Single): Integer; cdecl; external EpanetLib;
+ function ENsetcurve(Index: Integer; var X: Single; var Y: Single; N: Integer): Integer; cdecl; external EpanetLib;
+
+{Control Functions}
+ function ENaddcontrol(Ctype: Integer; Link: Integer; Setting: Single; Node: Integer; Level: Single; var Index: Integer): Integer; cdecl; external EpanetLib;
+ function ENdeletecontrol(Index: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetcontrol(Index: Integer; var Ctype: Integer; var Link: Integer; var Setting: Single; var Node: Integer; var Level: Single): Integer; cdecl; external EpanetLib;
+ function ENsetcontrol(Index: Integer; Ctype: Integer; Link: Integer; Setting: Single; Node: Integer; Level: Single): Integer; cdecl; external EpanetLib;
+ function ENgetcontrolenabled(Index: Integer; var out_enabled: Integer): Integer; cdecl; external EpanetLib;
+ function ENsetcontrolenabled(Index: Integer; enabled: Integer): Integer; cdecl; external EpanetLib;
+
+ {Rule-Based Control Functions}
+ function ENaddrule(Rule: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENdeleterule(Index: Integer): Integer; cdecl; external EpanetLib;
+ function ENgetrule(Index: Integer; var Npremises: Integer; var NthenActions: Integer;
+ var NelseActions: Integer; var Priority: Single): Integer; cdecl; external EpanetLib;
+ function ENgetruleID(Index: Integer; ID: PAnsiChar): Integer; cdecl; external EpanetLib;
+ function ENsetrulepriority(Index: Integer; Priority: Single): Integer; cdecl; external EpanetLib;
+ function ENgetpremise(RuleIndex: Integer; PremiseIndex: Integer; var LogOp: Integer;
+ var ObjType: Integer; var ObjIndex: Integer; var Param: Integer; var RelOp: Integer;
+ var Status: Integer; var Value: Single): Integer; cdecl; external EpanetLib;
+ function ENsetpremise(RuleIndex: Integer; PremiseIndex: Integer; LogOp: Integer; ObjType: Integer;
+ ObjIndex: Integer; Param: Integer; RelOp: Integer; Status: Integer; Value: Single): Integer; cdecl; external EpanetLib;
+ function ENsetpremiseindex(RuleIndex: Integer; PremiseIndex: Integer; ObjIndex: Integer): Integer; cdecl; external EpanetLib;
+ function ENsetpremisestatus(RuleIndex: Integer; PremiseIndex: Integer; Status: Integer): Integer; cdecl; external EpanetLib;
+ function ENsetpremisevalue(RuleIndex: Integer; PremiseIndex: Integer; Value: Single): Integer; cdecl; external EpanetLib;
+ function ENgetthenaction(RuleIndex: Integer; ActionIndex: Integer; var LinkIndex: Integer;
+ var Status: Integer; var Setting: Single): Integer; cdecl; external EpanetLib;
+ function ENsetthenaction(RuleIndex: Integer; ActionIndex: Integer; LinkIndex: Integer;
+ Status: Integer; Setting: Single): Integer; cdecl; external EpanetLib;
+ function ENgetelseaction(RuleIndex: Integer; ActionIndex: Integer; var LinkIndex: Integer;
+ var Status: Integer; var Setting: Single): Integer; cdecl; external EpanetLib;
+ function ENsetelseaction(RuleIndex: Integer; ActionIndex: Integer; LinkIndex: Integer;
+ Status: Integer; Setting: Single): Integer; cdecl; external EpanetLib;
+ function ENgetruleenabled(Index: Integer; var out_enabled: Integer): Integer; cdecl; external EpanetLib;
+ function ENsetruleenabled(Index: Integer; enabled: Integer): Integer; cdecl; external EpanetLib;
+
+implementation
+
+end.
diff --git a/epanet/linux/epanet2_2.h b/epanet/linux/epanet2_2.h
new file mode 100644
index 0000000..eca5095
--- /dev/null
+++ b/epanet/linux/epanet2_2.h
@@ -0,0 +1,1960 @@
+/** @file epanet2_2.h
+ @see http://github.com/openwateranalytics/epanet
+ */
+
+/*
+ ******************************************************************************
+ Project: OWA EPANET
+ Version: 2.3
+ Module: epanet2.h
+ Description: API function declarations
+ Authors: see AUTHORS
+ Copyright: see AUTHORS
+ License: see LICENSE
+ Last Updated: 04/25/2025
+ ******************************************************************************
+ */
+
+#ifndef EPANET2_2_H
+#define EPANET2_2_H
+
+#ifdef epanet_py_EXPORTS
+ #define DLLEXPORT
+#else
+ #ifndef DLLEXPORT
+ #ifdef _WIN32
+ #ifdef epanet2_EXPORTS
+ #define DLLEXPORT __declspec(dllexport) __stdcall
+ #else
+ #define DLLEXPORT __declspec(dllimport) __stdcall
+ #endif
+ #elif defined(__CYGWIN__)
+ #define DLLEXPORT __stdcall
+ #else
+ #define DLLEXPORT
+ #endif
+ #endif
+#endif
+
+#include "epanet2_enums.h"
+
+// --- Declare the EPANET toolkit functions
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/**
+ @brief The EPANET Project wrapper object
+*/
+typedef struct Project *EN_Project;
+
+/*===================================================================
+
+ Project Functions
+
+===================================================================*/
+
+ /**
+ @brief Creates an EPANET project.
+ @param[out] ph an EPANET project handle that is passed into all other API functions.
+ @return an error code.
+
+ EN_createproject must be called before any other API functions are used.
+ */
+ int DLLEXPORT EN_createproject(EN_Project *ph);
+
+ /**
+ @brief Deletes a currently opened EPANET project.
+ @param[in,out] ph an EPANET project handle which is returned as NULL.
+ @return an error code.
+
+ EN_deleteproject should be called after all network analysis has been completed.
+ */
+ int DLLEXPORT EN_deleteproject(EN_Project ph);
+
+ /**
+ @brief Runs a complete EPANET simulation.
+ @param ph an EPANET project handle.
+ @param inpFile the name of an existing EPANET-formatted input file.
+ @param rptFile the name of a report file to be created (or "" if not needed)
+ @param outFile the name of a binary output file to be created (or "" if not needed)
+ @param pviewprog a callback function that takes a character string (char *) as its only parameter.
+ @return an error code
+
+ The callback function should reside in and be used by the calling code to display
+ the progress messages that EPANET generates as it carries out its computations. Here is
+ an example of a such a function that displays progress messages to stdout:
+ \code {.c}
+ void writeConsole(char *s)
+ {
+ fprintf(stdout, "\n%s", s);
+ }
+ \endcode
+ It would be passed into EN_runproject as `&writeConsole`. If this feature is not needed then
+ the pviewprog argument should be `NULL`.
+ */
+ int DLLEXPORT EN_runproject(EN_Project ph, const char *inpFile, const char *rptFile,
+ const char *outFile, void (*pviewprog)(char *));
+
+ /**
+ @brief Initializes an EPANET project.
+ @param ph an EPANET project handle.
+ @param rptFile the name of a report file to be created (or "" if not needed).
+ @param outFile the name of a binary output file to be created (or "" if not needed).
+ @param unitsType the choice of flow units (see @ref EN_FlowUnits).
+ @param headLossType the choice of head loss formula (see @ref EN_HeadLossType).
+ @return an error code.
+
+ This function should be called immediately after ::EN_createproject if an EPANET-formatted input
+ file will not be used to supply network data. If the project receives it's network data
+ from an input file then there is no need to call this function.
+ */
+ int DLLEXPORT EN_init(EN_Project ph, const char *rptFile, const char *outFile,
+ int unitsType, int headLossType);
+
+ /**
+ @brief Reads an EPANET input file with no errors allowed.
+ @param ph an EPANET project handle.
+ @param inpFile the name of an existing EPANET-formatted input file.
+ @param rptFile the name of a report file to be created (or "" if not needed).
+ @param outFile the name of a binary output file to be created (or "" if not needed).
+ @return an error code.
+
+ This function should be called immediately after ::EN_createproject if an EPANET-formatted
+ input file will be used to supply network data. If errors are detected then the project is
+ not opened and will not accept toolkit function calls.
+ */
+ int DLLEXPORT EN_open(EN_Project ph, const char *inpFile, const char *rptFile,
+ const char *outFile);
+
+ /**
+ @brief Reads an EPANET input file with errors allowed.
+ @param ph an EPANET project handle.
+ @param inpFile the name of an existing EPANET-formatted input file.
+ @param rptFile the name of a report file to be created (or "" if not needed).
+ @param outFile the name of a binary output file to be created (or "" if not needed).
+ @return an error code.
+
+ This function should be called immediately after ::EN_createproject if an EPANET-formatted
+ input file will be used to supply network data. If formatting errors are detected (error
+ code = 200) then the project remains open and will accept toolkit function calls.
+ */
+ int DLLEXPORT EN_openX(EN_Project ph, const char *inpFile, const char *rptFile,
+ const char *outFile);
+
+ /**
+ @brief Retrieves the title lines of the project
+ @param ph an EPANET project handle.
+ @param[out] out_line1 first title line
+ @param[out] out_line2 second title line
+ @param[out] out_line3 third title line
+ @return an error code
+ */
+ int DLLEXPORT EN_gettitle(EN_Project ph, char *out_line1, char *out_line2, char *out_line3);
+
+ /**
+ @brief Sets the title lines of the project
+ @param ph an EPANET project handle.
+ @param line1 first title line
+ @param line2 second title line
+ @param line3 third title line
+ @return an error code
+ */
+ int DLLEXPORT EN_settitle(EN_Project ph, const char *line1, const char *line2,
+ const char *line3);
+
+ /**
+ @brief Retrieves a descriptive comment assigned to a Node, Link, Pattern or Curve.
+ @param ph an EPANET project handle.
+ @param object a type of object (either EN_NODE, EN_LINK, EN_TIMEPAT or EN_CURVE)
+ @param index the object's index starting from 1
+ @param[out] out_comment the comment string assigned to the object
+ @return an error code
+ */
+ int DLLEXPORT EN_getcomment(EN_Project ph, int object, int index, char *out_comment);
+
+ /**
+ @brief Assigns a descriptive comment to a Node, Link, Pattern or Curve.
+ @param ph an EPANET project handle.
+ @param object a type of object (either EN_NODE, EN_LINK, EN_TIMEPAT or EN_CURVE)
+ @param index the object's index starting from 1
+ @param comment the comment string assigned to the object
+ @return an error code
+ */
+ int DLLEXPORT EN_setcomment(EN_Project ph, int object, int index,
+ const char *comment);
+
+ /**
+ @brief Retrieves a tag string assigned to a Node or Link.
+ @param ph an EPANET project handle.
+ @param object a type of object (either EN_NODE or EN_LINK)
+ @param index the object's index starting from 1
+ @param[out] out_tag the tag string assigned to the object
+ @return an error code
+ */
+ int DLLEXPORT EN_gettag(EN_Project ph, int object, int index, char *out_tag);
+
+ /**
+ @brief Assigns a tag string to a Node or Link.
+ @param ph an EPANET project handle.
+ @param object a type of object (either EN_NODE or EN_LINK)
+ @param index the object's index starting from 1
+ @param tag the tag string assigned to the object
+ @return an error code
+ */
+ int DLLEXPORT EN_settag(EN_Project ph, int object, int index,
+ const char *tag);
+
+ /**
+ @brief Retrieves the number of objects of a given type in a project.
+ @param ph an EPANET project handle.
+ @param object a type of object to count (see @ref EN_CountType)
+ @param[out] out_count number of objects of the specified type
+ @return an error code
+ */
+ int DLLEXPORT EN_getcount(EN_Project ph, int object, int *out_count);
+
+ /**
+ @brief Saves a project's data to an EPANET-formatted text file.
+ @param ph an EPANET project handle.
+ @param filename the name of the file to create.
+ @return an error code
+ */
+ int DLLEXPORT EN_saveinpfile(EN_Project ph, const char *filename);
+
+ /**
+ @brief Closes a project and frees all of its memory.
+ @param ph an EPANET project handle.
+ @return an error code
+
+ This function clears all existing data from a project but does not delete the
+ project, so it can be re-used with another set of network data. Use ::EN_deleteproject
+ to actually delete a project from memory.
+ */
+ int DLLEXPORT EN_close(EN_Project ph);
+
+/*===================================================================
+
+ Hydraulic Analysis Functions
+
+===================================================================*/
+
+ /**
+ @brief Runs a complete hydraulic simulation with results for all time periods
+ written to a temporary hydraulics file.
+ @param ph an EPANET project handle.
+ @return an error code.
+
+ Use ::EN_solveH to generate a complete hydraulic solution which can stand alone
+ or be used as input to a water quality analysis. This function will not allow one to
+ examine intermediate hydraulic results as they are generated. It can also be followed by calls
+ to ::EN_saveH and ::EN_report to write hydraulic results to the report file.
+
+ The sequence ::EN_openH - ::EN_initH - ::EN_runH - ::EN_nextH - ::EN_closeH
+ can be used instead to gain access to results at intermediate time periods and
+ directly adjust link status and control settings as a simulation proceeds.
+
+ Example:
+ \code {.c}
+ EN_Project ph;
+ EN_createproject(&ph);
+ EN_open(ph, "net1.inp", "net1.rpt", "");
+ EN_solveH(ph);
+ EN_solveQ(ph);
+ EN_report(ph);
+ EN_deleteproject(ph);
+ \endcode
+ */
+ int DLLEXPORT EN_solveH(EN_Project ph);
+
+ /**
+ @brief Uses a previously saved binary hydraulics file to supply a project's hydraulics.
+ @param ph an EPANET project handle.
+ @param filename the name of the binary file containing hydraulic results.
+ @return an error code.
+
+ Call this function to re-use a set of hydraulic analysis results saved previously. This
+ can save computational time if water quality analyses are being made under the same set
+ of hydraulic conditions.
+
+ Do not call this function while the hydraulics solver is open.
+ */
+ int DLLEXPORT EN_usehydfile(EN_Project ph, const char *filename);
+
+ /**
+ @brief Opens a project's hydraulic solver.
+ @param ph an EPANET project handle.
+ @return an error code.
+
+ Call ::EN_openH prior to running the first hydraulic analysis using the
+ ::EN_initH - ::EN_runH - ::EN_nextH sequence. Multiple analyses can be made before
+ calling ::EN_closeH to close the hydraulic solver.
+
+ Do not call this function if ::EN_solveH is being used to run a complete hydraulic
+ analysis or if hydraulics are being supplied by a previously saved hydraulics file
+ using ::EN_usehydfile.
+ */
+ int DLLEXPORT EN_openH(EN_Project ph);
+
+ /**
+ @brief Initializes a network prior to running a hydraulic analysis.
+ @param ph an EPANET project handle.
+ @param initFlag a 2-digit initialization flag (see @ref EN_InitHydOption).
+ @return an error code.
+
+ This function initializes storage tank levels, link status and settings, and
+ the simulation time clock prior to running a hydraulic analysis.
+
+ The initialization flag is a two digit number where the 1st (left) digit
+ indicates if link flows should be re-initialized (1) or not (0), and the
+ 2nd digit indicates if hydraulic results should be saved to a temporary
+ binary hydraulics file (1) or not (0).
+
+ Be sure to call ::EN_initH prior to running a hydraulic analysis using a
+ ::EN_runH - ::EN_nextH loop.
+
+ Choose to save hydraulics results if you will be:
+ - making a subsequent water quality run,
+ - using ::EN_report to generate a report
+ - using ::EN_savehydfile to save the binary hydraulics file.
+
+ There is no need to save hydraulics if you will be writing custom code to
+ process hydraulic results as they are generated using the functions ::EN_getnodevalue
+ and ::EN_getlinkvalue.
+ */
+ int DLLEXPORT EN_initH(EN_Project ph, int initFlag);
+
+ /**
+ @brief Computes a hydraulic solution for the current point in time.
+ @param ph an EPANET project handle.
+ @param[out] out_currentTime the current simulation time in seconds.
+ @return an error or warning code.
+
+ This function is used in a loop with ::EN_nextH to run an extended period hydraulic
+ simulation. This process automatically updates the simulation clock time so `currentTime`
+ should be treated as a read-only variable.
+
+ ::EN_initH must have been called prior to running the ::EN_runH - ::EN_nextH loop.
+
+ See ::EN_nextH for an example of using this function.
+ */
+ int DLLEXPORT EN_runH(EN_Project ph, long *out_currentTime);
+
+ /**
+ @brief Determines the length of time until the next hydraulic event occurs in an
+ extended period simulation.
+ @param ph an EPANET project handle.
+ @param[out] out_tStep the time (in seconds) until the next hydraulic event or 0 if at
+ the end of the full simulation duration.
+ @return an error code.
+
+ This function is used in a loop with ::EN_runH to run an extended period hydraulic
+ simulation.
+
+ The value of `out_tstep` should be treated as a read-only variable. It is automatically
+ computed as the smaller of:
+ - the time interval until the next hydraulic time step begins
+ - the time interval until the next reporting time step begins
+ - the time interval until the next change in demands occurs
+ - the time interval until a tank becomes full or empty
+ - the time interval until a control or rule fires.
+
+ Example:
+ \code {.c}
+ long t, tstep;
+ EN_openH(ph);
+ EN_initH(ph, EN_NOSAVE);
+ do {
+ EN_runH(ph, &t);
+ // Retrieve hydraulic results for time t
+ EN_nextH(ph, &tstep);
+ } while (tstep > 0);
+ EN_closeH(ph);
+ \endcode
+ */
+ int DLLEXPORT EN_nextH(EN_Project ph, long *out_tStep);
+
+ /**
+ @brief Transfers a project's hydraulics results from its temporary hydraulics file
+ to its binary output file, where results are only reported at uniform reporting intervals.
+ @param ph an EPANET project handle.
+ @return an error code.
+
+ ::EN_saveH is used when only a hydraulic analysis is run and results at uniform reporting
+ intervals need to be transferred to a project's binary output file. Such would be the case
+ when results are to be written in formatted fashion to the project's report file using ::EN_report.
+ */
+ int DLLEXPORT EN_saveH(EN_Project ph);
+
+ /**
+ @brief Saves a project's temporary hydraulics file to disk.
+ @param ph an EPANET project handle.
+ @param filename the name of the file to be created.
+ @return an error code.
+
+ Use this function to save the current set of hydraulics results to a file, either for
+ post-processing or to be used at a later time by calling the ::EN_usehydfile function.
+
+ The hydraulics file contains nodal demands and heads and link flows, status, and settings
+ for all hydraulic time steps, even intermediate ones.
+
+ Before calling this function hydraulic results must have been generated and saved by having
+ called ::EN_solveH or the ::EN_initH - ::EN_runH - ::EN_nextH sequence with the initflag
+ argument of ::EN_initH set to `EN_SAVE` or `EN_SAVE_AND_INIT`.
+ */
+ int DLLEXPORT EN_savehydfile(EN_Project ph, const char *filename);
+
+ /**
+ @brief Closes the hydraulic solver freeing all of its allocated memory.
+ @return an error code.
+
+ Call ::EN_closeH after all hydraulics analyses have been made using
+ ::EN_initH - ::EN_runH - ::EN_nextH. Do not call this function if ::EN_solveH is being used.
+ */
+ int DLLEXPORT EN_closeH(EN_Project ph);
+
+/*===================================================================
+
+ Water Quality Analysis Functions
+
+===================================================================*/
+
+ /**
+ @brief Runs a complete water quality simulation with results at uniform
+ reporting intervals written to the project's binary output file.
+ @param ph an EPANET project handle.
+ @return an error code.
+
+ A hydraulic analysis must have been run and saved to a hydraulics file before
+ calling ::EN_solveQ. This function will not allow one to examine intermediate water
+ quality results as they are generated. It can be followed by a call to ::EN_report
+ to write all hydraulic and water quality results to a formatted report file.
+
+ One can instead use the ::EN_openQ - ::EN_initQ - ::EN_runQ - ::EN_nextQ - ::EN_closeQ
+ sequence to gain access to gain access to water quality results at intermediate time
+ periods.
+
+ Example: see ::EN_solveH.
+ */
+ int DLLEXPORT EN_solveQ(EN_Project ph);
+
+ /**
+ @brief Opens a project's water quality solver.
+ @param ph an EPANET project handle.
+ @return an error code.
+
+ Call ::EN_openQ prior to running the first water quality analysis using an
+ ::EN_initQ - ::EN_runQ - ::EN_nextQ (or ::EN_stepQ) sequence. Multiple water
+ quality analyses can be made before calling ::EN_closeQ to close the water
+ quality solver.
+
+ Do not call this function if a complete water quality analysis will be made
+ using ::EN_solveQ.
+ */
+ int DLLEXPORT EN_openQ(EN_Project ph);
+
+ /**
+ @brief Initializes a network prior to running a water quality analysis.
+ @param ph an EPANET project handle.
+ @param saveFlag set to `EN_SAVE` (1) if results are to be saved to the project's
+ binary output file, or to `EN_NOSAVE` (0) if not.
+ @return an error code.
+
+ Call ::EN_initQ prior to running a water quality analysis using ::EN_runQ in
+ conjunction with either ::EN_nextQ or ::EN_stepQ.
+
+ ::EN_openQ must have been called prior to calling ::EN_initQ.
+
+ Do not call ::EN_initQ if a complete water quality analysis will be made using ::EN_solveQ.
+ */
+ int DLLEXPORT EN_initQ(EN_Project ph, int saveFlag);
+
+ /**
+ @brief Makes hydraulic and water quality results at the start of the current time
+ period available to a project's water quality solver.
+ @param ph an EPANET project handle.
+ @param[out] out_currentTime current simulation time in seconds.
+ @return an error code.
+
+ Use ::EN_runQ along with ::EN_nextQ in a loop to access water quality results at the
+ start of each hydraulic period in an extended period simulation. Or use it in a loop
+ with ::EN_stepQ to access results at the start of each water quality time step. See
+ each of these functions for examples of how to code such loops.
+
+ ::EN_initQ must have been called prior to running an ::EN_runQ - ::EN_nextQ
+ (or ::EN_stepQ) loop.
+
+ The current time of the simulation, `out_currentTime`, is determined from information
+ saved with the hydraulic analysis that preceded the water quality analysis. Treat it
+ as a read-only variable.
+ */
+ int DLLEXPORT EN_runQ(EN_Project ph, long *out_currentTime);
+
+ /**
+ @brief Advances a water quality simulation over the time until the next hydraulic event.
+ @param ph an EPANET project handle.
+ @param[out] out_tStep time (in seconds) until the next hydraulic event or 0 if at the end
+ of the full simulation duration.
+ @return an error code.
+
+ This function is used in a loop with ::EN_runQ to perform an extended period water
+ quality analysis. It reacts and routes a project's water quality constituent over a
+ time step determined by when the next hydraulic event occurs. Use ::EN_stepQ instead
+ if you wish to generate results over each water quality time step.
+
+ The value of `out_tStep` is determined from information produced by the hydraulic analysis
+ that preceded the water quality analysis. Treat it as a read-only variable.
+
+ Example:
+ \code {.c}
+ long t, tStep;
+ EN_solveH(ph); // Generate & save hydraulics
+ EN_openQ(ph);
+ EN_initQ(ph, EN_NOSAVE);
+ do {
+ EN_runQ(ph, &t);
+ // Monitor results at time t, which
+ // begins a new hydraulic time period
+ EN_nextQ(ph, &tStep);
+ } while (tStep > 0);
+ EN_closeQ(ph);
+ \endcode
+ */
+ int DLLEXPORT EN_nextQ(EN_Project ph, long *out_tStep);
+
+ /**
+ @brief Advances a water quality simulation by a single water quality time step.
+ @param ph an EPANET project handle.
+ @param[out] out_timeLeft time left (in seconds) to the overall simulation duration.
+ @return an error code.
+
+ This function is used in a loop with ::EN_runQ to perform an extended period water
+ quality simulation. It allows one to generate water quality results at each water
+ quality time step of the simulation, rather than over each hydraulic event period
+ as with ::EN_nextQ.
+
+ Use the argument `out_timeLeft` to determine when no more calls to ::EN_runQ are needed
+ because the end of the simulation period has been reached (i.e., when `out_timeLeft` = 0).
+ */
+ int DLLEXPORT EN_stepQ(EN_Project ph, long *out_timeLeft);
+
+ /**
+ @brief Closes the water quality solver, freeing all of its allocated memory.
+ @param ph an EPANET project handle.
+ @return an error code.
+
+ Call ::EN_closeQ after all water quality analyses have been made using the
+ ::EN_initQ - ::EN_runQ - ::EN_nextQ (or ::EN_stepQ) sequence of function calls.
+
+ Do not call this function if ::EN_solveQ is being used.
+ */
+ int DLLEXPORT EN_closeQ(EN_Project ph);
+
+/*===================================================================
+
+ Reporting Functions
+
+===================================================================*/
+
+ /**
+ @brief Sets a user-supplied callback function for reporting
+ @param ph an EPANET project handle.
+ @param callback a function pointer used for reporting.
+ @return an error code.
+
+ The callback function replaces the project's report file as
+ the destination for all output written by ::EN_writeline. It must have
+ the following signature:
+
+ `void(void *userData, void *EN_projectHandle p, const char* s)`
+
+ The `userData` parameter is a pointer to a client-side data object.
+ It can be changed using the ::EN_setreportcallbackuserdata function.
+ The parameter `s` is a placeholder for the EPANET-generated string
+ that was passed into ::EN_writeline. Setting the callback function to
+ NULL reverts to having ::EN_writeline use the project's report file.
+ */
+ int DLLEXPORT EN_setreportcallback(EN_Project ph, void(*callback)(void *userData, void *EN_projectHandle, const char*));
+
+ /**
+ @brief Sets a pointer to a client-side data object
+ @param ph an EPANET project handle.
+ @param userData a pointer to a client-side data object.
+ @return an error code.
+
+ The data pointer supplied by this function is passed into the callback
+ function declared in ::EN_setreportcallback that replaces a project's
+ report file as the destination for output written with ::EN_writeline.
+ */
+ int DLLEXPORT EN_setreportcallbackuserdata(EN_Project ph, void *userData);
+
+ /**
+ @brief Writes a line of text to a project's report file.
+ @param ph an EPANET project handle.
+ @param line a text string to write.
+ @return an error code.
+
+ ::EN_setreportcallback can be used to assign an alternative destination
+ to write `line` to in place of the project's report file.
+ */
+ int DLLEXPORT EN_writeline(EN_Project ph, const char *line);
+
+ /**
+ @brief Writes simulation results in a tabular format to a project's report file.
+ @param ph an EPANET project handle.
+ @return an error code
+
+ Either a full hydraulic analysis or full hydraulic and water quality analysis must
+ have been run, with results saved to file, before ::EN_report is called. In the
+ former case, ::EN_saveH must also be called first to transfer results from the
+ project's intermediate hydraulics file to its output file.
+
+ The format of the report is controlled by commands issued with ::EN_setreport.
+ */
+ int DLLEXPORT EN_report(EN_Project ph);
+
+ /**
+ @brief Copies the current contents of a project's report file to another file.
+ @param ph an EPANET project handle.
+ @param filename the full path name of the destination file.
+ @return an error code.
+
+ This function allows toolkit clients to retrieve the contents of a project's
+ report file while the project is still open.
+ */
+ int DLLEXPORT EN_copyreport(EN_Project ph, const char *filename);
+
+ /**
+ @brief Clears the contents of a project's report file.
+ @param ph an EPANET project handle.
+ @return an error code.
+ */
+ int DLLEXPORT EN_clearreport(EN_Project ph);
+
+ /**
+ @brief Resets a project's report options to their default values.
+ @param ph an EPANET project handle.
+ @return an error code
+
+ After calling this function the default reporting options are in effect. These are:
+ - no status report
+ - no energy report
+ - no nodes reported on
+ - no links reported on
+ - node variables reported to 2 decimal places
+ - link variables reported to 2 decimal places (3 for friction factor)
+ - node variables reported are elevation, head, pressure, and quality
+ - link variables reported are flow, velocity, and head loss.
+ */
+ int DLLEXPORT EN_resetreport(EN_Project ph);
+
+ /**
+ @brief Processes a reporting format command.
+ @param ph an EPANET project handle.
+ @param format a report formatting command.
+ @return an error code
+
+ Acceptable report formatting commands are described in the @ref ReportPage section of
+ the @ref InpFile topic.
+
+ Formatted results of a simulation can be written to a project's report file
+ using the ::EN_report function.
+ */
+ int DLLEXPORT EN_setreport(EN_Project ph, const char *format);
+
+ /**
+ @brief Sets the level of hydraulic status reporting.
+ @param ph an EPANET project handle.
+ @param level a status reporting level code (see @ref EN_StatusReport).
+ @return an error code.
+
+ Status reporting writes changes in the hydraulics status of network elements to a
+ project's report file as a hydraulic simulation unfolds. There are three levels
+ of reporting: `EN_NO_REPORT` (no status reporting), `EN_NORMAL_REPORT` (normal
+ reporting) `EN_FULL_REPORT` (full status reporting).
+
+ The full status report contains information at each trial of the solution to the
+ system hydraulic equations at each time step of a simulation. It is useful mainly
+ for debugging purposes.
+
+ If many hydraulic analyses will be run in the application it is recommended that
+ status reporting be turned off (`level` = `EN_NO_REPORT`).
+ */
+ int DLLEXPORT EN_setstatusreport(EN_Project ph, int level);
+
+ /**
+ @brief Retrieves the toolkit API version number.
+ @param[out] out_version the version of the OWA-EPANET toolkit.
+ @return an error code.
+
+ The version number is to be interpreted with implied decimals, i.e.,
+ "20100" == "2(.)01(.)00"
+ */
+ int DLLEXPORT EN_getversion(int *out_version);
+
+ /**
+ @brief Returns the text of an error message generated by an error code.
+ @param errcode an error code.
+ @param[out] out_errmsg the error message generated by the error code
+ @param maxLen maximum number of characters that errmsg can hold
+ @return an error code
+
+ Error message strings should be greater than @ref EN_SizeLimits "EN_MAXMSG" characters in length.
+ */
+ int DLLEXPORT EN_geterror(int errcode, char *out_errmsg, int maxLen);
+
+ /**
+ @brief Retrieves a particular simulation statistic.
+ @param ph an EPANET project handle.
+ @param type the type of statistic to retrieve (see @ref EN_AnalysisStatistic).
+ @param[out] out_value the value of the statistic.
+ @return an error code
+ */
+ int DLLEXPORT EN_getstatistic(EN_Project ph, int type, double* out_value);
+
+
+ /**
+ @brief Gets information about when the next hydraulic time step occurs.
+ @param ph an EPANET project handle.
+ @param[out] eventType the type of event that will occur (see @ref EN_TimestepEvent).
+ @param[out] duration the amount of time in the future this event will occur
+ @param[out] elementIndex the index of the element causing the event.
+ **/
+ int DLLEXPORT EN_timetonextevent(EN_Project ph, int *eventType, long *duration, int *elementIndex);
+
+ /**
+ @brief Retrieves the order in which a node or link appears in an @ref OutFile "output file".
+ @param ph an EPANET project handle.
+ @param type a type of element (either @ref EN_NODE or @ref EN_LINK).
+ @param index the element's current index (starting from 1).
+ @param[out] out_value the order in which the element's results were written to file.
+ @return an error code.
+
+ If the element does not appear in the file then its result index is 0.
+
+ This function can be used to correctly retrieve results from an EPANET binary output file
+ after the order of nodes or links in a network's database has been changed due to editing
+ operations.
+ */
+ int DLLEXPORT EN_getresultindex(EN_Project ph, int type, int index, int *out_value);
+
+/*===================================================================
+
+ Analysis Options Functions
+
+===================================================================*/
+
+ /**
+ @brief Retrieves the value of an analysis option.
+ @param ph an EPANET project handle.
+ @param option a type of analysis option (see @ref EN_Option).
+ @param[out] out_value the current value of the option.
+ @return an error code
+ */
+ int DLLEXPORT EN_getoption(EN_Project ph, int option, double *out_value);
+
+ /**
+ @brief Sets the value for an analysis option.
+ @param ph an EPANET project handle.
+ @param option a type of analysis option (see @ref EN_Option).
+ @param value the new value assigned to the option.
+ @return an error code.
+ @see EN_Option
+ */
+ int DLLEXPORT EN_setoption(EN_Project ph, int option, double value);
+
+ /**
+ @brief Retrieves a project's flow units.
+ @param ph an EPANET project handle.
+ @param[out] out_units a flow units code (see @ref EN_FlowUnits)
+ @return an error code.
+
+ Flow units in liters or cubic meters implies that SI metric units are used for all
+ other quantities in addition to flow. Otherwise US Customary units are employed.
+ */
+ int DLLEXPORT EN_getflowunits(EN_Project ph, int *out_units);
+
+ /**
+ @brief Sets a project's flow units.
+ @param ph an EPANET project handle.
+ @param units a flow units code (see @ref EN_FlowUnits)
+ @return an error code.
+
+ Flow units in liters or cubic meters implies that SI metric units are used for all
+ other quantities in addition to flow. Otherwise US Customary units are employed.
+ */
+ int DLLEXPORT EN_setflowunits(EN_Project ph, int units);
+
+ /**
+ @brief Retrieves the value of a time parameter.
+ @param ph an EPANET project handle.
+ @param param a time parameter code (see @ref EN_TimeParameter).
+ @param[out] out_value the current value of the time parameter (in seconds).
+ @return an error code.
+ */
+ int DLLEXPORT EN_gettimeparam(EN_Project ph, int param, long *out_value);
+
+ /**
+ @brief Sets the value of a time parameter.
+ @param ph an EPANET project handle.
+ @param param a time parameter code (see @ref EN_TimeParameter).
+ @param value the new value of the time parameter (in seconds)
+ @return an error code.
+ */
+ int DLLEXPORT EN_settimeparam(EN_Project ph, int param, long value);
+
+ /**
+ @brief Gets information about the type of water quality analysis requested.
+ @param ph an EPANET project handle.
+ @param[out] out_qualType type of analysis to run (see @ref EN_QualityType).
+ @param[out] out_chemName name of chemical constituent.
+ @param[out] out_chemUnits concentration units of the constituent.
+ @param[out] out_traceNode index of the node being traced (if applicable).
+ @return an error code.
+ */
+ int DLLEXPORT EN_getqualinfo(EN_Project ph, int *out_qualType, char *out_chemName,
+ char *out_chemUnits, int *out_traceNode);
+
+ /**
+ @brief Retrieves the type of water quality analysis to be run.
+ @param ph an EPANET project handle.
+ @param[out] out_qualType the type of analysis to run (see @ref EN_QualityType).
+ @param[out] out_traceNode the index of node being traced if `out_qualType` = `EN_TRACE`.
+ @return an error code.
+ */
+ int DLLEXPORT EN_getqualtype(EN_Project ph, int *out_qualType, int *out_traceNode);
+
+ /**
+ @brief Sets the type of water quality analysis to run.
+ @param ph an EPANET project handle.
+ @param qualType the type of analysis to run (see @ref EN_QualityType).
+ @param chemName the name of the quality constituent.
+ @param chemUnits the concentration units of the constituent.
+ @param traceNode the ID name of the node being traced if `qualType` = `EN_TRACE`.
+ @return an error code.
+
+ Chemical name and units can be an empty string if the analysis is not for a chemical.
+ The same holds for the trace node if the analysis is not for source tracing.
+
+ Note that the trace node is specified by ID name and not by index.
+ */
+ int DLLEXPORT EN_setqualtype(EN_Project ph, int qualType, const char *chemName,
+ const char *chemUnits, const char *traceNode);
+
+/*===================================================================
+
+ Node Functions
+
+===================================================================*/
+
+ /**
+ @brief Adds a new node to a project.
+ @param ph an EPANET project handle.
+ @param id the ID name of the node to be added.
+ @param nodeType the type of node being added (see @ref EN_NodeType)
+ @param[out] out_index the index of the newly added node
+ @return an error code.
+
+ When a new node is created all of its properties (see @ref EN_NodeProperty) are set to 0.
+ */
+ int DLLEXPORT EN_addnode(EN_Project ph, const char *id, int nodeType, int *out_index);
+
+ /**
+ @brief Deletes a node from a project.
+ @param ph an EPANET project handle.
+ @param index the index of the node to be deleted.
+ @param actionCode the action taken if any control contains the node and its links.
+ @return an error code.
+
+ If `actionCode` is `EN_UNCONDITIONAL` then the node, its incident links and all
+ simple and rule-based controls that contain them are deleted. If set to
+ `EN_CONDITIONAL` then the node is not deleted if it or its incident links appear
+ in any controls and error code 261 is returned.
+
+ */
+ int DLLEXPORT EN_deletenode(EN_Project ph, int index, int actionCode);
+
+ /**
+ @brief Gets the index of a node given its ID name.
+ @param ph an EPANET project handle.
+ @param id a node ID name.
+ @param[out] out_index the node's index (starting from 1).
+ @return an error code
+ */
+ int DLLEXPORT EN_getnodeindex(EN_Project ph, const char *id, int *out_index);
+
+ /**
+ @brief Gets the ID name of a node given its index.
+ @param ph an EPANET project handle.
+ @param index a node's index (starting from 1).
+ @param[out] out_id the node's ID name.
+ @return an error code
+
+ The ID name must be sized to hold at least @ref EN_SizeLimits "EN_MAXID+1" characters.
+ */
+ int DLLEXPORT EN_getnodeid(EN_Project ph, int index, char *out_id);
+
+ /**
+ @brief Changes the ID name of a node.
+ @param ph an EPANET project handle.
+ @param index a node's index (starting from 1).
+ @param newid the new ID name for the node.
+ @return an error code.
+
+ The ID name must not be longer than @ref EN_SizeLimits "EN_MAXID" characters.
+ */
+ int DLLEXPORT EN_setnodeid(EN_Project ph, int index, const char *newid);
+
+ /**
+ @brief Retrieves a node's type given its index.
+ @param ph an EPANET project handle.
+ @param index a node's index (starting from 1).
+ @param[out] out_nodeType the node's type (see @ref EN_NodeType).
+ @return an error code.
+ */
+ int DLLEXPORT EN_getnodetype(EN_Project ph, int index, int *out_nodeType);
+
+ /**
+ @brief Retrieves a property value for a node.
+ @param ph an EPANET project handle.
+ @param index a node's index.
+ @param property the property to retrieve (see @ref EN_NodeProperty).
+ @param[out] out_value the current value of the property.
+ @return an error code.
+
+ Values are returned in units that depend on the units used for flow rate
+ (see @ref Units).
+ */
+
+ int DLLEXPORT EN_getnodevalue(EN_Project ph, int index, int property, double *out_value);
+
+ /**
+ @brief Retrieves an array of property values for all nodes.
+ @param ph an EPANET project handle.
+ @param property the property to retrieve (see @ref EN_NodeProperty).
+ @param[out] out_values an array of values for all nodes.
+ @return an error code.
+
+ Values are returned in units that depend on the units used for flow rate
+ (see @ref Units).
+ */
+
+ int DLLEXPORT EN_getnodevalues(EN_Project ph, int property, double *out_values);
+
+ /**
+ @brief Sets a property value for a node.
+ @param ph an EPANET project handle.
+ @param index a node's index (starting from 1).
+ @param property the property to set (see @ref EN_NodeProperty).
+ @param value the new value for the property.
+ @return an error code.
+
+ Values are in units that depend on the units used for flow rate (see @ref Units).
+ */
+ int DLLEXPORT EN_setnodevalue(EN_Project ph, int index, int property, double value);
+
+ /**
+ @brief Sets a group of properties for a junction node.
+ @param ph an EPANET project handle.
+ @param index a junction node's index (starting from 1).
+ @param elev the value of the junction's elevation.
+ @param dmnd the value of the junction's primary base demand.
+ @param dmndpat the ID name of the demand's time pattern ("" for no pattern)
+ @return an error code.
+
+ These properties have units that depend on the units used for flow rate (see @ref Units).
+ */
+ int DLLEXPORT EN_setjuncdata(EN_Project ph, int index, double elev, double dmnd,
+ const char *dmndpat);
+
+ /**
+ @brief Sets a group of properties for a tank node.
+ @param ph an EPANET project handle.
+ @param index a tank node's index (starting from 1).
+ @param elev the tank's bottom elevation.
+ @param initlvl the initial water level in the tank.
+ @param minlvl the minimum water level for the tank.
+ @param maxlvl the maximum water level for the tank.
+ @param diam the tank's diameter (0 if a volume curve is supplied).
+ @param minvol the volume of the tank at its minimum water level.
+ @param volcurve the name of the tank's volume curve ("" for no curve)
+ @return an error code.
+
+ These properties have units that depend on the units used for flow rate (see @ref Units).
+ */
+ int DLLEXPORT EN_settankdata(EN_Project ph, int index, double elev, double initlvl,
+ double minlvl, double maxlvl, double diam, double minvol, const char *volcurve);
+
+ /**
+ @brief Gets the (x,y) coordinates of a node.
+ @param ph an EPANET project handle.
+ @param index a node index (starting from 1).
+ @param[out] out_x the node's X-coordinate value.
+ @param[out] out_y the node's Y-coordinate value.
+ @return an error code.
+ */
+ int DLLEXPORT EN_getcoord(EN_Project ph, int index, double *out_x, double *out_y);
+
+ /**
+ @brief Sets the (x,y) coordinates of a node.
+ @param ph an EPANET project handle.
+ @param index a node index (starting from 1).
+ @param x the node's X-coordinate value.
+ @param y the node's Y-coordinate value.
+ @return an error code.
+ */
+ int DLLEXPORT EN_setcoord(EN_Project ph, int index, double x, double y);
+
+/*===================================================================
+
+ Nodal Demand Functions
+
+===================================================================*/
+
+ /**
+ @brief Retrieves the type of demand model in use and its parameters.
+ @param ph an EPANET project handle.
+ @param[out] out_type Type of demand model (see @ref EN_DemandModel).
+ @param[out] out_pmin Pressure below which there is no demand.
+ @param[out] out_preq Pressure required to deliver full demand.
+ @param[out] out_pexp Pressure exponent in demand function.
+ @return an error code.
+
+ Parameters `out_pmin`, `out_preq`, and `out_pexp` are only used when the demand model is `EN_PDA`.
+ */
+ int DLLEXPORT EN_getdemandmodel(EN_Project ph, int *out_type, double *out_pmin,
+ double *out_preq, double *out_pexp);
+
+ /**
+ @brief Sets the type of demand model to use and its parameters.
+ @param ph an EPANET project handle.
+ @param type Type of demand model (see @ref EN_DemandModel).
+ @param pmin Pressure below which there is no demand.
+ @param preq Pressure required to deliver full demand.
+ @param pexp Pressure exponent in demand function.
+ @return an error code.
+
+ Set `type` to `EN_DDA` for a traditional demand driven analysis (in which case the
+ remaining three parameter values are ignored) or to `EN_PDA` for a pressure driven
+ analysis. In the latter case a node's demand is 0 when pressure is below `pmin`, is at full demand when pressure is above `preq`, or is otherwise computed as:\n
+ `Dfull * [ (P - pmin) / (preq - pmin) ] ^ pexp`\n
+ where `Dfull` is the full demand and `P` is the current pressure.
+
+ A valid value for `preq` must be at least 0.1 pressure units larger than `pmin`.
+ */
+ int DLLEXPORT EN_setdemandmodel(EN_Project ph, int type, double pmin,
+ double preq, double pexp);
+
+
+ /**
+ @brief appends a new demand to a junction node demands list.
+ @param ph an EPANET project handle.
+ @param nodeIndex the index of a node (starting from 1).
+ @param baseDemand the demand's base value.
+ @param demandPattern the name of a time pattern used by the demand
+ @param demandName the name of the demand's category
+ @return an error code.
+
+ A NULL or blank string can be used for `demandPattern` and for `demandName` to indicate
+ that no time pattern or category name is associated with the demand.
+ */
+ int DLLEXPORT EN_adddemand(EN_Project ph, int nodeIndex, double baseDemand,
+ const char *demandPattern, const char *demandName);
+
+ /**
+ @brief deletes a demand from a junction node.
+ @param ph an EPANET project handle.
+ @param nodeIndex the index of a node (starting from 1).
+ @param demandIndex the position of the demand in the node's demands list (starting from 1).
+ @return an error code.
+ */
+ int DLLEXPORT EN_deletedemand(EN_Project ph, int nodeIndex, int demandIndex);
+
+ /**
+ @brief Retrieves the index of a node's named demand category
+ @param ph an EPANET project handle.
+ @param nodeIndex the index of a node (starting from 1)
+ @param demandName the name of a demand category for the node
+ @param[out] out_demandIndex the index of the demand being sought
+ @return an error code
+ */
+ int DLLEXPORT EN_getdemandindex(EN_Project ph, int nodeIndex, const char *demandName,
+ int *out_demandIndex);
+
+ /**
+ @brief Retrieves the number of demand categories for a junction node.
+ @param ph an EPANET project handle.
+ @param nodeIndex the index of a node (starting from 1).
+ @param[out] out_numDemands the number of demand categories assigned to the node.
+ @return an error code.
+ */
+ int DLLEXPORT EN_getnumdemands(EN_Project ph, int nodeIndex, int *out_numDemands);
+
+ /**
+ @brief Gets the base demand for one of a node's demand categories.
+ @param ph an EPANET project handle.
+ @param nodeIndex a node's index (starting from 1).
+ @param demandIndex the index of a demand category for the node (starting from 1).
+ @param[out] out_baseDemand the category's base demand.
+ @return an error code.
+ */
+ int DLLEXPORT EN_getbasedemand(EN_Project ph, int nodeIndex, int demandIndex,
+ double *out_baseDemand);
+
+ /**
+ @brief Sets the base demand for one of a node's demand categories.
+ @param ph an EPANET project handle.
+ @param nodeIndex a node's index (starting from 1).
+ @param demandIndex the index of a demand category for the node (starting from 1).
+ @param baseDemand the new base demand for the category.
+ @return an error code.
+ */
+ int DLLEXPORT EN_setbasedemand(EN_Project ph, int nodeIndex, int demandIndex,
+ double baseDemand);
+
+ /**
+ @brief Retrieves the index of a time pattern assigned to one of a node's demand categories.
+ @param ph an EPANET project handle.
+ @param nodeIndex the node's index (starting from 1).
+ @param demandIndex the index of a demand category for the node (starting from 1).
+ @param[out] out_patIndex the index of the category's time pattern.
+ @return an error code.
+
+ A returned pattern index of 0 indicates that no time pattern has been assigned to the
+ demand category.
+ */
+ int DLLEXPORT EN_getdemandpattern(EN_Project ph, int nodeIndex, int demandIndex,
+ int *out_patIndex);
+
+ /**
+ @brief Sets the index of a time pattern used for one of a node's demand categories.
+ @param ph an EPANET project handle.
+ @param nodeIndex a node's index (starting from 1).
+ @param demandIndex the index of one of the node's demand categories (starting from 1).
+ @param patIndex the index of the time pattern assigned to the category.
+ @return an error code.
+
+ Specifying a pattern index of 0 indicates that no time pattern is assigned to the
+ demand category.
+ */
+ int DLLEXPORT EN_setdemandpattern(EN_Project ph, int nodeIndex, int demandIndex, int patIndex);
+
+ /**
+ @brief Retrieves the name of a node's demand category.
+ @param ph an EPANET project handle.
+ @param nodeIndex a node's index (starting from 1).
+ @param demandIndex the index of one of the node's demand categories (starting from 1).
+ @param[out] out_demandName The name of the selected category.
+ @return an error code.
+
+ `out_demandName` must be sized to contain at least @ref EN_SizeLimits "EN_MAXID+1" characters.
+ */
+ int DLLEXPORT EN_getdemandname(EN_Project ph, int nodeIndex, int demandIndex, char *out_demandName);
+
+ /**
+ @brief Assigns a name to a node's demand category.
+ @param ph an EPANET project handle.
+ @param nodeIndex a node's index (starting from 1).
+ @param demandIdx the index of one of the node's demand categories (starting from 1).
+ @param demandName the new name assigned to the category.
+ @return an error code.
+
+ The category name must contain no more than @ref EN_SizeLimits "EN_MAXID" characters.
+ */
+ int DLLEXPORT EN_setdemandname(EN_Project ph, int nodeIndex, int demandIdx,
+ const char *demandName);
+
+/*===================================================================
+
+ Link Functions
+
+===================================================================*/
+
+ /**
+ @brief Adds a new link to a project.
+ @param ph an EPANET project handle.
+ @param id the ID name of the link to be added.
+ @param linkType The type of link being added (see @ref EN_LinkType)
+ @param fromNode The ID name of the link's starting node.
+ @param toNode The ID name of the link's ending node.
+ @param[out] out_index the index of the newly added link.
+ @return an error code.
+
+ A new pipe is assigned a diameter of 10 inches (254 mm) and a length of 330
+ feet (~ 100 meters). Its roughness coefficient depends on the head loss formula in effect (see @ref EN_HeadLossType) as follows:
+ - Hazen-Williams formula: 130
+ - Darcy-Weisbach formula: 0.5 millifeet (0.15 mm)
+ - Chezy-Manning formula: 0.01
+
+ All other pipe properties are set to 0.
+
+ A new pump has a status of `EN_OPEN`, a speed setting of 1, and has no pump
+ curve or power rating assigned to it.
+
+ A new valve has a diameter of 10 inches (254 mm) and all other properties set to 0.
+
+ See @ref EN_LinkProperty.
+ */
+ int DLLEXPORT EN_addlink(EN_Project ph, const char *id, int linkType, const char *fromNode,
+ const char *toNode, int *out_index);
+
+ /**
+ @brief Deletes a link from the project.
+ @param ph an EPANET project handle.
+ @param index the index of the link to be deleted.
+ @param actionCode The action taken if any control contains the link.
+ @return an error code.
+
+ If `actionCode` is `EN_UNCONDITIONAL` then the link and all simple and rule-based
+ controls that contain it are deleted. If set to `EN_CONDITIONAL` then the link
+ is not deleted if it appears in any control and error 261 is returned.
+ */
+ int DLLEXPORT EN_deletelink(EN_Project ph, int index, int actionCode);
+
+ /**
+ @brief Gets the index of a link given its ID name.
+ @param ph an EPANET project handle.
+ @param id a link's ID name.
+ @param[out] out_index the link's index (starting from 1).
+ @return an error code.
+ */
+ int DLLEXPORT EN_getlinkindex(EN_Project ph, const char *id, int *out_index);
+
+ /**
+ @brief Gets the ID name of a link given its index.
+ @param ph an EPANET project handle.
+ @param index a link's index (starting from 1).
+ @param[out] out_id The link's ID name.
+ @return an error code.
+
+ The ID name must be sized to hold at least @ref EN_SizeLimits "EN_MAXID+1" characters.
+ */
+ int DLLEXPORT EN_getlinkid(EN_Project ph, int index, char *out_id);
+
+ /**
+ @brief Changes the ID name of a link.
+ @param ph an EPANET project handle.
+ @param index a link's index (starting from 1).
+ @param newid the new ID name for the link.
+ @return an error code.
+
+ The ID name must not be longer than @ref EN_SizeLimits "EN_MAXID" characters.
+ */
+ int DLLEXPORT EN_setlinkid(EN_Project ph, int index, const char *newid);
+
+ /**
+ @brief Retrieves a link's type.
+ @param ph an EPANET project handle.
+ @param index a link's index (starting from 1).
+ @param[out] out_linkType the link's type (see @ref EN_LinkType).
+ @return an error code.
+ */
+ int DLLEXPORT EN_getlinktype(EN_Project ph, int index, int *out_linkType);
+
+ /**
+ @brief Changes a link's type.
+ @param ph an EPANET project handle.
+ @param[in,out] inout_index the link's index before [in] and after [out] the type change.
+ @param linkType the new type to change the link to (see @ref EN_LinkType).
+ @param actionCode the action taken if any controls contain the link.
+ @return an error code.
+
+ If `actionCode` is `EN_UNCONDITIONAL` then all simple and rule-based controls that
+ contain the link are deleted when the link's type is changed. If set to
+ `EN_CONDITIONAL` then the type change is cancelled if the link appears in any
+ control and error 261 is returned.
+
+ To only change a valve's type (such as from PRV to PSV) use ::EN_setlinkvalue with property `EN_VALVE_TYPE` whose value is selected from the valves in @ref EN_LinkType.
+ */
+ int DLLEXPORT EN_setlinktype(EN_Project ph, int *inout_index, int linkType, int actionCode);
+
+ /**
+ @brief Gets the indexes of a link's start- and end-nodes.
+ @param ph an EPANET project handle.
+ @param index a link's index (starting from 1).
+ @param[out] out_node1 the index of the link's start node (starting from 1).
+ @param[out] out_node2 the index of the link's end node (starting from 1).
+ @return an error code.
+ */
+ int DLLEXPORT EN_getlinknodes(EN_Project ph, int index, int *out_node1, int *out_node2);
+
+ /**
+ @brief Sets the indexes of a link's start- and end-nodes.
+ @param ph an EPANET project handle.
+ @param index a link's index (starting from 1).
+ @param node1 The index of the link's start node (starting from 1).
+ @param node2 The index of the link's end node (starting from 1).
+ @return an error code.
+ */
+ int DLLEXPORT EN_setlinknodes(EN_Project ph, int index, int node1, int node2);
+
+ /**
+ @brief Retrieves a property value for a link.
+ @param ph an EPANET project handle.
+ @param index a link's index (starting from 1).
+ @param property the property to retrieve (see @ref EN_LinkProperty).
+ @param[out] out_value the current value of the property.
+ @return an error code.
+
+ Values are returned in units that depend on the units used for flow rate (see @ref Units).
+ */
+ int DLLEXPORT EN_getlinkvalue(EN_Project ph, int index, int property, double *out_value);
+
+ /**
+ @brief Retrieves an array of property values for all links.
+ @param ph an EPANET project handle.
+ @param property the property to retrieve (see @ref EN_LinkProperty).
+ @param[out] out_values an array of values for all links.
+ @return an error code.
+
+ Values are returned in units that depend on the units used for flow rate (see @ref Units).
+ */
+ int DLLEXPORT EN_getlinkvalues(EN_Project ph, int property, double *out_values);
+
+ /**
+ @brief Sets a property value for a link.
+ @param ph an EPANET project handle.
+ @param index a link's index.
+ @param property the property to set (see @ref EN_LinkProperty).
+ @param value the new value for the property.
+ @return an error code.
+
+ Values are in units that depend on the units used for flow rate (see @ref Units).
+ */
+ int DLLEXPORT EN_setlinkvalue(EN_Project ph, int index, int property, double value);
+
+ /**
+ @brief Sets a group of properties for a pipe link.
+ @param ph an EPANET project handle.
+ @param index the index of a pipe link (starting from 1).
+ @param length the pipe's length.
+ @param diam the pipe's diameter.
+ @param rough the pipe's roughness coefficient.
+ @param mloss the pipe's minor loss coefficient.
+ @return an error code.
+
+ These properties have units that depend on the units used for flow rate (see @ref Units).
+ */
+ int DLLEXPORT EN_setpipedata(EN_Project ph, int index, double length, double diam,
+ double rough, double mloss);
+
+ /**
+ @brief Retrieves the number of internal vertex points assigned to a link.
+ @param ph an EPANET project handle.
+ @param index a link's index (starting from 1).
+ @param[out] out_count the number of vertex points that describe the link's shape.
+ @return an error code.
+ */
+ int DLLEXPORT EN_getvertexcount(EN_Project ph, int index, int *out_count);
+
+ /**
+ @brief Retrieves the coordinates of a vertex point assigned to a link.
+ @param ph an EPANET project handle.
+ @param index a link's index (starting from 1).
+ @param vertex a vertex point index (starting from 1).
+ @param[out] out_x the vertex's X-coordinate value.
+ @param[out] out_y the vertex's Y-coordinate value.
+ @return an error code.
+ */
+ int DLLEXPORT EN_getvertex(EN_Project ph, int index, int vertex, double *out_x, double *out_y);
+
+ /**
+ @brief Sets the coordinates of a vertex point assigned to a link.
+ @param ph an EPANET project handle.
+ @param index a link's index (starting from 1).
+ @param vertex a vertex point index (starting from 1).
+ @param x the vertex's X-coordinate value.
+ @param y the vertex's Y-coordinate value.
+ @return an error code.
+ */
+ int DLLEXPORT EN_setvertex(EN_Project ph, int index, int vertex, double x, double y);
+
+ /**
+ @brief Assigns a set of internal vertex points to a link.
+ @param ph an EPANET project handle.
+ @param index a link's index (starting from 1).
+ @param x an array of X-coordinates for the vertex points.
+ @param y an array of Y-coordinates for the vertex points.
+ @param count the number of vertex points being assigned.
+ @return an error code.
+
+ Replaces any existing vertices previously assigned to the link.
+ */
+ int DLLEXPORT EN_setvertices(EN_Project ph, int index, double *x, double *y, int count);
+
+/*===================================================================
+
+ Pump Functions
+
+===================================================================*/
+
+ /**
+ @brief Retrieves the type of head curve used by a pump.
+ @param ph an EPANET project handle.
+ @param linkIndex the index of a pump link (starting from 1).
+ @param[out] out_pumpType the type of head curve used by the pump (see @ref EN_PumpType).
+ @return an error code.
+ */
+ int DLLEXPORT EN_getpumptype(EN_Project ph, int linkIndex, int *out_pumpType);
+
+ /**
+ @brief Retrieves the curve assigned to a pump's head curve.
+ @param ph an EPANET project handle.
+ @param linkIndex the index of a pump link (starting from 1).
+ @param[out] out_curveIndex the index of the curve assigned to the pump's head curve.
+ @return an error code.
+ */
+ int DLLEXPORT EN_getheadcurveindex(EN_Project ph, int linkIndex, int *out_curveIndex);
+
+ /**
+ @brief Assigns a curve to a pump's head curve.
+ @param ph an EPANET project handle.
+ @param linkIndex the index of a pump link (starting from 1).
+ @param curveIndex the index of a curve to be assigned as the pump's head curve.
+ @return an error code.
+ */
+ int DLLEXPORT EN_setheadcurveindex(EN_Project ph, int linkIndex, int curveIndex);
+
+/*===================================================================
+
+ Time Pattern Functions
+
+===================================================================*/
+
+ /**
+ @brief Adds a new time pattern to a project.
+ @param ph an EPANET project handle.
+ @param id the ID name of the pattern to add.
+ @return an error code.
+
+ The new pattern contains a single time period whose factor is 1.0.
+ */
+ int DLLEXPORT EN_addpattern(EN_Project ph, const char *id);
+
+ /**
+ @brief Deletes a time pattern from a project.
+ @param ph an EPANET project handle.
+ @param index the time pattern's index (starting from 1).
+ @return an error code.
+ */
+ int DLLEXPORT EN_deletepattern(EN_Project ph, int index);
+
+ /**
+ @brief Retrieves the index of a time pattern given its ID name.
+ @param ph an EPANET project handle.
+ @param id the ID name of a time pattern.
+ @param[out] out_index the time pattern's index (starting from 1).
+ @return an error code.
+ */
+ int DLLEXPORT EN_getpatternindex(EN_Project ph, const char *id, int *out_index);
+
+ /**
+ @brief Retrieves the ID name of a time pattern given its index.
+ @param ph an EPANET project handle.
+ @param index a time pattern index (starting from 1).
+ @param[out] out_id the time pattern's ID name.
+ @return an error code.
+
+ The ID name must be sized to hold at least @ref EN_SizeLimits "EN_MAXID+1" characters.
+ */
+ int DLLEXPORT EN_getpatternid(EN_Project ph, int index, char *out_id);
+
+ /**
+ @brief Changes the ID name of a time pattern given its index.
+ @param ph an EPANET project handle.
+ @param index a time pattern index (starting from 1).
+ @param id the time pattern's new ID name.
+ @return an error code.
+
+ The new ID name must not exceed @ref EN_SizeLimits "EN_MAXID" characters.
+ */
+ int DLLEXPORT EN_setpatternid(EN_Project ph, int index, const char *id);
+
+ /**
+ @brief Retrieves the number of time periods in a time pattern.
+ @param ph an EPANET project handle.
+ @param index a time pattern index (starting from 1).
+ @param[out] out_len the number of time periods in the pattern.
+ @return an error code.
+ */
+ int DLLEXPORT EN_getpatternlen(EN_Project ph, int index, int *out_len);
+
+ /**
+ @brief Retrieves a time pattern's factor for a given time period.
+ @param ph an EPANET project handle.
+ @param index a time pattern index (starting from 1).
+ @param period a time period in the pattern (starting from 1).
+ @param[out] out_value the pattern factor for the given time period.
+ @return an error code.
+ */
+ int DLLEXPORT EN_getpatternvalue(EN_Project ph, int index, int period, double *out_value);
+
+ /**
+ @brief Sets a time pattern's factor for a given time period.
+ @param ph an EPANET project handle.
+ @param index a time pattern index (starting from 1).
+ @param period a time period in the pattern (starting from 1).
+ @param value the new value of the pattern factor for the given time period.
+ @return an error code.
+ */
+ int DLLEXPORT EN_setpatternvalue(EN_Project ph, int index, int period, double value);
+
+ /**
+ @brief Retrieves the average of all pattern factors in a time pattern.
+ @param ph an EPANET project handle.
+ @param index a time pattern index (starting from 1).
+ @param[out] out_value The average of all of the time pattern's factors.
+ @return an error code.
+ */
+ int DLLEXPORT EN_getaveragepatternvalue(EN_Project ph, int index, double *out_value);
+
+ /**
+ @brief Sets the pattern factors for a given time pattern.
+ @param ph an EPANET project handle.
+ @param index a time pattern index (starting from 1).
+ @param values an array of new pattern factor values.
+ @param len the number of factor values supplied.
+ @return an error code.
+
+ `values` is a zero-based array that contains `len` elements.
+
+ Use this function to redefine (and resize) a time pattern all at once;
+ use @ref EN_setpatternvalue to revise pattern factors one at a time.
+ */
+ int DLLEXPORT EN_setpattern(EN_Project ph, int index, double *values, int len);
+
+ /**
+ @brief Loads time patterns from a file into a project under a specific pattern ID.
+ @param ph an EPANET project handle.
+ @param filename the name of the file containing pattern data.
+ @param id the ID name of the new pattern to load.
+ @return an error code.
+ */
+ int DLLEXPORT EN_loadpatternfile(EN_Project ph, const char *filename, const char *id);
+
+/*===================================================================
+
+ Data Curve Functions
+
+===================================================================*/
+
+ /**
+ @brief Adds a new data curve to a project.
+ @param ph an EPANET project handle.
+ @param id The ID name of the curve to be added.
+ @return an error code.
+
+ The new curve contains a single data point (1.0, 1.0).
+ */
+ int DLLEXPORT EN_addcurve(EN_Project ph, const char *id);
+
+ /**
+ @brief Deletes a data curve from a project.
+ @param ph an EPANET project handle.
+ @param index the data curve's index (starting from 1).
+ @return an error code.
+ */
+ int DLLEXPORT EN_deletecurve(EN_Project ph, int index);
+
+ /**
+ @brief Retrieves the index of a curve given its ID name.
+ @param ph an EPANET project handle.
+ @param id the ID name of a curve.
+ @param[out] out_index The curve's index (starting from 1).
+ @return an error code.
+ */
+ int DLLEXPORT EN_getcurveindex(EN_Project ph, const char *id, int *out_index);
+
+ /**
+ @brief Retrieves the ID name of a curve given its index.
+ @param ph an EPANET project handle.
+ @param index a curve's index (starting from 1).
+ @param[out] out_id the curve's ID name.
+ @return an error code.
+
+ The ID name must be sized to hold at least @ref EN_SizeLimits "EN_MAXID+1" characters.
+ */
+ int DLLEXPORT EN_getcurveid(EN_Project ph, int index, char *out_id);
+
+ /**
+ @brief Changes the ID name of a data curve given its index.
+ @param ph an EPANET project handle.
+ @param index a data curve index (starting from 1).
+ @param id the data curve's new ID name.
+ @return an error code.
+
+ The new ID name must not exceed @ref EN_SizeLimits "EN_MAXID" characters.
+ */
+ int DLLEXPORT EN_setcurveid(EN_Project ph, int index, const char *id);
+
+ /**
+ @brief Retrieves the number of points in a curve.
+ @param ph an EPANET project handle.
+ @param index a curve's index (starting from 1).
+ @param[out] out_len The number of data points assigned to the curve.
+ @return an error code.
+ */
+ int DLLEXPORT EN_getcurvelen(EN_Project ph, int index, int *out_len);
+
+ /**
+ @brief Retrieves a curve's type.
+ @param ph an EPANET project handle.
+ @param index a curve's index (starting from 1).
+ @param[out] out_type the curve's type (see @ref EN_CurveType).
+ @return an error code.
+ */
+ int DLLEXPORT EN_getcurvetype(EN_Project ph, int index, int *out_type);
+
+ /**
+ @brief Sets a curve's type.
+ @param ph an EPANET project handle.
+ @param index a curve's index (starting from 1).
+ @param type the curve's type (see @ref EN_CurveType).
+ @return an error code.
+ */
+ int DLLEXPORT EN_setcurvetype(EN_Project ph, int index, int type);
+
+ /**
+ @brief Retrieves the value of a single data point for a curve.
+ @param ph an EPANET project handle.
+ @param curveIndex a curve's index (starting from 1).
+ @param pointIndex the index of a point on the curve (starting from 1).
+ @param[out] out_x the point's x-value.
+ @param[out] out_y the point's y-value.
+ @return an error code.
+ */
+ int DLLEXPORT EN_getcurvevalue(EN_Project ph, int curveIndex, int pointIndex,
+ double *out_x, double *out_y);
+
+ /**
+ @brief Sets the value of a single data point for a curve.
+ @param ph an EPANET project handle.
+ @param curveIndex a curve's index (starting from 1).
+ @param pointIndex the index of a point on the curve (starting from 1).
+ @param x the point's new x-value.
+ @param y the point's new y-value.
+ @return an error code.
+ */
+ int DLLEXPORT EN_setcurvevalue(EN_Project ph, int curveIndex, int pointIndex,
+ double x, double y);
+
+ /**
+ @brief Retrieves all of a curve's data.
+ @param ph an EPANET project handle.
+ @param index a curve's index (starting from 1).
+ @param[out] out_id the curve's ID name.
+ @param[out] out_nPoints the number of data points on the curve.
+ @param[out] out_xValues the curve's x-values.
+ @param[out] out_yValues the curve's y-values.
+ @return an error code.
+
+ The calling program is responsible for making `out_xValues` and `out_yValues` large enough
+ to hold `out_nPoints` number of data points and for sizing `out_id` to hold at least
+ @ref EN_SizeLimits "EN_MAXID+1" characters.
+ */
+ int DLLEXPORT EN_getcurve(EN_Project ph, int index, char *out_id, int *out_nPoints,
+ double *out_xValues, double *out_yValues);
+
+ /**
+ @brief assigns a set of data points to a curve.
+ @param ph an EPANET project handle.
+ @param index a curve's index (starting from 1).
+ @param xValues an array of new x-values for the curve.
+ @param yValues an array of new y-values for the curve.
+ @param nPoints the new number of data points for the curve.
+ @return an error code.
+
+ `xValues` and `yValues` are zero-based arrays that contains `nPoints` elements.
+
+ Use this function to redefine (and resize) a curve all at once;
+ use @ref EN_setcurvevalue to revise a curve's data points one at a time.
+ */
+ int DLLEXPORT EN_setcurve(EN_Project ph, int index, double *xValues,
+ double *yValues, int nPoints);
+
+/*===================================================================
+
+ Simple Controls Functions
+
+===================================================================*/
+
+ /**
+ @brief Adds a new simple control to a project.
+ @param ph an EPANET project handle.
+ @param type the type of control to add (see @ref EN_ControlType).
+ @param linkIndex the index of a link to control (starting from 1).
+ @param setting control setting applied to the link.
+ @param nodeIndex index of the node used to control the link
+ (0 for `EN_TIMER` and `EN_TIMEOFDAY` controls).
+ @param level action level (tank level, junction pressure, or time in seconds)
+ that triggers the control.
+ @param[out] out_index index of the new control.
+ @return an error code.
+ */
+ int DLLEXPORT EN_addcontrol(EN_Project ph, int type, int linkIndex,
+ double setting, int nodeIndex, double level, int *out_index);
+
+ /**
+ @brief Deletes an existing simple control.
+ @param ph an EPANET project handle.
+ @param index the index of the control to delete (starting from 1).
+ @return an error code.
+ */
+ int DLLEXPORT EN_deletecontrol(EN_Project ph, int index);
+
+ /**
+ @brief Retrieves the properties of a simple control.
+ @param ph an EPANET project handle.
+ @param index the control's index (starting from 1).
+ @param[out] out_type the type of control (see @ref EN_ControlType).
+ @param[out] out_linkIndex the index of the link being controlled.
+ @param[out] out_setting the control setting applied to the link.
+ @param[out] out_nodeIndex the index of the node used to trigger the control
+ (0 for `EN_TIMER` and `EN_TIMEOFDAY` controls).
+ @param[out] out_level the action level (tank level, junction pressure, or time in seconds)
+ that triggers the control.
+ @return an error code.
+ */
+ int DLLEXPORT EN_getcontrol(EN_Project ph, int index, int *out_type, int *out_linkIndex,
+ double *out_setting, int *out_nodeIndex, double *out_level);
+
+ /**
+ @brief Sets the properties of an existing simple control.
+ @param ph an EPANET project handle.
+ @param index the control's index (starting from 1).
+ @param type the type of control (see @ref EN_ControlType).
+ @param linkIndex the index of the link being controlled.
+ @param setting the control setting applied to the link.
+ @param nodeIndex the index of the node used to trigger the control
+ (0 for `EN_TIMER` and `EN_TIMEOFDAY` controls).
+ @param level the action level (tank level, junction pressure, or time in seconds)
+ that triggers the control.
+ @return an error code.
+ */
+ int DLLEXPORT EN_setcontrol(EN_Project ph, int index, int type, int linkIndex,
+ double setting, int nodeIndex, double level);
+
+ /**
+ @brief Gets the enabled status of a simple control.
+ @param ph an EPANET project handle.
+ @param index the control's index (starting from 1).
+ @param out_enabled `EN_TRUE` (= 1) if the control is enabled or `EN_FALSE` (= 0) if it is disabled.
+ @return an error code.
+ */
+ int DLLEXPORT EN_getcontrolenabled(EN_Project ph, int index, int *out_enabled);
+
+ /**
+ @brief Sets the enabled status of a simple control.
+ @param ph an EPANET project handle.
+ @param index the control's index (starting from 1).
+ @param enabled `EN_TRUE` (= 1) sets the control to enabled, `EN_FALSE` (= 0) sets it to disabled.
+ @return an error code.
+ */
+ int DLLEXPORT EN_setcontrolenabled(EN_Project ph, int index, int enabled);
+
+/*===================================================================
+
+ Rule-Based Controls Functions
+
+===================================================================*/
+
+ /**
+ @brief Adds a new rule-based control to a project.
+ @param ph an EPANET project handle.
+ @param rule text of the rule following the format used in an EPANET input file.
+ @return an error code.
+
+ Consult the @ref RulesPage section of the @ref InpFile topic to learn about a
+ rule's format. Each clause of the rule must end with a newline character `\n`.
+ */
+ int DLLEXPORT EN_addrule(EN_Project ph, char *rule);
+
+ /**
+ @brief Deletes an existing rule-based control.
+ @param ph an EPANET project handle.
+ @param index the index of the rule to be deleted (starting from 1).
+ @return an error code.
+ */
+ int DLLEXPORT EN_deleterule(EN_Project ph, int index);
+
+ /**
+ @brief Retrieves summary information about a rule-based control.
+ @param ph an EPANET project handle.
+ @param index the rule's index (starting from 1).
+ @param[out] out_nPremises number of premises in the rule's IF section.
+ @param[out] out_nThenActions number of actions in the rule's THEN section.
+ @param[out] out_nElseActions number of actions in the rule's ELSE section.
+ @param[out] out_priority the rule's priority value.
+ @return an error code.
+ */
+ int DLLEXPORT EN_getrule(EN_Project ph, int index, int *out_nPremises,
+ int *out_nThenActions, int *out_nElseActions, double *out_priority);
+
+ /**
+ @brief Gets the ID name of a rule-based control given its index.
+ @param ph an EPANET project handle.
+ @param index the rule's index (starting from 1).
+ @param[out] out_id the rule's ID name.
+ @return an error code.
+
+ The ID name must be sized to hold at least @ref EN_SizeLimits "EN_MAXID+1" characters.
+ */
+ int DLLEXPORT EN_getruleID(EN_Project ph, int index, char *out_id);
+
+ /**
+ @brief Gets the properties of a premise in a rule-based control.
+ @param ph an EPANET project handle.
+ @param ruleIndex the rule's index (starting from 1).
+ @param premiseIndex the position of the premise in the rule's list of premises
+ (starting from 1).
+ @param[out] out_logop the premise's logical operator (`IF` = 1, `AND` = 2, `OR` = 3` ).
+ @param[out] out_object the type of object the premise refers to (see @ref EN_RuleObject).
+ @param[out] out_objIndex the index of the object (e.g. the index of a tank).
+ @param[out] out_variable the object's variable being compared (see @ref EN_RuleVariable).
+ @param[out] out_relop the premise's comparison operator (see @ref EN_RuleOperator).
+ @param[out] out_status the status that the object's status is compared to
+ (see @ref EN_RuleStatus).
+ @param[out] out_value the value that the object's variable is compared to.
+ @return an error code.
+ */
+ int DLLEXPORT EN_getpremise(EN_Project ph, int ruleIndex, int premiseIndex,
+ int *out_logop, int *out_object, int *out_objIndex, int *out_variable,
+ int *out_relop, int *out_status, double *out_value);
+
+ /**
+ @brief Sets the properties of a premise in a rule-based control.
+ @param ph an EPANET project handle.
+ @param ruleIndex the rule's index (starting from 1).
+ @param premiseIndex the position of the premise in the rule's list of premises.
+ @param logop the premise's logical operator (`IF` = 1, `AND` = 2, `OR` = 3 ).
+ @param object the type of object the premise refers to (see @ref EN_RuleObject).
+ @param objIndex the index of the object (e.g. the index of a tank).
+ @param variable the object's variable being compared (see @ref EN_RuleVariable).
+ @param relop the premise's comparison operator (see @ref EN_RuleOperator).
+ @param status the status that the object's status is compared to
+ (see @ref EN_RuleStatus).
+ @param value the value that the object's variable is compared to.
+ @return an error code.
+ */
+ int DLLEXPORT EN_setpremise(EN_Project ph, int ruleIndex, int premiseIndex,
+ int logop, int object, int objIndex, int variable, int relop,
+ int status, double value);
+
+ /**
+ @brief Sets the index of an object in a premise of a rule-based control.
+ @param ph an EPANET project handle.
+ @param ruleIndex the rule's index (starting from 1).
+ @param premiseIndex the premise's index (starting from 1).
+ @param objIndex the index of the premise's object (e.g. the index of a tank).
+ @return an error code.
+ */
+ int DLLEXPORT EN_setpremiseindex(EN_Project ph, int ruleIndex, int premiseIndex,
+ int objIndex);
+
+ /**
+ @brief Sets the status being compared to in a premise of a rule-based control.
+ @param ph an EPANET project handle.
+ @param ruleIndex the rule's index (starting from 1).
+ @param premiseIndex the premise's index (starting from 1).
+ @param status the status that the premise's object status is compared to
+ (see @ref EN_RuleStatus).
+ @return an error code.
+ */
+ int DLLEXPORT EN_setpremisestatus(EN_Project ph, int ruleIndex, int premiseIndex,
+ int status);
+
+ /**
+ @brief Sets the value in a premise of a rule-based control.
+ @param ph an EPANET project handle.
+ @param ruleIndex the rule's index (staring from 1).
+ @param premiseIndex the premise's index (starting from 1).
+ @param value The value that the premise's variable is compared to.
+ @return an error code.
+ */
+ int DLLEXPORT EN_setpremisevalue(EN_Project ph, int ruleIndex, int premiseIndex,
+ double value);
+
+ /**
+ @brief Gets the properties of a THEN action in a rule-based control.
+ @param ph an EPANET project handle.
+ @param ruleIndex the rule's index (starting from 1).
+ @param actionIndex the index of the THEN action to retrieve (starting from 1).
+ @param[out] out_linkIndex the index of the link in the action (starting from 1).
+ @param[out] out_status the status assigned to the link (see @ref EN_RuleStatus)
+ @param[out] out_setting the value assigned to the link's setting.
+ @return an error code.
+ */
+ int DLLEXPORT EN_getthenaction(EN_Project ph, int ruleIndex, int actionIndex,
+ int *out_linkIndex, int *out_status, double *out_setting);
+
+ /**
+ @brief Sets the properties of a THEN action in a rule-based control.
+ @param ph an EPANET project handle.
+ @param ruleIndex the rule's index (starting from 1).
+ @param actionIndex the index of the THEN action to modify (starting from 1).
+ @param linkIndex the index of the link in the action.
+ @param status the new status assigned to the link (see @ref EN_RuleStatus).
+ @param setting the new value assigned to the link's setting.
+ @return an error code.
+ */
+ int DLLEXPORT EN_setthenaction(EN_Project ph, int ruleIndex, int actionIndex,
+ int linkIndex, int status, double setting);
+
+ /**
+ @brief Gets the properties of an ELSE action in a rule-based control.
+ @param ph an EPANET project handle.
+ @param ruleIndex the rule's index (starting from 1).
+ @param actionIndex the index of the ELSE action to retrieve (starting from 1).
+ @param[out] out_linkIndex the index of the link in the action.
+ @param[out] out_status the status assigned to the link (see @ref EN_RuleStatus).
+ @param[out] out_setting the value assigned to the link's setting.
+ @return an error code.
+ */
+ int DLLEXPORT EN_getelseaction(EN_Project ph, int ruleIndex, int actionIndex,
+ int *out_linkIndex, int *out_status, double *out_setting);
+
+ /**
+ @brief Sets the properties of an ELSE action in a rule-based control.
+ @param ph an EPANET project handle.
+ @param ruleIndex the rule's index (starting from 1).
+ @param actionIndex the index of the ELSE action being modified (starting from 1).
+ @param linkIndex the index of the link in the action (starting from 1).
+ @param status the new status assigned to the link (see @ref EN_RuleStatus)
+ @param setting the new value assigned to the link's setting.
+ @return an error code.
+ */
+ int DLLEXPORT EN_setelseaction(EN_Project ph, int ruleIndex, int actionIndex,
+ int linkIndex, int status, double setting);
+
+ /**
+ @brief Sets the priority of a rule-based control.
+ @param ph an EPANET project handle.
+ @param index the rule's index (starting from 1).
+ @param priority the priority value assigned to the rule.
+ @return an error code.
+ */
+ int DLLEXPORT EN_setrulepriority(EN_Project ph, int index, double priority);
+
+ /**
+ @brief Gets the enabled status of a rule-based control.
+ @param ph an EPANET project handle.
+ @param index the rule's index (starting from 1).
+ @param out_enabled the rule will be either EN_TRUE=enabled or EN_FALSE=disabled.
+ @return an error code.
+ */
+ int DLLEXPORT EN_getruleenabled(EN_Project ph, int index, int *out_enabled);
+
+ /**
+ @brief Sets the enabled status of a rule-based control.
+ @param ph an EPANET project handle.
+ @param index the rule's index (starting from 1).
+ @param enabled set the rule to either EN_TRUE=enabled or EN_FALSE=disabled.
+ @return an error code.
+ */
+ int DLLEXPORT EN_setruleenabled(EN_Project ph, int index, int enabled);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif //EPANET2_2_H
diff --git a/epanet/linux/epanet2_enums.h b/epanet/linux/epanet2_enums.h
new file mode 100644
index 0000000..2da2e68
--- /dev/null
+++ b/epanet/linux/epanet2_enums.h
@@ -0,0 +1,518 @@
+/** @file epanet2_enums.h
+*/
+/*
+ ******************************************************************************
+ Project: OWA EPANET
+ Version: 2.3
+ Module: epanet2_enums.h
+ Description: enumerations of symbolic constants used by the API functions
+ Authors: see AUTHORS
+ Copyright: see AUTHORS
+ License: see LICENSE
+ Last Updated: 04/23/2025
+ ******************************************************************************
+*/
+
+
+#ifndef EPANET2_ENUMS_H
+#define EPANET2_ENUMS_H
+
+// --- Define the EPANET toolkit constants
+/// Character array size limits
+/*! \enum EN_SizeLimits
+ * Limits on the size of character arrays used to store ID names
+ * and text messages.
+*/
+typedef enum {
+ EN_MAXID = 31, //!< Max. # characters in ID name
+ EN_MAXMSG = 255 //!< Max. # characters in message text
+} EN_SizeLimits;
+
+/// Node properties
+/*! \enum EN_NodeProperty
+ * These node properties are used with @ref EN_getnodevalue and @ref EN_setnodevalue.
+ * Those marked as read only are computed values that can only be retrieved.
+*/
+typedef enum {
+ EN_ELEVATION = 0, //!< Elevation
+ EN_BASEDEMAND = 1, //!< Primary demand baseline value
+ EN_PATTERN = 2, //!< Primary demand time pattern index
+ EN_EMITTER = 3, //!< Emitter flow coefficient
+ EN_INITQUAL = 4, //!< Initial quality
+ EN_SOURCEQUAL = 5, //!< Quality source strength
+ EN_SOURCEPAT = 6, //!< Quality source pattern index
+ EN_SOURCETYPE = 7, //!< Quality source type (see @ref EN_SourceType)
+ EN_TANKLEVEL = 8, //!< Current computed tank water level (read only)
+ EN_DEMAND = 9, //!< Current computed demand (read only)
+ EN_HEAD = 10, //!< Current computed hydraulic head (read only)
+ EN_PRESSURE = 11, //!< Current computed pressure (read only)
+ EN_QUALITY = 12, //!< Current computed quality (read only)
+ EN_SOURCEMASS = 13, //!< Current computed quality source mass inflow (read only)
+ EN_INITVOLUME = 14, //!< Tank initial volume (read only)
+ EN_MIXMODEL = 15, //!< Tank mixing model (see @ref EN_MixingModel)
+ EN_MIXZONEVOL = 16, //!< Tank mixing zone volume (read only)
+ EN_TANKDIAM = 17, //!< Tank diameter
+ EN_MINVOLUME = 18, //!< Tank minimum volume
+ EN_VOLCURVE = 19, //!< Tank volume curve index
+ EN_MINLEVEL = 20, //!< Tank minimum level
+ EN_MAXLEVEL = 21, //!< Tank maximum level
+ EN_MIXFRACTION = 22, //!< Tank mixing fraction
+ EN_TANK_KBULK = 23, //!< Tank bulk decay coefficient
+ EN_TANKVOLUME = 24, //!< Current computed tank volume (read only)
+ EN_MAXVOLUME = 25, //!< Tank maximum volume (read only)
+ EN_CANOVERFLOW = 26, //!< `EN_TRUE` (= 1) if the Tank can overflow, `EN_FALSE` (= 0) if it cannot
+ EN_DEMANDDEFICIT = 27,//!< Amount that full demand is reduced under PDA (read only)
+ EN_NODE_INCONTROL = 28, //!< `EN_TRUE` (= 1) if the node appears in any control, `EN_FALSE` (= 0) if not
+ EN_EMITTERFLOW = 29, //!< Current emitter flow (read only)
+ EN_LEAKAGEFLOW = 30, //!< Current leakage flow (read only)
+ EN_DEMANDFLOW = 31, //!< Current consumer demand delivered (read only)
+ EN_FULLDEMAND = 32 //!< Current consumer demand requested (read only)
+} EN_NodeProperty;
+
+/// Link properties
+/**
+These link properties are used with @ref EN_getlinkvalue and @ref EN_setlinkvalue.
+Those marked as read only are computed values that can only be retrieved.
+*/
+typedef enum {
+ EN_DIAMETER = 0, //!< Pipe/valve diameter
+ EN_LENGTH = 1, //!< Pipe length
+ EN_ROUGHNESS = 2, //!< Pipe roughness coefficient
+ EN_MINORLOSS = 3, //!< Pipe/valve minor loss coefficient
+ EN_INITSTATUS = 4, //!< Initial status (see @ref EN_LinkStatusType)
+ EN_INITSETTING = 5, //!< Initial pump speed or valve setting
+ EN_KBULK = 6, //!< Bulk flow chemical reaction coefficient
+ EN_KWALL = 7, //!< Pipe wall chemical reaction coefficient
+ EN_FLOW = 8, //!< Current computed flow rate (read only)
+ EN_VELOCITY = 9, //!< Current computed flow velocity (read only)
+ EN_HEADLOSS = 10, //!< Current computed head loss (read only)
+ EN_STATUS = 11, //!< Current link status (see @ref EN_LinkStatusType)
+ EN_SETTING = 12, //!< Current link setting
+ EN_ENERGY = 13, //!< Current computed pump energy usage (read only)
+ EN_LINKQUAL = 14, //!< Current computed link quality (read only)
+ EN_LINKPATTERN = 15, //!< Pump speed time pattern index
+ EN_PUMP_STATE = 16, //!< Current computed pump state (read only) (see @ref EN_PumpStateType)
+ EN_PUMP_EFFIC = 17, //!< Current computed pump efficiency (read only)
+ EN_PUMP_POWER = 18, //!< Pump constant power rating
+ EN_PUMP_HCURVE = 19, //!< Pump head v. flow curve index
+ EN_PUMP_ECURVE = 20, //!< Pump efficiency v. flow curve index
+ EN_PUMP_ECOST = 21, //!< Pump average energy price
+ EN_PUMP_EPAT = 22, //!< Pump energy price time pattern index
+ EN_LINK_INCONTROL = 23, //!< Is present in any simple or rule-based control (= 1) or not (= 0)
+ EN_GPV_CURVE = 24, //!< GPV head loss v. flow curve index
+ EN_PCV_CURVE = 25, //!< PCV characteristic curve index
+ EN_LEAK_AREA = 26, //!< Pipe leak area (sq mm per 100 length units)
+ EN_LEAK_EXPAN = 27, //!< Leak expansion rate (sq mm per unit of pressure head)
+ EN_LINK_LEAKAGE = 28, //!< Current leakage rate (read only)
+ EN_VALVE_TYPE = 29 //!< Type of valve (see @ref EN_LinkType)
+} EN_LinkProperty;
+
+/// Time parameters
+/**
+These time-related options are used with @ref EN_gettimeparam and@ref EN_settimeparam.
+All times are expressed in seconds The parameters marked as read only are
+computed values that can only be retrieved.
+*/
+typedef enum {
+ EN_DURATION = 0, //!< Total simulation duration
+ EN_HYDSTEP = 1, //!< Hydraulic time step
+ EN_QUALSTEP = 2, //!< Water quality time step
+ EN_PATTERNSTEP = 3, //!< Time pattern period
+ EN_PATTERNSTART = 4, //!< Time when time patterns begin
+ EN_REPORTSTEP = 5, //!< Reporting time step
+ EN_REPORTSTART = 6, //!< Time when reporting starts
+ EN_RULESTEP = 7, //!< Rule-based control evaluation time step
+ EN_STATISTIC = 8, //!< Reporting statistic code (see @ref EN_StatisticType)
+ EN_PERIODS = 9, //!< Number of reporting time periods (read only)
+ EN_STARTTIME = 10, //!< Simulation starting time of day
+ EN_HTIME = 11, //!< Elapsed time of current hydraulic solution (read only)
+ EN_QTIME = 12, //!< Elapsed time of current quality solution (read only)
+ EN_HALTFLAG = 13, //!< Flag indicating if the simulation was halted (read only)
+ EN_NEXTEVENT = 14, //!< Shortest time until a tank becomes empty or full (read only)
+ EN_NEXTEVENTTANK = 15 //!< Index of tank with shortest time to become empty or full (read only)
+} EN_TimeParameter;
+
+/// Time step events
+/**
+These are the types of events that can cause a new time step to be taken.
+**/
+typedef enum {
+ EN_STEP_REPORT = 0, //!< A reporting time step has ended
+ EN_STEP_HYD = 1, //!< A hydraulic time step has ended
+ EN_STEP_WQ = 2, //!< A water quality time step has ended
+ EN_STEP_TANKEVENT = 3, //!< A tank has become empty or full
+ EN_STEP_CONTROLEVENT = 4 //!< A link control needs to be activated
+} EN_TimestepEvent;
+
+/// Analysis convergence statistics
+/**
+These statistics report the convergence criteria for the most current hydraulic analysis
+and the cumulative water quality mass balance error at the current simulation time. They
+can be retrieved with @ref EN_getstatistic.
+*/
+typedef enum {
+ EN_ITERATIONS = 0, //!< Number of hydraulic iterations taken
+ EN_RELATIVEERROR = 1, //!< Sum of link flow changes / sum of link flows
+ EN_MAXHEADERROR = 2, //!< Largest head loss error for links
+ EN_MAXFLOWCHANGE = 3, //!< Largest flow change in links
+ EN_MASSBALANCE = 4, //!< Cumulative water quality mass balance ratio
+ EN_DEFICIENTNODES = 5, //!< Number of pressure deficient nodes
+ EN_DEMANDREDUCTION = 6, //!< % demand reduction at pressure deficient nodes
+ EN_LEAKAGELOSS = 7 //!< % flow lost to system leakage
+} EN_AnalysisStatistic;
+
+/// Types of network objects
+/**
+The types of objects that comprise a network model.
+*/
+typedef enum {
+ EN_NODE = 0, //!< Nodes
+ EN_LINK = 1, //!< Links
+ EN_TIMEPAT = 2, //!< Time patterns
+ EN_CURVE = 3, //!< Data curves
+ EN_CONTROL = 4, //!< Simple controls
+ EN_RULE = 5 //!< Control rules
+} EN_ObjectType;
+
+/// Types of objects to count
+/**
+These options tell @ref EN_getcount which type of object to count.
+*/
+typedef enum {
+ EN_NODECOUNT = 0, //!< Number of nodes (junctions + tanks + reservoirs)
+ EN_TANKCOUNT = 1, //!< Number of tanks and reservoirs
+ EN_LINKCOUNT = 2, //!< Number of links (pipes + pumps + valves)
+ EN_PATCOUNT = 3, //!< Number of time patterns
+ EN_CURVECOUNT = 4, //!< Number of data curves
+ EN_CONTROLCOUNT = 5, //!< Number of simple controls
+ EN_RULECOUNT = 6 //!< Number of rule-based controls
+} EN_CountType;
+
+/// Node Types
+/**
+These are the different types of nodes that can be returned by calling @ref EN_getnodetype.
+*/
+typedef enum {
+ EN_JUNCTION = 0, //!< Junction node
+ EN_RESERVOIR = 1, //!< Reservoir node
+ EN_TANK = 2 //!< Storage tank node
+} EN_NodeType;
+
+/// Link types
+/**
+These are the different types of links that can be returned by calling @ref EN_getlinktype.
+*/
+typedef enum {
+ EN_CVPIPE = 0, //!< Pipe with check valve
+ EN_PIPE = 1, //!< Pipe
+ EN_PUMP = 2, //!< Pump
+ EN_PRV = 3, //!< Pressure reducing valve
+ EN_PSV = 4, //!< Pressure sustaining valve
+ EN_PBV = 5, //!< Pressure breaker valve
+ EN_FCV = 6, //!< Flow control valve
+ EN_TCV = 7, //!< Throttle control valve
+ EN_GPV = 8, //!< General purpose valve
+ EN_PCV = 9 //!< Positional control valve
+} EN_LinkType;
+
+/// Link status
+/**
+One of these values is returned when @ref EN_getlinkvalue is used to retrieve a link's
+initial status (`EN_INITSTATUS`) or its current status (`EN_STATUS`). These options are
+also used with @ref EN_setlinkvalue to set values for these same properties.
+*/
+typedef enum {
+ EN_CLOSED = 0, //!< Link is closed and cannot convey any flow
+ EN_OPEN = 1 //!< Link is open and is able to convey flow
+} EN_LinkStatusType;
+
+/// Pump states
+/**
+One of these codes is returned when @ref EN_getlinkvalue is used to retrieve a pump's
+current operating state (`EN_PUMP_STATE`). `EN_PUMP_XHEAD` indicates that the pump has been
+shut down because it is being asked to deliver more than its shutoff head. `EN_PUMP_XFLOW`
+indicates that the pump is being asked to deliver more than its maximum flow.
+*/
+typedef enum {
+ EN_PUMP_XHEAD = 0, //!< Pump closed - cannot supply head
+ EN_PUMP_CLOSED = 2, //!< Pump closed
+ EN_PUMP_OPEN = 3, //!< Pump open
+ EN_PUMP_XFLOW = 5 //!< Pump open - cannot supply flow
+} EN_PumpStateType;
+
+/// Types of water quality analyses
+/**
+These are the different types of water quality analyses that EPANET can run. They
+are used with @ref EN_getqualinfo, @ref EN_getqualtype, and @ref EN_setqualtype.
+*/
+typedef enum {
+ EN_NONE = 0, //!< No quality analysis
+ EN_CHEM = 1, //!< Chemical fate and transport
+ EN_AGE = 2, //!< Water age analysis
+ EN_TRACE = 3 //!< Source tracing analysis
+} EN_QualityType;
+
+/// Water quality source types
+/**
+These are the different types of external water quality sources that can be assigned
+to a node's `EN_SOURCETYPE` property as used by @ref EN_getnodevalue and @ref EN_setnodevalue.
+*/
+typedef enum {
+ EN_CONCEN = 0, //!< Sets the concentration of external inflow entering a node
+ EN_MASS = 1, //!< Injects a given mass/minute into a node
+ EN_SETPOINT = 2, //!< Sets the concentration leaving a node to a given value
+ EN_FLOWPACED = 3 //!< Adds a given value to the concentration leaving a node
+} EN_SourceType;
+
+/// Head loss formulas
+/**
+The available choices for the `EN_HEADLOSSFORM` option in @ref EN_getoption and
+@ref EN_setoption. They are also used for the head loss type argument in @ref EN_init.
+Each head loss formula uses a different type of roughness coefficient (`EN_ROUGHNESS`)
+that can be set with @ref EN_setlinkvalue.
+*/
+typedef enum {
+ EN_HW = 0, //!< Hazen-Williams
+ EN_DW = 1, //!< Darcy-Weisbach
+ EN_CM = 2 //!< Chezy-Manning
+} EN_HeadLossType;
+
+/// Flow units
+/**
+These choices for flow units are used with @ref EN_getflowunits and @ref EN_setflowunits.
+They are also used for the flow units type argument in @ref EN_init. If flow units are
+expressed in US Customary units (`EN_CFS` through `EN_AFD`) then all other quantities are
+in US Customary units. Otherwise they are in metric units.
+*/
+typedef enum {
+ EN_CFS = 0, //!< Cubic feet per second
+ EN_GPM = 1, //!< Gallons per minute
+ EN_MGD = 2, //!< Million gallons per day
+ EN_IMGD = 3, //!< Imperial million gallons per day
+ EN_AFD = 4, //!< Acre-feet per day
+ EN_LPS = 5, //!< Liters per second
+ EN_LPM = 6, //!< Liters per minute
+ EN_MLD = 7, //!< Million liters per day
+ EN_CMH = 8, //!< Cubic meters per hour
+ EN_CMD = 9, //!< Cubic meters per day
+ EN_CMS = 10 //!< Cubic meters per second
+} EN_FlowUnits;
+
+/// Pressure units
+/**
+The available choices for pressure units for the `EN_PRESS_UNITS` option in @ref EN_getoption
+and @ref EN_setoption.
+*/
+typedef enum {
+ EN_PSI = 0, //!< Pounds per square inch
+ EN_KPA = 1, //!< Kilopascals
+ EN_METERS = 2, //!< Meters
+ EN_BAR = 3, //!< Bar
+ EN_FEET = 4 //!< Feet
+} EN_PressUnits;
+
+/// Demand models
+/**
+These choices for modeling consumer demands are used with @ref EN_getdemandmodel
+and @ref EN_setdemandmodel.
+
+A demand driven analysis requires that a junction's full demand be supplied
+in each time period independent of how much pressure is available. A pressure
+driven analysis makes demand be a power function of pressure, up to the point
+where the full demand is met.
+*/
+typedef enum {
+ EN_DDA = 0, //!< Demand driven analysis
+ EN_PDA = 1 //!< Pressure driven analysis
+} EN_DemandModel;
+
+/// Simulation options
+/**
+These constants identify the hydraulic and water quality simulation options
+that are applied on a network-wide basis. They are accessed using the
+@ref EN_getoption and @ref EN_setoption functions.
+*/
+typedef enum {
+ EN_TRIALS = 0, //!< Maximum trials allowed for hydraulic convergence
+ EN_ACCURACY = 1, //!< Total normalized flow change for hydraulic convergence
+ EN_TOLERANCE = 2, //!< Water quality tolerance
+ EN_EMITEXPON = 3, //!< Exponent in emitter discharge formula
+ EN_DEMANDMULT = 4, //!< Global demand multiplier
+ EN_HEADERROR = 5, //!< Maximum head loss error for hydraulic convergence
+ EN_FLOWCHANGE = 6, //!< Maximum flow change for hydraulic convergence
+ EN_HEADLOSSFORM = 7, //!< Head loss formula (see @ref EN_HeadLossType)
+ EN_GLOBALEFFIC = 8, //!< Global pump efficiency (percent)
+ EN_GLOBALPRICE = 9, //!< Global energy price per KWH
+ EN_GLOBALPATTERN = 10, //!< Index of a global energy price pattern
+ EN_DEMANDCHARGE = 11, //!< Energy charge per max. KW usage
+ EN_SP_GRAVITY = 12, //!< Specific gravity
+ EN_SP_VISCOS = 13, //!< Specific viscosity (relative to water at 20 deg C)
+ EN_UNBALANCED = 14, //!< Extra trials allowed if hydraulics don't converge
+ EN_CHECKFREQ = 15, //!< Frequency of hydraulic status checks
+ EN_MAXCHECK = 16, //!< Maximum trials for status checking
+ EN_DAMPLIMIT = 17, //!< Accuracy level where solution damping begins
+ EN_SP_DIFFUS = 18, //!< Specific diffusivity (relative to chlorine at 20 deg C)
+ EN_BULKORDER = 19, //!< Bulk water reaction order for pipes
+ EN_WALLORDER = 20, //!< Wall reaction order for pipes (either 0 or 1)
+ EN_TANKORDER = 21, //!< Bulk water reaction order for tanks
+ EN_CONCENLIMIT = 22, //!< Limiting concentration for growth reactions
+ EN_DEMANDPATTERN = 23, //!< Name of default demand pattern
+ EN_EMITBACKFLOW = 24, //!< `EN_TRUE` (= 1) if emitters can backflow, `EN_FALSE` (= 0) if not
+ EN_PRESS_UNITS = 25, //!< Pressure units (see @ref EN_PressUnits)
+ EN_STATUS_REPORT = 26 //!< Type of status report to produce (see @ref EN_StatusReport)
+} EN_Option;
+
+/// Simple control types
+/**
+These are the different types of simple (single statement) controls that can be applied
+to network links. They are used as an argument to @ref EN_addcontrol,@ref EN_getcontrol,
+and @ref EN_setcontrol.
+*/
+typedef enum {
+ EN_LOWLEVEL = 0, //!< Act when pressure or tank level drops below a setpoint
+ EN_HILEVEL = 1, //!< Act when pressure or tank level rises above a setpoint
+ EN_TIMER = 2, //!< Act at a prescribed elapsed amount of time
+ EN_TIMEOFDAY = 3 //!< Act at a particular time of day
+} EN_ControlType;
+
+/// Reporting statistic choices
+/**
+These options determine what kind of statistical post-processing should be done on
+the time series of simulation results before they are reported using @ref EN_report
+or saved to the project's binary output file. These options are used in the
+@ref EN_gettimeparam and @ref EN_settimeparam functions when `EN_STATISTIC` is the
+time parameter being set or retrieved.
+*/
+typedef enum {
+ EN_SERIES = 0, //!< Report all time series points
+ EN_AVERAGE = 1, //!< Report average value over simulation period
+ EN_MINIMUM = 2, //!< Report minimum value over simulation period
+ EN_MAXIMUM = 3, //!< Report maximum value over simulation period
+ EN_RANGE = 4 //!< Report maximum - minimum over simulation period
+} EN_StatisticType;
+
+/// Tank mixing models
+/**
+These are the different types of models that describe water quality mixing in storage tanks.
+The choice of model is accessed with the `EN_MIXMODEL` property of a Tank node using
+@ref EN_getnodevalue and @ref EN_setnodevalue.
+*/
+typedef enum {
+ EN_MIX1 = 0, //!< Complete mix model
+ EN_MIX2 = 1, //!< 2-compartment model
+ EN_FIFO = 2, //!< First in, first out model
+ EN_LIFO = 3 //!< Last in, first out model
+} EN_MixingModel;
+
+/// Hydraulic initialization options
+/**
+These options are used to initialize a new hydraulic analysis when @ref EN_initH is called.
+*/
+typedef enum {
+ EN_NOSAVE = 0, //!< Don't save hydraulics; don't re-initialize flows
+ EN_SAVE = 1, //!< Save hydraulics to file, don't re-initialize flows
+ EN_INITFLOW = 10, //!< Don't save hydraulics; re-initialize flows
+ EN_SAVE_AND_INIT = 11 //!< Save hydraulics; re-initialize flows
+} EN_InitHydOption;
+
+/// Types of pump curves
+/**
+@ref EN_getpumptype returns one of these values when it is called.
+*/
+typedef enum {
+ EN_CONST_HP = 0, //!< Constant horsepower
+ EN_POWER_FUNC = 1, //!< Power function
+ EN_CUSTOM = 2, //!< User-defined custom curve
+ EN_NOCURVE = 3 //!< No curve
+} EN_PumpType;
+
+/// Types of data curves
+/**
+These are the different types of physical relationships that a data curve can
+represent as returned by calling @ref EN_getcurvetype.
+*/
+typedef enum {
+ EN_VOLUME_CURVE = 0, //!< Tank volume v. depth curve
+ EN_PUMP_CURVE = 1, //!< Pump head v. flow curve
+ EN_EFFIC_CURVE = 2, //!< Pump efficiency v. flow curve
+ EN_HLOSS_CURVE = 3, //!< Valve head loss v. flow curve
+ EN_GENERIC_CURVE = 4, //!< Generic curve
+ EN_VALVE_CURVE = 5 //!< % of fully open flow v. % open
+} EN_CurveType;
+
+/// Deletion action codes
+/**
+These codes are used in @ref EN_deletenode and @ref EN_deletelink to indicate what action
+should be taken if the node or link being deleted appears in any simple or rule-based
+controls or if a deleted node has any links connected to it.
+*/
+typedef enum {
+ EN_UNCONDITIONAL = 0, //!< Delete all controls and connecting links
+ EN_CONDITIONAL = 1 //!< Cancel object deletion if it appears in controls or has connecting links
+} EN_ActionCodeType;
+
+/// Status reporting levels
+/**
+These choices specify the level of status reporting written to a project's report
+file during a hydraulic analysis. The level is set using the @ref EN_setstatusreport
+or the @ref EN_setoption functions.
+*/
+typedef enum {
+ EN_NO_REPORT = 0, //!< No status reporting
+ EN_NORMAL_REPORT = 1, //!< Normal level of status reporting
+ EN_FULL_REPORT = 2 //!< Full level of status reporting
+} EN_StatusReport;
+
+/// Network objects used in rule-based controls
+typedef enum {
+ EN_R_NODE = 6, //!< Clause refers to a node
+ EN_R_LINK = 7, //!< Clause refers to a link
+ EN_R_SYSTEM = 8 //!< Clause refers to a system parameter (e.g., time)
+} EN_RuleObject;
+
+/// Object variables used in rule-based controls
+typedef enum {
+ EN_R_DEMAND = 0, //!< Nodal demand
+ EN_R_HEAD = 1, //!< Nodal hydraulic head
+ EN_R_GRADE = 2, //!< Nodal hydraulic grade
+ EN_R_LEVEL = 3, //!< Tank water level
+ EN_R_PRESSURE = 4, //!< Nodal pressure
+ EN_R_FLOW = 5, //!< Link flow rate
+ EN_R_STATUS = 6, //!< Link status
+ EN_R_SETTING = 7, //!< Link setting
+ EN_R_POWER = 8, //!< Pump power output
+ EN_R_TIME = 9, //!< Elapsed simulation time
+ EN_R_CLOCKTIME = 10, //!< Time of day
+ EN_R_FILLTIME = 11, //!< Time to fill a tank
+ EN_R_DRAINTIME = 12 //!< Time to drain a tank
+} EN_RuleVariable;
+
+/// Comparison operators used in rule-based controls
+typedef enum {
+ EN_R_EQ = 0, //!< Equal to
+ EN_R_NE = 1, //!< Not equal
+ EN_R_LE = 2, //!< Less than or equal to
+ EN_R_GE = 3, //!< Greater than or equal to
+ EN_R_LT = 4, //!< Less than
+ EN_R_GT = 5, //!< Greater than
+ EN_R_IS = 6, //!< Is equal to
+ EN_R_NOT = 7, //!< Is not equal to
+ EN_R_BELOW = 8, //!< Is below
+ EN_R_ABOVE = 9 //!< Is above
+} EN_RuleOperator;
+
+/// Link status codes used in rule-based controls
+typedef enum {
+ EN_R_IS_OPEN = 1, //!< Link is open
+ EN_R_IS_CLOSED = 2, //!< Link is closed
+ EN_R_IS_ACTIVE = 3 //!< Control valve is active
+} EN_RuleStatus;
+
+#define EN_MISSING -1.E10 //!< Missing value indicator
+#define EN_SET_CLOSED -1.E10 //!< Link set closed indicator
+#define EN_SET_OPEN 1.E10 //!< Link set open indicator
+
+#define EN_FALSE 0 //!< boolean false
+#define EN_TRUE 1 //!< boolean true
+
+#endif //EPANET2_ENUMS_H
diff --git a/epanet/linux/libepanet-output.so b/epanet/linux/libepanet-output.so
new file mode 100644
index 0000000..6e9aec5
Binary files /dev/null and b/epanet/linux/libepanet-output.so differ
diff --git a/epanet/linux/libepanet2.so b/epanet/linux/libepanet2.so
new file mode 100644
index 0000000..168f215
Binary files /dev/null and b/epanet/linux/libepanet2.so differ
diff --git a/epanet/linux/runepanet b/epanet/linux/runepanet
new file mode 100644
index 0000000..c22bd1c
Binary files /dev/null and b/epanet/linux/runepanet differ