From 6dce827f1c4177ebbd0b47efbd238291934ba174 Mon Sep 17 00:00:00 2001 From: "WQY\\qiong" Date: Sat, 10 Dec 2022 19:24:03 +0800 Subject: [PATCH 1/2] Add error code --- epanet/error_code.py | 77 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 epanet/error_code.py diff --git a/epanet/error_code.py b/epanet/error_code.py new file mode 100644 index 0000000..e6bce6b --- /dev/null +++ b/epanet/error_code.py @@ -0,0 +1,77 @@ +ERROR_CODE = {} + +# EPANET 2 Error Messages +ERROR_CODE['0'] = "ok" +ERROR_CODE['101'] = "insufficient memory available" +ERROR_CODE['102'] = "no network data available" +ERROR_CODE['103'] = "hydraulic solver not opened" +ERROR_CODE['104'] = "no hydraulics for water quality analysis" +ERROR_CODE['105'] = "water quality solver not opened" +ERROR_CODE['106'] = "no results saved to report on" +ERROR_CODE['107'] = "hydraulics supplied from external file" +ERROR_CODE['108'] = "cannot use external file while hydraulics solver is active" +ERROR_CODE['110'] = "cannot solve network hydraulic equations" +ERROR_CODE['120'] = "cannot solve water quality transport equations" + +# These errors apply only to an input file +ERROR_CODE['200'] = "one or more errors in input file" +ERROR_CODE['201'] = "syntax error" + +# These errors apply to both an input file and to API functions +ERROR_CODE['202'] = "illegal numeric value" +ERROR_CODE['203'] = "undefined node" +ERROR_CODE['204'] = "undefined link" +ERROR_CODE['205'] = "undefined time pattern" +ERROR_CODE['206'] = "undefined curve" +ERROR_CODE['207'] = "attempt to control CV/GPV link" +ERROR_CODE['208'] = "illegal PDA pressure limits" +ERROR_CODE['209'] = "illegal node property value" +ERROR_CODE['211'] = "illegal link property value" +ERROR_CODE['212'] = "undefined trace node" +ERROR_CODE['213'] = "invalid option value" +ERROR_CODE['214'] = "too many characters in input line" +ERROR_CODE['215'] = "duplicate ID label" +ERROR_CODE['216'] = "reference to undefined pump" +ERROR_CODE['217'] = "invalid pump energy data" +ERROR_CODE['219'] = "illegal valve connection to tank node" +ERROR_CODE['220'] = "illegal valve connection to another valve" +ERROR_CODE['221'] = "mis-placed rule clause in rule-based control" +ERROR_CODE['222'] = "same start and end nodes for link" + +# These errors apply to network consistency check +ERROR_CODE['223'] = "not enough nodes in network" +ERROR_CODE['224'] = "no tanks or reservoirs in network" +ERROR_CODE['225'] = "invalid lower/upper levels for tank" +ERROR_CODE['226'] = "no head curve or power rating for pump" +ERROR_CODE['227'] = "invalid head curve for pump" +ERROR_CODE['230'] = "nonincreasing x-values for curve" +ERROR_CODE['233'] = "network has unconnected nodes" +ERROR_CODE['234'] = "network has an unconnected node with ID: " + +# These errors apply only to API functions +ERROR_CODE['240'] = "nonexistent source" +ERROR_CODE['241'] = "nonexistent control" +ERROR_CODE['250'] = "invalid format" +ERROR_CODE['251'] = "invalid parameter code" +ERROR_CODE['252'] = "invalid ID name" +ERROR_CODE['253'] = "nonexistent demand category" +ERROR_CODE['254'] = "node with no coordinates" +ERROR_CODE['255'] = "invalid link vertex" +ERROR_CODE['257'] = "nonexistent rule" +ERROR_CODE['258'] = "nonexistent rule clause" +ERROR_CODE['259'] = "attempt to delete a node that still has links connected to it" +ERROR_CODE['260'] = "attempt to delete node assigned as a Trace Node" +ERROR_CODE['261'] = "attempt to delete a node or link contained in a control" +ERROR_CODE['262'] = "attempt to modify network structure while solver is active" +ERROR_CODE['263'] = "node is not a tank" + +# File errors +ERROR_CODE['301'] = "identical file names" +ERROR_CODE['302'] = "cannot open input file" +ERROR_CODE['303'] = "cannot open report file" +ERROR_CODE['304'] = "cannot open binary output file" +ERROR_CODE['305'] = "cannot open hydraulics file" +ERROR_CODE['306'] = "hydraulics file does not match network data" +ERROR_CODE['307'] = "cannot read hydraulics file" +ERROR_CODE['308'] = "cannot save results to file" +ERROR_CODE['309'] = "cannot save results to report file" \ No newline at end of file From f6c14f1c81d75a006ca1ffa5fb3c7f64788382f2 Mon Sep 17 00:00:00 2001 From: "WQY\\qiong" Date: Sat, 10 Dec 2022 19:26:43 +0800 Subject: [PATCH 2/2] Add simulation result and report to output json --- epanet/epanet.py | 49 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/epanet/epanet.py b/epanet/epanet.py index 77314fa..86d216f 100644 --- a/epanet/epanet.py +++ b/epanet/epanet.py @@ -7,7 +7,7 @@ from typing import Any sys.path.append("..") from api import project from api import parser - +from .error_code import * def _verify_platform(): _platform = platform.system() @@ -196,7 +196,7 @@ class Output: return ds - def dump(self, cache: bool = True) -> str: + def dump(self) -> dict[str, Any]: data = {} data |= { 'version' : self.version() } data |= { 'net_size' : self.net_size() } @@ -207,15 +207,24 @@ class Output: data |= { 'reactions' : self.reactions() } data |= { 'node_results' : self.node_results() } data |= { 'link_results' : self.link_results() } - if cache: - with open(self._path + '.json', 'w') as f: - json.dump(data, f) - return json.dumps(data) + return data + + +def dump_report(path: str) -> str: + return open(path, mode='r').read() + + +def _dump_output(path: str) -> dict[str, Any]: + opt = Output(path) + data = opt.dump() + with open(path + '.json', 'w') as f: + json.dump(data, f) + return data def dump_output(path: str) -> str: - opt = Output(path) - return opt.dump() + data = _dump_output(path) + return json.dumps(data) def run_project(name: str) -> str: @@ -234,12 +243,18 @@ def run_project(name: str) -> str: opt = os.path.join(os.path.join(dir, 'temp'), input + '.opt') command = f'{exe} {inp} {rpt} {opt}' + data = {} + result = os.system(command) if result != 0: - msg = f'Failed to run simulation for project [{name}]' - raise Exception(msg) + data['simulation_result'] = 'failed' + else: + data['simulation_result'] = 'successful' + data |= _dump_output(opt) - return dump_output(opt) + data['report'] = dump_report(rpt) + + return json.dumps(data) def run_inp(name: str) -> str: @@ -251,12 +266,18 @@ def run_inp(name: str) -> str: opt = os.path.join(os.path.join(dir, 'temp'), name + '.opt') command = f'{exe} {inp} {rpt} {opt}' + data = {} + result = os.system(command) if result != 0: - msg = f'Failed to run simulation for project [{name}]' - raise Exception(msg) + data['simulation_result'] = 'failed' + else: + data['simulation_result'] = 'successful' + data |= _dump_output(opt) - return dump_output(opt) + data['report'] = dump_report(rpt) + + return json.dumps(data) if __name__ == '__main__':