Merge pull request #831 from OpenWaterAnalytics/dev-tags
Adds EN_gettag and EN_settag functions to the Toolkit
This commit is contained in:
@@ -3,70 +3,132 @@
|
||||
|
||||
This document describes the changes and updates that have been made in version 2.3 of EPANET.
|
||||
|
||||
- The check for at least two nodes, one tank/reservoir and no unconnected junction nodes was moved from `EN_open` to `EN_openH` and `EN_openQ` so that partial network data files could be opened by the toolkit.
|
||||
|
||||
### New Features
|
||||
|
||||
- A `EN_setcurvetype` function was added to allow API clients to set a curve's type (e.g., `EN_PUMP_CURVE,` `EN_VOLUME_CURVE,` etc.).
|
||||
|
||||
- A `EN_setvertex` function was added to allow API clients to change the coordinates of a single link vertex.
|
||||
- The indices of a General Purpose Valve (GPV) and a Positional Control Valve (PCV) were added to the list of editable Link Properties using the symbolic constant names `EN_GPV_CURVE` and `EN_PCV_CURVE`, respectively.
|
||||
- The `EN_getlinkvalue` and `EN_setlinkvalue` functions were updated to get and set the values of `EN_GPV_CURVE` and `EN_PCV_CURVE`.
|
||||
- Negative pressure values for `EN_SETTING` are now permitted in the `EN_setlinkvalue` function.
|
||||
- The `EN_STARTTIME` parameter was added into the `EN_settimeparam` function.
|
||||
- A `EN_DEMANDPATTERN` parameter was added as the index of the default time pattern used by demands with no specific pattern assigned. It can be set or retrieved with the `EN_setoption` and `EN_getoption` functions, respectively, and is saved to the file when the `EN_saveinpfile` function is called.
|
||||
- The `EN_getaveragepatternvalue` function will now accept a pattern index of zero which represents the constant pattern assigned to junction demands by default.
|
||||
- The adjustment of a tank's minimum volume (`Vmin`) when its parameters are changed using `EN_setnodevalue` or `EN_settankdata` has been corrected.
|
||||
- A pump whose status is set to CLOSED in the input file now also has its speed setting set to zero which allows a simple pressure control to activate the pump correctly.
|
||||
- A failure to raise an error condition for a non-positive pipe roughness in the input file has been fixed.
|
||||
- The calculation of head loss gradient for low flow conditions was corrected.
|
||||
- Improved updating and convergence tests were added to pressure-dependent demand analysis.
|
||||
- Improved checks to prevent outflow from empty tanks or inflow to full (non-overflow) tanks, including the case where a link is connected to a pair of tanks, were added.
|
||||
- The CI regression test protocol was modified by:
|
||||
- changing the absolute tolerance used to compare the closeness of test results to benchmark values from 0 to 0.0001
|
||||
- dropping the "correct decimal digits" test
|
||||
- dropping the check for identical status report content since it prevents accepting code changes that produce more accurate solutions in fewer iterations.
|
||||
- A possible loss of network connectivity when evaluating a Pressure Sustaining Valve was prevented.
|
||||
- Having the implied loss coefficient for an active Flow Control Valve be less than its fully opened value was prevented.
|
||||
- A new type of valve, a Positional Control Valve (PCV), was added. It uses a valve characteristic curve to relate its loss coefficient to a percentage open setting (parameter - `EN_PCV`).
|
||||
- `EN_VALVE_CURVE` can now be used with the `EN_getcurvetype` and `EN_setcurvetype` to get or set the valve position curve.
|
||||
- A new set of functions has been added to get information about upcoming time step events. Users will now see what type of event is going to cause the end of a time step to occur. See `EN_timetonextevent`.
|
||||
- A new set of functions has been added to allow users to set a reporting callback function. The user-supplied function will receive all output normally directed to the report file.
|
||||
- A `EN_EMITBACKFLOW` option was added that either allows emitters to have reverse flow through them (the default) or not.
|
||||
- An incorrect tank elevation value set using `EN_settankdata` with SI units has been fixed.
|
||||
- The `EN_INITSETTING` option in function `EN_getlinkvalue` will now return `EN_MISSING` for a valve whose initial status is fixed to `EN_OPEN` or `EN_CLOSED`.
|
||||
- The functions `EN_getnodevalue` and `EN_getlinkvalue` now include the options `EN_NODE_INCONTROL` and `EN_LINK_INCONTROL` to determine whether a node or link appears in any simple or rule-based control.
|
||||
- An error is no longer raised when a minor loss coefficient of zero is assigned in `EN_setlinkvalue(ph, index, EN_MINORLOSS, 0)`.
|
||||
- The incorrect display of unconnected nodes has been fixed.
|
||||
- A header file for binding C# to the Toolkit has been added.
|
||||
- A new error code `263 - node is not a tank` is returned when `EN_settankdata` or `EN_setnodevalue` attempts to set a tank-only parameter for a non-tank node.
|
||||
- The function `EN_saveinpfile` was corrected for simple controls on GPV's by saving their status instead of the index of their head loss curve.
|
||||
- Support was added for Conan dependency manager.
|
||||
- The internal Qualflag variable is now adjusted when an EPANET input file has a QUALITY option not equal to NONE and a simulation duration of zero.
|
||||
- Support was added for cubic meters per second (`EN_CMS`) flow units.
|
||||
- An EPANET input file with simple timer control that has more than 9 input tokens no longer results in an incorrect hour setting.
|
||||
- Errors in node and link vertex coordinates are now ignored when reading an EPANET input file.
|
||||
- Only non-zero demands are now included in the `[DEMANDS]` section of the input file produced by `EN_saveinpfile`.
|
||||
- `EN_SET_CLOSED` and `EN_SET_OPEN` constants were added that can be used with `EN_setcontrol` to fix the status of pipes and valves to completely closed or completely open.
|
||||
- `EN_EMITTERFLOW` can now be used with `EN_getnodevalue` to retrieve a node's emitter flow rate.
|
||||
- `EN_STATUS_REPORT` can now be used with `EN_getoption` and `EN_setoption` to get or set the type of status report that EPANET will generate (`EN_NO_REPORT`, `EN_NORMAL_REPORT` or `EN_FULL_REPORT`).
|
||||
- A possible parser error that could result in a Trace Node ID in an input file not being recognized was fixed.
|
||||
- Additional API functions for enabling/disabling controls and rules were added (`EN_getcontrolenabled`, `EN_setcontrolenabled`, `EN_getruleenabled`, `EN_setruleenabled`).
|
||||
- Updated the internal function `getclosedlink` in report.c to use a loop instead of recursion to prevent a stack overflow during the analysis of very large disconnections.
|
||||
- Setting the demand multiplier within the `[DEMANDS]` section of INP has been depreciated, please use `DEMAND MULTIPLIER` inside `[OPTIONS]` instead.
|
||||
- `EN_PRESS_UNITS` can now be used with `EN_getoption` and `EN_setoption` to get or set the pressure unit used in EPANET.
|
||||
- Continuous barrier functions were added to constrain emitter flows to allowable values.
|
||||
- The `EN_openX` function has been added to enable the opening of input files with formatting errors through the API. This allows users to continue using toolkit functions even when such errors are present.
|
||||
- The `EN_getnodesvalues` and `EN_getlinksvalues` were added to retrieve a property value for all nodes or links in the network.
|
||||
- Fixed a bug in EN_setnodevalue with EN_EMITTER option that could cause NaN results.
|
||||
|
||||
- Support has been added for FAVAD (Fixed And Variable Area Discharge) modeling of pipe leaks:
|
||||
- A new `[LEAKAGE]` section has been added to the input file format where each line contains the ID name of a pipe, its leak area in sq. mm per 100 length units, and its leak expansion rate in sq. mm per unit of pressure head.
|
||||
- `EN_LEAK_AREA` and `EN_LEAK_EXPAN` can be used with the functions `EN_getlinkvalue` and `EN_setlinkvalue` to retrieve and assign values for a pipe's leak area and expansion properties.
|
||||
- `EN_LINK_LEAKAGE` can be used with `EN_getlinkvalue` to retrieve a pipe's leakage rate at a given point in time.
|
||||
- `EN_LEAKAGEFLOW` can be used with `EN_getnodevalue` to retrieve the leakage demand generated at a node from all its connecting pipes at a given point in time.
|
||||
- `EN_LEAKAGELOSS` can be used with `EN_getstatistic` to retrieve the the total leakage loss in the system at a given point in time as a percentage of total flow entering the system.
|
||||
- A new Flow Balance Report has been added to end of a simulation run's Status Report that lists the various components of the system's total inflow and outflow over the simulation period. It also displays the ratio of outflow to inflow as a check on flow continuity.
|
||||
- The following constants can be used with EN_getnodevalue to retrieve the components of a node's total demand at a given point in time:
|
||||
|
||||
- Support has been added for reading the `[TAGS]` section of an EPANET input file. In addition:
|
||||
- A newly added `EN_settag` function will assign a Tag to a node or link.
|
||||
- A newly added `EN_gettag` function will retrieve a node or link's Tag.
|
||||
- The exisitng `EN_saveinpfile` will include saving all node and link tags to file.
|
||||
- A new Flow Balance Report has been added to end of a simulation run's Status Report that lists the various components of the system's total inflow and outflow over the simulation period. It also displays the ratio of outflow to inflow as a check on flow continuity.
|
||||
|
||||
- A new type of valve, a Positional Control Valve (PCV), was added. It uses a valve characteristic curve to relate its loss coefficient to a percentage open setting (parameter - `EN_PCV`).
|
||||
|
||||
- `EN_VALVE_CURVE` can now be used with the `EN_getcurvetype` and `EN_setcurvetype` to get or set the valve position curve.
|
||||
|
||||
- A new set of functions has been added to get information about upcoming time step events. Users will now see what type of event is going to cause the end of a time step to occur. See `EN_timetonextevent`.
|
||||
|
||||
- A new set of functions has been added to allow users to set a reporting callback function. The user-supplied function will receive all output normally directed to the report file.
|
||||
|
||||
- A `EN_EMITBACKFLOW` option was added that either allows emitters to have reverse flow through them (the default) or not.
|
||||
|
||||
- The functions `EN_getnodevalue` and `EN_getlinkvalue` now include the options `EN_NODE_INCONTROL` and `EN_LINK_INCONTROL` to determine whether a node or link appears in any simple or rule-based control.
|
||||
|
||||
- `EN_SET_CLOSED` and `EN_SET_OPEN` constants were added that can be used with `EN_setcontrol` to fix the status of pipes and valves to completely closed or completely open.
|
||||
|
||||
- `EN_STATUS_REPORT` can now be used with `EN_getoption` and `EN_setoption` to get or set the type of status report that EPANET will generate (`EN_NO_REPORT`, `EN_NORMAL_REPORT` or `EN_FULL_REPORT`).
|
||||
|
||||
- `EN_PRESS_UNITS` can now be used with `EN_getoption` and `EN_setoption` to get or set the pressure unit used in EPANET.
|
||||
|
||||
- The following constants can be used with EN_getnodevalue to retrieve the components of a node's total demand at a given point in time:
|
||||
- `EN_FULLDEMAND` - the consumer demand requested
|
||||
- `EN_DEMANDFLOW` - the consumer demand delivered
|
||||
- `EN_DEMANDDEFICIT` - the difference between the consumer demand requested and delivered
|
||||
- `EN_EMITTERFLOW` - the node's emitter flow
|
||||
- `EN_LEAKAGEFLOW` - the node's leakage flow
|
||||
- `EN_DEMAND` - the sum of the node's consumer demand, emitter flow, and leakage flow
|
||||
- `EN_DEMAND` - the sum of the node's consumer demand, emitter flow, and leakage flow
|
||||
|
||||
- Additional API functions for enabling/disabling controls and rules were added (`EN_getcontrolenabled`, `EN_setcontrolenabled`, `EN_getruleenabled`, `EN_setruleenabled`). A new keyword `DISABLED` is added to the end of a control or rule statement in an EPANET input file to indicate that the control is disabled.
|
||||
|
||||
- The `EN_openX` function has been added to enable the opening of input files with formatting errors through the API. This allows users to continue using toolkit functions even when such errors are present.
|
||||
|
||||
- The `EN_getnodesvalues` and `EN_getlinksvalues` were added to retrieve a property value for all nodes or links in the network.
|
||||
|
||||
- Support was added for cubic meters per second (`EN_CMS`) flow units.
|
||||
|
||||
- A header file for binding C# to the Toolkit has been added.
|
||||
|
||||
- Support was added for Conan dependency manager.
|
||||
|
||||
### Feature Updates
|
||||
|
||||
- The check for at least two nodes, one tank/reservoir and no unconnected junction nodes was moved from `EN_open` to `EN_openH` and `EN_openQ` so that partial network data files could be opened by the toolkit.
|
||||
|
||||
- The indices of a General Purpose Valve (GPV) and a Positional Control Valve (PCV) were added to the list of editable Link Properties using the symbolic constant names `EN_GPV_CURVE` and `EN_PCV_CURVE`, respectively.
|
||||
|
||||
- The `EN_getlinkvalue` and `EN_setlinkvalue` functions were updated to get and set the values of `EN_GPV_CURVE` and `EN_PCV_CURVE`.
|
||||
|
||||
- Negative pressure values for `EN_SETTING` are now permitted in the `EN_setlinkvalue` function.
|
||||
|
||||
- The `EN_STARTTIME` parameter was added into the `EN_settimeparam` function.
|
||||
|
||||
- A `EN_DEMANDPATTERN` parameter was added as the index of the default time pattern used by demands with no specific pattern assigned. It can be set or retrieved with the `EN_setoption` and `EN_getoption` functions, respectively, and is saved to the file when the `EN_saveinpfile` function is called.
|
||||
|
||||
- The `EN_getaveragepatternvalue` function will now accept a pattern index of zero which represents the constant pattern assigned to junction demands by default.
|
||||
|
||||
- Improved updating and convergence tests were added to pressure-dependent demand analysis.
|
||||
|
||||
- Improved checks to prevent outflow from empty tanks or inflow to full (non-overflow) tanks, including the case where a link is connected to a pair of tanks, were added.
|
||||
|
||||
- The `EN_INITSETTING` option in function `EN_getlinkvalue` will now return `EN_MISSING` for a valve whose initial status is fixed to `EN_OPEN` or `EN_CLOSED`.
|
||||
|
||||
- A new error code `263 - node is not a tank` is returned when `EN_settankdata` or `EN_setnodevalue` attempts to set a tank-only parameter for a non-tank node.
|
||||
|
||||
- Errors in node and link vertex coordinates are now ignored when reading an EPANET input file.
|
||||
|
||||
- Only non-zero demands are now included in the `[DEMANDS]` section of the input file produced by `EN_saveinpfile`.
|
||||
|
||||
- Setting the demand multiplier within the `[DEMANDS]` section of INP has been depreciated, please use `DEMAND MULTIPLIER` inside `[OPTIONS]` instead.
|
||||
|
||||
- Continuous barrier functions were added to constrain emitter flows to allowable values.
|
||||
|
||||
- The CI regression test protocol was modified by:
|
||||
- changing the absolute tolerance used to compare the closeness of test results to benchmark values from 0 to 0.0001
|
||||
- dropping the "correct decimal digits" test
|
||||
- dropping the check for identical status report content since it prevents accepting code changes that produce more accurate solutions in fewer iterations.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- The adjustment of a tank's minimum volume (`Vmin`) when its parameters are changed using `EN_setnodevalue` or `EN_settankdata` has been corrected.
|
||||
|
||||
- A pump whose status is set to CLOSED in the input file now also has its speed setting set to zero which allows a simple pressure control to activate the pump correctly.
|
||||
|
||||
- A failure to raise an error condition for a non-positive pipe roughness in the input file has been fixed.
|
||||
|
||||
- The calculation of head loss gradient for low flow conditions was corrected.
|
||||
|
||||
- A possible loss of network connectivity when evaluating a Pressure Sustaining Valve was prevented.
|
||||
|
||||
- Having the implied loss coefficient for an active Flow Control Valve be less than its fully opened value was prevented.
|
||||
|
||||
- An incorrect tank elevation value set using `EN_settankdata` with SI units has been fixed.
|
||||
|
||||
- An error is no longer raised when a minor loss coefficient of zero is assigned in `EN_setlinkvalue(ph, index, EN_MINORLOSS, 0)`.
|
||||
|
||||
- The incorrect display of unconnected nodes has been fixed.
|
||||
|
||||
- The function `EN_saveinpfile` was corrected for simple controls on GPV's by saving their status instead of the index of their head loss curve.
|
||||
|
||||
- The internal Qualflag variable is now adjusted when an EPANET input file has a QUALITY option not equal to NONE and a simulation duration of zero.
|
||||
|
||||
- An EPANET input file with simple timer control that has more than 9 input tokens no longer results in an incorrect hour setting.
|
||||
|
||||
- A possible parser error that could result in a Trace Node ID in an input file not being recognized was fixed.
|
||||
|
||||
- Updated the internal function `getclosedlink` in report.c to use a loop instead of recursion to prevent a stack overflow during the analysis of very large disconnections.
|
||||
|
||||
- Fixed a bug in EN_setnodevalue with EN_EMITTER option that could cause NaN results.
|
||||
|
||||
- A failure to close a temporary hydraulics file between successive simulations of an opened project was fixed.
|
||||
|
||||
- Corrupting the index of a water quality Trace Node when adding or deleting a node was fixed.
|
||||
|
||||
@@ -5,7 +5,7 @@ Attribute VB_Name = "Module1"
|
||||
'Declarations of functions in the EPANET PROGRAMMERs TOOLKIT
|
||||
'(EPANET2.DLL)
|
||||
|
||||
'Last updated on 06/23/2024
|
||||
'Last updated on 02/14/2025
|
||||
|
||||
' These are codes used by the DLL functions
|
||||
Public Const EN_ELEVATION = 0 ' Node parameters
|
||||
@@ -297,8 +297,8 @@ Public Const EN_TRUE = 1 ' boolean true
|
||||
Declare Function ENclose Lib "epanet2.dll" () As Long
|
||||
Declare Function ENgetcomment Lib "epanet2.dll" (ByVal ObjectType As Long, ByVal index As Long, ByVal comment As String) As Long
|
||||
Declare Function ENsetcomment Lib "epanet2.dll" (ByVal ObjectType As Long, ByVal index As Long, ByVal comment As String) As Long
|
||||
|
||||
|
||||
Declare Function ENgettag Lib "epanet2.dll" (ByVal ObjectType As Long, ByVal index As Long, ByVal tag As String) As Long
|
||||
Declare Function ENsettag Lib "epanet2.dll" (ByVal ObjectType As Long, ByVal index As Long, ByVal tag As String) As Long
|
||||
'Hydraulic Analysis Functions
|
||||
Declare Function ENsolveH Lib "epanet2.dll" () As Long
|
||||
Declare Function ENsaveH Lib "epanet2.dll" () As Long
|
||||
@@ -408,6 +408,7 @@ Public Const EN_TRUE = 1 ' boolean true
|
||||
Declare Function ENsetpatternvalue Lib "epanet2.dll" (ByVal index As Long, ByVal period As Long, ByVal value As Single) As Long
|
||||
Declare Function ENgetaveragepatternvalue Lib "epanet2.dll" (ByVal index As Long, value As Single) As Long
|
||||
Declare Function ENsetpattern Lib "epanet2.dll" (ByVal index As Long, values As Any, ByVal len_ As Long) As Long
|
||||
Declare Function ENloadpatternfile Lib "epanet2.dll" (ByVal filename As String, ByVal id As String) As Long
|
||||
|
||||
'Data Curve Functions
|
||||
Declare Function ENaddcurve Lib "epanet2.dll" (ByVal id As String) As Long
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
//epanet2.cs[By Oscar Vegas]
|
||||
//Last updated on 06/23/2024
|
||||
//Last updated on 02/14/2025
|
||||
|
||||
//Declarations of functions in the EPANET PROGRAMMERs TOOLKIT
|
||||
//(EPANET2.DLL) for use with C#
|
||||
@@ -303,7 +303,18 @@ namespace EpanetCSharpLibrary
|
||||
|
||||
[DllImport(EPANETDLL, EntryPoint = "ENsettitle")]
|
||||
public static extern int ENsettitle(string titleline1, string titleline2, string titleline3);
|
||||
|
||||
[DllImport(EPANETDLL, EntryPoint = "ENgetcomment")]
|
||||
public static extern int ENgetcomment(int type, int index, string comment);
|
||||
|
||||
[DllImport(EPANETDLL, EntryPoint = "ENsetcomment")]
|
||||
public static extern int ENsetcomment(int type, int index, string comment);
|
||||
|
||||
[DllImport(EPANETDLL, EntryPoint = "ENgettag")]
|
||||
public static extern int ENgettag(int type, int index, string tag);
|
||||
|
||||
[DllImport(EPANETDLL, EntryPoint = "ENsettag")]
|
||||
public static extern int ENsettag(int type, int index, string tag);
|
||||
[DllImport(EPANETDLL, EntryPoint = "ENsaveinpfile")]
|
||||
public static extern int ENsaveinpfile(string filename);
|
||||
|
||||
@@ -600,6 +611,9 @@ namespace EpanetCSharpLibrary
|
||||
[DllImport(EPANETDLL, EntryPoint = "ENsetpattern")]
|
||||
public static extern int ENsetpattern(int index, ref float[] values, int len);
|
||||
|
||||
[DllImport(EPANETDLL, EntryPoint = "ENloadpatternfile")]
|
||||
public static extern int ENdeletepattern(string filename, string id);
|
||||
|
||||
|
||||
//Data Curve Functions
|
||||
[DllImport(EPANETDLL, EntryPoint = "ENaddcurve")]
|
||||
|
||||
@@ -68,6 +68,7 @@ EXPORTS
|
||||
ENgetruleenabled = _ENgetruleenabled@8
|
||||
ENgetruleID = _ENgetruleID@8
|
||||
ENgetstatistic = _ENgetstatistic@8
|
||||
ENgettag = _ENgettag@12
|
||||
ENgetthenaction = _ENgetthenaction@20
|
||||
ENgettimeparam = _ENgettimeparam@8
|
||||
ENgettitle = _ENgettitle@12
|
||||
@@ -76,7 +77,8 @@ EXPORTS
|
||||
ENgetvertexcount = _ENgetvertexcount@8
|
||||
ENinit = _ENinit@16
|
||||
ENinitH = _ENinitH@4
|
||||
ENinitQ = _ENinitQ@4
|
||||
ENinitQ = _ENinitQ@4
|
||||
ENloadpatternfile = _ENloadpatternfile@8
|
||||
ENnextH = _ENnextH@4
|
||||
ENnextQ = _ENnextQ@4
|
||||
ENopen = _ENopen@12
|
||||
@@ -126,6 +128,7 @@ EXPORTS
|
||||
ENsetruleenabled = _ENsetruleenabled@8
|
||||
ENsetrulepriority = _ENsetrulepriority@8
|
||||
ENsetstatusreport = _ENsetstatusreport@4
|
||||
ENsettag = _ENsettag@12
|
||||
ENsettankdata = _ENsettankdata@32
|
||||
ENsetthenaction = _ENsetthenaction@20
|
||||
ENsettimeparam = _ENsettimeparam@8
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
Project: OWA EPANET
|
||||
Version: 2.2
|
||||
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: 09/28/2023
|
||||
Last Updated: 02/14/2025
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
@@ -84,6 +84,10 @@ extern "C" {
|
||||
|
||||
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);
|
||||
@@ -328,7 +332,7 @@ extern "C" {
|
||||
********************************************************************/
|
||||
|
||||
int DLLEXPORT ENaddpattern(const char *id);
|
||||
|
||||
|
||||
int DLLEXPORT ENdeletepattern(int index);
|
||||
|
||||
int DLLEXPORT ENgetpatternindex(const char *id, int *index);
|
||||
@@ -346,7 +350,7 @@ extern "C" {
|
||||
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);
|
||||
|
||||
/********************************************************************
|
||||
|
||||
@@ -3,7 +3,7 @@ unit epanet2;
|
||||
{ Declarations of imported procedures from the EPANET PROGRAMMERs TOOLKIT }
|
||||
{ (EPANET2.DLL) }
|
||||
|
||||
{Last updated on 06/06/2024}
|
||||
{Last updated on 02/14/2025}
|
||||
|
||||
interface
|
||||
|
||||
@@ -314,6 +314,8 @@ const
|
||||
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;
|
||||
|
||||
@@ -473,8 +475,8 @@ const
|
||||
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; out_enabled: Integer): Integer; cdecl; external EpanetLib;
|
||||
function ENsetruleenabled(Index: Integer; var enabled: Integer): Integer; cdecl; external EpanetLib;
|
||||
function ENgetruleenabled(Index: Integer; var enabled: Integer): Integer; cdecl; external EpanetLib;
|
||||
function ENsetruleenabled(Index: Integer; enabled: Integer): Integer; cdecl; external EpanetLib;
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
'Declarations of functions in the EPANET PROGRAMMERs TOOLKIT
|
||||
'(EPANET2.DLL) for use with VB.Net.
|
||||
|
||||
'Last updated on 06/23/2024
|
||||
'Last updated on 02/14/2025
|
||||
|
||||
Imports System.Runtime.InteropServices
|
||||
Imports System.Text
|
||||
@@ -281,6 +281,10 @@ Public Const EN_TRUE = 1 ' boolean true
|
||||
Declare Function ENopenX Lib "epanet2.dll" (ByVal inpFile As String, ByVal rptFile As String, ByVal outFile As String) As Int32
|
||||
Declare Function ENgettitle Lib "epanet2.dll" (ByVal titleline1 As String, ByVal titleline2 As String, ByVal titleline3 As String) As Int32
|
||||
Declare Function ENsettitle Lib "epanet2.dll" (ByVal titleline1 As String, ByVal titleline2 As String, ByVal titleline3 As String) As Int32
|
||||
Declare Function ENgetcomment Lib "epanet2.dll" (ByVal type_ As Int32, ByVal index As Int32, ByVal comment As String) As Int32
|
||||
Declare Function ENsetcomment Lib "epanet2.dll" (ByVal type_ As Int32, ByVal index As Int32, ByVal comment As String) As Int32
|
||||
Declare Function ENgettag Lib "epanet2.dll" (ByVal type_ As Int32, ByVal index As Int32, ByVal tag As String) As Int32
|
||||
Declare Function ENsettag Lib "epanet2.dll" (ByVal type_ As Int32, ByVal index As Int32, ByVal tag As String) As Int32
|
||||
Declare Function ENsaveinpfile Lib "epanet2.dll" (ByVal filename As String) As Int32
|
||||
Declare Function ENclose Lib "epanet2.dll" () As Int32
|
||||
|
||||
@@ -393,6 +397,7 @@ Public Const EN_TRUE = 1 ' boolean true
|
||||
Declare Function ENsetpatternvalue Lib "epanet2.dll" (ByVal index As Int32, ByVal period As Int32, ByVal value As Single) As Int32
|
||||
Declare Function ENgetaveragepatternvalue Lib "epanet2.dll" (ByVal index As Int32, value As Single) As Int32
|
||||
Declare Function ENsetpattern Lib "epanet2.dll" (ByVal index As Int32, values As Any, ByVal len_ As Int32) As Int32
|
||||
Declare Function ENloadpatternfile Lib "epanet2.dll" (ByVal filename As String, ByVal id As String) As Int32
|
||||
|
||||
'Data Curve Functions
|
||||
Declare Function ENaddcurve Lib "epanet2.dll" (ByVal id As String) As Int32
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
Project: OWA EPANET
|
||||
Version: 2.2
|
||||
Version: 2.3
|
||||
Module: epanet2.h
|
||||
Description: API function declarations
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 09/28/2023
|
||||
Last Updated: 02/14/2025
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
@@ -184,6 +184,27 @@ typedef struct Project *EN_Project;
|
||||
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.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 07/17/2023
|
||||
Last Updated: 02/14/2025
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
46
src/epanet.c
46
src/epanet.c
@@ -7,7 +7,7 @@
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 06/26/2024
|
||||
Last Updated: 02/14/2025
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
@@ -203,7 +203,6 @@ int DLLEXPORT EN_openX(EN_Project p, const char *inpFile,
|
||||
return openproject(p, inpFile, rptFile, outFile, TRUE);
|
||||
}
|
||||
|
||||
|
||||
int DLLEXPORT EN_gettitle(EN_Project p, char *line1, char *line2, char *line3)
|
||||
/*----------------------------------------------------------------
|
||||
** Input: None
|
||||
@@ -263,6 +262,32 @@ int DLLEXPORT EN_setcomment(EN_Project p, int object, int index,
|
||||
return setcomment(&p->network, object, index, comment);
|
||||
}
|
||||
|
||||
int DLLEXPORT EN_gettag(EN_Project p, int object, int index, char *tag)
|
||||
/*----------------------------------------------------------------
|
||||
** Input: object = either EN_NODE or EN_LINK
|
||||
** index = the object's index
|
||||
** Output: tag = the tag string assigned to the object
|
||||
** Returns: error code
|
||||
** Purpose: Retrieves an object's tag string
|
||||
**----------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
return gettag(&p->network, object, index, tag);
|
||||
}
|
||||
|
||||
int DLLEXPORT EN_settag(EN_Project p, int object, int index,
|
||||
const char *tag)
|
||||
/*----------------------------------------------------------------
|
||||
** Input: object = either EN_NODE or EN_LINK
|
||||
** index = the object's index
|
||||
** tag = a descriptive comment to assign
|
||||
** Returns: error code
|
||||
** Purpose: Assigns a tag string to an object
|
||||
**----------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
return settag(&p->network, object, index, tag);
|
||||
}
|
||||
int DLLEXPORT EN_getcount(EN_Project p, int object, int *count)
|
||||
/*----------------------------------------------------------------
|
||||
** Input: object = type of object to count (see EN_CountType)
|
||||
@@ -1790,7 +1815,6 @@ int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, const char *chemName,
|
||||
qual->Ctol *= Ucf[QUALITY];
|
||||
if (qual->Qualflag == CHEM) // Chemical analysis
|
||||
{
|
||||
qual->TraceNode = 0;
|
||||
strncpy(qual->ChemName, chemName, MAXID);
|
||||
strncpy(qual->ChemUnits, chemUnits, MAXID);
|
||||
strncpy(rpt->Field[QUALITY].Units, qual->ChemUnits, MAXID);
|
||||
@@ -1808,16 +1832,10 @@ int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, const char *chemName,
|
||||
}
|
||||
if (qual->Qualflag == AGE) // Water age analysis
|
||||
{
|
||||
qual->TraceNode = 0;
|
||||
strncpy(qual->ChemName, w_AGE, MAXID);
|
||||
strncpy(qual->ChemUnits, u_HOURS, MAXID);
|
||||
strcpy(rpt->Field[QUALITY].Units, u_HOURS);
|
||||
}
|
||||
if (qual->Qualflag == NONE)
|
||||
{
|
||||
qual->TraceNode = 0;
|
||||
strcpy(qual->ChemName, "");
|
||||
}
|
||||
|
||||
// When changing from CHEM to AGE or TRACE, nodes initial quality
|
||||
// values must be returned to their original ones
|
||||
@@ -1923,8 +1941,6 @@ int DLLEXPORT EN_addnode(EN_Project p, const char *id, int nodeType, int *index)
|
||||
}
|
||||
// adjust indices of tanks/reservoirs in Rule premises (see RULES.C)
|
||||
adjusttankrules(p, 1);
|
||||
// adjust index of trace node
|
||||
if (qual->TraceNode > net->Njuncs - 1) qual->TraceNode += 1;
|
||||
}
|
||||
|
||||
// Actions taken when a new Tank/Reservoir is added
|
||||
@@ -1974,6 +1990,7 @@ int DLLEXPORT EN_addnode(EN_Project p, const char *id, int nodeType, int *index)
|
||||
node->X = MISSING;
|
||||
node->Y = MISSING;
|
||||
node->Comment = NULL;
|
||||
node->Tag = NULL;
|
||||
|
||||
// Insert new node into hash table
|
||||
hashtable_insert(net->NodeHashTable, node->ID, nIdx);
|
||||
@@ -1996,7 +2013,6 @@ int DLLEXPORT EN_deletenode(EN_Project p, int index, int actionCode)
|
||||
*/
|
||||
{
|
||||
Network *net = &p->network;
|
||||
Quality *qual = &p->quality;
|
||||
|
||||
int i, nodeType, tankindex;
|
||||
Snode *node;
|
||||
@@ -2034,6 +2050,7 @@ int DLLEXPORT EN_deletenode(EN_Project p, int index, int actionCode)
|
||||
freedemands(node);
|
||||
free(node->S);
|
||||
free(node->Comment);
|
||||
free(node->Tag);
|
||||
|
||||
// Shift position of higher entries in Node & Coord arrays down one
|
||||
for (i = index; i <= net->Nnodes - 1; i++)
|
||||
@@ -2042,9 +2059,6 @@ int DLLEXPORT EN_deletenode(EN_Project p, int index, int actionCode)
|
||||
// ... update node's entry in the hash table
|
||||
hashtable_update(net->NodeHashTable, net->Node[i].ID, i);
|
||||
}
|
||||
|
||||
// Adjust index of water quality trace node
|
||||
if (qual->TraceNode > index) qual->TraceNode -= 1;
|
||||
|
||||
// If deleted node is a tank, remove it from the Tank array
|
||||
if (nodeType != EN_JUNCTION)
|
||||
@@ -3396,6 +3410,7 @@ int DLLEXPORT EN_addlink(EN_Project p, const char *id, int linkType,
|
||||
link->Rpt = 0;
|
||||
link->ResultIndex = 0;
|
||||
link->Comment = NULL;
|
||||
link->Tag = NULL;
|
||||
link->Vertices = NULL;
|
||||
|
||||
hashtable_insert(net->LinkHashTable, link->ID, n);
|
||||
@@ -3448,6 +3463,7 @@ int DLLEXPORT EN_deletelink(EN_Project p, int index, int actionCode)
|
||||
|
||||
// Remove link's comment and vertices
|
||||
free(link->Comment);
|
||||
free(link->Tag);
|
||||
freelinkvertices(link);
|
||||
|
||||
// Shift position of higher entries in Link array down one
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
Project: OWA EPANET
|
||||
Version: 2.2
|
||||
Version: 2.3
|
||||
Module: epanet2.c
|
||||
Description: implementation of the legacy EPANET API functions
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 09/28/2023
|
||||
Last Updated: 02/14/2025
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
@@ -127,6 +127,15 @@ int DLLEXPORT ENsetcomment(int object, int index, const char *comment)
|
||||
return EN_setcomment(_defaultProject, object, index, comment);
|
||||
}
|
||||
|
||||
int DLLEXPORT ENgettag(int object, int index, char *tag)
|
||||
{
|
||||
return EN_gettag(_defaultProject, object, index, tag);
|
||||
}
|
||||
|
||||
int DLLEXPORT ENsettag(int object, int index, const char *tag)
|
||||
{
|
||||
return EN_settag(_defaultProject, object, index, tag);
|
||||
}
|
||||
int DLLEXPORT ENgetcount(int object, int *count)
|
||||
{
|
||||
return EN_getcount(_defaultProject, object, count);
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
Project: OWA EPANET
|
||||
Version: 2.2
|
||||
Version: 2.3
|
||||
Module: funcs.h
|
||||
Description: prototypes of external functions called by various modules
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 06/26/2024
|
||||
Last Updated: 02/14/2025
|
||||
******************************************************************************
|
||||
*/
|
||||
#ifndef FUNCS_H
|
||||
@@ -54,6 +54,8 @@ int setcontrol(Project *, int, int, double, int, double, Scontrol *);
|
||||
|
||||
int getcomment(Network *, int, int, char *);
|
||||
int setcomment(Network *, int, int, const char *);
|
||||
int gettag(Network *, int, int, char *);
|
||||
int settag(Network *, int, int, const char *);
|
||||
|
||||
int namevalid(const char *);
|
||||
void getTmpName(char *);
|
||||
@@ -109,6 +111,7 @@ int reportdata(Project *);
|
||||
int timedata(Project *);
|
||||
int optiondata(Project *);
|
||||
int vertexdata(Project *);
|
||||
int tagdata(Project *);
|
||||
|
||||
// ------- RULES.C ------------------
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ Description: saves network data to an EPANET formatted text file
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 02/11/2025
|
||||
Last Updated: 02/14/2025
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
@@ -44,7 +44,6 @@ void saveauxdata(Project *pr, FILE *f)
|
||||
{
|
||||
int sect, newsect;
|
||||
char *tok;
|
||||
char write;
|
||||
char line[MAXLINE + 1];
|
||||
char s[MAXLINE + 1];
|
||||
FILE *InFile = pr->parser.InFile;
|
||||
@@ -79,7 +78,6 @@ void saveauxdata(Project *pr, FILE *f)
|
||||
{
|
||||
case _LABELS:
|
||||
case _BACKDROP:
|
||||
case _TAGS:
|
||||
fprintf(f, "\n%s", line);
|
||||
}
|
||||
}
|
||||
@@ -88,22 +86,15 @@ void saveauxdata(Project *pr, FILE *f)
|
||||
// Write line of auxilary data to file
|
||||
else
|
||||
{
|
||||
write = FALSE;
|
||||
switch (sect)
|
||||
{
|
||||
case _TAGS:
|
||||
if (*tok == ';' ||
|
||||
(match("NODE", tok) && findnode(&pr->network, strtok(NULL, SEPSTR))) ||
|
||||
(match("LINK", tok) && findlink(&pr->network, strtok(NULL, SEPSTR))))
|
||||
write = TRUE;
|
||||
break;
|
||||
case _LABELS:
|
||||
case _BACKDROP:
|
||||
write = TRUE; break;
|
||||
fprintf(f, "%s", line);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (write) fprintf(f, "%s", line);
|
||||
}
|
||||
}
|
||||
fclose(InFile);
|
||||
@@ -834,7 +825,23 @@ int saveinpfile(Project *pr, const char *fname)
|
||||
}
|
||||
else fprintf(f, "\n %-20sNO",field->Name);
|
||||
}
|
||||
|
||||
|
||||
// Write [TAGS] section
|
||||
fprintf(f, "\n\n");
|
||||
fprintf(f, s_TAGS);
|
||||
fprintf(f, "\n;;%-8s\t%-31s\t%s", "Object", "ID", "Tag");
|
||||
for (i = 1; i <= net->Nnodes; i++)
|
||||
{
|
||||
node = &net->Node[i];
|
||||
if (node->Tag == NULL || strlen(node->Tag) == 0) continue;
|
||||
fprintf(f, "\n %-8s\t%-31s\t%s", "NODE", node->ID, node->Tag);
|
||||
}
|
||||
for (i = 1; i <= net->Nlinks; i++)
|
||||
{
|
||||
link = &net->Link[i];
|
||||
if (link->Tag == NULL || strlen(link->Tag) == 0) continue;
|
||||
fprintf(f, "\n %-8s\t%-31s\t%s", "LINK", link->ID, link->Tag);
|
||||
}
|
||||
// Write [COORDINATES] section
|
||||
fprintf(f, "\n\n");
|
||||
fprintf(f, s_COORDS);
|
||||
|
||||
@@ -7,7 +7,7 @@ Description: reads and interprets network data from an EPANET input file
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 09/28/2023
|
||||
Last Updated: 02/19/2025
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
@@ -320,12 +320,12 @@ int newline(Project *pr, int sect, char *line)
|
||||
case _REPORT: return (reportdata(pr));
|
||||
case _TIMES: return (timedata(pr));
|
||||
case _OPTIONS: return (optiondata(pr));
|
||||
case _TAGS: return (tagdata(pr));
|
||||
case _COORDS: return (coordata(pr));
|
||||
case _VERTICES: return (vertexdata(pr));
|
||||
|
||||
// Data in these sections are not used for any computations
|
||||
case _LABELS:
|
||||
case _TAGS:
|
||||
case _BACKDROP:
|
||||
return (0);
|
||||
}
|
||||
|
||||
39
src/input3.c
39
src/input3.c
@@ -7,7 +7,7 @@ Description: parses network data from a line of an EPANET input file
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 02/11/2025
|
||||
Last Updated: 02/14/2025
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
@@ -2023,7 +2023,7 @@ int optionchoice(Project *pr, int n)
|
||||
int optionvalue(Project *pr, int n)
|
||||
/*
|
||||
**-------------------------------------------------------------
|
||||
** Input: *line = line read from input file
|
||||
** Input: n = index of last input token
|
||||
** Output: returns error code
|
||||
** Purpose: processes numerical value [OPTIONS] data
|
||||
** Formats:
|
||||
@@ -2170,7 +2170,42 @@ int optionvalue(Project *pr, int n)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tagdata(Project *pr)
|
||||
/*
|
||||
**-------------------------------------------------------------
|
||||
** Input: none
|
||||
** Output: returns error code
|
||||
** Purpose: processes [TAGS] data
|
||||
** Formats:
|
||||
** NODE id tag
|
||||
** LINK id tag
|
||||
**--------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
Network *net = &pr->network;
|
||||
Parser *parser = &pr->parser;
|
||||
|
||||
int j, n;
|
||||
|
||||
// Check for sufficient data
|
||||
n = parser->Ntokens;
|
||||
if (n < 3) return 201;
|
||||
|
||||
// First keyword is NODE
|
||||
if (match(parser->Tok[0], w_NODE))
|
||||
{
|
||||
if ((j = findnode(net, parser->Tok[1])) == 0) return setError(parser, 0, 203);
|
||||
xstrcpy(&net->Node[j].Tag, parser->Tok[2], MAXMSG);
|
||||
}
|
||||
|
||||
// First keyword is LINK
|
||||
else if (match(parser->Tok[0], w_LINK))
|
||||
{
|
||||
if ((j = findlink(net, parser->Tok[1])) == 0) return setError(parser, 0, 203);
|
||||
xstrcpy(&net->Link[j].Tag, parser->Tok[2], MAXMSG);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void changestatus(Network *net, int j, StatusType status, double y)
|
||||
/*
|
||||
**--------------------------------------------------------------
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
License: see LICENSE
|
||||
Last Updated: 08/02/2023
|
||||
|
||||
This module is based code by Steve Hill in Graphics Gems III,
|
||||
This module is based on code by Steve Hill in Graphics Gems III,
|
||||
David Kirk (ed.), Academic Press, Boston, MA, 1992
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
Project: OWA EPANET
|
||||
Version: 2.2
|
||||
Version: 2.3
|
||||
Module: project.c
|
||||
Description: project data management routines
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 02/08/2025
|
||||
Last Updated: 02/19/2025
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
@@ -448,11 +448,13 @@ int allocdata(Project *pr)
|
||||
pr->network.Node[n].D = NULL; // node demand
|
||||
pr->network.Node[n].S = NULL; // node source
|
||||
pr->network.Node[n].Comment = NULL;
|
||||
pr->network.Node[n].Tag = NULL;
|
||||
}
|
||||
for (n = 0; n <= pr->parser.MaxLinks; n++)
|
||||
{
|
||||
pr->network.Link[n].Vertices = NULL;
|
||||
pr->network.Link[n].Comment = NULL;
|
||||
pr->network.Link[n].Tag = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,6 +497,7 @@ void freedata(Project *pr)
|
||||
freedemands(&(pr->network.Node[j]));
|
||||
free(pr->network.Node[j].S);
|
||||
free(pr->network.Node[j].Comment);
|
||||
free(pr->network.Node[j].Tag);
|
||||
}
|
||||
free(pr->network.Node);
|
||||
}
|
||||
@@ -506,6 +509,7 @@ void freedata(Project *pr)
|
||||
{
|
||||
freelinkvertices(&pr->network.Link[j]);
|
||||
free(pr->network.Link[j].Comment);
|
||||
free(pr->network.Link[j].Tag);
|
||||
}
|
||||
}
|
||||
free(pr->network.Link);
|
||||
@@ -1361,6 +1365,68 @@ int setcomment(Network *network, int object, int index, const char *newcomment)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int gettag(Network *network, int object, int index, char *tag)
|
||||
//----------------------------------------------------------------
|
||||
// Input: object = a type of network object
|
||||
// index = index of the specified object
|
||||
// tag = the object's tag string
|
||||
// Output: error code
|
||||
// Purpose: gets the tag string assigned to an object.
|
||||
//----------------------------------------------------------------
|
||||
{
|
||||
char *currenttag;
|
||||
|
||||
// Get pointer to specified object's tag
|
||||
switch (object)
|
||||
{
|
||||
case NODE:
|
||||
if (index < 1 || index > network->Nnodes) return 251;
|
||||
currenttag = network->Node[index].Tag;
|
||||
break;
|
||||
case LINK:
|
||||
if (index < 1 || index > network->Nlinks) return 251;
|
||||
currenttag = network->Link[index].Tag;
|
||||
break;
|
||||
default:
|
||||
strcpy(tag, "");
|
||||
return 251;
|
||||
}
|
||||
// Copy the object's tag to the returned string
|
||||
if (currenttag) strcpy(tag, currenttag);
|
||||
else tag[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
int settag(Network *network, int object, int index, const char *newtag)
|
||||
//----------------------------------------------------------------
|
||||
// Input: object = a type of network object
|
||||
// index = index of the specified object
|
||||
// newtag = new tag string
|
||||
// Output: error code
|
||||
// Purpose: sets the tag string of an object.
|
||||
//----------------------------------------------------------------
|
||||
{
|
||||
char *tag;
|
||||
|
||||
switch (object)
|
||||
{
|
||||
case NODE:
|
||||
if (index < 1 || index > network->Nnodes) return 251;
|
||||
tag = network->Node[index].Tag;
|
||||
network->Node[index].Tag = xstrcpy(&tag, newtag, MAXMSG);
|
||||
return 0;
|
||||
|
||||
case LINK:
|
||||
if (index < 1 || index > network->Nlinks) return 251;
|
||||
tag = network->Link[index].Tag;
|
||||
network->Link[index].Tag = xstrcpy(&tag, newtag, MAXMSG);
|
||||
return 0;
|
||||
|
||||
default: return 251;
|
||||
}
|
||||
}
|
||||
|
||||
int namevalid(const char *name)
|
||||
//----------------------------------------------------------------
|
||||
// Input: name = name used to ID an object
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
Project: OWA EPANET
|
||||
Version: 2.2
|
||||
Version: 2.3
|
||||
Module: quality.c
|
||||
Description: implements EPANET's water quality engine
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 02/03/2020
|
||||
Last Updated: 02/14/2025
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
@@ -183,6 +183,7 @@ int initqual(Project *pr)
|
||||
qual->MassBalance.reacted = 0.0;
|
||||
qual->MassBalance.final = 0.0;
|
||||
qual->MassBalance.ratio = 0.0;
|
||||
qual->MassBalance.segCount = 0;
|
||||
return errcode;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
Project: OWA EPANET
|
||||
Version: 2.2
|
||||
Version: 2.3
|
||||
Module: qualroute.c
|
||||
Description: computes water quality transport over a single time step
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 08/02/2023
|
||||
Last Updated: 02/14/2025
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
@@ -183,6 +183,7 @@ void evalnodeinflow(Project *pr, int k, long tstep, double *volin,
|
||||
// ... recycle the used up segment
|
||||
seg->prev = qual->FreeSeg;
|
||||
qual->FreeSeg = seg;
|
||||
qual->MassBalance.segCount--;
|
||||
}
|
||||
|
||||
// ... otherwise just reduce this segment's volume
|
||||
@@ -691,4 +692,5 @@ void addseg(Project *pr, int k, double v, double c)
|
||||
if (qual->FirstSeg[k] == NULL) qual->FirstSeg[k] = seg;
|
||||
if (qual->LastSeg[k] != NULL) qual->LastSeg[k]->prev = seg;
|
||||
qual->LastSeg[k] = seg;
|
||||
qual->MassBalance.segCount++;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
Project: OWA EPANET
|
||||
Version: 2.2
|
||||
Version: 2.3
|
||||
Module: report.c
|
||||
Description: procedures for writing formatted text to a report file
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 07/22/2019
|
||||
Last Updated: 02/14/2025
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
@@ -501,6 +501,8 @@ void writemassbalance(Project *pr)
|
||||
writeline(pr, s1);
|
||||
snprintf(s1, MAXMSG, "Mass Ratio: %-.5f", qual->MassBalance.ratio);
|
||||
writeline(pr, s1);
|
||||
snprintf(s1, MAXMSG, "Total Segments: %d", qual->MassBalance.segCount);
|
||||
writeline(pr, s1);
|
||||
snprintf(s1, MAXMSG, "================================\n");
|
||||
writeline(pr, s1);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 06/15/2024
|
||||
Last Updated: 02/14/2025
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
@@ -398,6 +398,7 @@ typedef struct // Node Object
|
||||
int ResultIndex; // saved result index
|
||||
NodeType Type; // node type
|
||||
char *Comment; // node comment
|
||||
char *Tag; // optional category tag
|
||||
} Snode;
|
||||
|
||||
typedef struct // Link Object
|
||||
@@ -421,6 +422,7 @@ typedef struct // Link Object
|
||||
int Rpt; // reporting flag
|
||||
int ResultIndex; // saved result index
|
||||
char *Comment; // link comment
|
||||
char *Tag; // optional category tag
|
||||
} Slink;
|
||||
|
||||
typedef struct // Tank Object
|
||||
@@ -549,6 +551,7 @@ typedef struct // Mass Balance Components
|
||||
double reacted; // mass reacted in system
|
||||
double final; // final mass in system
|
||||
double ratio; // ratio of mass added to mass lost
|
||||
int segCount; // total number of pipe segments used
|
||||
} SmassBalance;
|
||||
|
||||
typedef struct
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
Project: OWA EPANET
|
||||
Version: 2.2
|
||||
Version: 2.3
|
||||
Module: test_node.cpp
|
||||
Description: Tests EPANET toolkit api functions
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 03/21/2019
|
||||
Last Updated: 02/14/2025
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
@@ -255,17 +255,22 @@ BOOST_FIXTURE_TEST_CASE(test_node_comments, FixtureOpenClose)
|
||||
{
|
||||
int index;
|
||||
char comment[EN_MAXMSG + 1];
|
||||
char tag[EN_MAXMSG + 1];
|
||||
|
||||
// Add comments to selected objects
|
||||
error = EN_getnodeindex(ph, (char *)"11", &index);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_setcomment(ph, EN_NODE, index, (char *)"J11");
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_settag(ph, EN_NODE, index, (char *)"J11_Tag");
|
||||
BOOST_REQUIRE(error == 0);
|
||||
|
||||
error = EN_getnodeindex(ph, (char *)"23", &index);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_setcomment(ph, EN_NODE, index, (char *)"Junc23");
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_settag(ph, EN_NODE, index, (char *)"Junc23_Tag");
|
||||
BOOST_REQUIRE(error == 0);
|
||||
|
||||
// Check comments
|
||||
error = EN_getnodeindex(ph, (char *)"11", &index);
|
||||
@@ -273,18 +278,25 @@ BOOST_FIXTURE_TEST_CASE(test_node_comments, FixtureOpenClose)
|
||||
error = EN_getcomment(ph, EN_NODE, index, comment);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
BOOST_CHECK(check_string(comment, (char *)"J11"));
|
||||
error = EN_gettag(ph, EN_NODE, index, tag);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
BOOST_CHECK(check_string(tag, (char *)"J11_Tag"));
|
||||
|
||||
error = EN_getnodeindex(ph, (char *)"23", &index);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_getcomment(ph, EN_NODE, index, comment);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
BOOST_CHECK(check_string(comment, (char *)"Junc23"));
|
||||
error = EN_gettag(ph, EN_NODE, index, tag);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
BOOST_CHECK(check_string(tag, (char *)"Junc23_Tag"));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(test_replace_comment, FixtureOpenClose)
|
||||
{
|
||||
int index;
|
||||
char comment[EN_MAXMSG + 1];
|
||||
char tag[EN_MAXMSG + 1];
|
||||
|
||||
// Replace short comment with longer one and vice versa
|
||||
error = EN_getnodeindex(ph, (char *)"11", &index);
|
||||
@@ -295,11 +307,23 @@ BOOST_FIXTURE_TEST_CASE(test_replace_comment, FixtureOpenClose)
|
||||
BOOST_REQUIRE(error == 0);
|
||||
BOOST_CHECK(check_string(comment, (char *)"Junction11"));
|
||||
|
||||
error = EN_settag(ph, EN_NODE, index, (char *)"Junction11_Tag");
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_gettag(ph, EN_NODE, index, tag);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
BOOST_CHECK(check_string(tag, (char *)"Junction11_Tag"));
|
||||
|
||||
error = EN_setcomment(ph, EN_NODE, index, (char *)"J11");
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_getcomment(ph, EN_NODE, index, comment);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
BOOST_CHECK(check_string(comment, (char *)"J11"));
|
||||
|
||||
error = EN_settag(ph, EN_NODE, index, (char *)"J11_Tag");
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_gettag(ph, EN_NODE, index, tag);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
BOOST_CHECK(check_string(tag, (char *)"J11_Tag"));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(test_save_comment, FixtureOpenClose)
|
||||
@@ -311,11 +335,15 @@ BOOST_FIXTURE_TEST_CASE(test_save_comment, FixtureOpenClose)
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_setcomment(ph, EN_NODE, index, (char *)"J11");
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_settag(ph, EN_NODE, index, (char *)"J11_Tag");
|
||||
BOOST_REQUIRE(error == 0);
|
||||
|
||||
error = EN_getnodeindex(ph, (char *)"23", &index);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_setcomment(ph, EN_NODE, index, (char *)"Junc23");
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_settag(ph, EN_NODE, index, (char *)"Junc23_Tag");
|
||||
BOOST_REQUIRE(error == 0);
|
||||
|
||||
error = EN_saveinpfile(ph, DATA_PATH_TMP);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
@@ -325,6 +353,7 @@ BOOST_AUTO_TEST_CASE(test_reopen_comment, * boost::unit_test::depends_on("node_c
|
||||
{
|
||||
int error, index;
|
||||
char comment[EN_MAXMSG + 1];
|
||||
char tag[EN_MAXMSG + 1];
|
||||
|
||||
// Create & load a project
|
||||
EN_Project ph = NULL;
|
||||
@@ -340,12 +369,18 @@ BOOST_AUTO_TEST_CASE(test_reopen_comment, * boost::unit_test::depends_on("node_c
|
||||
error = EN_getcomment(ph, EN_NODE, index, comment);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
BOOST_CHECK(check_string(comment, (char *)"J11"));
|
||||
error = EN_gettag(ph, EN_NODE, index, tag);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
BOOST_CHECK(check_string(tag, (char *)"J11_Tag"));
|
||||
|
||||
error = EN_getnodeindex(ph, (char *)"23", &index);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_getcomment(ph, EN_NODE, index, comment);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
BOOST_CHECK(check_string(comment, (char *)"Junc23"));
|
||||
error = EN_gettag(ph, EN_NODE, index, tag);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
BOOST_CHECK(check_string(tag, (char *)"Junc23_Tag"));
|
||||
|
||||
// Close project
|
||||
EN_close(ph);
|
||||
|
||||
Reference in New Issue
Block a user