From baa7ba93577be3489c450d6b9cacbc43f30ed732 Mon Sep 17 00:00:00 2001 From: Lew Rossman Date: Wed, 2 Jan 2019 11:04:34 -0500 Subject: [PATCH] Update ReleaseNotes2_2.md --- ReleaseNotes2_2.md | 196 +++++++++++++++++++++++++++------------------ 1 file changed, 119 insertions(+), 77 deletions(-) diff --git a/ReleaseNotes2_2.md b/ReleaseNotes2_2.md index 3996833..19d42eb 100644 --- a/ReleaseNotes2_2.md +++ b/ReleaseNotes2_2.md @@ -1,11 +1,10 @@ -Release Notes for EPANET 2.2 (Draft) +Release Notes for EPANET 2.2 (Draft) ============================ - This document describes the changes and updates that have been made to version 2.2 of EPANET. ## Thread-Safe API Functions -A duplicate set of the version 2.1 API functions has been provided that allow multiple EPANET projects to be analyzed concurrently in a thread-safe manner. These functions maintain the same name as the original but use a `EN_` prefix instead of `EN`. In addition, the first argument to each of these functions is a handle that identifies the network data for the particular project being analyzed. For example, instead of writing: +A duplicate set of API functions has been provided that allow multiple EPANET projects to be analyzed concurrently in a thread-safe manner. These functions maintain the same name as the original but use a `EN_` prefix instead of `EN`. In addition, the first argument to each of these functions is a handle that identifies the particular project being analyzed. For example, instead of writing: `ENgetnodevalue(nodeIndex, EN_ELEVATION, &elev)` @@ -13,14 +12,14 @@ one would use: `EN_getnodevalue(ph, nodeIndex, EN_ELEVATION, &elev)` -where `ph` is the handle assigned to the project. +where `ph` is the handle assigned to the project. Two new functions have been added to the API to manage the creation and deletion of project handles. `EN_createproject` creates a new project along with its handle, while `EN_deleteproject` deletes a project. An example of using the thread-safe version of the API is shown below: ``` -#include "epanet2.h" +#include "epanet2_2.h" int runEpanet(char *finp, char *frpt) { - EN_ProjectHandle ph = 0; + EN_Project ph = 0; int err; err = EN_createproject(&ph); if (err) return err; @@ -32,6 +31,35 @@ int runEpanet(char *finp, char *frpt) return err; } ``` +Prototypes of the thread-safe functions appear in the `epanet2_2.h` header file while `epanet2.h` contains prototypes of the legacy-style API functions. The enumerated constants used with both types of functions have been moved to `epanet2_enums.h`. + +## Network Building By Code + +API users now have the ability to build a complete EPANET network model using just function calls, without the need to open an EPANET-formatted input file. All types of network objects can be created and have their properties set using these calls, including both simple and rule-based controls. Here is an example of building a simple 2-node, 1-pipe network just through code: +``` +#include "epanet2_2.h" +int buildandrunEpanet(char *frpt) +{ + EN_Project ph = 0; + int err; + err = EN_createproject(&ph); + if (err) return err; + EN_init(ph, frpt, "", EN_GPM, EN_HW); + EN_addnode(ph, "J1, EN_JUNCTION); + EN_setjuncdata(ph, 1, 710, 500, ""); //elev, demand + EN_addnode(ph, "R1", EN_RESERVOIR); + EN_setnodevalue(ph, 2, EN_ELEVATION, 800); + EN_addlink(ph, "P1", EN_PIPE, "R1", "J1"); + EN_setpipedata(ph, 1, 5280, 14, 100, 0); // length, diam, C-factor + EN_setreport(ph, "NODES ALL"); + err = EN_solveH(ph); + if (!err) err = EN_report(ph); + EN_close(ph); + EN_deleteproject(&ph); + return err; +} +``` +Instead of using `EN_open` to load data from a file, `EN_init` is used to initialize a project with the names of its report and binary files, and its flow units and head loss formula. The legacy-style API has a complementary set of functions for building networks from code. ## Additional Convergence Parameters @@ -44,16 +72,19 @@ Two new analysis options have been added to provide more rigorous convergence cr These new parameters augment the current `EN_ACCURACY` option which always remains in effect. In addition, both `EN_HEADERROR` and `EN_FLOWCHANGE` can be used as parameters in the `ENgetstatistic` (or `EN_getstatistic`) function to retrieve their computed values (even when their option values are 0) after a hydraulic solution has been completed. ## Improved Linear Solver Routine + EPANET's hydraulic solver requires solving a system of linear equations over a series of iterations until a set of convergence criteria are met. The coefficient matrix of this linear system is square and symmetric. It has a row for each network node and a non-zero off-diagonal coefficient for each link. The numerical effort needed to solve the linear system can be reduced if the nodes are re-ordered so that the non-zero coefficients cluster more tightly around the diagonal. EPANET's original node re-ordering scheme has been replaced by the more powerful **Multiple Minimum Degree (MMD)** algorithm. On a series of eight networks ranging in size from 7,700 to 100,000 nodes **MMD** reduced the solution time for a single period (steady state) hydraulic analysis by an average of 58%. ## Improved Handling of Near-Zero Flows + EPANET's hydraulic solver can generate an ill-conditioned solution matrix when pipe flows approach zero unless some adjustment is made (i.e., as a pipe's flow approaches 0 its head loss gradient also approaches 0 causing its reciprocal, which is used to form the solution matrix's coefficients, to approach infinity). EPANET 2.0 used an arbitrary cutoff on head loss gradient to prevent it from becoming 0. This approach doesn't allow a pipe to follow any head loss v. flow relation in the region below the cutoff and can produce incorrect solutions for some networks (see [Estrada et al., 2009](https://ascelibrary.org/doi/full/10.1061/%28ASCE%29IR.1943-4774.0000100)). The hydraulic solver has been modified to use a linear head loss v. flow relation for flows approaching zero. For the Darcy-Weisbach equation, the linear Hagen-Poiseuille formula is used for laminar flow where the Reynolds Number is <= 2000. For the Hazen-Williams and Chezy-Manning equations, a flow limit `Qa` is established for each pipe, equal to the flow that produces the EPANET 2 gradient cutoff. For flows below this a linear head loss relation is used between 0 and the head loss at `Qa` and the gradient always equals the cutoff. EPANET 2.2 is now able to correctly solve the examples presented in Estrada et al. (2009) as well as those in [Gorev et al., (2013)](https://ascelibrary.org/doi/10.1061/%28ASCE%29HY.1943-7900.0000694) and [Elhay and Simpson (2011)](https://ascelibrary.org/doi/10.1061/%28ASCE%29HY.1943-7900.0000411). ## Pressure Dependent Demands + EPANET has always employed a Demand Driven Analysis (**DDA**) when modeling network hydraulics. Under this approach nodal demands at a given point in time are fixed values that must be delivered no matter what nodal heads and link flows are produced by a hydraulic solution. This can result in situations where required demands are satisfied at nodes that have negative pressures - a physical impossibility. To address this issue EPANET has been extended to use a Pressure Driven Analysis (**PDA**) if so desired. Under **PDA**, the demand *D* delivered at a node depends on the node's available pressure *P* according to: @@ -64,7 +95,6 @@ where *Df* is the full demand required, *Pmin* is the pres To implement pressure driven analysis four new parameters have been added to the [OPTIONS] section of the EPANET input file: - | Parameter | Description | Default | |--|--|--| | DEMAND MODEL | either DDA or PDA | DDA | @@ -89,6 +119,7 @@ for the thread-safe API. Some additional points regarding the new **PDA** option - *Pmin* is allowed to equal to *Preq*. This condition can be used to find a solution that results in the smallest amount of demand reductions needed to insure that no node delivers positive demand at a pressure below *Pmin*. ## Improved Water Quality Mass Balance + As described by [Davis et al. (2018)](https://www.drink-water-eng-sci.net/11/25/2018/dwes-11-25-2018.pdf) EPANET's water quality simulations can result in some significant mass balance errors when modeling short term mass injections (errors are much smaller for continuous source flows). The entire water quality engine has been re-written to eliminate these errors. It still uses the Lagrangian Time Driven transport method but now analyzes each network node in topologically sorted order rather than in arbitrary order. A Mass Balance Report now appears the end of a simulation's Status Report that lists the various components (inflow, outflow, reaction) that comprise the network's overall mass balance. In addition `EN_MASSBALANCE` can be used as a parameter in the `ENgetstatistic` (or `EN_getstatistic`) function to retrieve the Mass Balance Ratio (Total Outflow Mass / Total Inflow Mass) at any point during a water quality simulation. @@ -106,98 +137,109 @@ Mass balance ratio (MBR) results for two of the networks analyzed by Davis et al Both network files are available [here](https://doi.org/10.23719/1375314). -## Code Changes - - - The header file `vars.h` containing global variables has been eliminated. Instead a number of new structures incorporating these variables has been added to `types.h`. These structures have been incorporated into the new `EN_Project` structure, also defined in `types.h`, which gets passed into each of the thread-safe API functions as a pointer. - - Each of the legacy API functions now simply calls its thread-safe counterpart passing in a pointer to a default global`EN_Project` variable that is declared in `types.h`. - - Throughout all code modules, global variables that were previously accessed through `vars.h` are now accessed using the `EN_Project` pointer that is passed into the functions where the variables appear. - - The exceedingly long `hydraul.c` file has been split into four separate files: - - `hydraul.c` now contains just the code needed to initialize a hydraulic analysis, set demands and control actions at each time step, and determine the length of the next time step to take. - - `hydsolver.c` implements EPANET's hydraulic solver at a single point in time. - - `hydcoeffs.c` computes values of the matrix coefficients (derived from link head losses and their gradients) used by the hydraulic solver. - - `hydstatus.c` checks for status changes in valves and pumps as requested by the hydraulic solver. - - The Multiple Minimum Degree re-ordering algorithm appears in a new file named `genmmd.c`. This is 1990's legacy code that is readily available on the web and can be found in several linear equation solver libraries. - - The original `quality.c` file has also been split into three separate files: - - `quality.c` initializes the quality solver and supervises the quality calculations over each simulation time step. - - `qualreact.c` reacts the quality constituent within each pipe and tank over a single time step and also implements the various tank mixing models. - - `qualroute.c` topologically sorts the network's nodes when flow directions change and implements the Lagrangian Time Driven transport algorithm over a single time step. - -## General changes - - Read and write demand categories names - ## New API functions |Function|Description| |--|--| -|`ENinit`|Initializes an EPANET session| -|`ENsetflowunits`|Sets the flow units| -|`ENgetdemandmodel`|Retrieves the type of demand model in use and its parameters| -|`ENsetdemandmodel`|Sets the type of demand model to use and its parameters| -|`ENgetdemandname`|Sets the node's demand name for a category| -|`ENsetdemandname`|Sets the node's demand name for a category| -|`ENsetdemandpattern`|Sets the index of the demand pattern assigned to a node for a category index| -|`ENsetheadcurveindex`|Sets the curve id for a specified pump index| -|`ENgetrule`|Gets the number of premises, true actions, and false actions and the priority of an existing rule-based control| -|`ENsetrulepriority`|Sets the priority of the existing rule-based control| -|`ENgetpremise`|Gets the components of a premise/condition in an existing rule-based control| -|`ENsetpremise`|Sets the components of a premise/condition in an existing rule-based control| -|`ENsetpremiseindex`|Sets the index of an object in a premise of an existing rule-based control| -|`ENsetpremisestatus`|Sets the status in a premise of an existing rule-based control| -|`ENsetpremisevalue`|Sets the value in a premise of an existing rule-based control| -|`ENgetthenaction`|Get the components of a THEN action in a rule-based control| -|`ENsetthenaction`|Set the components of a THEN action in a rule-based control| -|`ENgetelseaction`|Get the components of an ELSE action in a rule-based control| -|`ENsetelseaction`|Set the components of an ELSE action in a rule-based control| -|`ENgetruleID`|Returns the ID of a rule| -|`ENgetcurvetype`|Get the type of a curve| -|`ENsetlinknodes`|Set the indexes of a link's start- and end-nodes| -|`ENsetlinktype`|Set the link type code for a specified link| -|`ENaddnode`|Adds a new node| -|`ENaddlink`|Adds a new link| -|`ENaddcontrol`|Specify parameters to add a new simple control| -|`ENaddrule`|Add a new control rule to the project| -|`ENdeletenode`|Deletes a node| -|`ENdeletelink`|Deletes a link| -|`ENdeletecontrol`|Delete an existing simple control| -|`ENdeleterule`|Delete a rule-based control| -|`ENsetnodeid`|Change the ID name for a node| -|`ENsetlinkid`|Change the ID name for a link| +|`EN_createproject` | creates a new EPANET project | +|`EN_deleteproject` | deletes an EPANET project | +|`EN_init`|Initializes an EPANET project| +|`EN_setflowunits`|Sets the project's flow units| +|`EN_addnode`|Adds a new node to a project| +|`EN_addlink`|Adds a new link to a project| +|`EN_addcontrol`|Adds a new simple control to a project| +|`EN_addrule`|Adds a new control rule to a project| +|`EN_deletenode`|Deletes a node from the project| +|`EN_deletelink`|Deletes a link from the project| +|`EN_deletecontrol`|Deletes a simple control from the project| +|`EN_deleterule`|Deletes a rule-based control from the project| +|`EN_setnodeid`|Changes the ID name for a node| +|`EN_setjuncdata` |Sets values for a junction's parameters | +|`EN_settankdata` |Sets values for a tank's parameters| +|`EN_setlinkid`|Changes the ID name for a link| +|`EN_setlinknodes`|Sets a link's start- and end-nodes| +|`EN_setlinktype`|Changes the type of a specific link| +|`EN_setpipedata`|Sets values for a pipe's parameters| +|`EN_getdemandmodel`|Retrieves the type of demand model in use | +|`EN_setdemandmodel`|Sets the type of demand model to use| +|`EN_getdemandname`|Gets the name of a node's demand category| +|`EN_setdemandname`|Sets the name of a node's demand category| +|`EN_setdemandpattern`|Assigns a time pattern to a node's demand category | +|`EN_getcurvetype`|Gets a curve's type| +|`EN_setheadcurveindex`|Sets the index of a head curve used by a pump | +|`EN_getrule`|Gets the number of elements in a rule-based control | +|`EN_getruleid` | Gets the name assigned to a rule-based control | +|`EN_getpremise`|Gets the contents of a premise in a rule-based control| +|`EN_setpremise`|Sets the contents of a premise in a rule-based control| +|`EN_setpremiseindex`|Sets the index of an object in a premise of a rule-based control| +|`EN_setpremisestatus`|Sets the status of an object in a premise of a rule-based control| +|`EN_setpremisevalue`|Sets the value of a property in a premise of a rule-based control| +|`EN_getthenaction`|Gets the contents of a THEN action in a rule-based control| +|`EN_setthenaction`|Sets the contents of a THEN action in a rule-based control| +|`EN_getelseaction`|Gets the contents of an ELSE action in a rule-based control| +|`EN_setelseaction`|Set the contents of an ELSE action in a rule-based control| +|`EN_setrulepriority`|Sets the priority of a rule-based control| +In addition to these new functions, a tank's volume curve `EN_VOLCURVE` can be set using `EN_setnodevalue` and `EN_setlinkvalue` can now be used to set the following pump properties: + - `EN_PUMP_POWER` (constant power rating) + - `EN_PUMP_HCURVE` (head characteristic curve) + - `EN_PUMP_ECURVE` (efficiency curve) + - `EN_PUMP_ECOST` (average energy price) + - `EN_PUMP_EPAT` (energy pricing pattern) + - `EN_LINKPATTERN` (speed setting pattern) + +Access to the following global energy options have been added to `EN_getoption` and `EN_setoption`: + - `EN_GLOBALEFFIC` (global pump efficiency) + - `EN_GLOBALPRICE` (global average energy price per kW-Hour) + - `EN_GLOBALPATTERN` (global energy price pattern) + - `EN_DEMANDCHARGE` (price per maximum kW of energy consumption) + +## New API Constants -## API Extensions (additional definitions) ### Link value types: -- `EN_EFFICIENCY` -- `EN_HEADCURVE` -- `EN_EFFICIENCYCURVE` -- `EN_PRICEPATTERN` -- `EN_STATE` -- `EN_CONST_POWER` -- `EN_SPEED` +- `EN_PUMP_STATE` +- `EN_PUMP_EFFIC` +- `EN_PUMP_POWER` +- `EN_PUMP_HCURVE` +- `EN_PUMP_ECURVE` +- `EN_PUMP_ECOST` +- `EN_PUMP_EPAT` + ### Count types: - `EN_RULECOUNT` + ### Head loss formula: - `EN_HW` - `EN_DW` - `EN_CM` -### Option types: + +### Hydraulic option types: - `EN_HEADERROR` - `EN_FLOWCHANGE` - - `EN_DEMANDDEFPAT` + - `EN_DEFDEMANDPAT` - `EN_HEADLOSSFORM` -### Time statistic types: + - `EN_GLOBALEFFIC` + - `EN_GLOBALPRICE` + - `EN_GLOBALPATTERN` + - `EN_DEMANDCHARGE` + +### Simulation statistic types: - `EN_MAXHEADERROR` - `EN_MAXFLOWCHANGE` - `EN_MASSBALANCE` - ### Action code types: + +### Action code types: - `EN_UNCONDITIONAL` - `EN_CONDITIONAL` + ### Curve types: - - `EN_V_CURVE` - - `EN_P_CURVE` - - `EN_E_CURVE` - - `EN_H_CURVE` - - `EN_G_CURVE` + - `EN_VOLUME_CURVE` + - `EN_PUMP_CURVE` + - `EN_EFFIC_CURVE` + - `EN_HLOSS_CURVE` + - `EN_GENERIC_CURVE` + ### Demand model types: - `EN_DDA` - `EN_PDA` ## Authors contributing to this release: - - List item \ No newline at end of file + - List item