diff --git a/include/epanet2.bas b/include/epanet2.bas index 6ddb0ad..2f4eb5f 100644 --- a/include/epanet2.bas +++ b/include/epanet2.bas @@ -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 diff --git a/include/epanet2.cs b/include/epanet2.cs index 0327c4d..7d1a12d 100644 --- a/include/epanet2.cs +++ b/include/epanet2.cs @@ -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")] diff --git a/include/epanet2.def b/include/epanet2.def index d3472c1..12c4bd7 100644 --- a/include/epanet2.def +++ b/include/epanet2.def @@ -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 diff --git a/include/epanet2.h b/include/epanet2.h index fc99a06..7022c34 100644 --- a/include/epanet2.h +++ b/include/epanet2.h @@ -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); /******************************************************************** diff --git a/include/epanet2.pas b/include/epanet2.pas index 6f2e8da..a66a0bd 100644 --- a/include/epanet2.pas +++ b/include/epanet2.pas @@ -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 diff --git a/include/epanet2.vb b/include/epanet2.vb index a7b3179..a73f28c 100644 --- a/include/epanet2.vb +++ b/include/epanet2.vb @@ -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 diff --git a/include/epanet2_2.h b/include/epanet2_2.h index 81f2f9f..287c9c6 100644 --- a/include/epanet2_2.h +++ b/include/epanet2_2.h @@ -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. diff --git a/include/epanet2_enums.h b/include/epanet2_enums.h index 4fc7755..fdfd2cd 100644 --- a/include/epanet2_enums.h +++ b/include/epanet2_enums.h @@ -9,7 +9,7 @@ Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE - Last Updated: 07/17/2023 + Last Updated: 02/14/2025 ****************************************************************************** */ diff --git a/src/epanet.c b/src/epanet.c index cccd107..3b6a0d7 100644 --- a/src/epanet.c +++ b/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 diff --git a/src/epanet2.c b/src/epanet2.c index 435a571..2bbc75f 100644 --- a/src/epanet2.c +++ b/src/epanet2.c @@ -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); diff --git a/src/funcs.h b/src/funcs.h index 87a6be2..2fae94b 100755 --- a/src/funcs.h +++ b/src/funcs.h @@ -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 ------------------ diff --git a/src/inpfile.c b/src/inpfile.c index b91e666..da69fd0 100644 --- a/src/inpfile.c +++ b/src/inpfile.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); diff --git a/src/input2.c b/src/input2.c index f1ce8bf..9303840 100644 --- a/src/input2.c +++ b/src/input2.c @@ -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/14/2025 ****************************************************************************** */ @@ -320,6 +320,7 @@ 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)); diff --git a/src/input3.c b/src/input3.c index 3d1a89c..281c09b 100644 --- a/src/input3.c +++ b/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) /* **-------------------------------------------------------------- diff --git a/src/mempool.c b/src/mempool.c index 81087eb..f95ac29 100755 --- a/src/mempool.c +++ b/src/mempool.c @@ -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 ****************************************************************************** */ diff --git a/src/project.c b/src/project.c index 5e71204..217e633 100644 --- a/src/project.c +++ b/src/project.c @@ -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/14/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); @@ -1357,6 +1361,64 @@ int setcomment(Network *network, int object, int index, const char *newcomment) network->Curve[index].Comment = xstrcpy(&comment, newcomment, MAXMSG); return 0; + +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; } } diff --git a/src/quality.c b/src/quality.c index 0739c15..79642a9 100644 --- a/src/quality.c +++ b/src/quality.c @@ -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; } diff --git a/src/qualroute.c b/src/qualroute.c index 144be67..30294f5 100644 --- a/src/qualroute.c +++ b/src/qualroute.c @@ -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++; } diff --git a/src/report.c b/src/report.c index 25bb137..676b7d1 100644 --- a/src/report.c +++ b/src/report.c @@ -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); } diff --git a/src/types.h b/src/types.h index 30fd64e..53b97b1 100755 --- a/src/types.h +++ b/src/types.h @@ -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