├── R ├── epanet2toolkit.r ├── title.r ├── pumps.r ├── util.r ├── enums.r ├── codes.r ├── coords.r ├── epanet.r ├── curves.r └── options.r ├── .Rbuildignore ├── LICENSE ├── .gitignore ├── tests ├── testthat.r └── testthat │ ├── test_title.r │ ├── test_flowunits.r │ ├── test_util.r │ ├── test_ENclose.r │ ├── test_codes.r │ ├── test_ENopen.r │ ├── test_epanet_example_2.r │ ├── test_curves.r │ ├── test_coords.r │ ├── test_pumps.r │ ├── test_call.r │ ├── test_epanet_example_3.r │ ├── test_controls.R │ ├── test_links22.r │ ├── test_times.r │ ├── test_rules.r │ ├── test_options.r │ ├── test_epanet.r │ ├── test_demand.r │ └── test_Rtoolkit.r ├── inst ├── CITATION └── COPYRIGHTS ├── man ├── ENgettitle.Rd ├── ENstepQ.Rd ├── ENclearreport.Rd ├── ENdeletepattern.Rd ├── ENgetcurvetype.Rd ├── ENsetnodeid.Rd ├── ENgetdemandmodel.Rd ├── ENsetlinkid.Rd ├── ENsetreport.Rd ├── ENdeletecurve.Rd ├── ENdeleterule.Rd ├── ENgetpumptype.Rd ├── ENgetvertexcount.Rd ├── ENsetstatusreport.Rd ├── ENaddrule.Rd ├── ENgeterror.Rd ├── ENsetvertices.Rd ├── ENgetcurveid.Rd ├── ENgetheadcurveindex.Rd ├── ENgetnumdemands.Rd ├── ENgetruleID.Rd ├── ENdeletecontrol.Rd ├── ENgetcurveindex.Rd ├── ENgetvertex.Rd ├── ENcloseQ.Rd ├── ENgetcurvelen.Rd ├── ENaddcurve.Rd ├── ENgetaveragepatternvalue.Rd ├── ENaddpattern.Rd ├── ENsetcurveid.Rd ├── ENdeletedemand.Rd ├── ENsetheadcurveindex.Rd ├── ENsetrulepriority.Rd ├── ENsaveinpfile.Rd ├── ENsetpatternid.Rd ├── ENsaveH.Rd ├── ENgetdemandindex.Rd ├── ENaddnode.Rd ├── ENgetdemandname.Rd ├── ENgetcurvevalue.Rd ├── ENsetlinknodes.Rd ├── ENgetbasedemand.Rd ├── ENgetcoord.Rd ├── ENgetqualinfo.Rd ├── ENgetversion.Rd ├── ENsetbasedemand.Rd ├── ENsetdemandname.Rd ├── ENsetpremisevalue.Rd ├── ENsetcurvevalue.Rd ├── ENadddemand.Rd ├── ENsetpremiseindex.Rd ├── ENcloseH.Rd ├── ENgetrule.Rd ├── ENsetflowunits.Rd ├── ENsetdemandmodel.Rd ├── ENopenQ.Rd ├── ENsetpremisestatus.Rd ├── ENcopyreport.Rd ├── ENreport.Rd ├── ENsolveH.Rd ├── ENsolveQ.Rd ├── ENdeletelink.Rd ├── ENgetthenaction.Rd ├── ENsetjuncdata.Rd ├── ENrunQ.Rd ├── ENsetthenaction.Rd ├── ENusehydfile.Rd ├── ENsetcoord.Rd ├── ENdeletenode.Rd ├── ENgetlinkindex.Rd ├── ENgetelseaction.Rd ├── ENsetpatternvalue.Rd ├── ENclose.Rd ├── ENgetnodeindex.Rd ├── ENsetelseaction.Rd ├── ENgetlinkid.Rd ├── ENnextQ.Rd ├── ENaddcontrol.Rd ├── ENgetpatternindex.Rd ├── ENsetdemandpattern.Rd ├── ENgetpatternid.Rd ├── ENgetpatternlen.Rd ├── ENgetnodeid.Rd ├── ENgetdemandpattern.Rd ├── ENresetreport.Rd ├── ENgetresultindex.Rd ├── ENgetcontrol.Rd ├── ENsetlinktype.Rd ├── ENepanet.Rd ├── ENsettankdata.Rd ├── ENgetlinknodes.Rd ├── ENinitQ.Rd ├── ENgetnodetype.Rd ├── ENsetoption.Rd ├── ENgetpremise.Rd ├── ENinit.Rd ├── ENsavehydfile.Rd ├── ENgetoption.Rd ├── ENopenH.Rd ├── ENsetpremise.Rd ├── ENgetpatternvalue.Rd ├── ENgetstatistic.Rd ├── ENsetpattern.Rd ├── ENaddlink.Rd ├── ENrunH.Rd ├── ENopen.Rd ├── ENgetcount.Rd ├── ENgetlinktype.Rd ├── ENgetqualtype.Rd ├── ENgetflowunits.Rd ├── ENnextH.Rd ├── ENsetqualtype.Rd ├── epanet2toolkit-package.Rd ├── ENinitH.Rd ├── ENsettimeparam.Rd ├── ENgettimeparam.Rd ├── ENsetnodevalue.Rd ├── ENgetnodevalue.Rd ├── ENgetlinkvalue.Rd ├── ENsetlinkvalue.Rd └── ENsetcontrol.Rd ├── src ├── mempool.h ├── cstr_helper.h ├── hash.h ├── errormanager.h ├── cstr_helper.c ├── toolkit.h ├── filemanager.h ├── errormanager.c ├── mempool.c ├── enumstxt.h └── hash.c ├── DESCRIPTION ├── .github └── workflows │ └── rhub.yaml └── README.md /R/epanet2toolkit.r: -------------------------------------------------------------------------------- 1 | #' @keywords internal 2 | "_PACKAGE" 3 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | travis.yml$ 2 | ^\.so$ 3 | ^\.o$ 4 | Makefile 5 | .github 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2020 2 | COPYRIGHT HOLDER: IBM Corp., Open Water Analytics 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.so 2 | *.o 3 | *.dll 4 | *.swp 5 | *.rpt 6 | *.gz 7 | .project 8 | *.bin 9 | -------------------------------------------------------------------------------- /tests/testthat.r: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2017 4 | # Author: Ernesto Arandia & Bradley J Eck 5 | # 6 | #***************************************** 7 | 8 | 9 | 10 | 11 | library(testthat) 12 | library(epanet2toolkit) 13 | 14 | test_check("epanet2toolkit") 15 | -------------------------------------------------------------------------------- /inst/CITATION: -------------------------------------------------------------------------------- 1 | bibentry('article', 2 | year="2018", 3 | title = "An R package for EPANET simulations", 4 | pages = "59-63", 5 | doi = "10.1016/j.envsoft.2018.05.016", 6 | author = "Ernesto Arandia and Bradley J. Eck", 7 | journal = "Environmental Modeling and Software", 8 | volume = "107", 9 | publisher = "Elsevier") 10 | -------------------------------------------------------------------------------- /man/ENgettitle.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/title.r 3 | \name{ENgettitle} 4 | \alias{ENgettitle} 5 | \title{ENgettitle} 6 | \usage{ 7 | ENgettitle() 8 | } 9 | \value{ 10 | character vector of title lines 11 | } 12 | \description{ 13 | Retrieves the title lines of the project 14 | } 15 | -------------------------------------------------------------------------------- /man/ENstepQ.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/quality.r 3 | \name{ENstepQ} 4 | \alias{ENstepQ} 5 | \title{Advances WQ simulation one water quality time step.} 6 | \usage{ 7 | ENstepQ() 8 | } 9 | \value{ 10 | time remaining in the overall simulation 11 | } 12 | \description{ 13 | Advances WQ simulation one water quality time step. 14 | } 15 | -------------------------------------------------------------------------------- /man/ENclearreport.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/report.r 3 | \name{ENclearreport} 4 | \alias{ENclearreport} 5 | \title{Clears the contents of a project's report file.} 6 | \usage{ 7 | ENclearreport() 8 | } 9 | \value{ 10 | Returns NULL invisibly; called for side effect 11 | } 12 | \description{ 13 | Clears the contents of a project's report file. 14 | } 15 | -------------------------------------------------------------------------------- /man/ENdeletepattern.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/patterns.r 3 | \name{ENdeletepattern} 4 | \alias{ENdeletepattern} 5 | \title{Delete a new time pattern} 6 | \usage{ 7 | ENdeletepattern(index) 8 | } 9 | \arguments{ 10 | \item{index}{of the pattern to delete} 11 | } 12 | \value{ 13 | invisible NULL 14 | } 15 | \description{ 16 | Delete a new time pattern 17 | } 18 | -------------------------------------------------------------------------------- /man/ENgetcurvetype.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/curves.r 3 | \name{ENgetcurvetype} 4 | \alias{ENgetcurvetype} 5 | \title{Retrieves a curve's type} 6 | \usage{ 7 | ENgetcurvetype(index) 8 | } 9 | \arguments{ 10 | \item{index}{a curve's index (starting from 1).} 11 | } 12 | \value{ 13 | the curve's type 14 | } 15 | \description{ 16 | Retrieves a curve's type 17 | } 18 | -------------------------------------------------------------------------------- /man/ENsetnodeid.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/nodes.r 3 | \name{ENsetnodeid} 4 | \alias{ENsetnodeid} 5 | \title{Changes the ID name of a node} 6 | \usage{ 7 | ENsetnodeid(nodeindex, newid) 8 | } 9 | \arguments{ 10 | \item{nodeindex}{index of the node} 11 | 12 | \item{newid}{new ID name of the node} 13 | } 14 | \description{ 15 | Changes the ID name of a node 16 | } 17 | -------------------------------------------------------------------------------- /man/ENgetdemandmodel.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/demand.r 3 | \name{ENgetdemandmodel} 4 | \alias{ENgetdemandmodel} 5 | \title{Get type of demand model in use and its parameters} 6 | \usage{ 7 | ENgetdemandmodel() 8 | } 9 | \value{ 10 | named list with parameters of the demand model 11 | } 12 | \description{ 13 | Get type of demand model in use and its parameters 14 | } 15 | -------------------------------------------------------------------------------- /man/ENsetlinkid.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/links22.r 3 | \name{ENsetlinkid} 4 | \alias{ENsetlinkid} 5 | \title{Change the ID of a link} 6 | \usage{ 7 | ENsetlinkid(index, newid) 8 | } 9 | \arguments{ 10 | \item{index}{of the target link} 11 | 12 | \item{newid}{new name for the link (no more than 30 characters)} 13 | } 14 | \description{ 15 | Change the ID of a link 16 | } 17 | -------------------------------------------------------------------------------- /man/ENsetreport.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/report.r 3 | \name{ENsetreport} 4 | \alias{ENsetreport} 5 | \title{Processes a reporting format command.} 6 | \usage{ 7 | ENsetreport(format) 8 | } 9 | \arguments{ 10 | \item{format}{report formatting command: one line from the [REPORT] section of an inp file} 11 | } 12 | \description{ 13 | Processes a reporting format command. 14 | } 15 | -------------------------------------------------------------------------------- /man/ENdeletecurve.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/curves.r 3 | \name{ENdeletecurve} 4 | \alias{ENdeletecurve} 5 | \title{Deletes a data curve from a project} 6 | \usage{ 7 | ENdeletecurve(index) 8 | } 9 | \arguments{ 10 | \item{index}{the data curve's index (starting from 1).} 11 | } 12 | \value{ 13 | null invisibly 14 | } 15 | \description{ 16 | Deletes a data curve from a project 17 | } 18 | -------------------------------------------------------------------------------- /man/ENdeleterule.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rules.r 3 | \name{ENdeleterule} 4 | \alias{ENdeleterule} 5 | \title{Deletes an existing rule-based control} 6 | \usage{ 7 | ENdeleterule(index) 8 | } 9 | \arguments{ 10 | \item{index}{the index of the rule to be deleted (starting from 1).} 11 | } 12 | \value{ 13 | null 14 | } 15 | \description{ 16 | Deletes an existing rule-based control 17 | } 18 | -------------------------------------------------------------------------------- /man/ENgetpumptype.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pumps.r 3 | \name{ENgetpumptype} 4 | \alias{ENgetpumptype} 5 | \title{Retrieves type of head curve used by a pump} 6 | \usage{ 7 | ENgetpumptype(linkindex) 8 | } 9 | \arguments{ 10 | \item{linkindex}{index of the pump} 11 | } 12 | \value{ 13 | type of head curve 14 | } 15 | \description{ 16 | Retrieves type of head curve used by a pump 17 | } 18 | -------------------------------------------------------------------------------- /man/ENgetvertexcount.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/links22.r 3 | \name{ENgetvertexcount} 4 | \alias{ENgetvertexcount} 5 | \title{Get number of vertices for a link} 6 | \usage{ 7 | ENgetvertexcount(index) 8 | } 9 | \arguments{ 10 | \item{index}{a link's index (starting from 1).} 11 | } 12 | \value{ 13 | number of indices 14 | } 15 | \description{ 16 | Get number of vertices for a link 17 | } 18 | -------------------------------------------------------------------------------- /man/ENsetstatusreport.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/report.r 3 | \name{ENsetstatusreport} 4 | \alias{ENsetstatusreport} 5 | \title{Sets the level of hydraulic status reporting.} 6 | \usage{ 7 | ENsetstatusreport(level) 8 | } 9 | \arguments{ 10 | \item{level}{one of: EN_NO_REPORT, EN_NORMAL_REPORT, EN_FULL_REPORT} 11 | } 12 | \description{ 13 | Sets the level of hydraulic status reporting. 14 | } 15 | -------------------------------------------------------------------------------- /tests/testthat/test_title.r: -------------------------------------------------------------------------------- 1 | context('ENgettitle') 2 | 3 | test_that("func exists",{ 4 | expect_true( is.loaded("RENgettitle")) 5 | }) 6 | 7 | test_that("func works",{ 8 | 9 | ENopen("Net1.inp", "Net1.rpt") 10 | title <- ENgettitle() 11 | expect_equal(length(title), 3) 12 | expect_true( grepl("EPANET", title[1])) 13 | expect_true( grepl("chlorine", title[2])) 14 | expect_true( grepl("wall", title[3])) 15 | ENclose() 16 | }) -------------------------------------------------------------------------------- /man/ENaddrule.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rules.r 3 | \name{ENaddrule} 4 | \alias{ENaddrule} 5 | \title{Adds a new rule-based control to a project} 6 | \usage{ 7 | ENaddrule(rule) 8 | } 9 | \arguments{ 10 | \item{rule}{text of the rule following the format used in an EPANET input file.} 11 | } 12 | \value{ 13 | null 14 | } 15 | \description{ 16 | Adds a new rule-based control to a project 17 | } 18 | -------------------------------------------------------------------------------- /man/ENgeterror.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/report.r 3 | \name{ENgeterror} 4 | \alias{ENgeterror} 5 | \title{Returns the text of an error message generated by an error code} 6 | \usage{ 7 | ENgeterror(errcode) 8 | } 9 | \arguments{ 10 | \item{errcode}{an error code.} 11 | } 12 | \value{ 13 | error message 14 | } 15 | \description{ 16 | Returns the text of an error message generated by an error code 17 | } 18 | -------------------------------------------------------------------------------- /man/ENsetvertices.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/links22.r 3 | \name{ENsetvertices} 4 | \alias{ENsetvertices} 5 | \title{Set a link's vertices} 6 | \usage{ 7 | ENsetvertices(index, x, y) 8 | } 9 | \arguments{ 10 | \item{index}{a link's index} 11 | 12 | \item{x}{numeric vector of x-coordinates} 13 | 14 | \item{y}{numeric vector of y-coordinates} 15 | } 16 | \description{ 17 | Set a link's vertices 18 | } 19 | -------------------------------------------------------------------------------- /man/ENgetcurveid.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/curves.r 3 | \name{ENgetcurveid} 4 | \alias{ENgetcurveid} 5 | \title{Retrieves the ID name of a curve given its index.} 6 | \usage{ 7 | ENgetcurveid(index) 8 | } 9 | \arguments{ 10 | \item{index}{a curve's index (starting from 1).} 11 | } 12 | \value{ 13 | the curve's ID name. 14 | } 15 | \description{ 16 | Retrieves the ID name of a curve given its index. 17 | } 18 | -------------------------------------------------------------------------------- /man/ENgetheadcurveindex.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pumps.r 3 | \name{ENgetheadcurveindex} 4 | \alias{ENgetheadcurveindex} 5 | \title{Retrieves index of head curve used by a pump} 6 | \usage{ 7 | ENgetheadcurveindex(linkindex) 8 | } 9 | \arguments{ 10 | \item{linkindex}{index of the pump} 11 | } 12 | \value{ 13 | index of head curve 14 | } 15 | \description{ 16 | Retrieves index of head curve used by a pump 17 | } 18 | -------------------------------------------------------------------------------- /man/ENgetnumdemands.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/demand.r 3 | \name{ENgetnumdemands} 4 | \alias{ENgetnumdemands} 5 | \title{Get number of demands for a junction node} 6 | \usage{ 7 | ENgetnumdemands(nodeindex) 8 | } 9 | \arguments{ 10 | \item{nodeindex}{the index of a node (starting from 1).} 11 | } 12 | \value{ 13 | number of demands 14 | } 15 | \description{ 16 | Get number of demands for a junction node 17 | } 18 | -------------------------------------------------------------------------------- /man/ENgetruleID.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rules.r 3 | \name{ENgetruleID} 4 | \alias{ENgetruleID} 5 | \title{Gets the ID name of a rule-based control given its index.} 6 | \usage{ 7 | ENgetruleID(index) 8 | } 9 | \arguments{ 10 | \item{index}{the rule's index (starting from 1).} 11 | } 12 | \value{ 13 | rule's ID name. 14 | } 15 | \description{ 16 | Gets the ID name of a rule-based control given its index. 17 | } 18 | -------------------------------------------------------------------------------- /man/ENdeletecontrol.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/controls.r 3 | \name{ENdeletecontrol} 4 | \alias{ENdeletecontrol} 5 | \title{Deletes an existing simple control} 6 | \usage{ 7 | ENdeletecontrol(controlIndex) 8 | } 9 | \arguments{ 10 | \item{controlIndex}{the index of the control to delete (starting from 1).} 11 | } 12 | \value{ 13 | null invisibly 14 | } 15 | \description{ 16 | Deletes an existing simple control 17 | } 18 | -------------------------------------------------------------------------------- /man/ENgetcurveindex.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/curves.r 3 | \name{ENgetcurveindex} 4 | \alias{ENgetcurveindex} 5 | \title{Retrieves the index of a curve given its ID name.} 6 | \usage{ 7 | ENgetcurveindex(id) 8 | } 9 | \arguments{ 10 | \item{id}{the ID name of a curve.} 11 | } 12 | \value{ 13 | The curve's index (starting from 1). 14 | } 15 | \description{ 16 | Retrieves the index of a curve given its ID name. 17 | } 18 | -------------------------------------------------------------------------------- /man/ENgetvertex.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/links22.r 3 | \name{ENgetvertex} 4 | \alias{ENgetvertex} 5 | \title{Get vertex coordinates} 6 | \usage{ 7 | ENgetvertex(index, vertex) 8 | } 9 | \arguments{ 10 | \item{index}{a link's index (starting from 1).} 11 | 12 | \item{vertex}{index of vertex for getting coords} 13 | } 14 | \value{ 15 | list with elements x and y 16 | } 17 | \description{ 18 | Get vertex coordinates 19 | } 20 | -------------------------------------------------------------------------------- /man/ENcloseQ.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/quality.r 3 | \name{ENcloseQ} 4 | \alias{ENcloseQ} 5 | \title{Close water quality analysis and free allocated memory} 6 | \usage{ 7 | ENcloseQ() 8 | } 9 | \value{ 10 | Returns NULL invisibly; called for side effect 11 | } 12 | \description{ 13 | Close water quality analysis and free allocated memory 14 | } 15 | \details{ 16 | Do not call this function if ENsolveQ is being used. 17 | } 18 | -------------------------------------------------------------------------------- /man/ENgetcurvelen.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/curves.r 3 | \name{ENgetcurvelen} 4 | \alias{ENgetcurvelen} 5 | \title{Retrieves the number of points in a curve.} 6 | \usage{ 7 | ENgetcurvelen(index) 8 | } 9 | \arguments{ 10 | \item{index}{a curve's index (starting from 1).} 11 | } 12 | \value{ 13 | The number of data points assigned to the curve. 14 | } 15 | \description{ 16 | Retrieves the number of points in a curve. 17 | } 18 | -------------------------------------------------------------------------------- /man/ENaddcurve.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/curves.r 3 | \name{ENaddcurve} 4 | \alias{ENaddcurve} 5 | \title{Adds a new data curve to a project.} 6 | \usage{ 7 | ENaddcurve(id) 8 | } 9 | \arguments{ 10 | \item{id}{The ID name of the curve to be added.} 11 | } 12 | \value{ 13 | null invisibly 14 | } 15 | \description{ 16 | Adds a new data curve to a project. 17 | } 18 | \details{ 19 | The new curve contains a single data point (1.0, 1.0). 20 | } 21 | -------------------------------------------------------------------------------- /man/ENgetaveragepatternvalue.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/patterns.r 3 | \name{ENgetaveragepatternvalue} 4 | \alias{ENgetaveragepatternvalue} 5 | \title{Get average of all time factors in a pattern} 6 | \usage{ 7 | ENgetaveragepatternvalue(index) 8 | } 9 | \arguments{ 10 | \item{index}{a time pattern index (starting from 1).} 11 | } 12 | \value{ 13 | the average value 14 | } 15 | \description{ 16 | Get average of all time factors in a pattern 17 | } 18 | -------------------------------------------------------------------------------- /man/ENaddpattern.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/patterns.r 3 | \name{ENaddpattern} 4 | \alias{ENaddpattern} 5 | \title{Add a new time pattern} 6 | \usage{ 7 | ENaddpattern(patternid) 8 | } 9 | \arguments{ 10 | \item{patternid}{the ID name of the pattern to add.} 11 | } 12 | \value{ 13 | invisible NULL 14 | } 15 | \description{ 16 | Add a new time pattern 17 | } 18 | \details{ 19 | The new pattern contains a single time period whose factor is 1.0. 20 | } 21 | -------------------------------------------------------------------------------- /man/ENsetcurveid.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/curves.r 3 | \name{ENsetcurveid} 4 | \alias{ENsetcurveid} 5 | \title{Changes the ID name of a data curve given its index.} 6 | \usage{ 7 | ENsetcurveid(index, id) 8 | } 9 | \arguments{ 10 | \item{index}{a data curve index (starting from 1).} 11 | 12 | \item{id}{the data curve's new ID name.} 13 | } 14 | \value{ 15 | null invisibly 16 | } 17 | \description{ 18 | Changes the ID name of a data curve given its index. 19 | } 20 | -------------------------------------------------------------------------------- /man/ENdeletedemand.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/demand.r 3 | \name{ENdeletedemand} 4 | \alias{ENdeletedemand} 5 | \title{Delete a demand from a junction node} 6 | \usage{ 7 | ENdeletedemand(nodeindex, demandindex) 8 | } 9 | \arguments{ 10 | \item{nodeindex}{the index of a node (starting from 1).} 11 | 12 | \item{demandindex}{the position of the demand in the node's demands list (starting from 1).} 13 | } 14 | \description{ 15 | Delete a demand from a junction node 16 | } 17 | -------------------------------------------------------------------------------- /man/ENsetheadcurveindex.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pumps.r 3 | \name{ENsetheadcurveindex} 4 | \alias{ENsetheadcurveindex} 5 | \title{Sets index of head curve used by a pump} 6 | \usage{ 7 | ENsetheadcurveindex(linkindex, curveindex) 8 | } 9 | \arguments{ 10 | \item{linkindex}{index of the pump} 11 | 12 | \item{curveindex}{index of head curve to assign} 13 | } 14 | \value{ 15 | null invisibly 16 | } 17 | \description{ 18 | Sets index of head curve used by a pump 19 | } 20 | -------------------------------------------------------------------------------- /man/ENsetrulepriority.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rules.r 3 | \name{ENsetrulepriority} 4 | \alias{ENsetrulepriority} 5 | \title{Sets the priority of a rule-based control.} 6 | \usage{ 7 | ENsetrulepriority(index, priority) 8 | } 9 | \arguments{ 10 | \item{index}{the rule's index (starting from 1).} 11 | 12 | \item{priority}{the priority value assigned to the rule.} 13 | } 14 | \value{ 15 | null 16 | } 17 | \description{ 18 | Sets the priority of a rule-based control. 19 | } 20 | -------------------------------------------------------------------------------- /R/title.r: -------------------------------------------------------------------------------- 1 | #' ENgettitle 2 | #' 3 | #' Retrieves the title lines of the project 4 | #' @return character vector of title lines 5 | #' @useDynLib epanet2toolkit RENgettitle 6 | ENgettitle <- function(){ 7 | 8 | # allocate character buffers for the title lines 9 | row1 <- strrep(" ", 255) 10 | row2 <- strrep(" ", 255) 11 | row3 <- strrep(" ", 255) 12 | arg <- .C("RENgettitle", row1, row2, row3, as.integer(-1)) 13 | err <- arg[[4]] 14 | check_epanet_error(err) 15 | title <- unlist(arg)[1:3] 16 | return(title) 17 | } -------------------------------------------------------------------------------- /man/ENsaveinpfile.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/epanet.r 3 | \name{ENsaveinpfile} 4 | \alias{ENsaveinpfile} 5 | \title{ENaveinpfile 6 | 7 | Saves current data to "INP" formatted text file.} 8 | \usage{ 9 | ENsaveinpfile(filename) 10 | } 11 | \arguments{ 12 | \item{filename}{The file path to create} 13 | } 14 | \value{ 15 | Returns NULL invisibly; called for side effect 16 | } 17 | \description{ 18 | ENaveinpfile 19 | 20 | Saves current data to "INP" formatted text file. 21 | } 22 | -------------------------------------------------------------------------------- /man/ENsetpatternid.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/patterns.r 3 | \name{ENsetpatternid} 4 | \alias{ENsetpatternid} 5 | \title{Change the ID name of a time pattern given its index.} 6 | \usage{ 7 | ENsetpatternid(index, id) 8 | } 9 | \arguments{ 10 | \item{index}{a time pattern index (starting from 1).} 11 | 12 | \item{id}{the time pattern's new ID name.} 13 | } 14 | \value{ 15 | NULL invisibly 16 | } 17 | \description{ 18 | Change the ID name of a time pattern given its index. 19 | } 20 | -------------------------------------------------------------------------------- /man/ENsaveH.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/hydraulics.r 3 | \name{ENsaveH} 4 | \alias{ENsaveH} 5 | \title{ENsaveH 6 | 7 | Saves hydraulic results to binary file} 8 | \usage{ 9 | ENsaveH() 10 | } 11 | \value{ 12 | Returns NULL invisibly; called for side effect 13 | } 14 | \description{ 15 | ENsaveH 16 | 17 | Saves hydraulic results to binary file 18 | } 19 | \details{ 20 | Must be called before ENreport() if no WQ simulation has been made. 21 | Should not be called if ENsolveQ() will be used. 22 | } 23 | -------------------------------------------------------------------------------- /man/ENgetdemandindex.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/demand.r 3 | \name{ENgetdemandindex} 4 | \alias{ENgetdemandindex} 5 | \title{Retrieves the index of a node's named demand category} 6 | \usage{ 7 | ENgetdemandindex(nodeindex, demand_name) 8 | } 9 | \arguments{ 10 | \item{nodeindex}{the index of a node (starting from 1).} 11 | 12 | \item{demand_name}{the name of the demand's category} 13 | } 14 | \value{ 15 | demand category index 16 | } 17 | \description{ 18 | Retrieves the index of a node's named demand category 19 | } 20 | -------------------------------------------------------------------------------- /inst/COPYRIGHTS: -------------------------------------------------------------------------------- 1 | Copyright in epanet2toolkit is held by IBM Corp. 2017 except as noted below. 2 | 3 | Copyright in the following files is held by Open Water Analytics 2017: 4 | src/enumstxt.h 5 | src/epanet.c 6 | src/epanet2.h 7 | src/funcs.h 8 | src/hash.c 9 | src/hash.h 10 | src/hydraul.c 11 | src/input1.c 12 | src/input2.c 13 | src/input3.c 14 | src/inpfile.c 15 | src/mempool.c 16 | src/mempool.h 17 | src/output.c 18 | src/quality.c 19 | src/report.c 20 | src/rules.c 21 | src/smatrix.c 22 | src/text.h 23 | src/types.h 24 | src/vars.h 25 | -------------------------------------------------------------------------------- /man/ENaddnode.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/nodes.r 3 | \name{ENaddnode} 4 | \alias{ENaddnode} 5 | \title{Adds a new node} 6 | \usage{ 7 | ENaddnode(nodeid, nodetype) 8 | } 9 | \arguments{ 10 | \item{nodeid}{name of the node to be added} 11 | 12 | \item{nodetype}{the type of node being added. One of: EN_JUNCTION, EN_RESERVOIR, EN_TANK} 13 | } 14 | \value{ 15 | index the index of the newly added node 16 | } 17 | \description{ 18 | Adds a new node 19 | } 20 | \details{ 21 | When a new node is created all of its properties are set to 0. 22 | } 23 | -------------------------------------------------------------------------------- /man/ENgetdemandname.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/demand.r 3 | \name{ENgetdemandname} 4 | \alias{ENgetdemandname} 5 | \title{Retrieves the name of a node's demand category.} 6 | \usage{ 7 | ENgetdemandname(nodeindex, demand_index = 1) 8 | } 9 | \arguments{ 10 | \item{nodeindex}{a node's index (starting from 1).} 11 | 12 | \item{demand_index}{the index of one of the node's demand categories (starting from 1).} 13 | } 14 | \value{ 15 | The name of the selected category. 16 | } 17 | \description{ 18 | Retrieves the name of a node's demand category. 19 | } 20 | -------------------------------------------------------------------------------- /man/ENgetcurvevalue.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/curves.r 3 | \name{ENgetcurvevalue} 4 | \alias{ENgetcurvevalue} 5 | \title{Retrieves the value of a single data point for a curve.} 6 | \usage{ 7 | ENgetcurvevalue(curveIndex, pointIndex) 8 | } 9 | \arguments{ 10 | \item{curveIndex}{a curve's index (starting from 1).} 11 | 12 | \item{pointIndex}{the index of a point on the curve (starting from 1).} 13 | } 14 | \value{ 15 | list with the point's x-value and y-value 16 | } 17 | \description{ 18 | Retrieves the value of a single data point for a curve. 19 | } 20 | -------------------------------------------------------------------------------- /man/ENsetlinknodes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/links22.r 3 | \name{ENsetlinknodes} 4 | \alias{ENsetlinknodes} 5 | \title{Set the indexes of a link's start- and end-nodes} 6 | \usage{ 7 | ENsetlinknodes(index, node1_index, node2_index) 8 | } 9 | \arguments{ 10 | \item{index}{a link's index (starting from 1).} 11 | 12 | \item{node1_index}{The index of the link's start node (starting from 1).} 13 | 14 | \item{node2_index}{The index of the link's end node (starting from 1).} 15 | } 16 | \description{ 17 | Set the indexes of a link's start- and end-nodes 18 | } 19 | -------------------------------------------------------------------------------- /man/ENgetbasedemand.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/demand.r 3 | \name{ENgetbasedemand} 4 | \alias{ENgetbasedemand} 5 | \title{Gets the base demand for one of a node's demand categories.} 6 | \usage{ 7 | ENgetbasedemand(nodeindex, demand_index = 1) 8 | } 9 | \arguments{ 10 | \item{nodeindex}{a node's index (starting from 1).} 11 | 12 | \item{demand_index}{the index of a demand category for the node (starting from 1).} 13 | } 14 | \value{ 15 | the category's base demand. 16 | } 17 | \description{ 18 | Gets the base demand for one of a node's demand categories. 19 | } 20 | -------------------------------------------------------------------------------- /man/ENgetcoord.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/coords.r 3 | \name{ENgetcoord} 4 | \alias{ENgetcoord} 5 | \title{Get coordinates for a node} 6 | \usage{ 7 | ENgetcoord(nodeindex) 8 | } 9 | \arguments{ 10 | \item{nodeindex}{of node} 11 | } 12 | \value{ 13 | vector of x,y coordinate 14 | } 15 | \description{ 16 | Get coordinates for a node 17 | } 18 | \examples{ 19 | # path to Net1.inp example file included with this package 20 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 21 | ENopen( inp, "Net1.rpt") 22 | ENgetcoord(3) 23 | ENclose() 24 | } 25 | -------------------------------------------------------------------------------- /man/ENgetqualinfo.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/quality.r 3 | \name{ENgetqualinfo} 4 | \alias{ENgetqualinfo} 5 | \title{Get quality analysis information} 6 | \usage{ 7 | ENgetqualinfo() 8 | } 9 | \value{ 10 | list with elements: qualcode, chemname, 11 | chemunits, tracenode 12 | } 13 | \description{ 14 | Get quality analysis information 15 | } 16 | \examples{ 17 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 18 | ENopen( inp, "Net1.rpt") 19 | ENgetqualinfo() 20 | ENclose() 21 | # clean-up the created files 22 | file.remove("Net1.rpt") 23 | } 24 | -------------------------------------------------------------------------------- /man/ENgetversion.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/epanet.r 3 | \name{ENgetversion} 4 | \alias{ENgetversion} 5 | \title{Retrieve the current version number of the EPANET Toolkit.} 6 | \usage{ 7 | ENgetversion() 8 | } 9 | \value{ 10 | An integer, the Toolkit version number. 11 | } 12 | \description{ 13 | \code{ENgetversion} retrieves the current version number of the EPANET Toolkit. 14 | } 15 | \note{ 16 | The version number is a 5-digit integer that increases sequentially from 17 | 20001 with each new update of the Toolkit. 18 | } 19 | \examples{ 20 | ENgetversion() 21 | } 22 | -------------------------------------------------------------------------------- /man/ENsetbasedemand.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/demand.r 3 | \name{ENsetbasedemand} 4 | \alias{ENsetbasedemand} 5 | \title{Sets the base demand for one of a node's demand categories.} 6 | \usage{ 7 | ENsetbasedemand(nodeindex, demand_index = 1, base_demand) 8 | } 9 | \arguments{ 10 | \item{nodeindex}{a node's index (starting from 1).} 11 | 12 | \item{demand_index}{the index of a demand category for the node (starting from 1).} 13 | 14 | \item{base_demand}{the category's base demand.} 15 | } 16 | \description{ 17 | Sets the base demand for one of a node's demand categories. 18 | } 19 | -------------------------------------------------------------------------------- /man/ENsetdemandname.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/demand.r 3 | \name{ENsetdemandname} 4 | \alias{ENsetdemandname} 5 | \title{Sets the name of a node's demand category.} 6 | \usage{ 7 | ENsetdemandname(nodeindex, demand_index, demand_name) 8 | } 9 | \arguments{ 10 | \item{nodeindex}{a node's index (starting from 1).} 11 | 12 | \item{demand_index}{the index of one of the node's demand categories (starting from 1).} 13 | 14 | \item{demand_name}{The name of the selected category. No more than 30 characters} 15 | } 16 | \description{ 17 | Sets the name of a node's demand category. 18 | } 19 | -------------------------------------------------------------------------------- /man/ENsetpremisevalue.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rules.r 3 | \name{ENsetpremisevalue} 4 | \alias{ENsetpremisevalue} 5 | \title{Sets the value in a premise of a rule-based control} 6 | \usage{ 7 | ENsetpremisevalue(ruleIndex, premiseIndex, value) 8 | } 9 | \arguments{ 10 | \item{ruleIndex}{the rule's index (staring from 1).} 11 | 12 | \item{premiseIndex}{the premise's index (starting from 1).} 13 | 14 | \item{value}{The value that the premise's variable is compared to.} 15 | } 16 | \value{ 17 | null 18 | } 19 | \description{ 20 | Sets the value in a premise of a rule-based control 21 | } 22 | -------------------------------------------------------------------------------- /man/ENsetcurvevalue.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/curves.r 3 | \name{ENsetcurvevalue} 4 | \alias{ENsetcurvevalue} 5 | \title{Sets the value of a single data point for a curve.} 6 | \usage{ 7 | ENsetcurvevalue(curveIndex, pointIndex, x, y) 8 | } 9 | \arguments{ 10 | \item{curveIndex}{a curve's index (starting from 1).} 11 | 12 | \item{pointIndex}{the index of a point on the curve (starting from 1).} 13 | 14 | \item{x}{the point's new x-value.} 15 | 16 | \item{y}{the point's new y-value.} 17 | } 18 | \value{ 19 | null invisibly 20 | } 21 | \description{ 22 | Sets the value of a single data point for a curve. 23 | } 24 | -------------------------------------------------------------------------------- /man/ENadddemand.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/demand.r 3 | \name{ENadddemand} 4 | \alias{ENadddemand} 5 | \title{Appends a new demand to a junction node demands list.} 6 | \usage{ 7 | ENadddemand(nodeindex, base_demand, demand_pattern, demand_name) 8 | } 9 | \arguments{ 10 | \item{nodeindex}{the index of a node (starting from 1).} 11 | 12 | \item{base_demand}{the demand's base value.} 13 | 14 | \item{demand_pattern}{the name of a time pattern used by the demand} 15 | 16 | \item{demand_name}{the name of the demand's category} 17 | } 18 | \description{ 19 | Appends a new demand to a junction node demands list. 20 | } 21 | -------------------------------------------------------------------------------- /man/ENsetpremiseindex.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rules.r 3 | \name{ENsetpremiseindex} 4 | \alias{ENsetpremiseindex} 5 | \title{Sets the index of an object in a premise of a rule-based control} 6 | \usage{ 7 | ENsetpremiseindex(ruleIndex, premiseIndex, objIndex) 8 | } 9 | \arguments{ 10 | \item{ruleIndex}{the rule's index (starting from 1).} 11 | 12 | \item{premiseIndex}{the premise's index (starting from 1).} 13 | 14 | \item{objIndex}{the index of the premise's object (e.g. the index of a tank).} 15 | } 16 | \value{ 17 | null 18 | } 19 | \description{ 20 | Sets the index of an object in a premise of a rule-based control 21 | } 22 | -------------------------------------------------------------------------------- /man/ENcloseH.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/hydraulics.r 3 | \name{ENcloseH} 4 | \alias{ENcloseH} 5 | \title{close hydraulics engine} 6 | \usage{ 7 | ENcloseH() 8 | } 9 | \value{ 10 | Returns NULL invisibly; called for side effect 11 | } 12 | \description{ 13 | \code{ENcloseH} closes the hydraulic analysis system, freeing all 14 | allocated memory 15 | } 16 | \details{ 17 | Call \code{ENcloseH} after all hydraulics analyses have been made using 18 | \code{ENinitH-ENrunH-ENnextH}. Do not call this function if \code{ENsolveH} is being used. 19 | } 20 | \seealso{ 21 | \code{ENopenH}, \code{ENinitH}, \code{ENrunH}, \code{ENnextH} 22 | } 23 | -------------------------------------------------------------------------------- /man/ENgetrule.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rules.r 3 | \name{ENgetrule} 4 | \alias{ENgetrule} 5 | \title{Retrieves summary information about a rule-based control.} 6 | \usage{ 7 | ENgetrule(index) 8 | } 9 | \arguments{ 10 | \item{index}{the rule's index (starting from 1).} 11 | } 12 | \value{ 13 | list with components: 14 | nPremises number of premises in the rule's IF section; 15 | nThenActions number of actions in the rule's THEN section; 16 | nElseActions number of actions in the rule's ELSE section; 17 | priority the rule's priority value. 18 | } 19 | \description{ 20 | Retrieves summary information about a rule-based control. 21 | } 22 | -------------------------------------------------------------------------------- /man/ENsetflowunits.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/options.r 3 | \name{ENsetflowunits} 4 | \alias{ENsetflowunits} 5 | \title{Sets flow units.} 6 | \usage{ 7 | ENsetflowunits(units) 8 | } 9 | \arguments{ 10 | \item{units}{the choice of flow units. One of: "EN_CFS", "EN_GPM", "EN_MGD", 11 | "EN_IMGD", "EN_AFD", "EN_LPS", "EN_LPM", "EN_MLD", "EN_CMH", "EN_CMD"} 12 | } 13 | \value{ 14 | null invisibly 15 | } 16 | \description{ 17 | Sets flow units. 18 | } 19 | \details{ 20 | Flow units in liters or cubic meters implies that SI metric units 21 | are used for all other quantities in addition to flow. Otherwise US Customary 22 | units are employed. 23 | } 24 | -------------------------------------------------------------------------------- /man/ENsetdemandmodel.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/demand.r 3 | \name{ENsetdemandmodel} 4 | \alias{ENsetdemandmodel} 5 | \title{Sets the type of demand model to use and its parameters.} 6 | \usage{ 7 | ENsetdemandmodel(model, pmin, preq, pexp) 8 | } 9 | \arguments{ 10 | \item{model}{Type of demand model. EN_DDA for demand driven analysis or EN_PDA for pressure driven analysis} 11 | 12 | \item{pmin}{Pressure below which there is no demand} 13 | 14 | \item{preq}{Pressure required to deliver full demand} 15 | 16 | \item{pexp}{Pressure exponent in demand function} 17 | } 18 | \description{ 19 | Sets the type of demand model to use and its parameters. 20 | } 21 | -------------------------------------------------------------------------------- /man/ENopenQ.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/quality.r 3 | \name{ENopenQ} 4 | \alias{ENopenQ} 5 | \title{Sets up for Water Quality analysis} 6 | \usage{ 7 | ENopenQ() 8 | } 9 | \value{ 10 | Returns NULL invisibly on success or throws an error or warning 11 | } 12 | \description{ 13 | Sets up for Water Quality analysis 14 | } 15 | \examples{ 16 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 17 | ENopen( inp, "Net1.rpt") 18 | ENsolveH() 19 | ENsetqualtype("EN_CHEM", "Chlorine", "mg/L", "") 20 | ENopenQ() 21 | ENinitQ(0) 22 | ENrunQ() 23 | ENcloseQ() 24 | ENclose() 25 | # clean-up the created files 26 | file.remove("Net1.rpt") 27 | } 28 | -------------------------------------------------------------------------------- /man/ENsetpremisestatus.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rules.r 3 | \name{ENsetpremisestatus} 4 | \alias{ENsetpremisestatus} 5 | \title{Sets the status being compared to in a premise of a rule-based control} 6 | \usage{ 7 | ENsetpremisestatus(ruleIndex, premiseIndex, status) 8 | } 9 | \arguments{ 10 | \item{ruleIndex}{the rule's index (starting from 1).} 11 | 12 | \item{premiseIndex}{the premise's index (starting from 1).} 13 | 14 | \item{status}{the status that the premise's object status is compared to (see @ref EN_RuleStatus).} 15 | } 16 | \value{ 17 | null 18 | } 19 | \description{ 20 | Sets the status being compared to in a premise of a rule-based control 21 | } 22 | -------------------------------------------------------------------------------- /man/ENcopyreport.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/report.r 3 | \name{ENcopyreport} 4 | \alias{ENcopyreport} 5 | \title{Copies the current contents of a project's report file to another file} 6 | \usage{ 7 | ENcopyreport(rptFile) 8 | } 9 | \arguments{ 10 | \item{rptFile}{destination file} 11 | } 12 | \value{ 13 | Returns NULL invisibly; called for side effect 14 | 15 | Returns NULL invisibly; called for side effect 16 | } 17 | \description{ 18 | Copies the current contents of a project's report file to another file 19 | } 20 | \details{ 21 | This function allows toolkit clients to retrieve the contents of a project's 22 | report file while the project is still open. 23 | } 24 | -------------------------------------------------------------------------------- /man/ENreport.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/report.r 3 | \name{ENreport} 4 | \alias{ENreport} 5 | \title{Write simulation report to the report file} 6 | \usage{ 7 | ENreport() 8 | } 9 | \value{ 10 | Returns NULL invisibly; called for side effect 11 | } 12 | \description{ 13 | Write simulation report to the report file 14 | } 15 | \examples{ 16 | # path to Net1.inp example file included with this package 17 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 18 | ENopen( inp, "Net1.rpt", "Net1.bin") 19 | ENsolveH() 20 | ENsolveQ() 21 | ENreport() 22 | ENclose() 23 | # clean up the created files 24 | file.remove("Net1.rpt") 25 | file.remove("Net1.bin") 26 | } 27 | -------------------------------------------------------------------------------- /man/ENsolveH.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/hydraulics.r 3 | \name{ENsolveH} 4 | \alias{ENsolveH} 5 | \title{ENsolveH} 6 | \usage{ 7 | ENsolveH() 8 | } 9 | \value{ 10 | Returns NULL invisibly; called for side effect 11 | } 12 | \description{ 13 | Solves the network hydraulics for all time periods 14 | } 15 | \examples{ 16 | # path to Net1.inp example file included with this package 17 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 18 | ENopen( inp, "Net1.rpt","Net1.bin") 19 | ENsolveH() 20 | ENsolveQ() 21 | ENgetnodevalue(2, "EN_PRESSURE") 22 | ENclose() 23 | # clean-up the created files 24 | file.remove("Net1.rpt") 25 | file.remove("Net1.bin") 26 | } 27 | -------------------------------------------------------------------------------- /man/ENsolveQ.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/quality.r 3 | \name{ENsolveQ} 4 | \alias{ENsolveQ} 5 | \title{Solve network water quality for all time periods} 6 | \usage{ 7 | ENsolveQ() 8 | } 9 | \value{ 10 | Returns NULL invisibly on success or throws an error or warning 11 | } 12 | \description{ 13 | Solve network water quality for all time periods 14 | } 15 | \examples{ 16 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 17 | ENopen( inp, "Net1.rpt","Net1.bin") 18 | ENsolveH() 19 | ENsetqualtype("EN_CHEM", "Chlorine", "mg/L", "") 20 | ENsolveQ() 21 | ENclose() 22 | # clean-up the created files 23 | file.remove("Net1.rpt") 24 | file.remove("Net1.bin") 25 | } 26 | -------------------------------------------------------------------------------- /man/ENdeletelink.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/links22.r 3 | \name{ENdeletelink} 4 | \alias{ENdeletelink} 5 | \title{Delete a link from the project.} 6 | \usage{ 7 | ENdeletelink(index, action = "EN_UNCONDITIONAL") 8 | } 9 | \arguments{ 10 | \item{index}{the index of the link to be deleted.} 11 | 12 | \item{action}{The action taken if any control contains the link.} 13 | } 14 | \description{ 15 | Delete a link from the project. 16 | } 17 | \details{ 18 | If actionCode is EN_UNCONDITIONAL then the link and all simple and rule-based 19 | controls that contain it are deleted. If set to EN_CONDITIONAL then the link 20 | is not deleted if it appears in any control and error 261 is returned. 21 | } 22 | -------------------------------------------------------------------------------- /man/ENgetthenaction.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rules.r 3 | \name{ENgetthenaction} 4 | \alias{ENgetthenaction} 5 | \title{Gets properties of THEN action in rule-based control} 6 | \usage{ 7 | ENgetthenaction(ruleIndex, actionIndex) 8 | } 9 | \arguments{ 10 | \item{ruleIndex}{the rule's index (starting from 1).} 11 | 12 | \item{actionIndex}{the index of the THEN action to retrieve (starting from 1).} 13 | } 14 | \value{ 15 | list with components: 16 | * linkIndex the index of the link in the action (starting from 1) 17 | * status the status assigned to the link 18 | * setting the value assigned to the link's setting 19 | } 20 | \description{ 21 | Gets properties of THEN action in rule-based control 22 | } 23 | -------------------------------------------------------------------------------- /man/ENsetjuncdata.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/nodes.r 3 | \name{ENsetjuncdata} 4 | \alias{ENsetjuncdata} 5 | \title{Sets properties for a junction} 6 | \usage{ 7 | ENsetjuncdata(nodeindex, elevation, demand, demand_pattern = "") 8 | } 9 | \arguments{ 10 | \item{nodeindex}{a junction node's index (starting from 1).} 11 | 12 | \item{elevation}{the value of the junction's elevation.} 13 | 14 | \item{demand}{the value of the junction's primary base demand.} 15 | 16 | \item{demand_pattern}{the ID name of the demand's time pattern ("" for no pattern)} 17 | } 18 | \description{ 19 | Sets properties for a junction 20 | } 21 | \details{ 22 | These properties have units that depend on the units used for flow rate. 23 | } 24 | -------------------------------------------------------------------------------- /man/ENrunQ.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/quality.r 3 | \name{ENrunQ} 4 | \alias{ENrunQ} 5 | \title{Computs WQ results at current time .} 6 | \usage{ 7 | ENrunQ() 8 | } 9 | \value{ 10 | current simulation time in seconds 11 | } 12 | \description{ 13 | Computs WQ results at current time . 14 | } 15 | \details{ 16 | used in a loop with ENnextQ() to run 17 | an extended period WQ simulation. 18 | } 19 | \examples{ 20 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 21 | ENopen( inp, "Net1.rpt") 22 | ENsolveH() 23 | ENsetqualtype("EN_CHEM", "Chlorine", "mg/L", "") 24 | ENopenQ() 25 | ENinitQ(0) 26 | ENrunQ() 27 | ENcloseQ() 28 | ENclose() 29 | # clean-up the created files 30 | file.remove("Net1.rpt") 31 | } 32 | -------------------------------------------------------------------------------- /src/mempool.h: -------------------------------------------------------------------------------- 1 | /* 2 | ****************************************************************************** 3 | Project: OWA EPANET 4 | Version: 2.2 5 | Module: mempool.h 6 | Description: header for a simple pooled memory allocator 7 | Authors: see AUTHORS 8 | Copyright: see AUTHORS 9 | License: see LICENSE 10 | Last Updated: 11/27/2018 11 | ****************************************************************************** 12 | */ 13 | 14 | #ifndef MEMPOOL_H 15 | #define MEMPOOL_H 16 | 17 | struct Mempool; 18 | 19 | struct Mempool * mempool_create(void); 20 | void mempool_delete(struct Mempool *mempool); 21 | void mempool_reset(struct Mempool *mempool); 22 | char * mempool_alloc(struct Mempool *mempool, size_t size); 23 | 24 | #endif -------------------------------------------------------------------------------- /man/ENsetthenaction.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rules.r 3 | \name{ENsetthenaction} 4 | \alias{ENsetthenaction} 5 | \title{Set properties of THEN action in a rule-based control} 6 | \usage{ 7 | ENsetthenaction(ruleIndex, actionIndex, linkIndex, status, setting) 8 | } 9 | \arguments{ 10 | \item{ruleIndex}{the rule's index (starting from 1)} 11 | 12 | \item{actionIndex}{the index of the THEN action to modify (starting from 1)} 13 | 14 | \item{linkIndex}{the index of the link in the action} 15 | 16 | \item{status}{the new status assigned to the link} 17 | 18 | \item{setting}{the new value assigned to the link's setting} 19 | } 20 | \value{ 21 | null 22 | } 23 | \description{ 24 | Set properties of THEN action in a rule-based control 25 | } 26 | -------------------------------------------------------------------------------- /man/ENusehydfile.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/hydraulics.r 3 | \name{ENusehydfile} 4 | \alias{ENusehydfile} 5 | \title{Uses previously saved binary hydraulics file to supply a project's hydraulics.} 6 | \usage{ 7 | ENusehydfile(hydfile) 8 | } 9 | \arguments{ 10 | \item{hydfile}{name of file containing hydraulic results} 11 | } 12 | \description{ 13 | Uses previously saved binary hydraulics file to supply a project's hydraulics. 14 | } 15 | \details{ 16 | Call this function to re-use a set of hydraulic analysis results saved previously. This 17 | can save computational time if water quality analyses are being made under the same set 18 | of hydraulic conditions. 19 | 20 | Do not call this function while the hydraulics solver is open. 21 | } 22 | -------------------------------------------------------------------------------- /man/ENsetcoord.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/coords.r 3 | \name{ENsetcoord} 4 | \alias{ENsetcoord} 5 | \title{Set coordinates for a node} 6 | \usage{ 7 | ENsetcoord(nodeindex, x, y) 8 | } 9 | \arguments{ 10 | \item{nodeindex}{index of nodes for which to set coords} 11 | 12 | \item{x}{coordinate} 13 | 14 | \item{y}{coordinate} 15 | } 16 | \value{ 17 | returns NULL invisibily on success or raises an error or warning 18 | } 19 | \description{ 20 | Set coordinates for a node 21 | } 22 | \examples{ 23 | # path to Net1.inp example file included with this package 24 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 25 | ENopen( inp, "Net1.rpt") 26 | ENgetcoord(3) 27 | ENsetcoord(3,33,44) 28 | ENgetcoord(3) 29 | ENclose() 30 | } 31 | -------------------------------------------------------------------------------- /man/ENdeletenode.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/nodes.r 3 | \name{ENdeletenode} 4 | \alias{ENdeletenode} 5 | \title{Deletes a node} 6 | \usage{ 7 | ENdeletenode(nodeindex, actionCode) 8 | } 9 | \arguments{ 10 | \item{nodeindex}{the index of the node to be deleted.} 11 | 12 | \item{actionCode}{the action taken if any control contains the node and its links: EN_UNCONDITIONAL or EN_CONDITIONAL.} 13 | } 14 | \description{ 15 | Deletes a node 16 | } 17 | \details{ 18 | If `actionCode` is EN_UNCONDITIONAL then the node, its incident links and all 19 | simple and rule-based controls that contain them are deleted. If set to 20 | EN_CONDITIONAL then the node is not deleted if it or its incident links appear 21 | in any controls and error code 261 is returned. 22 | } 23 | -------------------------------------------------------------------------------- /man/ENgetlinkindex.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/links.r 3 | \name{ENgetlinkindex} 4 | \alias{ENgetlinkindex} 5 | \title{Retrieve the index of a link} 6 | \usage{ 7 | ENgetlinkindex(linkid) 8 | } 9 | \arguments{ 10 | \item{linkid}{character} 11 | } 12 | \value{ 13 | integer index of requested link 14 | } 15 | \description{ 16 | \code{ENgetlinkindex} retrieves the index of a link with specified ID. 17 | } 18 | \note{ 19 | Link indexes are consecutive integers starting from 1. 20 | } 21 | \examples{ 22 | # path to Net1.inp example file included with this package 23 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 24 | ENopen( inp, "Net1.rpt") 25 | ENgetlinkindex("22") 26 | ENclose() 27 | } 28 | \seealso{ 29 | \code{\link{ENgetlinkid} } 30 | } 31 | -------------------------------------------------------------------------------- /man/ENgetelseaction.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rules.r 3 | \name{ENgetelseaction} 4 | \alias{ENgetelseaction} 5 | \title{Gets the properties of an ELSE action in a rule-based control.} 6 | \usage{ 7 | ENgetelseaction(ruleIndex, actionIndex) 8 | } 9 | \arguments{ 10 | \item{ruleIndex}{the rule's index (starting from 1).} 11 | 12 | \item{actionIndex}{the index of the ELSE action to retrieve (starting from 1).} 13 | } 14 | \value{ 15 | list with the following components: 16 | \describe{ 17 | \item{linkIndex}{ the index of the link in the action} 18 | \item{status}{the status assigned to the link} 19 | \item{setting}{the value assigned to the link's setting} 20 | } 21 | } 22 | \description{ 23 | Gets the properties of an ELSE action in a rule-based control. 24 | } 25 | -------------------------------------------------------------------------------- /man/ENsetpatternvalue.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/patterns.r 3 | \name{ENsetpatternvalue} 4 | \alias{ENsetpatternvalue} 5 | \title{set pattern value} 6 | \usage{ 7 | ENsetpatternvalue(index, period, value) 8 | } 9 | \arguments{ 10 | \item{index}{index of pattern} 11 | 12 | \item{period}{time period for setting the value} 13 | 14 | \item{value}{value to set} 15 | } 16 | \value{ 17 | returns NULL inivisbly on success 18 | } 19 | \description{ 20 | set pattern value 21 | } 22 | \examples{ 23 | # path to Net1.inp example file included with this package 24 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 25 | ENopen( inp, "Net1.rpt") 26 | ENgetpatternvalue(1,3) 27 | ENsetpatternvalue(1,3, 9.876) 28 | ENgetpatternvalue(1,3) 29 | ENclose() 30 | } 31 | -------------------------------------------------------------------------------- /man/ENclose.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/Rtoolkit.R 3 | \name{ENclose} 4 | \alias{ENclose} 5 | \title{Close down the EPANET Toolkit system.} 6 | \usage{ 7 | ENclose() 8 | } 9 | \value{ 10 | Returns NULL invisibly; called for the side effect of closing EPANET. 11 | } 12 | \description{ 13 | \code{ENclose} closes the EPANET Toolkit system (including all files being processed). 14 | } 15 | \note{ 16 | \code{ENclose} must be called when all processing has been completed, even if an error 17 | condition was encountered. 18 | } 19 | \examples{ 20 | # path to Net1.inp example file included with this package 21 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 22 | ENopen( inp, "Net1.rpt") 23 | ENclose() 24 | } 25 | \seealso{ 26 | \code{\link{ENopen}} 27 | } 28 | -------------------------------------------------------------------------------- /tests/testthat/test_flowunits.r: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2020 4 | # Author: Bradley J Eck 5 | # 6 | #*****************************************/ 7 | 8 | 9 | context("flow units") 10 | 11 | test_that("behavior calling on closed toolkit",{ 12 | expect_warning( flowunits <- ENgetflowunits() ) 13 | expect_true( is.null(flowunits) ) 14 | 15 | }) 16 | 17 | test_that("basic usage",{ 18 | 19 | ENopen("Net1.inp", "Net1.rpt") 20 | units <- ENgetflowunits() 21 | expect_equal( unname(units), 1 ) 22 | ENclose() 23 | 24 | 25 | }) 26 | 27 | test_that("works",{ 28 | 29 | 30 | ENopen("Net1.inp","Net1.rpt") 31 | x <- ENgetflowunits() 32 | ENclose() 33 | 34 | y <- 1 35 | names(y) <- "EN_GPM" 36 | expect_equal(x,y ) 37 | }) 38 | 39 | -------------------------------------------------------------------------------- /man/ENgetnodeindex.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/nodes.r 3 | \name{ENgetnodeindex} 4 | \alias{ENgetnodeindex} 5 | \title{Retrieve the index of a node} 6 | \usage{ 7 | ENgetnodeindex(nodeid) 8 | } 9 | \arguments{ 10 | \item{nodeid}{A character string specifying the node ID.} 11 | } 12 | \value{ 13 | An integer index of the specified node. 14 | } 15 | \description{ 16 | Retrieve the index of a node 17 | } 18 | \note{ 19 | Node indexes are consecutive integers starting from 1. 20 | } 21 | \examples{ 22 | # path to Net1.inp example file included with this package 23 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 24 | ENopen( inp, "Net1.rpt") 25 | ENgetnodeindex("10") 26 | ENgetnodeindex("23") 27 | ENclose() 28 | } 29 | \seealso{ 30 | \code{ENgetnodeid} 31 | } 32 | -------------------------------------------------------------------------------- /man/ENsetelseaction.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rules.r 3 | \name{ENsetelseaction} 4 | \alias{ENsetelseaction} 5 | \title{Set properties of an ELSE action in a rule-based control} 6 | \usage{ 7 | ENsetelseaction(ruleIndex, actionIndex, linkIndex, status, setting) 8 | } 9 | \arguments{ 10 | \item{ruleIndex}{the rule's index (starting from 1).} 11 | 12 | \item{actionIndex}{the index of the ELSE action being modified (starting from 1).} 13 | 14 | \item{linkIndex}{the index of the link in the action (starting from 1).} 15 | 16 | \item{status}{the new status assigned to the link} 17 | 18 | \item{setting}{the new value assigned to the link's setting.} 19 | } 20 | \value{ 21 | null invisibly 22 | } 23 | \description{ 24 | Set properties of an ELSE action in a rule-based control 25 | } 26 | -------------------------------------------------------------------------------- /man/ENgetlinkid.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/links.r 3 | \name{ENgetlinkid} 4 | \alias{ENgetlinkid} 5 | \title{Retrieve the ID label of a link} 6 | \usage{ 7 | ENgetlinkid(linkindex) 8 | } 9 | \arguments{ 10 | \item{linkindex}{integer specifying the link index.} 11 | } 12 | \value{ 13 | character ID 14 | } 15 | \description{ 16 | \code{ENgetlinkid} retrieves the ID label of the link given its index. 17 | } 18 | \note{ 19 | Link indexes are consecutive integers starting from 1. 20 | } 21 | \examples{ 22 | # path to Net1.inp example file included with this package 23 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 24 | ENopen( inp, "Net1.rpt") 25 | ENgetlinkid(1) 26 | ENgetlinkid(12) 27 | ENclose() 28 | } 29 | \seealso{ 30 | \code{\link{ENgetlinkindex} } 31 | } 32 | -------------------------------------------------------------------------------- /man/ENnextQ.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/quality.r 3 | \name{ENnextQ} 4 | \alias{ENnextQ} 5 | \title{Advances WQ simulation to start of the next hydraulic time period.} 6 | \usage{ 7 | ENnextQ() 8 | } 9 | \value{ 10 | seconds until next hydraulic event occurs or 11 | 0 if at the end of the simulation period. 12 | } 13 | \description{ 14 | Advances WQ simulation to start of the next hydraulic time period. 15 | } 16 | \examples{ 17 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 18 | ENopen( inp, "Net1.rpt") 19 | ENsolveH() 20 | ENsetqualtype("EN_CHEM", "Chlorine", "mg/L", "") 21 | ENopenQ() 22 | ENinitQ(0) 23 | ENrunQ() 24 | ENnextQ() 25 | ENrunQ() 26 | ENcloseQ() 27 | ENclose() 28 | # clean-up the created files 29 | file.remove("Net1.rpt") 30 | } 31 | -------------------------------------------------------------------------------- /man/ENaddcontrol.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/controls.r 3 | \name{ENaddcontrol} 4 | \alias{ENaddcontrol} 5 | \title{Add a new simple control} 6 | \usage{ 7 | ENaddcontrol(type, linkIndex, setting, nodeIndex, level) 8 | } 9 | \arguments{ 10 | \item{type}{the type of control to add (see details)} 11 | 12 | \item{linkIndex}{the index of a link to control (starting from 1)} 13 | 14 | \item{setting}{control setting applied to the link} 15 | 16 | \item{nodeIndex}{index of the node used to control the link 17 | (0 for EN_TIMER and EN_TIMEOFDAY controls).} 18 | 19 | \item{level}{action level (tank level, junction pressure, or time in seconds) 20 | that triggers the control.} 21 | } 22 | \value{ 23 | index index of the new control. 24 | } 25 | \description{ 26 | Add a new simple control 27 | } 28 | -------------------------------------------------------------------------------- /man/ENgetpatternindex.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/patterns.r 3 | \name{ENgetpatternindex} 4 | \alias{ENgetpatternindex} 5 | \title{Retrieve the index a time pattern.} 6 | \usage{ 7 | ENgetpatternindex(patternid) 8 | } 9 | \arguments{ 10 | \item{patternid}{A character string specifying the pattern ID} 11 | } 12 | \value{ 13 | An integer, the index of the specified time pattern. 14 | } 15 | \description{ 16 | \code{ENgetpatternindex} retrieves the index of a time pattern. 17 | } 18 | \note{ 19 | Pattern indexes are consecutive integers starting from 1. 20 | } 21 | \examples{ 22 | # path to Net1.inp example file included with this package 23 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 24 | ENopen( inp, "Net1.rpt") 25 | ENgetpatternindex("1") 26 | ENclose() 27 | } 28 | -------------------------------------------------------------------------------- /man/ENsetdemandpattern.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/demand.r 3 | \name{ENsetdemandpattern} 4 | \alias{ENsetdemandpattern} 5 | \title{Sets the index of a time pattern used for one of a node's demand categories.} 6 | \usage{ 7 | ENsetdemandpattern(nodeindex, demand_index, pattern_index) 8 | } 9 | \arguments{ 10 | \item{nodeindex}{a node's index (starting from 1).} 11 | 12 | \item{demand_index}{the index of one of the node's demand categories (starting from 1).} 13 | 14 | \item{pattern_index}{the index of the time pattern assigned to the category.} 15 | } 16 | \description{ 17 | Sets the index of a time pattern used for one of a node's demand categories. 18 | } 19 | \details{ 20 | Specifying a pattern index of 0 indicates that no time pattern is assigned to the 21 | demand category. 22 | } 23 | -------------------------------------------------------------------------------- /tests/testthat/test_util.r: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2017, 2020 4 | # Author: Bradley J Eck 5 | # 6 | # 7 | #****************************************/ 8 | 9 | 10 | 11 | 12 | context("long stored as char to int or char") 13 | 14 | test_that("can return int",{ 15 | 16 | x <- charlong_to_int_or_char( "123") 17 | expect_equal(x,123) 18 | 19 | }) 20 | 21 | test_that("can return char",{ 22 | 23 | x <- charlong_to_int_or_char( "12345678901") 24 | expect_equal(x,"12345678901") 25 | 26 | }) 27 | 28 | context("enum lookup") 29 | test_that("lookup works",{ 30 | 31 | option_enums <- c("EN_TRIALS", "EN_ACCURACY", "EN_TOLERANCE", "EN_EMITEXPON", "EN_DEMANDMULT") 32 | intval <- lookup_enum_value(option_enums, "EN_ACCURACY") 33 | expect_equal(intval,1) 34 | }) 35 | 36 | -------------------------------------------------------------------------------- /man/ENgetpatternid.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/patterns.r 3 | \name{ENgetpatternid} 4 | \alias{ENgetpatternid} 5 | \title{Retrieve the ID label a time pattern} 6 | \usage{ 7 | ENgetpatternid(patternindex) 8 | } 9 | \arguments{ 10 | \item{patternindex}{An integer specifying the time pattern index.} 11 | } 12 | \value{ 13 | A character string, the pattern ID label of the specified time pattern. 14 | } 15 | \description{ 16 | \code{ENgetpatternid} retrieves the ID label of a particular time pattern. 17 | } 18 | \note{ 19 | Pattern indexes are consecutive integers starting from 1. 20 | } 21 | \examples{ 22 | # path to Net1.inp example file included with this package 23 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 24 | ENopen( inp, "Net1.rpt") 25 | ENgetpatternid(1) 26 | ENclose() 27 | } 28 | -------------------------------------------------------------------------------- /man/ENgetpatternlen.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/patterns.r 3 | \name{ENgetpatternlen} 4 | \alias{ENgetpatternlen} 5 | \title{Retrieve the number of time periods in a time pattern.} 6 | \usage{ 7 | ENgetpatternlen(patternindex) 8 | } 9 | \arguments{ 10 | \item{patternindex}{An integer specifying a time pattern index.} 11 | } 12 | \value{ 13 | An integer, the time pattern length. 14 | } 15 | \description{ 16 | \code{ENgetpatternlen} retrieves the number of time periods in a specific time pattern. 17 | } 18 | \note{ 19 | Pattern indexes are consecutive integers starting from 1. 20 | } 21 | \examples{ 22 | # path to Net1.inp example file included with this package 23 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 24 | ENopen( inp, "Net1.rpt") 25 | ENgetpatternlen(1) 26 | ENclose() 27 | } 28 | -------------------------------------------------------------------------------- /man/ENgetnodeid.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/nodes.r 3 | \name{ENgetnodeid} 4 | \alias{ENgetnodeid} 5 | \title{Retrieve the ID label a node.} 6 | \usage{ 7 | ENgetnodeid(nodeindex) 8 | } 9 | \arguments{ 10 | \item{nodeindex}{An integer node index} 11 | } 12 | \value{ 13 | A character string, the ID label of the specified node. 14 | } 15 | \description{ 16 | \code{ENgetnodeid} retrieves the ID label a node from its index 17 | } 18 | \note{ 19 | Node indexes are consecutive integers starting from 1. 20 | } 21 | \examples{ 22 | # path to Net1.inp example file included with this package 23 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 24 | ENopen( inp, "Net1.rpt") 25 | ENgetnodeid(1) 26 | ENgetnodeid(5) 27 | ENgetnodeid(9) 28 | ENclose() 29 | } 30 | \seealso{ 31 | \code{ENgetnodeindex} 32 | } 33 | -------------------------------------------------------------------------------- /src/cstr_helper.h: -------------------------------------------------------------------------------- 1 | /* 2 | ****************************************************************************** 3 | Project: OWA EPANET 4 | Version: 2.2 5 | Module: util/cstr_helper.h 6 | Description: Provides C string helper functions 7 | Authors: see AUTHORS 8 | Copyright: see AUTHORS 9 | License: see LICENSE 10 | Last Updated: 04/02/2019 11 | ****************************************************************************** 12 | */ 13 | 14 | #ifndef CSTR_HELPER_H_ 15 | #define CSTR_HELPER_H_ 16 | 17 | 18 | #include 19 | 20 | 21 | #if defined(__cplusplus) 22 | extern "C" { 23 | #endif 24 | 25 | 26 | int cstr_duplicate(char **dest, const char *source); 27 | 28 | bool cstr_isvalid(const char *element_id); 29 | 30 | bool cstr_isnullterm(const char *source); 31 | 32 | 33 | #if defined(__cplusplus) 34 | } 35 | #endif 36 | 37 | 38 | #endif /* CSTR_HELPER_H_ */ 39 | -------------------------------------------------------------------------------- /tests/testthat/test_ENclose.r: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2017, 2020 4 | # Author: Bradley J Eck 5 | # 6 | # 7 | #****************************************/ 8 | 9 | context("ENclose") 10 | 11 | 12 | test_that("func exists",{ 13 | expect_true( is.loaded("RENclose")) 14 | }) 15 | 16 | test_that("func works",{ 17 | ENopen("Net1.inp","n1.rpt") 18 | ENclose() 19 | # if you got here it's OK 20 | expect_true(TRUE) 21 | # clean-up 22 | file.remove("n1.rpt") 23 | }) 24 | test_that("warns not crashes when already closed",{ 25 | 26 | expect_warning(ENclose()) 27 | 28 | }) 29 | 30 | test_that("returns NULL invisibly on Success",{ 31 | ENopen("Net1.inp","n1.rpt") 32 | x <- withVisible( ENclose() ) 33 | expect_null( x$value) 34 | expect_false( x$visible) 35 | # clean-up 36 | file.remove("n1.rpt") 37 | }) 38 | 39 | -------------------------------------------------------------------------------- /man/ENgetdemandpattern.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/demand.r 3 | \name{ENgetdemandpattern} 4 | \alias{ENgetdemandpattern} 5 | \title{Gets the base demand for one of a node's demand categories.} 6 | \usage{ 7 | ENgetdemandpattern(nodeindex, demand_index = 1) 8 | } 9 | \arguments{ 10 | \item{nodeindex}{the node's index (starting from 1).} 11 | 12 | \item{demand_index}{the index of a demand category for the node (starting from 1).} 13 | } 14 | \value{ 15 | the category's base demand. 16 | 17 | 18 | Retrieves index of a time pattern assigned to one of a node's demand categories. 19 | 20 | patIndex the index of the category's time pattern. 21 | } 22 | \description{ 23 | Gets the base demand for one of a node's demand categories. 24 | } 25 | \details{ 26 | A returned pattern index of 0 indicates that no time pattern has been assigned to the 27 | demand category. 28 | } 29 | -------------------------------------------------------------------------------- /man/ENresetreport.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/report.r 3 | \name{ENresetreport} 4 | \alias{ENresetreport} 5 | \title{Resets a project's report options to their default values.} 6 | \usage{ 7 | ENresetreport() 8 | } 9 | \value{ 10 | Returns NULL invisibly; called for side effect 11 | } 12 | \description{ 13 | Resets a project's report options to their default values. 14 | } 15 | \details{ 16 | After calling this function the default reporting options are in effect. These are: 17 | \itemize{ 18 | \item no status report 19 | \item no energy report 20 | \item no nodes reported on 21 | \item no links reported on 22 | \item node variables reported to 2 decimal places 23 | \item link variables reported to 2 decimal places (3 for friction factor) 24 | \item node variables reported are elevation, head, pressure, and quality 25 | \item link variables reported are flow, velocity, and head loss. 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /man/ENgetresultindex.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/report.r 3 | \name{ENgetresultindex} 4 | \alias{ENgetresultindex} 5 | \title{Retrieves the order in which a node or link appears in an output file.} 6 | \usage{ 7 | ENgetresultindex(type, index) 8 | } 9 | \arguments{ 10 | \item{type}{a type of element (either EN_NODE or EN_LINK).} 11 | 12 | \item{index}{the element's current index (starting from 1).} 13 | } 14 | \value{ 15 | the order in which the element's results were written to file. 16 | } 17 | \description{ 18 | Retrieves the order in which a node or link appears in an output file. 19 | } 20 | \details{ 21 | If the element does not appear in the file then its result index is 0. 22 | 23 | This function can be used to correctly retrieve results from an EPANET binary output file 24 | after the order of nodes or links in a network's database has been changed due to editing 25 | operations. 26 | } 27 | -------------------------------------------------------------------------------- /tests/testthat/test_codes.r: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2017 4 | # Author: Ernesto Arandia & Bradley J Eck 5 | # 6 | #***************************************** 7 | 8 | 9 | context("error codes") 10 | test_that("verify no error",{ 11 | 12 | x <- check_epanet_error( as.integer(0)) 13 | expect_true( is.null(x)) 14 | }) 15 | test_that("verify error",{ 16 | expect_error(check_epanet_error( as.integer(302)), "302") 17 | }) 18 | test_that("verify warning",{ 19 | expect_warning(check_epanet_error( as.integer(55)), "55") 20 | }) 21 | 22 | context("quality codes") 23 | 24 | test_that("numeric input",{ 25 | 26 | x <- check_enum_code( 0, c("a","b") ) 27 | expect_true( is.integer(x)) 28 | 29 | }) 30 | 31 | test_that("character input",{ 32 | 33 | x <- check_enum_code( "b", c("a","b") ) 34 | expect_true( is.integer(x)) 35 | expect_equal(x,1) 36 | 37 | }) 38 | -------------------------------------------------------------------------------- /man/ENgetcontrol.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/controls.r 3 | \name{ENgetcontrol} 4 | \alias{ENgetcontrol} 5 | \title{ENgetcontrol} 6 | \usage{ 7 | ENgetcontrol(controlindex) 8 | } 9 | \arguments{ 10 | \item{controlindex}{An integer specifying the control statement index.} 11 | } 12 | \value{ 13 | list of parameters of the control statement: ctype, lindex, setting, nindex, level 14 | } 15 | \description{ 16 | Retrieve the parameters of a simple control statement. 17 | } 18 | \note{ 19 | Controls are indexed starting from 1 in the order in which they were entered into the 20 | \code{[CONTROLS]} section of the EPANET input file. 21 | } 22 | \examples{ 23 | # path to Net1.inp example file included with this package 24 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 25 | ENopen( inp, "Net1.rpt") 26 | ENgetcontrol(1) 27 | ENclose() 28 | } 29 | \seealso{ 30 | \code{\link{ENsetcontrol}} 31 | } 32 | -------------------------------------------------------------------------------- /src/hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | ****************************************************************************** 3 | Project: OWA EPANET 4 | Version: 2.2 5 | Module: hash.h 6 | Description: header for a simple hash table 7 | Authors: see AUTHORS 8 | Copyright: see AUTHORS 9 | License: see LICENSE 10 | Last Updated: 11/27/2018 11 | ****************************************************************************** 12 | */ 13 | #ifndef HASH_H 14 | #define HASH_H 15 | 16 | #define NOTFOUND 0 17 | 18 | typedef struct DataEntryStruct *HashTable; 19 | 20 | HashTable *hashtable_create(void); 21 | int hashtable_insert(HashTable *, char *, int); 22 | int hashtable_find(HashTable *, char *); 23 | char *hashtable_findkey(HashTable *, char *); 24 | void hashtable_free(HashTable *); 25 | int hashtable_update(HashTable *ht, char *key, int new_data); 26 | int hashtable_delete(HashTable *ht, char *key); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /man/ENsetlinktype.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/links22.r 3 | \name{ENsetlinktype} 4 | \alias{ENsetlinktype} 5 | \title{Change a link's type} 6 | \usage{ 7 | ENsetlinktype(index, type, action = "EN_UNCONDITIONAL") 8 | } 9 | \arguments{ 10 | \item{index}{of link before type change} 11 | 12 | \item{type}{the new type to change the link to (see details)} 13 | 14 | \item{action}{the action taken if any controls contain the link (see details)} 15 | } 16 | \value{ 17 | link index after the type change 18 | } 19 | \description{ 20 | Change a link's type 21 | } 22 | \details{ 23 | Link type is one of: EN_CVPIPE, EN_PIPE, EN_PUMP, EN_PRV, EN_PSV, EN_PBV, EN_FCV, EN_TCV, EN_GPV 24 | 25 | If actionCode is EN_UNCONDITIONAL then all simple and rule-based controls that 26 | contain the link are deleted when the link's type is changed. If set to 27 | EN_CONDITIONAL then the type change is cancelled if the link appears in any 28 | control and error 261 is returned. 29 | } 30 | -------------------------------------------------------------------------------- /man/ENepanet.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/epanet.r 3 | \name{ENepanet} 4 | \alias{ENepanet} 5 | \title{ENepanet} 6 | \usage{ 7 | ENepanet(inpFile, rptFile, binOutFile = "") 8 | } 9 | \arguments{ 10 | \item{inpFile}{name of input file} 11 | 12 | \item{rptFile}{name of report file (to be created)} 13 | 14 | \item{binOutFile}{name of optional binary output file} 15 | } 16 | \value{ 17 | Returns NULL invisibly; called for side effect 18 | } 19 | \description{ 20 | runs a complete EPANET simulation 21 | } 22 | \examples{ 23 | # path to Net1.inp example file included with this package 24 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 25 | print(inp) 26 | ENepanet( inp, "Net1.rpt") 27 | # try opening Net1.rpt in a text editor or reading it back 28 | # into R with the read.rpt() function in package epanetReader 29 | myRpt <- epanetReader::read.rpt("Net1.rpt") 30 | summary(myRpt) 31 | # clean-up the created file 32 | file.remove("Net1.rpt") 33 | } 34 | -------------------------------------------------------------------------------- /man/ENsettankdata.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/nodes.r 3 | \name{ENsettankdata} 4 | \alias{ENsettankdata} 5 | \title{Sets properties for a tank} 6 | \usage{ 7 | ENsettankdata( 8 | nodeindex, 9 | elevation, 10 | init_level, 11 | min_level, 12 | max_level, 13 | diameter, 14 | min_volume, 15 | volume_curve = "" 16 | ) 17 | } 18 | \arguments{ 19 | \item{nodeindex}{tank's node index (starting from 1)} 20 | 21 | \item{elevation}{the tank's bottom elevation.} 22 | 23 | \item{init_level}{the initial water level in the tank.} 24 | 25 | \item{min_level}{the minimum water level for the tank.} 26 | 27 | \item{max_level}{the maximum water level for the tank.} 28 | 29 | \item{diameter}{the tank's diameter (0 if a volume curve is supplied).} 30 | 31 | \item{min_volume}{the volume of the tank at its minimum water level.} 32 | 33 | \item{volume_curve}{the name of the tank's volume curve ("" for no curve)} 34 | } 35 | \description{ 36 | Sets properties for a tank 37 | } 38 | -------------------------------------------------------------------------------- /man/ENgetlinknodes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/links.r 3 | \name{ENgetlinknodes} 4 | \alias{ENgetlinknodes} 5 | \title{Retrieve the index of the end nodes of a link} 6 | \usage{ 7 | ENgetlinknodes(linkindex) 8 | } 9 | \arguments{ 10 | \item{linkindex}{integer specifying the link index} 11 | } 12 | \value{ 13 | integer vector of node indices for this link 14 | } 15 | \description{ 16 | Retrieve the index of the end nodes of a link 17 | } 18 | \note{ 19 | Node and link indexes are consecutive integers starting from 1. 20 | 21 | The From and To nodes are as defined for the link in the EPANET input file. The actual direction of 22 | flow in the link is not considered. 23 | } 24 | \examples{ 25 | # path to Net1.inp example file included with this package 26 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 27 | ENopen( inp, "Net1.rpt") 28 | ENgetlinknodes(1) 29 | ENgetlinknodes(11) 30 | ENclose() 31 | } 32 | \seealso{ 33 | \code{\link{ENgetlinkindex} } 34 | } 35 | -------------------------------------------------------------------------------- /man/ENinitQ.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/quality.r 3 | \name{ENinitQ} 4 | \alias{ENinitQ} 5 | \title{Initialize water quality analysis} 6 | \usage{ 7 | ENinitQ(saveFlag) 8 | } 9 | \arguments{ 10 | \item{saveFlag}{boolean or integer indicating whether to save quality results to a file} 11 | } 12 | \value{ 13 | Returns NULL invisibly on success or throws an error or warning 14 | } 15 | \description{ 16 | Initialize water quality analysis 17 | } 18 | \details{ 19 | Call ENinitQ before running quality analysis using ENrunQ with ENnextQ or ENstepQ. 20 | ENopenQ must have been called prior to calling ENinitQ. 21 | Do not call ENinitQ with ENsolveQ. 22 | } 23 | \examples{ 24 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 25 | ENopen( inp, "Net1.rpt") 26 | ENsolveH() 27 | ENsetqualtype("EN_CHEM", "Chlorine", "mg/L", "") 28 | ENopenQ() 29 | ENinitQ(0) 30 | ENrunQ() 31 | ENcloseQ() 32 | ENclose() 33 | # clean-up the created files 34 | file.remove("Net1.rpt") 35 | } 36 | -------------------------------------------------------------------------------- /tests/testthat/test_ENopen.r: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2017, 2020 4 | # Author: Ernesto Arandia & Bradley J Eck 5 | # 6 | #***************************************** 7 | 8 | context("ENopen") 9 | 10 | test_that("open w good inputs",{ 11 | expect_silent( ENopen("Net1.inp", "Net1.rpt")) 12 | ENclose() 13 | }) 14 | 15 | test_that("error if it's already open",{ 16 | 17 | ENopen("Net1.inp", "Net1.rpt", "") 18 | expect_false( suppressWarnings( is.null(ENgetflowunits() ) ) ) 19 | expect_error(ENopen("Net3.inp", "Net3.rpt") ) 20 | ENclose() 21 | expect_true( suppressWarnings( is.null(ENgetflowunits() ) ) ) 22 | 23 | }) 24 | 25 | test_that("returns NULL invisibly on success",{ 26 | x <- withVisible( ENopen("Net1.inp", "Net1.rpt") ) 27 | ENclose() 28 | 29 | expect_null( x$value) 30 | 31 | expect_false( x$visible) 32 | 33 | }) 34 | 35 | test_that("returns error code",{ 36 | 37 | expect_error( ENopen("Net55.inp", "Net55.rpt"), "302") 38 | 39 | }) 40 | -------------------------------------------------------------------------------- /man/ENgetnodetype.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/nodes.r 3 | \name{ENgetnodetype} 4 | \alias{ENgetnodetype} 5 | \title{Retrieve the node-type code} 6 | \usage{ 7 | ENgetnodetype(nodeindex) 8 | } 9 | \arguments{ 10 | \item{nodeindex}{An integer specifying the node index.} 11 | } 12 | \value{ 13 | integer type-code of the node. 14 | } 15 | \description{ 16 | \code{ENgetnodetype} retrieves the node-type code 17 | } 18 | \note{ 19 | Node indexes are consecutive integers starting from 1. 20 | 21 | Node type codes consist of the following constants: 22 | 23 | \tabular{lll}{ 24 | \code{EN_JUNCTION} \tab 0 \tab Junction node\cr 25 | \code{EN_RESERVOIR} \tab 1 \tab Reservoir node\cr 26 | \code{EN_TANK} \tab 2 \tab Tank node 27 | } 28 | } 29 | \examples{ 30 | # path to Net1.inp example file included with this package 31 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 32 | ENopen( inp, "Net1.rpt") 33 | ENgetnodetype(1) 34 | ENgetnodetype(10) 35 | ENgetnodetype(11) 36 | ENclose() 37 | } 38 | -------------------------------------------------------------------------------- /man/ENsetoption.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/options.r 3 | \name{ENsetoption} 4 | \alias{ENsetoption} 5 | \title{Set the value of a particular analysis option.} 6 | \usage{ 7 | ENsetoption(optioncode, value) 8 | } 9 | \arguments{ 10 | \item{optioncode}{An integer or character vector specifying the option} 11 | 12 | \item{value}{numeric} 13 | } 14 | \description{ 15 | \code{ENsetoption} sets the value of a particular analysis option. 16 | } 17 | \details{ 18 | Option codes consist of the following constants: 19 | 20 | \tabular{lr}{ 21 | \code{EN_TRIALS} \tab 0\cr 22 | \code{EN_ACCURACY} \tab 1\cr 23 | \code{EN_TOLERANCE} \tab 2\cr 24 | \code{EN_EMITEXPON} \tab 3\cr 25 | \code{EN_DEMANDMULT} \tab 4 26 | } 27 | } 28 | \examples{ 29 | # path to Net1.inp example file included with this package 30 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 31 | ENopen( inp, "Net1.rpt") 32 | ENgetoption("EN_TRIALS") 33 | ENsetoption("EN_TRIALS", 22) 34 | ENgetoption("EN_TRIALS") 35 | ENclose() 36 | } 37 | -------------------------------------------------------------------------------- /man/ENgetpremise.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rules.r 3 | \name{ENgetpremise} 4 | \alias{ENgetpremise} 5 | \title{Gets the properties of a premise in a rule-based control.} 6 | \usage{ 7 | ENgetpremise(ruleIndex, premiseIndex) 8 | } 9 | \arguments{ 10 | \item{ruleIndex}{the rule's index (starting from 1).} 11 | 12 | \item{premiseIndex}{the position of the premise in the rule's list of premises (starting from 1).} 13 | } 14 | \value{ 15 | list with components: 16 | \describe{ 17 | \item{logop}{the premise's logical operator ( IF = 1, AND = 2, OR = 3 )} 18 | \item{object}{the type of object the premise refers to} 19 | \item{objIndex}{the index of the object (e.g. the index of a tank)} 20 | \item{variable}{the object's variable being compared} 21 | \item{relop}{the premise's comparison operator} 22 | \item{status}{the status that the object's status is compared to} 23 | \item{value}{the value that the object's variable is compared to} 24 | } 25 | } 26 | \description{ 27 | Gets the properties of a premise in a rule-based control. 28 | } 29 | -------------------------------------------------------------------------------- /man/ENinit.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/epanet.r 3 | \name{ENinit} 4 | \alias{ENinit} 5 | \title{ENinit} 6 | \usage{ 7 | ENinit(rptFile, outFile, unitsType, headLossType) 8 | } 9 | \arguments{ 10 | \item{rptFile}{the name of a report file to be created (or "" if not needed).} 11 | 12 | \item{outFile}{the name of a binary output file to be created (or "" if not needed).} 13 | 14 | \item{unitsType}{the choice of flow units. One of: "EN_CFS", "EN_GPM", "EN_MGD", 15 | "EN_IMGD", "EN_AFD", "EN_LPS", "EN_LPM", "EN_MLD", "EN_CMH", "EN_CMD"} 16 | 17 | \item{headLossType}{the choice of head loss formula . One of: EN_HW, EN_DW, EN_CM} 18 | } 19 | \value{ 20 | Returns NULL invisibly; called for side effect 21 | } 22 | \description{ 23 | Initializes an empty EPANET network 24 | } 25 | \details{ 26 | This function should be called to create an empty EPANET project without 27 | an EPANET-formatted input file. If the 28 | project receives it's network data from an input file then there is no need to 29 | call this function; use ENopen instead. 30 | } 31 | -------------------------------------------------------------------------------- /man/ENsavehydfile.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/hydraulics.r 3 | \name{ENsavehydfile} 4 | \alias{ENsavehydfile} 5 | \title{Saves temporary hydraulics file to disk} 6 | \usage{ 7 | ENsavehydfile(hydfile) 8 | } 9 | \arguments{ 10 | \item{hydfile}{the name of the file to be created.} 11 | } 12 | \value{ 13 | Returns NULL invisibly; called for side effect 14 | } 15 | \description{ 16 | Saves temporary hydraulics file to disk 17 | } 18 | \details{ 19 | Use this function to save the current set of hydraulics results to a file, either for 20 | post-processing or to be used at a later time by calling \code{ENusehydfile}. 21 | 22 | The hydraulics file contains nodal demands and heads and link flows, status, and settings 23 | for all hydraulic time steps, even intermediate ones. 24 | 25 | Before calling this function hydraulic results must have been generated and saved by having 26 | called \code{ENsolveH} or the \code{ENinitH} - \code{ENrunH} - \code{ENnextH} sequence with the initflag 27 | argument of \code{ENinitH} set to EN_SAVE or EN_SAVE_AND_INIT. 28 | } 29 | -------------------------------------------------------------------------------- /man/ENgetoption.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/options.r 3 | \name{ENgetoption} 4 | \alias{ENgetoption} 5 | \title{Retrieve the value of an analysis option.} 6 | \usage{ 7 | ENgetoption(optioncode) 8 | } 9 | \arguments{ 10 | \item{optioncode}{A character or integer specifying the option code 11 | (see below).} 12 | } 13 | \value{ 14 | numeric value of the specified analysis option(s). 15 | } 16 | \description{ 17 | \code{ENgetoption} retrieves the value of one or more particular analysis options. 18 | } 19 | \details{ 20 | Option codes consist of the following constants: 21 | \tabular{ll}{ 22 | \code{EN_TRIALS} \tab 0 \cr 23 | \code{EN_ACCURACY} \tab 1 \cr 24 | \code{EN_TOLERANCE} \tab 2 \cr 25 | \code{EN_EMITEXPON} \tab 3 \cr 26 | \code{EN_DEMANDMULT} \tab 4 27 | } 28 | } 29 | \examples{ 30 | # path to Net1.inp example file included with this package 31 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 32 | ENopen( inp, "Net1.rpt") 33 | ENgetoption(0) 34 | ENgetoption("EN_TRIALS") 35 | ENclose() 36 | } 37 | -------------------------------------------------------------------------------- /src/errormanager.h: -------------------------------------------------------------------------------- 1 | /* 2 | ****************************************************************************** 3 | Project: OWA EPANET 4 | Version: 2.2 5 | Module: util/errormanager.h 6 | Description: Provides a simple interface for managing errors 7 | Authors: see AUTHORS 8 | Copyright: see AUTHORS 9 | License: see LICENSE 10 | Last Updated: 04/02/2019 11 | ****************************************************************************** 12 | */ 13 | 14 | #ifndef ERRORMANAGER_H_ 15 | #define ERRORMANAGER_H_ 16 | 17 | #define ERR_MAXMSG 256 18 | 19 | 20 | #if defined(__cplusplus) 21 | extern "C" { 22 | #endif 23 | 24 | // Forward declaration 25 | typedef struct error_s error_handle_t; 26 | 27 | error_handle_t* create_error_manager(void (*p_error_message)(int, char*, int)); 28 | void delete_error_manager(error_handle_t* error_handle); 29 | 30 | int set_error(error_handle_t* error_handle, int error_code); 31 | int check_error(error_handle_t* error_handle, char **error_message); 32 | void clear_error(error_handle_t* error_handle); 33 | 34 | 35 | #if defined(__cplusplus) 36 | } 37 | #endif 38 | 39 | #endif /* ERRORMANAGER_H_ */ 40 | -------------------------------------------------------------------------------- /man/ENopenH.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/hydraulics.r 3 | \name{ENopenH} 4 | \alias{ENopenH} 5 | \title{Open hydraulics analysis system.} 6 | \usage{ 7 | ENopenH() 8 | } 9 | \value{ 10 | Returns NULL invisibly; called for side effect 11 | } 12 | \description{ 13 | \code{ENopenH} opens the EPANET hydraulics analysis system. 14 | } 15 | \details{ 16 | Call \code{ENopenH} prior to running the first hydraulic analysis using the 17 | \code{ENinitH-ENrunH-ENnextH} sequence. Multiple analyses can be made before calling 18 | \code{ENcloseH} to close the hydraulic analysis system. 19 | 20 | Do not call this function if \code{ENsolveH} is being used to run a complete hydraulic analysis. 21 | } 22 | \examples{ 23 | # path to Net1.inp example file included with this package 24 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 25 | ENopen( inp, "Net1.rpt") 26 | ENopenH() 27 | ENinitH(0) 28 | ENrunH() 29 | ENcloseH() 30 | ENclose() 31 | # clean-up the created files 32 | file.remove("Net1.rpt") 33 | } 34 | \seealso{ 35 | \code{ENinitH}, \code{ENrunH}, \code{ENnextH}, \code{ENcloseH} 36 | } 37 | -------------------------------------------------------------------------------- /man/ENsetpremise.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rules.r 3 | \name{ENsetpremise} 4 | \alias{ENsetpremise} 5 | \title{Sets the properties of a premise in a rule-based control.} 6 | \usage{ 7 | ENsetpremise( 8 | ruleIndex, 9 | premiseIndex, 10 | logop, 11 | object, 12 | objIndex, 13 | variable, 14 | relop, 15 | status, 16 | value 17 | ) 18 | } 19 | \arguments{ 20 | \item{ruleIndex}{the rule's index (starting from 1).} 21 | 22 | \item{premiseIndex}{the position of the premise in the rule's list of premises.} 23 | 24 | \item{logop}{the premise's logical operator ( IF = 1, AND = 2, OR = 3 ).} 25 | 26 | \item{object}{the type of object the premise refers to} 27 | 28 | \item{objIndex}{the index of the object (e.g. the index of a tank)} 29 | 30 | \item{variable}{the object's variable being compared} 31 | 32 | \item{relop}{the premise's comparison operator} 33 | 34 | \item{status}{the status that the object's status is compared to} 35 | 36 | \item{value}{the value that the object's variable is compared to.} 37 | } 38 | \value{ 39 | null 40 | } 41 | \description{ 42 | Sets the properties of a premise in a rule-based control. 43 | } 44 | -------------------------------------------------------------------------------- /man/ENgetpatternvalue.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/patterns.r 3 | \name{ENgetpatternvalue} 4 | \alias{ENgetpatternvalue} 5 | \title{Retrieve the multiplier factor for a specific time period} 6 | \usage{ 7 | ENgetpatternvalue(index, period) 8 | } 9 | \arguments{ 10 | \item{index}{An integer specifying the time pattern index.} 11 | 12 | \item{period}{An integer or integer vector of the periods within the time pattern.} 13 | } 14 | \value{ 15 | A numeric or numeric vector, the multiplier factor for the specific time pattern and period. 16 | } 17 | \description{ 18 | \code{ENgetpatternvalue} retrieves the multiplier factor for specific time periods in a pattern. 19 | } 20 | \note{ 21 | Pattern indexes and periods are consecutive integers starting from 1. 22 | } 23 | \examples{ 24 | # path to Net1.inp example file included with this package 25 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 26 | ENopen( inp, "Net1.rpt") 27 | ENgetpatternvalue(1,1) 28 | ENgetpatternvalue(1,2) 29 | ENgetpatternvalue(1,3) 30 | ENclose() 31 | } 32 | \seealso{ 33 | \code{ENgetpatternindex}, \code{ENgetpatternlen}, \code{ENsetpatternvalue} 34 | } 35 | -------------------------------------------------------------------------------- /man/ENgetstatistic.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/report.r 3 | \name{ENgetstatistic} 4 | \alias{ENgetstatistic} 5 | \title{Analysis convergence statistics.} 6 | \usage{ 7 | ENgetstatistic(stat) 8 | } 9 | \arguments{ 10 | \item{stat}{one of the statistics tabulated below} 11 | } 12 | \value{ 13 | value of the stat 14 | } 15 | \description{ 16 | Analysis convergence statistics. 17 | } 18 | \details{ 19 | These statistics report the convergence criteria for the most current 20 | hydraulic analysis and the cumulative water quality mass balance error at the 21 | current simulation time. 22 | 23 | \tabular{ll}{ 24 | \code{EN_ITERATIONS} \tab Number of hydraulic iterations taken. \cr 25 | \code{EN_RELATIVEERROR} \tab Sum of link flow changes / sum of link flows. \cr 26 | \code{EN_MAXHEADERROR} \tab Largest head loss error for links. \cr 27 | \code{EN_MAXFLOWCHANGE} \tab Largest flow change in links. \cr 28 | \code{EN_MASSBALANCE} \tab Cumulative water quality mass balance ratio. \cr 29 | \code{EN_DEFICIENTNODES} \tab Number of pressure deficient nodes. \cr 30 | \code{EN_DEMANDREDUCTION} \tab % demand reduction at pressure deficient nodes \cr 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /man/ENsetpattern.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/patterns.r 3 | \name{ENsetpattern} 4 | \alias{ENsetpattern} 5 | \title{Set all of the multiplier factors for a specific time pattern.} 6 | \usage{ 7 | ENsetpattern(index, factors) 8 | } 9 | \arguments{ 10 | \item{index}{An integer, the pattern index.} 11 | 12 | \item{factors}{A numeric vector, the multiplier factors for the entire pattern.} 13 | } 14 | \description{ 15 | \code{ENsetpattern} sets all of the multiplier factors for a specific time pattern. 16 | } 17 | \details{ 18 | Pattern indexes are consecutive integers starting from 1. 19 | 20 | Use this function to redefine (and resize) a time pattern all at once; use 21 | \code{ENsetpatternvalue} to revise pattern factors in specific time periods of a pattern. 22 | } 23 | \examples{ 24 | # path to Net1.inp example file included with this package 25 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 26 | ENopen( inp, "Net1.rpt") 27 | ENsetpattern(1, 1:10) 28 | ENgetpatternvalue(1,1) 29 | ENgetpatternvalue(1,10) 30 | ENclose() 31 | } 32 | \seealso{ 33 | \code{ENgetpatternindex}, \code{ENgetpatternlen}, 34 | \code{ENgetpatternvalue}, \code{ENsetpatternvalue} 35 | } 36 | -------------------------------------------------------------------------------- /tests/testthat/test_epanet_example_2.r: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2017 4 | # 5 | # Author: Bradley J Eck & Ernesto Arandia 6 | # 7 | #***************************************** 8 | 9 | context("Hydrant Rating Example") 10 | 11 | test_that("verify example 2",{ 12 | 13 | MyNode <- "11" 14 | Demand <- seq(from = 2, to = 50, by = 2) 15 | N <- length(Demand) 16 | Pressure <- rep(NA, N) 17 | 18 | # Open the toolkit and hydraulics solver 19 | ENopen("Net2.inp", "Net2.rpt") 20 | ENopenH() 21 | 22 | # Get the node index of interest 23 | index <- ENgetnodeindex(MyNode) 24 | 25 | # iterate over all demands 26 | 27 | for( i in 1:N){ 28 | 29 | ENsetnodevalue(index, 'EN_BASEDEMAND', Demand[i]) 30 | ENinitH(0) 31 | ENrunH() 32 | Pressure[i] <- ENgetnodevalue(index, 'EN_PRESSURE') 33 | } 34 | 35 | # close hydraulics solver and toolkit 36 | ENcloseH() 37 | ENclose() 38 | 39 | # Visualize the result 40 | #plot( Pressure ~ Demand, las=1, 41 | # main = "Example 2 - Hydrant Rating Curve", 42 | # sub = paste("Net 2, node", MyNode)) 43 | 44 | # test succeeds if you got here 45 | expect_true( TRUE ) 46 | }) 47 | -------------------------------------------------------------------------------- /man/ENaddlink.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/links22.r 3 | \name{ENaddlink} 4 | \alias{ENaddlink} 5 | \title{Add a link to the network} 6 | \usage{ 7 | ENaddlink(id, type, from_node, to_node) 8 | } 9 | \arguments{ 10 | \item{id}{name of new link} 11 | 12 | \item{type}{of new link, see details} 13 | 14 | \item{from_node}{id of source node for this link} 15 | 16 | \item{to_node}{id of target node for this link} 17 | } 18 | \value{ 19 | index of new link 20 | } 21 | \description{ 22 | Add a link to the network 23 | } 24 | \details{ 25 | A new pipe is assigned a diameter of 10 inches (254 mm) and a length of 330 26 | feet (~ 100 meters). Its roughness coefficient depends on the head loss formula in effect as follows: 27 | - Hazen-Williams formula: 130 28 | - Darcy-Weisbach formula: 0.5 millifeet (0.15 mm) 29 | - Chezy-Manning formula: 0.01 30 | 31 | All other pipe properties are set to 0. 32 | 33 | A new pump has a status of EN_OPEN, a speed setting of 1, and has no pump 34 | curve or power rating assigned to it. 35 | 36 | A new valve has a diameter of 10 inches (254 mm) and all other properties set to 0. 37 | 38 | Type must be one of: EN_CVPIPE, EN_PIPE, EN_PUMP, EN_PRV, EN_PSV, EN_PBV, EN_FCV, EN_TCV, EN_GPV 39 | } 40 | -------------------------------------------------------------------------------- /man/ENrunH.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/hydraulics.r 3 | \name{ENrunH} 4 | \alias{ENrunH} 5 | \title{run hydraulics engine} 6 | \usage{ 7 | ENrunH() 8 | } 9 | \value{ 10 | Current simulation clock time. 11 | } 12 | \description{ 13 | \code{ENrunH} Runs a single period hydraulic analysis, retrieving the 14 | current simulation clock time \code{t}. 15 | } 16 | \details{ 17 | Use \code{ENrunH} along with \code{ENnextH} in a while loop to 18 | analyze hydraulics in each period of an extended period simulation. 19 | This process automatically updates the simulation clock time so treat 20 | \code{t} as a read-only variable. 21 | 22 | \code{ENinitH} must have been called prior to running the 23 | \code{ENrunH-ENnextH} loop. 24 | 25 | See \code{ENnextH} for an example of using this function. 26 | } 27 | \examples{ 28 | # path to Net1.inp example file included with this package 29 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 30 | ENopen( inp, "Net1.rpt") 31 | ENopenH() 32 | ENinitH(0) 33 | ENrunH() 34 | ENcloseH() 35 | ENclose() 36 | # clean-up the created files 37 | file.remove("Net1.rpt") 38 | } 39 | \seealso{ 40 | \code{ENopenH}, \code{ENinitH}, \code{ENnextH}, \code{ENcloseH} 41 | } 42 | -------------------------------------------------------------------------------- /man/ENopen.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/Rtoolkit.R 3 | \name{ENopen} 4 | \alias{ENopen} 5 | \title{Open the EPANET Toolkit.} 6 | \usage{ 7 | ENopen(inpFileName, rptFileName, outFileName) 8 | } 9 | \arguments{ 10 | \item{inpFileName}{A string, the name of the EPANET Input file.} 11 | 12 | \item{rptFileName}{A string, the name of the EPANET Report file.} 13 | 14 | \item{outFileName}{A string, the name of an optional binary Output file.} 15 | } 16 | \value{ 17 | returns NULL invisibly on success or raises an error or warning. 18 | } 19 | \description{ 20 | \code{ENopen} opens the EPANET Toolkit to analyze a particular water distribution system. 21 | } 22 | \note{ 23 | If there is no need to save an EPANET's binary Output file, then \code{outFileName} 24 | can be an empty string (""). 25 | 26 | If \code{rptFileName} is an empty string, reporting will be made to the operating system 27 | \code{stdout} device (which is usually the console/terminal). 28 | 29 | \code{enOpen} must be called before any of the other toolkit functions are used. The only 30 | exception is \code{enEpanet}. 31 | } 32 | \examples{ 33 | # path to Net1.inp example file included with this package 34 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 35 | ENopen( inp, "Net1.rpt") 36 | ENclose() 37 | } 38 | \seealso{ 39 | \code{ENclose} 40 | } 41 | -------------------------------------------------------------------------------- /man/ENgetcount.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/Rtoolkit.R 3 | \name{ENgetcount} 4 | \alias{ENgetcount} 5 | \title{Get number of network elements.} 6 | \usage{ 7 | ENgetcount(compcode) 8 | } 9 | \arguments{ 10 | \item{compcode}{A character string, integer or numeric specifying the component code(s) 11 | (see below).} 12 | } 13 | \value{ 14 | The number of network components. 15 | } 16 | \description{ 17 | \code{ENgetcount} retrieves the number of network components of a specific type. 18 | } 19 | \details{ 20 | Component codes consist of the following: 21 | \tabular{lll}{ 22 | \code{EN_NODECOUNT} \tab 0 \tab Nodes\cr 23 | \code{EN_TANKCOUNT} \tab 1 \tab Reservoirs and tank nodes\cr 24 | \code{EN_LINKCOUNT} \tab 2 \tab Links\cr 25 | \code{EN_PATCOUNT} \tab 3 \tab Time patterns\cr 26 | \code{EN_CURVECOUNT} \tab 4 \tab Curves\cr 27 | \code{EN_CONTROLCOUNT} \tab 5 \tab Simple controls\cr 28 | \code{EN_RULECOUNT} \tab 5 \tab Simple controls 29 | } 30 | 31 | The number of junctions in a network equals the number of nodes minus the number of tanks and reservoirs. 32 | } 33 | \examples{ 34 | # path to Net1.inp example file included with this package 35 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 36 | ENopen( inp, "Net1.rpt") 37 | ENgetcount(0) 38 | ENgetcount("EN_NODECOUNT") 39 | ENclose() 40 | } 41 | -------------------------------------------------------------------------------- /man/ENgetlinktype.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/links.r 3 | \name{ENgetlinktype} 4 | \alias{ENgetlinktype} 5 | \title{Retrieve the type code for a link} 6 | \usage{ 7 | ENgetlinktype(linkindex) 8 | } 9 | \arguments{ 10 | \item{linkindex}{for which type code is requested} 11 | } 12 | \value{ 13 | integer type-code of the link 14 | } 15 | \description{ 16 | Retrieve the type code for a link 17 | } 18 | \note{ 19 | Link indexes are consecutive integers starting from 1. Link type codes 20 | consist of the following constants: 21 | \tabular{lll}{ 22 | \code{EN_CVPIPE} \tab 0 \tab Pipe with Check Valve\cr 23 | \code{EN_PIPE} \tab 1 \tab Pipe\cr 24 | \code{EN_PUMP} \tab 2 \tab Pump\cr 25 | \code{EN_PRV} \tab 3 \tab Pressure Reducing Valve\cr 26 | \code{EN_PSV} \tab 4 \tab Pressure Sustaining Valve\cr 27 | \code{EN_PBV} \tab 5 \tab Pressure Breaker Valve\cr 28 | \code{EN_FCV} \tab 6 \tab Flow Control Valve\cr 29 | \code{EN_TCV} \tab 7 \tab Throttle Control Valve\cr 30 | \code{EN_GPV} \tab 8 \tab General Purpose Valve\cr 31 | } 32 | } 33 | \examples{ 34 | # path to Net1.inp example file included with this package 35 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 36 | ENopen( inp, "Net1.rpt") 37 | ENgetlinktype(1) 38 | ENgetlinktype(12) 39 | ENclose() 40 | } 41 | \seealso{ 42 | \code{\link{ENgetlinkindex}} 43 | } 44 | -------------------------------------------------------------------------------- /R/pumps.r: -------------------------------------------------------------------------------- 1 | #' Retrieves type of head curve used by a pump 2 | #' 3 | #' @param linkindex index of the pump 4 | #' @return type of head curve 5 | #' @export 6 | #' @useDynLib epanet2toolkit RENgetpumptype 7 | ENgetpumptype <- function(linkindex){ 8 | 9 | res <- .C("RENgetpumptype", as.integer(linkindex), as.integer(-1), as.integer(-1)) 10 | check_epanet_error(res[[3]]) 11 | pump_type_int <- res[[2]] 12 | pump_type_char <- EN_PumpType[pump_type_int+1] 13 | return(pump_type_char) 14 | } 15 | 16 | 17 | 18 | #' Retrieves index of head curve used by a pump 19 | #' 20 | #' @param linkindex index of the pump 21 | #' @return index of head curve 22 | #' @export 23 | #' @useDynLib epanet2toolkit RENgetheadcurveindex 24 | ENgetheadcurveindex <- function(linkindex){ 25 | res <- .C("RENgetheadcurveindex", as.integer(linkindex), as.integer(-1), as.integer(-1)) 26 | check_epanet_error(res[[3]]) 27 | return( res[[2]]) 28 | } 29 | 30 | #' Sets index of head curve used by a pump 31 | #' 32 | #' @param linkindex index of the pump 33 | #' @param curveindex index of head curve to assign 34 | #' @return null invisibly 35 | #' @export 36 | #' @useDynLib epanet2toolkit RENsetheadcurveindex 37 | ENsetheadcurveindex <- function(linkindex, curveindex){ 38 | res <- .C("RENsetheadcurveindex", as.integer(linkindex), as.integer(curveindex), as.integer(-1)) 39 | check_epanet_error(res[[3]]) 40 | return( invisible()) 41 | } -------------------------------------------------------------------------------- /R/util.r: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2017, 2020 4 | # Author: Bradley J Eck 5 | # 6 | # 7 | #****************************************/ 8 | 9 | # take an integer from a character vector 10 | # and return an integer if possible 11 | # or a trimmed character if not 12 | charlong_to_int_or_char <- function( charlong ){ 13 | 14 | # check the argument 15 | if( !is.character(charlong)) stop("argument must be character") 16 | 17 | suppressWarnings( return_value <- as.integer( charlong)) 18 | 19 | if( is.na(return_value)){ 20 | return_value <- gsub("\\s*", "", charlong) 21 | } 22 | return( return_value) 23 | 24 | } 25 | 26 | check_char_length_1 <- function( x ){ 27 | if( !is.character(x)) stop("must be character") 28 | if(length(x)!=1) stop("must have length 1") 29 | } 30 | 31 | 32 | lookup_enum_value <- function(codeTable, optioncode){ 33 | 34 | # check the arguments 35 | if( length(optioncode) != 1 ) stop("can only get one option at time") 36 | if (is.character(optioncode)) { 37 | code <- as.integer(match(optioncode, codeTable) - 1) 38 | } 39 | else if (is.numeric(optioncode)) { 40 | code <- as.integer(optioncode) 41 | } 42 | else if (is.integer(optioncode)) { 43 | code <- optioncode 44 | } 45 | else{ 46 | stop("This parameter must must be a character string or an integer.") 47 | } 48 | if (any(is.na(code))) { 49 | stop("The code specified is incorrect.") 50 | } 51 | 52 | return(code) 53 | } -------------------------------------------------------------------------------- /man/ENgetqualtype.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/Rtoolkit.R, R/quality.r 3 | \name{ENgetqualtype} 4 | \alias{ENgetqualtype} 5 | \title{Retrieve the type of water quality analysis called for.} 6 | \usage{ 7 | ENgetqualtype() 8 | 9 | ENgetqualtype() 10 | } 11 | \value{ 12 | A named integer vector, the water quality analysis code (see below) and 13 | the index of node traced in a source tracing analysis. 14 | 15 | list of qualcode and trace node 16 | } 17 | \description{ 18 | \code{ENgetqualtype} retrieves the type of water quality analysis called for. 19 | } 20 | \note{ 21 | Water quality analysis codes are as follows: 22 | \tabular{lll}{ 23 | \code{EN_NONE} \tab 0 \tab No quality analysis\cr 24 | \code{EN_CHEM} \tab 1 \tab Chemical analysis\cr 25 | \code{EN_AGE} \tab 2 \tab Water age analysis\cr 26 | \code{EN_TRACE} \tab 3 \tab Source tracing 27 | } 28 | 29 | The tracenode value will be 0 when the quality code is not \code{EN_TRACE}. 30 | } 31 | \examples{ 32 | # path to Net1.inp example file included with this package 33 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 34 | ENopen( inp, "Net1.rpt") 35 | ENgetqualtype() 36 | ENclose() 37 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 38 | ENopen( inp, "Net1.rpt") 39 | ENgetqualtype() 40 | ENclose() 41 | # clean-up the created files 42 | file.remove("Net1.rpt") 43 | } 44 | \seealso{ 45 | \code{ENsetqualtype} 46 | } 47 | -------------------------------------------------------------------------------- /R/enums.r: -------------------------------------------------------------------------------- 1 | 2 | actionTypes <- c("EN_UNCONDITIONAL", "EN_CONDITIONAL") 3 | 4 | 5 | linkTypes <- c( 6 | "EN_CVPIPE",# = 0, //!< Pipe with check valve 7 | "EN_PIPE",# = 1, //!< Pipe 8 | "EN_PUMP",# = 2, //!< Pump 9 | "EN_PRV",# = 3, //!< Pressure reducing valve 10 | "EN_PSV",# = 4, //!< Pressure sustaining valve 11 | "EN_PBV",# = 5, //!< Pressure breaker valve 12 | "EN_FCV",# = 6, //!< Flow control valve 13 | "EN_TCV",# = 7, //!< Throttle control valve 14 | "EN_GPV")# = 8 //!< General purpose valve 15 | 16 | EN_PumpType <-c( 17 | "EN_CONST_HP",# = 0, //!< Constant horsepower 18 | "EN_POWER_FUNC",# = 1, //!< Power function 19 | "EN_CUSTOM",# = 2, //!< User-defined custom curve 20 | "EN_NOCURVE")# = 3 //!< No curve 21 | 22 | EN_CurveType <- c( 23 | "EN_VOLUME_CURVE",# = 0, //!< Tank volume v. depth curve 24 | "EN_PUMP_CURVE",# = 1, //!< Pump head v. flow curve 25 | "EN_EFFIC_CURVE",# = 2, //!< Pump efficiency v. flow curve 26 | "EN_HLOSS_CURVE",# = 3, //!< Valve head loss v. flow curve 27 | "EN_GENERIC_CURVE")# = 4 //!< Generic curve 28 | 29 | EN_MAXID <- as.integer(31) 30 | 31 | EN_ControlType <- c( 32 | "EN_LOWLEVEL",# = 0, //!< Act when pressure or tank level drops below a setpoint 33 | "EN_HILEVEL",# = 1, //!< Act when pressure or tank level rises above a setpoint 34 | "EN_TIMER",# = 2, //!< Act at a prescribed elapsed amount of time 35 | "EN_TIMEOFDAY"# = 3 //!< Act at a particular time of day 36 | ) -------------------------------------------------------------------------------- /src/cstr_helper.c: -------------------------------------------------------------------------------- 1 | /* 2 | ****************************************************************************** 3 | Project: OWA EPANET 4 | Version: 2.2 5 | Module: util/cstr_helper.c 6 | Description: Provides C string helper functions 7 | Authors: see AUTHORS 8 | Copyright: see AUTHORS 9 | License: see LICENSE 10 | Last Updated: 04/02/2019 11 | ****************************************************************************** 12 | */ 13 | 14 | #include 15 | #include 16 | 17 | #include "cstr_helper.h" 18 | 19 | 20 | int cstr_duplicate(char **dest, const char *source) 21 | // Duplicates source string 22 | { 23 | size_t size = 1 + strlen(source); 24 | *dest = (char *) calloc(size, sizeof(char)); 25 | 26 | if (*dest == NULL) 27 | return -1; 28 | else { 29 | #ifdef _MSC_VER 30 | strncpy_s(*dest, size, source, size); 31 | #else 32 | strncpy(*dest, source, size); 33 | #endif 34 | } 35 | return 0; 36 | } 37 | 38 | 39 | bool cstr_isvalid(const char *element_id) 40 | // Determines if invalid characters are present in an element id string 41 | { 42 | const char *invalid_chars = " \";"; 43 | 44 | // if invalid char is present a pointer to it is returned else NULL 45 | if (strpbrk(element_id, invalid_chars)) 46 | return false; 47 | else 48 | return true; 49 | } 50 | 51 | 52 | bool cstr_isnullterm(const char *source) 53 | // Determines if the string passed is null terminated or not 54 | { 55 | if (strchr(source, '\0')) 56 | return true; 57 | else 58 | return false; 59 | } 60 | -------------------------------------------------------------------------------- /tests/testthat/test_curves.r: -------------------------------------------------------------------------------- 1 | 2 | context("curves") 3 | 4 | test_that("Net 3 curve gets",{ 5 | 6 | suffix <- paste0( sample(letters, 4), collapse="") 7 | rptFile <- paste0("curve-tests-", suffix,".rpt") 8 | ENopen("Net3.inp", rptFile) 9 | 10 | cid <- ENgetcurveid(1) 11 | idx <- ENgetcurveindex(cid) 12 | expect_equal(1, idx) 13 | 14 | len <- ENgetcurvelen(idx) 15 | expect_true(len > 0) 16 | 17 | type <- ENgetcurvetype(idx) 18 | expect_false(is.null(type)) 19 | expect_equal(type,"EN_PUMP_CURVE") 20 | 21 | val <- ENgetcurvevalue(idx, 3) 22 | expect_equal(as.integer(val$x), 4000) 23 | expect_equal(as.integer(val$y), 63) 24 | 25 | ENclose() 26 | file.remove(rptFile) 27 | }) 28 | 29 | test_that("Net 3 curve CRUD",{ 30 | 31 | suffix <- paste0( sample(letters, 4), collapse="") 32 | rptFile <- paste0("curve-tests-", suffix,".rpt") 33 | ENopen("Net3.inp", rptFile) 34 | 35 | ENaddcurve(suffix) 36 | idx <- ENgetcurveindex(suffix) 37 | expect_equal(idx, 3) 38 | 39 | len <- ENgetcurvelen(idx) 40 | expect_equal(len, 1) 41 | 42 | ENsetcurvevalue(idx, 2, 2, 2) 43 | val <- ENgetcurvevalue(idx, 2) 44 | expect_equal(as.integer(val$x), 2) 45 | expect_equal(as.integer(val$y), 2) 46 | 47 | len <- ENgetcurvelen(idx) 48 | expect_equal(len, 2) 49 | 50 | 51 | suff2 <- paste0( sample(letters, 4), collapse="") 52 | ENsetcurveid(idx,suff2) 53 | idx2 <- ENgetcurveindex(suff2) 54 | expect_equal(idx, idx2) 55 | 56 | 57 | 58 | ENdeletecurve(idx) 59 | 60 | 61 | 62 | ENclose() 63 | file.remove(rptFile) 64 | }) 65 | -------------------------------------------------------------------------------- /man/ENgetflowunits.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/Rtoolkit.R 3 | \name{ENgetflowunits} 4 | \alias{ENgetflowunits} 5 | \title{Retrieve a code number indicating the units used to express all flow rates.} 6 | \usage{ 7 | ENgetflowunits() 8 | } 9 | \value{ 10 | An integer, the code numnber indicating the flow units. 11 | } 12 | \description{ 13 | \code{ENgetflowunits} retrieves a code number indicating the units used to express all flow rates. 14 | } 15 | \note{ 16 | Flow units codes are as follows: 17 | \tabular{lll}{ 18 | 0 \tab = \code{EN_CFS} \tab cubic feet per second\cr 19 | 1 \tab = \code{EN_GPM} \tab gallons per minute\cr 20 | 2 \tab = \code{EN_MGD} \tab million gallons per day\cr 21 | 3 \tab = \code{EN_IMGD} \tab Imperial mgd\cr 22 | 4 \tab = \code{EN_AFD} \tab acre-feet per day\cr 23 | 5 \tab = \code{EN_LPS} \tab liters per second\cr 24 | 6 \tab = \code{EN_LPM} \tab liters per minute\cr 25 | 7 \tab = \code{EN_MLD} \tab million liters per day\cr 26 | 8 \tab = \code{EN_CMH} \tab cubic meters per hour\cr 27 | 9 \tab = \code{EN_CMD} \tab cubic meters per day 28 | } 29 | 30 | Flow units are specified in the \code{[OPTIONS]} section of the EPANET Input file. 31 | 32 | Flow units in liters or cubic meters implies that metric units are used for all other quantities in 33 | addition to flow. Otherwise US units are employed. (See Units of Measurement). 34 | } 35 | \examples{ 36 | # path to Net1.inp example file included with this package 37 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 38 | ENopen( inp, "Net1.rpt") 39 | ENgetflowunits() 40 | ENclose() 41 | } 42 | -------------------------------------------------------------------------------- /R/codes.r: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2017 4 | # Author: Ernesto Arandia & Bradley J Eck 5 | # 6 | #***************************************** 7 | 8 | 9 | 10 | check_epanet_error <- function( rv ){ 11 | 12 | if( !is.integer(rv)) stop("rv must be integer") 13 | 14 | goodMsg <- NA 15 | try(goodMsg <- ENgeterror(rv)) 16 | 17 | if( rv == 0){ 18 | return() 19 | } else if( rv > 100){ 20 | # return values greater than 100 are fatal errors 21 | if( is.na(goodMsg)){ 22 | msg <- paste("epanet error ", rv) 23 | } else { 24 | msg <- goodMsg 25 | } 26 | stop(msg) 27 | } else if( rv <= 100 ){ 28 | # return value 100 or less are warnings; continue evaluating 29 | if (is.na(goodMsg)){ 30 | # unable to obtain a good message so just return the error code 31 | msg <- paste("epanet warning ", rv) 32 | } else { 33 | msg <- paste("epanet warning", rv, goodMsg) 34 | } 35 | warning(msg) 36 | } 37 | } 38 | 39 | check_enum_code <- function( mycode, mytable){ 40 | 41 | if( !is.character(mytable)) stop("table must be character vector") 42 | 43 | if( length(mycode) != 1 ) stop("code must have length of 1") 44 | 45 | # check the arguments 46 | if (missing(mycode)) { 47 | stop("Need to specify the time parameter code.") 48 | } 49 | if (is.character(mycode)) { 50 | code <- as.integer(match(mycode, mytable) - 1) 51 | } 52 | else if (is.numeric(mycode)) { 53 | code = as.integer(mycode) 54 | } 55 | else { 56 | stop("The code must be a character, integer, or number. ") 57 | } 58 | if (any(is.na(code))) { 59 | stop("The time parameter code specified is incorrect.") 60 | } 61 | 62 | return( code ) 63 | 64 | } -------------------------------------------------------------------------------- /man/ENnextH.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/hydraulics.r 3 | \name{ENnextH} 4 | \alias{ENnextH} 5 | \title{determine the next hydraulic step} 6 | \usage{ 7 | ENnextH() 8 | } 9 | \value{ 10 | An integer, the time (in seconds) until next hydraulic event 11 | occurs or 0 if at the end of the simulation period. 12 | } 13 | \description{ 14 | \code{ENnextH} determines the length of time until the next 15 | hydraulic event occurs in an extended period simulation. 16 | } 17 | \details{ 18 | This function is used in conjunction with \code{ENrunH} to 19 | perform an extended period hydraulic analysis (see example below). 20 | 21 | The return value is automatically computed as the smaller of: 22 | 23 | \itemize{ 24 | \item the time interval until the next hydraulic time step begins 25 | \item the time interval until the next reporting time step begins 26 | \item the time interval until the next change in demands occurs 27 | \item the time interval until a tank becomes full or empty 28 | \item the time interval until a control or rule fires 29 | } 30 | } 31 | \examples{ 32 | # path to Net1.inp example file included with this package 33 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 34 | ENopen( inp, "Net1.rpt") 35 | # store simulation times 36 | t = NULL 37 | ENopenH() 38 | ENinitH(11) 39 | repeat { 40 | t <- c(t, ENrunH()) 41 | tstep <- ENnextH() 42 | if (tstep == 0) { 43 | break 44 | } 45 | } 46 | ENcloseH() 47 | ENclose() 48 | # clean-up the created files 49 | file.remove("Net1.rpt") 50 | 51 | } 52 | \seealso{ 53 | \code{ENopenH}, \code{ENinitH}, \code{ENrunH}, \code{ENcloseH}, \code{ENsettimeparam} 54 | } 55 | -------------------------------------------------------------------------------- /tests/testthat/test_coords.r: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2017, 2020 4 | # Author: Ernesto Arandia & Bradley J Eck 5 | # 6 | #***************************************** 7 | 8 | context("get coord") 9 | test_that("no crash calling on closed toolkit",{ 10 | expect_error( x <- ENgetcoord(1) ) 11 | }) 12 | test_that("works for single input",{ 13 | 14 | ENopen("Net1.inp","Net1.rpt") 15 | xy <- ENgetcoord(1) 16 | ENclose() 17 | expect_equal(xy, c(x=20.0, y=70.0)) 18 | 19 | 20 | }) 21 | test_that("works for single input",{ 22 | ENopen("Net3.inp","Net3.rpt") 23 | ix <- ENgetnodeindex("15") 24 | expect_true( is.numeric( ix)) 25 | xy <- ENgetcoord(ix) 26 | ENclose() 27 | expect_equal(xy, c(x=38.68, y=23.76)) 28 | }) 29 | test_that("rejcects char input",{ 30 | ENopen("Net3.inp","Net3.rpt") 31 | expect_error(ENgetcoord("15")) 32 | ENclose() 33 | }) 34 | 35 | test_that("get error 203 on no index",{ 36 | ENopen("Net3.inp","Net3.rpt") 37 | expect_error(ENgetcoord(155),"203") 38 | ENclose() 39 | }) 40 | 41 | context("set coord") 42 | test_that("no crash calling on closed toolkit",{ 43 | expect_error( x <- ENsetcoord(1) ) 44 | }) 45 | test_that("works for single input",{ 46 | ENopen("Net3.inp","Net3.rpt") 47 | ix <- ENgetnodeindex("15") 48 | ENsetcoord(ix, 39.98, 23.23) 49 | xy <- ENgetcoord(ix) 50 | ENclose() 51 | expect_equal(xy, c(x=39.98, y=23.23)) 52 | }) 53 | test_that("rejcects char input",{ 54 | ENopen("Net3.inp","Net3.rpt") 55 | expect_error(ENsetcoord("15", 1,2)) 56 | ENclose() 57 | }) 58 | test_that("get error 203 on no index",{ 59 | ENopen("Net3.inp","Net3.rpt") 60 | expect_error(ENsetcoord(155, 1,2),"203") 61 | ENclose() 62 | }) 63 | 64 | -------------------------------------------------------------------------------- /man/ENsetqualtype.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/quality.r 3 | \name{ENsetqualtype} 4 | \alias{ENsetqualtype} 5 | \title{Set the type of water quality analysis called for.} 6 | \usage{ 7 | ENsetqualtype(qualcode, chemname = "", chemunits = "", tracenode = "") 8 | } 9 | \arguments{ 10 | \item{qualcode}{An integer or a character string, the water quality analysis code (see below).} 11 | 12 | \item{chemname}{A character string, the name of the chemical being analyzed.} 13 | 14 | \item{chemunits}{A character string, units that the chemical is measured in.} 15 | 16 | \item{tracenode}{A character string, ID of node traced in a source tracing analysis.} 17 | } 18 | \value{ 19 | returns NULL invisibly on success 20 | } 21 | \description{ 22 | \code{ENsetqualtype} sets the type of water quality analysis called for. 23 | } 24 | \details{ 25 | Water quality analysis codes are as follows: 26 | 27 | \tabular{lrl}{ 28 | \code{EN_NONE} \tab 0 \tab No quality analysis\cr 29 | \code{EN_CHEM} \tab 1 \tab Chemical analysis\cr 30 | \code{EN_AGE} \tab 2 \tab Water age analysis\cr 31 | \code{EN_TRACE} \tab 3 \tab Source tracing 32 | } 33 | 34 | Chemical name and units can be an empty string if the analysis is not for a chemical. 35 | The same holds for the trace node if the analysis is not for source tracing. 36 | Note that the trace node is specified by ID and not by index. 37 | } 38 | \examples{ 39 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 40 | ENopen( inp, "Net1.rpt") 41 | ENgetqualtype() 42 | ENsetqualtype("EN_CHEM", "Chlorine", "mg/L", "") 43 | ENgetqualtype() 44 | ENclose() 45 | # clean-up the created files 46 | file.remove("Net1.rpt") 47 | } 48 | \seealso{ 49 | \code{ENgetqualtype} 50 | } 51 | -------------------------------------------------------------------------------- /tests/testthat/test_pumps.r: -------------------------------------------------------------------------------- 1 | 2 | context("pumps") 3 | 4 | 5 | test_that("Net 1 pump type",{ 6 | 7 | suffix <- paste0( sample(letters, 4), collapse="") 8 | rptFile <- paste0("pump-tests-", suffix,".rpt") 9 | 10 | ENopen("Net1.inp", rptFile) 11 | 12 | pidx <- ENgetlinkindex("9") 13 | 14 | type <- ENgetpumptype(pidx) 15 | expect_true(is.character(type)) 16 | 17 | ENclose() 18 | 19 | file.remove(rptFile) 20 | }) 21 | 22 | test_that("Net 3 pump type",{ 23 | 24 | suffix <- paste0( sample(letters, 4), collapse="") 25 | rptFile <- paste0("pump-tests-", suffix,".rpt") 26 | ENopen("Net3.inp", rptFile) 27 | 28 | pidx <- ENgetlinkindex("10") 29 | type <- ENgetpumptype(pidx) 30 | expect_true(is.character(type)) 31 | 32 | pidx <- ENgetlinkindex("335") 33 | type <- ENgetpumptype(pidx) 34 | expect_true(is.character(type)) 35 | 36 | ENclose() 37 | 38 | file.remove(rptFile) 39 | }) 40 | 41 | test_that("net 1 get head curve index",{ 42 | 43 | suffix <- paste0( sample(letters, 4), collapse="") 44 | rptFile <- paste0("pump-tests-", suffix,".rpt") 45 | ENopen("Net1.inp", rptFile) 46 | 47 | hcidx <- ENgetheadcurveindex(13) 48 | 49 | expect_equal(hcidx, 1) 50 | 51 | ENclose() 52 | file.remove(rptFile) 53 | 54 | }) 55 | 56 | 57 | test_that("net 3 set head curve index",{ 58 | 59 | suffix <- paste0( sample(letters, 4), collapse="") 60 | rptFile <- paste0("pump-tests-", suffix,".rpt") 61 | ENopen("Net3.inp", rptFile) 62 | 63 | p335idx <- ENgetlinkindex("335") 64 | p335_old_hcidx <- ENgetheadcurveindex(p335idx) 65 | expect_equal(p335_old_hcidx, 2) 66 | 67 | ENsetheadcurveindex(p335idx, 1) 68 | p335_new_hcidx <- ENgetheadcurveindex(p335idx) 69 | expect_equal(p335_new_hcidx, 1) 70 | 71 | 72 | ENclose() 73 | file.remove(rptFile) 74 | 75 | }) -------------------------------------------------------------------------------- /tests/testthat/test_call.r: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2017 4 | # Author: Ernesto Arandia & Bradley J Eck 5 | # 6 | #***************************************** 7 | 8 | 9 | 10 | 11 | context("using .Call ") 12 | 13 | test_that("call the funcs",{ 14 | 15 | expect_silent({ 16 | 17 | # open the inp file 18 | rptFile = "net3.rpt" 19 | args <- .C("RENopen", "Net3.inp", rptFile," ", as.integer(-1)) 20 | 21 | # get functions for nodes 22 | ind1 <- .Call("enGetNodeIndex", "10") 23 | ind2 <- .Call("enGetNodeIndex", "15") 24 | ind3 <- .Call("enGetNodeIndex", "20") 25 | id1 <- .Call("enGetNodeID", 1) 26 | type1 <- .Call("enGetNodeType", ind3) 27 | type2 <- .Call("enGetNodeType", ind2) 28 | elev1 <- .Call("enGetNodeValue", ind3, 0) 29 | 30 | # get functions for links 31 | indlink <- .Call("enGetLinkIndex", "20") 32 | idlink <- .Call("enGetLinkID", 5) 33 | typelink <- .Call("enGetLinkType", indlink) 34 | diamlink <- .Call("enGetLinkValue", indlink, 0) 35 | nodeslink <- .Call("enGetLinkNodes", indlink) 36 | 37 | # get functions for patterns 38 | idpatt <- .Call("enGetPatternID", 3) 39 | indexpatt <- .Call("enGetPatternIndex", "2") 40 | lenpatt <- .Call("enGetPatternLen", 5) 41 | valpatt <- .Call("enGetPatternValue", 3, 12) 42 | 43 | # get control 44 | ctrl1 <-.Call("enGetControl", 1) 45 | ctrl2 <-.Call("enGetControl", 2) 46 | ctrl3 <-.Call("enGetControl", 3) 47 | ctrl4 <-.Call("enGetControl", 4) 48 | ctrl5 <-.Call("enGetControl", 5) 49 | 50 | # get flow units 51 | units <- .Call("enGetFlowUnits") 52 | 53 | # time parameter 54 | timepar <- .Call("enGetTimeParam", 0) 55 | 56 | # quality type 57 | qtype <- .Call("enGetQualType") 58 | 59 | # get option 60 | 61 | # version 62 | ver <- .Call("enGetVersion") 63 | 64 | # close the toolkit 65 | args <- .C("RENclose", as.integer(-1)) 66 | 67 | # cleanup 68 | file.remove(rptFile) 69 | }) 70 | 71 | }) -------------------------------------------------------------------------------- /tests/testthat/test_epanet_example_3.r: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2017 4 | # Author: Ernesto Arandia & Bradley J Eck 5 | # 6 | #***************************************** 7 | 8 | context("Epanet Example 3") 9 | 10 | test_that("ex3",{ 11 | 12 | # determine lowest dose of chlorine applied at entrace to 13 | # a distribution system needed to ensure a minimum residual 14 | # throughought the system. 15 | # Inputs: SourceID & Ctarget 16 | # only check target after startup duration of 432000 seconds 17 | 18 | # inputs 19 | SourceID = "Lake" # chlorine source 20 | Ctarget = 0.3 # target min concentration 21 | 22 | #open toolkit and obtain hydraulic solution 23 | ENopen("Net3.inp", "Net3.rpt") 24 | ENsolveH() 25 | 26 | # get the nunber of nodes and the source node's index 27 | nnodes <- ENgetcount("EN_NODECOUNT") 28 | sourceindex <- ENgetnodeindex(SourceID) 29 | 30 | # Setup system to analyze for chlorine 31 | # (in case it was not done in the input file) 32 | ENsetqualtype("EN_CHEM", "Chlorine", "mg/L", "") 33 | 34 | # Open water quality solver 35 | ENopenQ() 36 | 37 | # Begin search for the source concentration 38 | csource = seq( from = 0, to = 4, by = 0.1) 39 | N = length(csource) 40 | for( i in 1:N){ 41 | # update source concentration 42 | ENsetnodevalue( sourceindex, "EN_SOURCEQUAL", csource[i]) 43 | 44 | # Run WQ simulation & check for target violations 45 | ENinitQ(0) 46 | t <- ENrunQ() 47 | if( t > 432000){ 48 | for( i in 1:nnodes){ 49 | conc <- ENgetnodevalue(i, "EN_QUALITY") 50 | if( conc < Ctarget) break 51 | } 52 | } 53 | tstep <- ENnextQ() 54 | if( tstep == 0 ) break 55 | } 56 | 57 | Cdose <- csource[i] 58 | expect_true( Cdose <= 4 ) 59 | expect_true( Cdose > 0 ) 60 | 61 | ENclose() 62 | }) 63 | 64 | 65 | -------------------------------------------------------------------------------- /man/epanet2toolkit-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/epanet2toolkit.r 3 | \docType{package} 4 | \name{epanet2toolkit-package} 5 | \alias{epanet2toolkit} 6 | \alias{epanet2toolkit-package} 7 | \title{epanet2toolkit: Call 'EPANET' Functions to Simulate Pipe Networks} 8 | \description{ 9 | Enables simulation of water piping networks using 'EPANET'. The package provides functions from the 'EPANET' programmer's toolkit as R functions so that basic or customized simulations can be carried out from R. The package uses 'EPANET' version 2.2 from Open Water Analytics \url{https://github.com/OpenWaterAnalytics/EPANET/releases/tag/v2.2}. 10 | } 11 | \seealso{ 12 | Useful links: 13 | \itemize{ 14 | \item \url{https://github.com/bradleyjeck/epanet2toolkit} 15 | } 16 | 17 | } 18 | \author{ 19 | \strong{Maintainer}: Bradley Eck \email{brad@bradeck.net} 20 | 21 | Authors: 22 | \itemize{ 23 | \item Ernesto Arandia \email{earandia.ie@gmail.com} 24 | \item Lew Rossman 25 | } 26 | 27 | Other contributors: 28 | \itemize{ 29 | \item Michael Tryby [contributor] 30 | \item Sam Hatchett [contributor] 31 | \item Feng Shang [contributor] 32 | \item James Uber [contributor] 33 | \item Tom Taxon [contributor] 34 | \item Hyoungmin Woo [contributor] 35 | \item Jinduan Chen [contributor] 36 | \item Yunier Soad [contributor] 37 | \item Mike Kane [contributor] 38 | \item Demetrios Eliades [contributor] 39 | \item Will Furnass [contributor] 40 | \item Steffen Macke [contributor] 41 | \item Marios Kyriakou [contributor] 42 | \item Elad Salomons [contributor] 43 | \item Maurizio Cingi [contributor] 44 | \item Bryant McDonnell [contributor] 45 | \item Angela Marchi [contributor] 46 | \item Markus Sunela [contributor] 47 | \item Milad Ghiami [contributor] 48 | \item IBM Corp. [copyright holder] 49 | \item Open Water Analytics [copyright holder] 50 | } 51 | 52 | } 53 | \keyword{internal} 54 | -------------------------------------------------------------------------------- /man/ENinitH.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/hydraulics.r 3 | \name{ENinitH} 4 | \alias{ENinitH} 5 | \title{Initialize hydraulic engine} 6 | \usage{ 7 | ENinitH(flag) 8 | } 9 | \arguments{ 10 | \item{flag}{A two-digit flag indicating if hydraulic results will be saved to the 11 | hydraulics file (rightmost digit) and if link flows should be re-initialized.} 12 | } 13 | \value{ 14 | Returns NULL invisibly; called for side effect 15 | } 16 | \description{ 17 | \code{ENinitH} Initializes storage tank levels, link status and settings, and the simulation clock 18 | time prior to running a hydraulic analysis. 19 | } 20 | \details{ 21 | Call \code{ENinitH} prior to running a hydraulic analysis using \code{ENrunH} and 22 | \code{ENnextH}.\code{ENopenH} must have been called prior to calling \code{ENinitH}. Do not call 23 | \code{ENinitH} if a complete hydraulic analysis is being made with a call to \code{ENsolveH}. 24 | Values of flag have the following meanings: 25 | 26 | \tabular{ll}{ 27 | 00 \tab do not re-initialize flows, do not save results to file\cr 28 | 01 \tab do not re-initialize flows, save results to file\cr 29 | 10 \tab re-initialize flows, do not save results to file\cr 30 | 11 \tab re-initialize flows, save results to file 31 | } 32 | 33 | Set \code{flag} to 1 (or 11) if you will be making a subsequent water quality run, using 34 | \code{ENreport} to generate a report, or using \code{ENsavehydfile} to save the binary 35 | hydraulics file. 36 | } 37 | \examples{ 38 | # path to Net1.inp example file included with this package 39 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 40 | ENopen( inp, "Net1.rpt") 41 | ENopenH() 42 | ENinitH(0) 43 | ENrunH() 44 | ENcloseH() 45 | ENclose() 46 | # clean-up the created files 47 | file.remove("Net1.rpt") 48 | } 49 | \seealso{ 50 | \code{ENopenH}, \code{ENrunH}, \code{ENnextH}, \code{ENcloseH} 51 | } 52 | -------------------------------------------------------------------------------- /man/ENsettimeparam.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/times.r 3 | \name{ENsettimeparam} 4 | \alias{ENsettimeparam} 5 | \title{Set the value of a time parameter.} 6 | \usage{ 7 | ENsettimeparam(paramcode, timevalue) 8 | } 9 | \arguments{ 10 | \item{paramcode}{An integer or character} 11 | 12 | \item{timevalue}{An integer or character value of the time parameters in seconds.} 13 | } 14 | \description{ 15 | \code{ENsettimeparam} sets the value of a time parameter. 16 | } 17 | \details{ 18 | Time parameter codes consist of the following constants: 19 | 20 | \tabular{lrl}{ 21 | \code{EN_DURATION} \tab 0 \tab Simulation duration\cr 22 | \code{EN_HYDSTEP} \tab 1 \tab Hydraulic time step\cr 23 | \code{EN_QUALSTEP} \tab 2 \tab Water quality time step\cr 24 | \code{EN_PATTERNSTEP} \tab 3 \tab Time pattern time step\cr 25 | \code{EN_PATTERNSTART} \tab 4 \tab Time pattern start time\cr 26 | \code{EN_REPORTSTEP} \tab 5 \tab Reporting time step\cr 27 | \code{EN_REPORTSTART} \tab 6 \tab Reporting starting time\cr 28 | \code{EN_RULESTEP} \tab 7 \tab Time step for evaluating rule-based controls\cr 29 | \code{EN_STATISTIC} \tab 8 \tab Type of time series post-processing to use:\cr 30 | \tab \tab \code{EN_NONE} (0) = none\cr 31 | \tab \tab \code{EN_AVERAGE} (1) = averaged\cr 32 | \tab \tab \code{EN_MINIMUM} (2) = minimums\cr 33 | \tab \tab \code{EN_MAXIMUM} (3) = maximums\cr 34 | \tab \tab \code{EN_RANGE} (4) = ranges 35 | } 36 | 37 | Do not change time parameters after calling ENinitH in a hydraulic analysis or 38 | \code{ENinitQ} in a water quality analysis 39 | } 40 | \examples{ 41 | # path to Net1.inp example file included with this package 42 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 43 | ENopen(inp, "Net1.rpt") 44 | ENgettimeparam("EN_HYDSTEP") 45 | ENsettimeparam("EN_HYDSTEP", 600) 46 | ENgettimeparam("EN_HYDSTEP") 47 | ENclose() 48 | } 49 | -------------------------------------------------------------------------------- /src/toolkit.h: -------------------------------------------------------------------------------- 1 | //***************************************** 2 | // 3 | // (C) Copyright IBM Corp. 2017 4 | // Author: Ernesto Arandia & Bradley J Eck 5 | // 6 | //***************************************** 7 | 8 | 9 | #ifndef TOOLKIT_H 10 | #define TOOLKIT_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | //#include "types.h" 18 | #define EXTERN extern 19 | #include "epanet2.h" 20 | 21 | //void RgetOpenHflag(int* flagval ); 22 | SEXP enGetNodeIndex(SEXP id); 23 | SEXP enGetNodeID(SEXP index); 24 | SEXP enGetNodeType(SEXP index); 25 | SEXP enGetNodeValue(SEXP index, SEXP paramCode); 26 | SEXP enGetLinkIndex(SEXP id); 27 | SEXP enGetLinkID(SEXP index); 28 | SEXP enGetLinkType(SEXP index); 29 | SEXP enGetLinkValue(SEXP index, SEXP paramCode); 30 | SEXP enGetLinkNodes(SEXP index); 31 | SEXP enGetPatternID(SEXP index); 32 | SEXP enGetPatternIndex(SEXP id); 33 | SEXP enGetPatternLen(SEXP index); 34 | SEXP enGetPatternValue(SEXP index, SEXP period); 35 | SEXP enGetControl(SEXP cindex); 36 | SEXP enGetCount(SEXP countcode); 37 | SEXP enGetFlowUnits(void); 38 | SEXP enGetTimeParam(SEXP paramcode); 39 | SEXP enGetQualType(void); 40 | SEXP enGetOption(SEXP optioncode); 41 | SEXP enGetVersion(void); 42 | SEXP enSetQualType(SEXP qualcode, SEXP chemname, SEXP chemunits, SEXP tracenode); 43 | SEXP int2SEXP(int myInt); 44 | SEXP char2SEXP(char *myChar); 45 | int SEXP2int(SEXP mySEXP); 46 | SEXP float2SEXP(float myFloat); 47 | float SEXP2float(SEXP mySEXP); 48 | char *SEXP2char(SEXP mySEXP); 49 | SEXP setlistint(SEXP sxvalue, SEXP sxerrorcode); 50 | SEXP setlistfloat(SEXP sxvalue, SEXP sxerrorcode); 51 | SEXP setlist2int(SEXP sxvalue1, SEXP sxvalue2, SEXP sxerrorcode); 52 | SEXP setcontrollist(SEXP sxctype, SEXP sxlindex, SEXP sxsetting, SEXP sxnindex, SEXP sxlevel, SEXP sxerrorcode); 53 | 54 | SEXP setlistci(SEXP sxvalue, SEXP sxerrorcode); 55 | SEXP setlistic(SEXP sxvalue, SEXP sxerrorcode); 56 | 57 | #endif 58 | 59 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: epanet2toolkit 2 | Type: Package 3 | Title: Call 'EPANET' Functions to Simulate Pipe Networks 4 | Version: 1.0.8 5 | Date: 2024-12-16 6 | Authors@R: c( 7 | person("Ernesto", "Arandia", email="earandia.ie@gmail.com", role='aut'), 8 | person("Bradley", "Eck", email="brad@bradeck.net", role = c('aut','cre')), 9 | person("Lew", "Rossman", role='aut'), 10 | person("Michael Tryby", role = 'ctb'), 11 | person("Sam","Hatchett", role = 'ctb'), 12 | person("Feng","Shang", role = 'ctb'), 13 | person("James","Uber", role = 'ctb'), 14 | person("Tom","Taxon", role = 'ctb'), 15 | person("Hyoungmin","Woo", role = 'ctb'), 16 | person("Jinduan","Chen", role = 'ctb'), 17 | person("Yunier","Soad", role = 'ctb'), 18 | person("Mike","Kane", role = 'ctb'), 19 | person("Demetrios","Eliades", role = 'ctb'), 20 | person("Will","Furnass", role = 'ctb'), 21 | person("Steffen","Macke", role = 'ctb'), 22 | person("Marios", "Kyriakou", role = 'ctb'), 23 | person("Elad","Salomons", role = 'ctb'), 24 | person("Maurizio","Cingi", role = 'ctb'), 25 | person("Bryant","McDonnell", role = 'ctb'), 26 | person("Angela","Marchi",role='ctb'), 27 | person("Markus","Sunela",role='ctb'), 28 | person("Milad","Ghiami",role='ctb'), 29 | person("IBM Corp.", role = 'cph'), 30 | person("Open Water Analytics", role = 'cph') 31 | ) 32 | Maintainer: Bradley Eck 33 | Suggests: 34 | testthat, 35 | epanetReader 36 | Description: Enables simulation of water piping networks using 'EPANET'. 37 | The package provides functions from the 'EPANET' programmer's toolkit as R 38 | functions so that basic or customized simulations can be carried out from R. 39 | The package uses 'EPANET' version 2.2 from Open Water Analytics 40 | . 41 | License: MIT + file LICENSE 42 | Copyright: COPYRIGHTS 43 | URL: https://github.com/bradleyjeck/epanet2toolkit 44 | RoxygenNote: 7.3.2 45 | -------------------------------------------------------------------------------- /man/ENgettimeparam.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/times.r 3 | \name{ENgettimeparam} 4 | \alias{ENgettimeparam} 5 | \title{Get the value of one or more specific analysis time parameters.} 6 | \usage{ 7 | ENgettimeparam(paramcode) 8 | } 9 | \arguments{ 10 | \item{paramcode}{A character string or integer specifying the parameter code 11 | (see below).} 12 | } 13 | \value{ 14 | A named integer with the value of the specified time parameter. 15 | } 16 | \description{ 17 | \code{ENgettimeparam} retrieves the value of one or more specific analysis time parameters. 18 | } 19 | \details{ 20 | Time parameter codes consist of the following constants: 21 | \tabular{lll}{ 22 | \code{EN_DURATION} \tab 0 \tab Simulation duration\cr 23 | \code{EN_HYDSTEP} \tab 1 \tab Hydraulic time step\cr 24 | \code{EN_QUALSTEP} \tab 2 \tab Water quality time step\cr 25 | \code{EN_PATTERNSTEP} \tab 3 \tab Time pattern time step\cr 26 | \code{EN_PATTERNSTART} \tab 4 \tab Time pattern start time\cr 27 | \code{EN_REPORTSTEP} \tab 5 \tab Reporting time step\cr 28 | \code{EN_REPORTSTART} \tab 6 \tab Report starting time\cr 29 | \code{EN_RULESTEP} \tab 7 \tab Time step for evaluating rule-based controls\cr 30 | \code{EN_STATISTIC} \tab 8 \tab Type of time series post-processing used:\cr 31 | \tab \tab 0 = none\cr 32 | \tab \tab 1 = averaged\cr 33 | \tab \tab 2 = minimums\cr 34 | \tab \tab 3 = maximums\cr 35 | \tab \tab 4 = ranges\cr 36 | \code{EN_PERIODS} \tab 9 \tab Number of reporting periods saved to binary output file 37 | } 38 | } 39 | \examples{ 40 | # path to Net1.inp example file included with this package 41 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 42 | ENopen(inp, "Net1.rpt") 43 | ENgettimeparam("EN_DURATION") 44 | ENgettimeparam("EN_HYDSTEP") 45 | ENclose() 46 | } 47 | -------------------------------------------------------------------------------- /src/filemanager.h: -------------------------------------------------------------------------------- 1 | /* 2 | ****************************************************************************** 3 | Project: OWA EPANET 4 | Version: 2.2 5 | Module: util/filemanager.h 6 | Description: Provides a simple interface for managing files 7 | Authors: see AUTHORS 8 | Copyright: see AUTHORS 9 | License: see LICENSE 10 | Last Updated: 04/01/2019 11 | ****************************************************************************** 12 | */ 13 | 14 | #ifndef FILEMANAGER_H_ 15 | #define FILEMANAGER_H_ 16 | 17 | 18 | #include 19 | #include 20 | 21 | #include "cstr_helper.h" 22 | 23 | 24 | // F_OFF Must be a 8 byte / 64 bit integer for large file support 25 | #ifdef _MSC_VER // Windows (32-bit and 64-bit) 26 | #define F_OFF __int64 27 | #else // Other platforms 28 | #define F_OFF off_t 29 | #endif 30 | 31 | #define FILE_MAXNAME 259 32 | 33 | 34 | #if defined(__cplusplus) 35 | extern "C" { 36 | #endif 37 | 38 | // Forward declariation of file_handle_t 39 | typedef struct file_s file_handle_t; 40 | 41 | 42 | file_handle_t *create_file_manager(void); 43 | 44 | void delete_file_manager(file_handle_t *file_handle); 45 | 46 | 47 | int get_filename(file_handle_t *file_handle, char **filename); 48 | 49 | 50 | int open_file(file_handle_t *file_handle, const char *filename, const char *file_mode); 51 | 52 | int seek_file(file_handle_t *file_handle, F_OFF offset, int whence); 53 | 54 | F_OFF tell_file(file_handle_t *file_handle); 55 | 56 | 57 | // Functions for working with binary files 58 | size_t read_file(void *ptr, size_t size, size_t nmemb, file_handle_t *file_handle); 59 | 60 | size_t write_file(const void *ptr, size_t size, size_t count, file_handle_t *file_handle); 61 | 62 | 63 | // Functions for working with text files 64 | int printf_file(file_handle_t *file_handle, const char *format, ... ); 65 | 66 | 67 | 68 | int close_file(file_handle_t *file_handle); 69 | 70 | int remove_file(file_handle_t *file_handle); 71 | 72 | 73 | bool is_valid(file_handle_t *file_handle); 74 | 75 | 76 | #if defined(__cplusplus) 77 | } 78 | #endif 79 | 80 | #endif /* FILEMANAGER_H_ */ 81 | -------------------------------------------------------------------------------- /man/ENsetnodevalue.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/nodes.r 3 | \name{ENsetnodevalue} 4 | \alias{ENsetnodevalue} 5 | \title{Set the parameter value for a node.} 6 | \usage{ 7 | ENsetnodevalue(index, paramcode = NULL, value = NULL) 8 | } 9 | \arguments{ 10 | \item{index}{An integer vector, the node index.} 11 | 12 | \item{paramcode}{An integer vector, the parameter code (see Details below).} 13 | 14 | \item{value}{A numeric vector, the new value of the parameter.} 15 | } 16 | \value{ 17 | returns NULL invisibly on success or raises an error or warning. 18 | } 19 | \description{ 20 | \code{ENsetnodevalue} sets parameter value for one node. 21 | } 22 | \details{ 23 | Nodes are indexed starting from 1 in the order in which they were entered into the 24 | \code{[NODES]} section of the EPANET input file. 25 | 26 | Node parameter codes consist of the following constants: 27 | \tabular{lrl}{ 28 | \code{EN_ELEVATION} \tab 0 \tab Elevation\cr 29 | \code{EN_BASEDEMAND} \tab 1 \tab Base demand\cr 30 | \code{EN_PATTERN} \tab 2 \tab Demand pattern index\cr 31 | \code{EN_EMITTER} \tab 3 \tab Emitter coeff.\cr 32 | \code{EN_INITQUAL} \tab 4 \tab Initial quality\cr 33 | \code{EN_SOURCEQUAL} \tab 5 \tab Source quality\cr 34 | \code{EN_SOURCEPAT} \tab 6 \tab Source pattern index\cr 35 | \code{EN_SOURCETYPE} \tab 7 \tab Source type (see note below)\cr 36 | \code{EN_TANKLEVEL} \tab 8 \tab Initial water level in tank\cr 37 | } 38 | 39 | Source types are identified with the following constants: 40 | \tabular{ll}{ 41 | \code{EN_CONCEN} \tab 0\cr 42 | \code{EN_MASS} \tab 1\cr 43 | \code{EN_SETPOINT} \tab 2\cr 44 | \code{EN_FLOWPACED} \tab 3 45 | } 46 | 47 | See \code{[SOURCES]} for a description of these source types. 48 | 49 | Values are supplied in units which depend on the units used for flow rate in the EPANET 50 | input file (see Units of Measurement). 51 | } 52 | \examples{ 53 | # path to Net1.inp example file included with this package 54 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 55 | ENopen( inp, "Net1.rpt") 56 | ENgetnodevalue(3, "EN_ELEVATION") 57 | ENsetnodevalue(3, "EN_ELEVATION", 777) 58 | ENgetnodevalue(3, "EN_ELEVATION") 59 | ENclose() 60 | } 61 | -------------------------------------------------------------------------------- /src/errormanager.c: -------------------------------------------------------------------------------- 1 | /* 2 | ****************************************************************************** 3 | Project: OWA EPANET 4 | Version: 2.2 5 | Module: util/errormanager.c 6 | Description: Provides a simple interface for managing errors 7 | Authors: see AUTHORS 8 | Copyright: see AUTHORS 9 | License: see LICENSE 10 | Last Updated: 04/02/2019 11 | ****************************************************************************** 12 | */ 13 | 14 | //#ifdef _WIN32 15 | //#define _CRTDBG_MAP_ALLOC 16 | //#include 17 | //#include 18 | //#else 19 | #include 20 | //#endif 21 | #include 22 | 23 | #include "errormanager.h" 24 | 25 | 26 | typedef struct error_s { 27 | int error_status; 28 | void (*p_msg_lookup)(int, char*, int); 29 | } error_handle_t; 30 | 31 | 32 | error_handle_t *create_error_manager(void (*p_error_message)(int, char*, int)) 33 | // 34 | // Purpose: Constructs a new error handle. 35 | // 36 | { 37 | error_handle_t *error_handle; 38 | error_handle = (error_handle_t*)calloc(1, sizeof(error_handle_t)); 39 | 40 | error_handle->p_msg_lookup = p_error_message; 41 | 42 | return error_handle; 43 | } 44 | 45 | void delete_error_manager(error_handle_t *error_handle) 46 | // 47 | // Purpose: Destroys the error handle. 48 | // 49 | { 50 | free(error_handle); 51 | } 52 | 53 | int set_error(error_handle_t *error_handle, int error_code) 54 | // 55 | // Purpose: Sets an error code in the handle. 56 | // 57 | { 58 | // If the error code is 0 no action is taken and 0 is returned. 59 | // This is a feature not a bug. 60 | if (error_code) 61 | error_handle->error_status = error_code; 62 | 63 | return error_code; 64 | } 65 | 66 | int check_error(error_handle_t *error_handle, char **error_message) 67 | // 68 | // Purpose: Returns the error message or NULL. 69 | // 70 | // Note: Caller must free memory allocated by check_error 71 | // 72 | { int error_code = error_handle->error_status; 73 | char *temp = NULL; 74 | 75 | if (error_code != 0) { 76 | temp = (char*) calloc(ERR_MAXMSG + 1, sizeof(char)); 77 | 78 | if (temp) 79 | error_handle->p_msg_lookup(error_code, temp, ERR_MAXMSG); 80 | } 81 | *error_message = temp; 82 | return error_code; 83 | } 84 | 85 | void clear_error(error_handle_t *error_handle) 86 | // 87 | // Purpose: Clears the error from the handle. 88 | // 89 | { 90 | error_handle->error_status = 0; 91 | } 92 | -------------------------------------------------------------------------------- /man/ENgetnodevalue.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/nodes.r 3 | \name{ENgetnodevalue} 4 | \alias{ENgetnodevalue} 5 | \title{Retrieve node parameter value.} 6 | \usage{ 7 | ENgetnodevalue(nodeindex, paramcode) 8 | } 9 | \arguments{ 10 | \item{nodeindex}{An integer vector specifying the node index.} 11 | 12 | \item{paramcode}{An integer or character string, the parameter codes (see below).} 13 | } 14 | \value{ 15 | parameter value 16 | } 17 | \description{ 18 | \code{ENgetnodevalue} retrieves the values of specific node parameters. 19 | } 20 | \note{ 21 | Node indexes are consecutive integers starting from 1. 22 | 23 | Node parameter codes consist of the following constants: 24 | \tabular{lrl}{ 25 | \code{EN_ELEVATION} \tab 0 \tab Elevation\cr 26 | \code{EN_BASEDEMAND} \tab 1 \tab Base demand\cr 27 | \code{EN_PATTERN} \tab 2 \tab Demand pattern index\cr 28 | \code{EN_EMITTER} \tab 3 \tab Emitter coeff.\cr 29 | \code{EN_INITQUAL} \tab 4 \tab Initial quality\cr 30 | \code{EN_SOURCEQUAL} \tab 5 \tab Source quality\cr 31 | \code{EN_SOURCEPAT} \tab 6 \tab Source pattern index\cr 32 | \code{EN_SOURCETYPE} \tab 7 \tab Source type (see note below)\cr 33 | \code{EN_TANKLEVEL} \tab 8 \tab Initial water level in tank\cr 34 | \code{EN_DEMAND} \tab 9 \tab Actual demand\cr 35 | \code{EN_HEAD} \tab 10 \tab Hydraulic head\cr 36 | \code{EN_PRESSURE} \tab 11 \tab Pressure\cr 37 | \code{EN_QUALITY} \tab 12 \tab Actual quality\cr 38 | \code{EN_SOURCEMASS} \tab 13 \tab Mass flow rate per minute of a chemical source 39 | } 40 | 41 | Parameters 9 - 13 (\code{EN_DEMAND} through \code{EN_SOURCEMASS}) are computed values. The 42 | others are input design parameters. 43 | 44 | Source types are identified with the following constants: 45 | \tabular{ll}{ 46 | \code{EN_CONCEN} \tab 0\cr 47 | \code{EN_MASS} \tab 1\cr 48 | \code{EN_SETPOINT} \tab 2\cr 49 | \code{EN_FLOWPACED} \tab 3 50 | } 51 | 52 | See \code{[SOURCES]} for a description of these source types. 53 | 54 | Values are returned in units which depend on the units used for flow rate in the EPANET 55 | input file (see Units of Measurement). 56 | } 57 | \examples{ 58 | # path to Net1.inp example file included with this package 59 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 60 | ENopen( inp, "Net1.rpt") 61 | ENgetnodevalue(1, "EN_ELEVATION") 62 | ENgetnodevalue(5, "EN_BASEDEMAND") 63 | ENclose() 64 | } 65 | -------------------------------------------------------------------------------- /tests/testthat/test_controls.R: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2017, 2020 4 | # Author: Ernesto Arandia & Bradley J Eck 5 | # 6 | #***************************************** 7 | 8 | context("get control") 9 | test_that("no crash calling on closed toolkit",{ 10 | expect_error( x <- ENgetcontrol(1) ) 11 | }) 12 | test_that("works for single input (1)",{ 13 | ENopen("Net3.inp","Net3.rpt") 14 | lidx <- ENgetcontrol(1) 15 | ENclose() 16 | expect_equal(lidx, list(ctype=2, lindex=118, setting=1, nindex=0, level=3600)) 17 | }) 18 | test_that("works for single input (2)",{ 19 | ENopen("Net3.inp","Net3.rpt") 20 | lidx <- ENgetcontrol(5) 21 | ENclose() 22 | expect_equal(lidx, list(ctype=0, lindex=116, setting=0, nindex=95, level=17.1), 23 | tolerance=1e-7) 24 | }) 25 | test_that("works for multiple input",{ 26 | ENopen("Net3.inp","Net3.rpt") 27 | expect_error(lid <- ENgetcontrol(c(1,2,3))) 28 | ENclose() 29 | }) 30 | test_that("get error 241 on no ID",{ 31 | ENopen("Net3.inp","Net3.rpt") 32 | expect_error(ENgetcontrol(7),"241") 33 | ENclose() 34 | }) 35 | 36 | context("set control") 37 | test_that("no crash calling on closed toolkit",{ 38 | expect_error( ENsetcontrol(1, ctype=2, lindex=118, setting=1, nindex=0, level=5400) ) 39 | }) 40 | test_that("works on single input",{ 41 | ENopen("Net3.inp","Net3.rpt") 42 | ENsetcontrol(1, ctype=2, lindex=118, setting=1, nindex=0, level=5400) 43 | x <- ENgetcontrol(1) 44 | ENclose() 45 | expect_equal(x, list(ctype=2, lindex=118, setting=1, nindex=0, level=5400), tolerance = 1e-7) 46 | }) 47 | test_that("error on multiple indexes",{ 48 | ENopen("Net3.inp","Net3.rpt") 49 | expect_error(ENsetcontrol(c(1,2), ctype=2, lindex=118, setting=1, nindex=0, level=5400)) 50 | ENclose() 51 | }) 52 | test_that("get error on wrong control",{ 53 | ENopen("Net3.inp","Net3.rpt") 54 | expect_error(ENsetcontrol(7,1,116,1,95,21.5)) 55 | ENclose() 56 | }) 57 | 58 | context("delete control") 59 | test_that("can delete existing control",{ 60 | 61 | ENopen("Net3.inp", "Net3.rpt") 62 | x <- ENdeletecontrol(1) 63 | ENclose() 64 | expect_null(x) 65 | 66 | }) 67 | 68 | context("add control") 69 | test_that("can add new control",{ 70 | 71 | ENopen("Net3.inp", "Net3.rpt") 72 | # pipe from river operates only part of the day 73 | lidx <- ENgetlinkindex("50") 74 | cidx <- ENaddcontrol(type="EN_TIMEOFDAY", linkIndex=lidx,setting=0, nodeIndex = 0, level=20000) 75 | ctrl <- ENgetcontrol(cidx) 76 | expect_equal(ctrl$lindex,lidx) 77 | ENclose() 78 | }) 79 | -------------------------------------------------------------------------------- /tests/testthat/test_links22.r: -------------------------------------------------------------------------------- 1 | context("links crud") 2 | test_that("link crud",{ 3 | suffix <- paste0( sample(letters, 4), collapse="") 4 | rptFile <- paste0("link22-tests-", suffix,".rpt") 5 | ENopen("Net1.inp", rptFile) 6 | 7 | #Create 8 | lidx <- ENaddlink("new", "EN_CVPIPE","12","22") 9 | expect_true(lidx>0) 10 | #Read 11 | new_link_nodes <- ENgetlinknodes(lidx) 12 | n1idx <- ENgetnodeindex("12") 13 | expect_equal(n1idx, new_link_nodes[[1]]) 14 | n2idx <- ENgetnodeindex("22") 15 | expect_equal(n2idx, new_link_nodes[[2]]) 16 | # Update 17 | ENsetlinkid(lidx,"newnew") 18 | id <- ENgetlinkid(lidx) 19 | expect_equal("newnew", id) 20 | 21 | ENsetlinktype(lidx,"EN_PIPE") 22 | lt <- ENgetlinktype(lidx) 23 | expect_equal(lt,lookup_enum_value(linkTypes,"EN_PIPE")) 24 | 25 | ENsetlinknodes(lidx,2,7) 26 | updated_link_nodes <- ENgetlinknodes(lidx) 27 | expect_equal(2, updated_link_nodes[[1]]) 28 | expect_equal(7, updated_link_nodes[[2]]) 29 | 30 | # Delete 31 | ENdeletelink(lidx) 32 | #expect_error( ENgetlinknodes(lidx)) 33 | 34 | 35 | 36 | ENclose() 37 | 38 | file.remove(rptFile) 39 | 40 | }) 41 | 42 | 43 | context("vertex crud") 44 | test_that("ENgetvertexcount",{ 45 | suffix <- paste0( sample(letters, 4), collapse="") 46 | rptFile <- paste0("link22-tests-", suffix,".rpt") 47 | ENopen("Net1.inp", rptFile) 48 | 49 | nv5 <- ENgetvertexcount(5) 50 | expect_equal(nv5,0) 51 | 52 | ENclose() 53 | 54 | file.remove(rptFile) 55 | 56 | }) 57 | 58 | test_that("Create vertex",{ 59 | suffix <- paste0( sample(letters, 4), collapse="") 60 | rptFile <- paste0("link22-tests-", suffix,".rpt") 61 | ENopen("Net1.inp", rptFile) 62 | 63 | ENsetvertices(5, 22, 33) 64 | 65 | nv5 <- ENgetvertexcount(5) 66 | expect_equal(nv5,1) 67 | 68 | v5 <- ENgetvertex(5,1) 69 | 70 | expect_equal( as.integer(v5$x), 22) 71 | expect_equal( as.integer(v5$y), 33) 72 | 73 | ENclose() 74 | file.remove(rptFile) 75 | 76 | }) 77 | 78 | test_that("Create vertices",{ 79 | suffix <- paste0( sample(letters, 4), collapse="") 80 | rptFile <- paste0("link22-tests-", suffix,".rpt") 81 | ENopen("Net1.inp", rptFile) 82 | 83 | ENsetvertices(5, c(22,44), c(33,55)) 84 | 85 | nv5 <- ENgetvertexcount(5) 86 | expect_equal(nv5,2) 87 | 88 | v5 <- ENgetvertex(5,1) 89 | expect_equal( as.integer(v5$x), 22) 90 | expect_equal( as.integer(v5$y), 33) 91 | 92 | v52 <- ENgetvertex(5,2) 93 | expect_equal( as.integer(v52$x), 44) 94 | expect_equal( as.integer(v52$y), 55) 95 | 96 | ENclose() 97 | file.remove(rptFile) 98 | 99 | }) -------------------------------------------------------------------------------- /man/ENgetlinkvalue.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/links.r 3 | \name{ENgetlinkvalue} 4 | \alias{ENgetlinkvalue} 5 | \title{Retrieve parameter value for a link} 6 | \usage{ 7 | ENgetlinkvalue(linkindex, paramcode) 8 | } 9 | \arguments{ 10 | \item{linkindex}{index of the link} 11 | 12 | \item{paramcode}{requested parameter type either as name or number} 13 | } 14 | \value{ 15 | The parameter value of a specified link. 16 | } 17 | \description{ 18 | \code{ENgetlinkvalue} retrieves the value of a specific link parameter for a link. 19 | } 20 | \note{ 21 | Link indexes are consecutive integers starting from 1. 22 | Link parameter codes consist of the following constants: 23 | \tabular{lrl}{ 24 | \code{EN_DIAMETER} \tab 0 \tab Diameter\cr 25 | \code{EN_LENGTH} \tab 1 \tab Length\cr 26 | \code{EN_ROUGHNESS} \tab 2 \tab Roughness coeff.\cr 27 | \code{EN_MINORLOSS} \tab 3 \tab Minor loss coeff.\cr 28 | \code{EN_INITSTATUS} \tab 4 \tab Initial link status (0 = closed, 1 = open)\cr 29 | \code{EN_INITSETTING} \tab 5 \tab Initial pipe roughness\cr 30 | \tab \tab Initial pump speed\cr 31 | \tab \tab Initial valve setting\cr 32 | \code{EN_KBULK} \tab 6 \tab Bulk reaction coeff.\cr 33 | \code{EN_KWALL} \tab 7 \tab Wall reaction coeff.\cr 34 | \code{EN_FLOW} \tab 8 \tab Flow rate\cr 35 | \code{EN_VELOCITY} \tab 9 \tab Flow velocity\cr 36 | \code{EN_HEADLOSS} \tab 10 \tab Head loss\cr 37 | \code{EN_STATUS} \tab 11 \tab Actual link status (0 = closed, 1 = open)\cr 38 | \code{EN_SETTING} \tab 12 \tab Pipe roughness\cr 39 | \tab \tab Actual pump speed\cr 40 | \tab \tab Actal valve setting\cr 41 | \code{EN_ENERGY} \tab 13 \tab Energy expended in kwatts 42 | } 43 | Parameters 8 - 13 (\code{EN_FLOW} through \code{EN_ENERGY}) are computed values. The others 44 | are design parameters. 45 | 46 | Flow rate is positive if the direction of flow is from the designated start node of the link to 47 | its designated end node, and negative otherwise. 48 | 49 | Values are returned in units which depend on the units used for flow rate in the EPANET 50 | input file. 51 | } 52 | \examples{ 53 | # path to Net1.inp example file included with this package 54 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 55 | ENopen(inp, "Net1.rpt") 56 | ENgetlinkvalue(1, "EN_DIAMETER") 57 | ENgetlinkvalue(1, "EN_LENGTH") 58 | ENgetlinkvalue(8, "EN_DIAMETER") 59 | ENgetlinkvalue(8, "EN_LENGTH") 60 | ENclose() 61 | } 62 | \seealso{ 63 | \code{ENgetlinkindex} \code{\link{ENgetflowunits}} 64 | } 65 | -------------------------------------------------------------------------------- /man/ENsetlinkvalue.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/links.r 3 | \name{ENsetlinkvalue} 4 | \alias{ENsetlinkvalue} 5 | \title{Set a parameter value for a link} 6 | \usage{ 7 | ENsetlinkvalue(index, paramcode, value) 8 | } 9 | \arguments{ 10 | \item{index}{of the link} 11 | 12 | \item{paramcode}{number or name of parameter code, see details} 13 | 14 | \item{value}{new value of the parameter.} 15 | } 16 | \value{ 17 | Returns NULL invisibly on success or raises a warning or error. 18 | } 19 | \description{ 20 | Set a parameter value for a link 21 | } 22 | \details{ 23 | Links are indexed starting from 1. 24 | 25 | Link parameter codes consist of the following constants: 26 | \tabular{lrl}{ 27 | \code{EN_DIAMETER} \tab 0 \tab Diameter\cr 28 | \code{EN_LENGTH} \tab 1 \tab Length\cr 29 | \code{EN_ROUGHNESS} \tab 2 \tab Roughness coeff.\cr 30 | \code{EN_MINORLOSS} \tab 3 \tab Minor loss coeff.\cr 31 | \code{EN_INITSTATUS} \tab 4 \tab Initial link status (0 = closed, 1 = open)\cr 32 | \code{EN_INITSETTING} \tab 5 \tab Pipe roughness\cr 33 | \tab \tab Initial pump speed\cr 34 | \tab \tab Initial valve setting\cr 35 | \code{EN_KBULK} \tab 6 \tab Bulk reaction coeff.\cr 36 | \code{EN_KWALL} \tab 7 \tab Wall reaction coeff.\cr 37 | \code{EN_STATUS} \tab 11 \tab Current pump or valve status (0 = closed, 1 = open)\cr 38 | \code{EN_SETTING} \tab 12 \tab Current pump speed of valve setting. 39 | } 40 | 41 | Values are supplied in units which depend on the units used for flow rate in the EPANET input file 42 | (see Units of Measurement). Use \code{EN_INITSTATUS} and \code{EN_INITSETTING} to set the design value 43 | for a link's status or setting that exists prior to the start of a simulation. Use \code{EN_STATUS} and 44 | \code{EN_SETTING} to change these values while a simulation is being run (within the 45 | \code{ENrunH} - \code{ENnextH} loop). 46 | 47 | 48 | If a control valve has its status explicitly set to \code{OPEN} or \code{CLOSED}, then to make it active again 49 | during a simulation you must provide a new valve setting value using the \code{EN_SETTING} parameter. 50 | 51 | For pipes, either \code{EN_ROUGHNESS} or \code{EN_INITSETTING} can be used to change roughness. 52 | } 53 | \examples{ 54 | # path to Net1.inp example file included with this package 55 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 56 | ENopen(inp, "Net1.rpt") 57 | ENgetlinkvalue(8, "EN_LENGTH") 58 | ENsetlinkvalue(8, "EN_LENGTH", 3333) 59 | ENgetlinkvalue(8, "EN_DIAMETER") 60 | ENclose() 61 | } 62 | -------------------------------------------------------------------------------- /tests/testthat/test_times.r: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2017, 2020 4 | # Author: Ernesto Arandia & Bradley J Eck 5 | # 6 | #***************************************** 7 | 8 | 9 | context("Get time param") 10 | 11 | test_that("no crash calling on closed toolkit",{ 12 | expect_error( x <- ENgettimeparam(1) ) 13 | }) 14 | 15 | test_that("works for single character input",{ 16 | ENopen("Net1.inp", "Net1.rpt") 17 | dur <- ENgettimeparam("EN_DURATION") 18 | expect_equal( 86400, dur) 19 | step <- ENgettimeparam("EN_HYDSTEP") 20 | expect_equal( 3600, step) 21 | ENclose() 22 | }) 23 | 24 | test_that("works for integer input",{ 25 | ENopen("Net1.inp", "Net1.rpt") 26 | dur <- ENgettimeparam(0) 27 | expect_equal( 86400, dur) 28 | step <- ENgettimeparam(1) 29 | expect_equal( 3600, step) 30 | ENclose() 31 | 32 | }) 33 | 34 | test_that("returns error 251",{ 35 | 36 | ENopen("Net1.inp", "Net1.rpt") 37 | expect_error(ENgettimeparam(40) , "251") 38 | ENclose() 39 | 40 | }) 41 | 42 | test_that("warns if time param is too large for integers in R",{ 43 | ENopen("Net1-longduration.inp", "Net1-ld.rpt") 44 | expect_warning( dur <- ENgettimeparam("EN_DURATION")) 45 | ENclose() 46 | # clean-up the test file 47 | file.remove("Net1-ld.rpt") 48 | 49 | }) 50 | 51 | 52 | context("Set time param") 53 | 54 | test_that("no crash calling on closed toolkit",{ 55 | expect_error( x <- ENsettimeparam(1,1800) ) 56 | }) 57 | 58 | test_that("works for character inputs",{ 59 | ENopen("Net1.inp", "Net1.rpt") 60 | ENsettimeparam("EN_DURATION", "7777") 61 | dur <- ENgettimeparam(0 ) 62 | ENclose() 63 | expect_equal( 7777, dur) 64 | }) 65 | 66 | test_that("works for numeric inputs",{ 67 | ENopen("Net1.inp", "Net1.rpt") 68 | ENsettimeparam(0,7777 ) 69 | dur <- ENgettimeparam(0 ) 70 | ENclose() 71 | expect_equal( 7777, dur) 72 | }) 73 | test_that("works for integer inputs",{ 74 | ENopen("Net1.inp", "Net1.rpt") 75 | ENsettimeparam(as.integer(0) , as.integer(7777 )) 76 | dur <- ENgettimeparam(0 ) 77 | ENclose() 78 | expect_equal( 7777, dur) 79 | }) 80 | 81 | test_that("reterns NULL invisibly on success",{ 82 | ENopen("Net1.inp", "Net1.rpt") 83 | x <- withVisible( ENsettimeparam(0,7777 )) 84 | ENclose() 85 | expect_null( x$value ) 86 | expect_false( x$visible ) 87 | 88 | }) 89 | 90 | test_that("returns error 202",{ 91 | 92 | ENopen("Net1.inp", "Net1.rpt") 93 | expect_error(ENsettimeparam(1,-100) ) 94 | ENclose() 95 | 96 | }) 97 | -------------------------------------------------------------------------------- /R/coords.r: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2017 4 | # Author: Ernesto Arandia & Bradley J Eck 5 | # 6 | #***************************************** 7 | 8 | #' Get coordinates for a node 9 | #' 10 | #' @param nodeindex of node 11 | #' @return vector of x,y coordinate 12 | #' @export 13 | #' @useDynLib epanet2toolkit RENgetcoord 14 | #' @examples 15 | #' # path to Net1.inp example file included with this package 16 | #' inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 17 | #' ENopen( inp, "Net1.rpt") 18 | #' ENgetcoord(3) 19 | #' ENclose() 20 | ENgetcoord <- function( nodeindex ){ 21 | 22 | if (missing(nodeindex)) { 23 | stop("Need to specify the node index.") 24 | } 25 | if (is.numeric(nodeindex)) { 26 | nodeindex = as.integer(nodeindex) 27 | } 28 | else { 29 | stop("The node index must be an integer.") 30 | } 31 | if (length(nodeindex) != 1 ) { 32 | stop("Can only get ID for one node index at a time.") 33 | } 34 | 35 | z <- .C("RENgetcoord", nodeindex, 0.0, 0.0, as.integer(-1)) 36 | check_epanet_error( z[[4]]) 37 | 38 | coord <- c( x= z[[2]], y = z[[3]]) 39 | return( coord) 40 | } 41 | 42 | #' Set coordinates for a node 43 | #' 44 | #' @param nodeindex index of nodes for which to set coords 45 | #' @param x coordinate 46 | #' @param y coordinate 47 | #' @return returns NULL invisibily on success or raises an error or warning 48 | #' @export 49 | #' @useDynLib epanet2toolkit RENsetcoord 50 | #' @examples 51 | #' # path to Net1.inp example file included with this package 52 | #' inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 53 | #' ENopen( inp, "Net1.rpt") 54 | #' ENgetcoord(3) 55 | #' ENsetcoord(3,33,44) 56 | #' ENgetcoord(3) 57 | #' ENclose() 58 | ENsetcoord <- function( nodeindex, x, y){ 59 | if (missing(nodeindex)) { 60 | stop("Need to specify the node index.") 61 | } 62 | if (is.numeric(nodeindex)) { 63 | nodeindex = as.integer(nodeindex) 64 | } 65 | else { 66 | stop("The node index must be an integer.") 67 | } 68 | if (length(nodeindex) != 1 ) { 69 | stop("Can only get ID for one node index at a time.") 70 | } 71 | 72 | if( missing(x)) stop("need to specify x coordinate") 73 | if( missing(y)) stop("need to specify y coordinate") 74 | if( !is.numeric(x)) stop("coord values must be numeric") 75 | if( !is.numeric(y)) stop("coord values must be numeric") 76 | if( length(x) != 1 ) stop("x must have 1") 77 | if( length(y) != 1 ) stop("y must have 1") 78 | 79 | z <- .C("RENsetcoord", nodeindex, x, y, as.integer(-1)) 80 | check_epanet_error( z[[4]]) 81 | return( invisible() ) 82 | 83 | } 84 | -------------------------------------------------------------------------------- /tests/testthat/test_rules.r: -------------------------------------------------------------------------------- 1 | context("rule based controls") 2 | 3 | test_that("rule create and delete",{ 4 | 5 | R1 <- "RULE 1 \n IF NODE 2 LEVEL < 100 \n THEN LINK 9 STATUS = OPEN" 6 | 7 | ENopen("Net1.inp", "Net1-rules.rpt") 8 | ct_before <- ENgetcount("EN_RULECOUNT") 9 | 10 | ENaddrule(R1) 11 | ct_afteradd <- ENgetcount("EN_RULECOUNT") 12 | expect_true(ct_afteradd>ct_before) 13 | 14 | rid <- ENgetruleID(1) 15 | 16 | rule1 <- ENgetrule(1) 17 | 18 | prem1 <- ENgetpremise(ruleIndex = 1, premiseIndex = 1) 19 | 20 | # now let's update prem1 21 | ENsetpremise(ruleIndex = 1, premiseIndex = 1, 22 | logop = 1, # changed this to 1 instead of 2 23 | object=6, 24 | objIndex=11, variable=3, relop=4, status=0, value=100) 25 | prem <- ENgetpremise(1,1) 26 | expect_equal(prem$logop, 1) 27 | 28 | # change object index to 10 29 | ENsetpremiseindex(1,1,objIndex = 10) 30 | prem <- ENgetpremise(1,1) 31 | expect_equal(prem$objIndex, 10) 32 | 33 | # change status to 1 34 | ENsetpremisestatus(1,1,1) 35 | prem <- ENgetpremise(1,1) 36 | expect_equal(prem$status, 1) 37 | 38 | # change value to 99 39 | ENsetpremisevalue(1,1,99) 40 | prem <- ENgetpremise(1,1) 41 | expect_equal(prem$value, 99) 42 | 43 | ENdeleterule(1) 44 | ct_afterdel <- ENgetcount("EN_RULECOUNT") 45 | expect_equal(ct_before, ct_afterdel) 46 | 47 | ENclose() 48 | 49 | file.remove(("Net1-rules.rpt")) 50 | }) 51 | 52 | test_that("rule actions",{ 53 | rptFile <- "Net1-rule-actions.rpt" 54 | ENopen("Net1.inp", rptFile) 55 | R3 <- paste("RULE 3", 56 | "IF NODE 23 PRESSURE ABOVE 140", 57 | "AND NODE 2 LEVEL > 120", 58 | "THEN LINK 113 STATUS = CLOSED", 59 | "ELSE LINK 22 STATUS = CLOSED", 60 | sep = "\n") 61 | ENaddrule(R3) 62 | rule <- ENgetrule(1) 63 | 64 | act <- ENgetthenaction(1,1) 65 | 66 | ENsetthenaction(ruleIndex=1, actionIndex=1,linkIndex = 11, status=1, setting=-1e10) 67 | act <- ENgetthenaction(1,1) 68 | expect_equal(act$linkIndex, 11) 69 | expect_equal(act$status,1) 70 | 71 | act <- ENgetelseaction(1,1) 72 | lk22idx <- ENgetlinkindex("22") 73 | expect_equal(act$linkIndex, lk22idx) 74 | 75 | ENsetelseaction(1,1,linkIndex = 6, status = 1, setting = -1e10) 76 | act <- ENgetelseaction(1,1) 77 | expect_equal(act$linkIndex, 6) 78 | expect_equal(act$status, 1) 79 | 80 | ENsetrulepriority(index = 1, priority = 0.5) 81 | rule <- ENgetrule(1) 82 | expect_equal(rule$priority, 0.5) 83 | 84 | ENclose() 85 | file.remove(rptFile) 86 | }) -------------------------------------------------------------------------------- /man/ENsetcontrol.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/controls.r 3 | \name{ENsetcontrol} 4 | \alias{ENsetcontrol} 5 | \title{Set the parameters of a simple control statement} 6 | \usage{ 7 | ENsetcontrol( 8 | cindex, 9 | ctype = NULL, 10 | lindex = NULL, 11 | setting = NULL, 12 | nindex = NULL, 13 | level = NULL 14 | ) 15 | } 16 | \arguments{ 17 | \item{cindex}{Integer, control statement index} 18 | 19 | \item{ctype}{Integer or character string, the control type code (see Details below).} 20 | 21 | \item{lindex}{Integer, index of the link being controlled.} 22 | 23 | \item{setting}{Numeric, value of the control setting.} 24 | 25 | \item{nindex}{Integer, the index of the controlling node.} 26 | 27 | \item{level}{value of controlling water level or pressure for level controls or of 28 | time of control action (in seconds) for time-based controls} 29 | } 30 | \value{ 31 | Returns NULL invisibly on success or raises an error or warning. 32 | } 33 | \description{ 34 | \code{ENsetcontrol} sets the parameters of a simple control statements. 35 | } 36 | \details{ 37 | Controls are indexed starting from 1 in the order in which they were entered into the 38 | \code{[CONTROLS]} section of the EPANET input file. 39 | Control type codes consist of the following: 40 | 41 | \tabular{lll}{ 42 | \code{EN_LOWLEVEL} \tab 0 \tab Control applied when tank level or node pressure\cr 43 | \tab \tab drops below specified level\cr 44 | \code{EN_HILEVEL} \tab 1 \tab Control applied when tank level or node pressure\cr 45 | \tab \tab rises above specified level\cr 46 | \code{EN_TIMER} \tab 2 \tab Control applied at specific time into simulation\cr 47 | \code{EN_TIMEOFDAY} \tab 3 \tab Control applied at specific time of day 48 | } 49 | For pipes, a \code{setting} of 0 means the pipe is closed and 1 means it is open. For a 50 | pump, the \code{setting} contains the pump's speed, with 0 meaning the pump is closed and 51 | 1 meaning it is open at its normal speed. For a valve, the \code{setting} refers to the valve's 52 | pressure, flow, or loss coefficient, depending on valve type. 53 | 54 | For Timer or Time-of-Day controls set the \code{nindex} parameter to 0. 55 | 56 | For level controls, if the controlling node \code{nindex} is a tank then the level parameter 57 | should be a water level above the tank bottom (not an elevation). Otherwise \code{level} 58 | should be a junction pressure. 59 | 60 | To remove a control on a particular link, set the \code{lindex} parameter to 0. Values for the 61 | other parameters in the function will be ignored. 62 | } 63 | \examples{ 64 | # path to Net1.inp example file included with this package 65 | inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 66 | ENopen( inp, "Net1.rpt") 67 | ENgetcontrol(1) 68 | ENsetcontrol(1, ctype=2, lindex=3, setting=1, nindex=0, level=54) 69 | ENgetcontrol(1) 70 | ENclose() 71 | } 72 | \seealso{ 73 | \code{ENsetcontrol} 74 | } 75 | -------------------------------------------------------------------------------- /tests/testthat/test_options.r: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2017, 2020 4 | # Author: Ernesto Arandia & Bradley J Eck 5 | # 6 | #***************************************** 7 | 8 | 9 | 10 | context("Get option") 11 | 12 | test_that("no crash calling on closed toolkit",{ 13 | expect_error( x <- ENgetoption(0) ) 14 | }) 15 | 16 | test_that("works for single character input",{ 17 | ENopen("Net1.inp", "Net1.rpt") 18 | opt <- ENgetoption("EN_TRIALS") 19 | expect_equal( 40, opt) 20 | ENclose() 21 | }) 22 | 23 | test_that("works for integer input",{ 24 | ENopen("Net1.inp", "Net1.rpt") 25 | opt <- ENgetoption(as.integer(0)) 26 | expect_equal( 40, opt) 27 | ENclose() 28 | 29 | }) 30 | 31 | test_that("works for numeric input",{ 32 | ENopen("Net1.inp", "Net1.rpt") 33 | opt <- ENgetoption(0) 34 | expect_equal( 40, opt) 35 | ENclose() 36 | }) 37 | test_that("returns a numeric ok",{ 38 | ENopen("Net1.inp", "Net1.rpt") 39 | opt <- ENgetoption(1) 40 | expect_equal( 0.001, opt) 41 | ENclose() 42 | }) 43 | 44 | test_that("gives error on multiple input",{ 45 | ENopen("Net1.inp", "Net1.rpt") 46 | expect_error( ENgetoption(c(0,1))) 47 | ENclose() 48 | }) 49 | 50 | test_that("returns error 251",{ 51 | 52 | ENopen("Net1.inp", "Net1.rpt") 53 | expect_error(ENgetoption(40) , "251") 54 | ENclose() 55 | 56 | }) 57 | 58 | 59 | context("Set option") 60 | 61 | test_that("no crash calling on closed toolkit",{ 62 | expect_error( x <- ENsetoption(0,33) ) 63 | }) 64 | 65 | test_that("works for character input",{ 66 | ENopen("Net1.inp", "Net1.rpt") 67 | ENsetoption("EN_TRIALS", 33) 68 | opt <- ENgetoption("EN_TRIALS") 69 | expect_equal( 33, opt) 70 | ENclose() 71 | }) 72 | 73 | test_that("works for integer input",{ 74 | ENopen("Net1.inp", "Net1.rpt") 75 | ENsetoption(as.integer(0), 33) 76 | opt <- ENgetoption(as.integer(0)) 77 | expect_equal( 33, opt) 78 | ENclose() 79 | 80 | }) 81 | 82 | test_that("works for numeric input",{ 83 | ENopen("Net1.inp", "Net1.rpt") 84 | ENsetoption(0, 33) 85 | opt <- ENgetoption(0) 86 | expect_equal( 33, opt) 87 | ENclose() 88 | }) 89 | 90 | test_that("gives error on multiple input",{ 91 | ENopen("Net1.inp", "Net1.rpt") 92 | expect_error( ENsetoption(c(0,1),c(3,4))) 93 | ENclose() 94 | }) 95 | 96 | test_that("returns error 251",{ 97 | 98 | ENopen("Net1.inp", "Net1.rpt") 99 | expect_error(ENsetoption(40,40) , "251") 100 | ENclose() 101 | }) 102 | 103 | test_that("returns NULL invisibly on success",{ 104 | ENopen("Net1.inp", "Net1.rpt") 105 | x <- withVisible(ENsetoption(0, 33) ) 106 | ENclose() 107 | expect_null(x$value) 108 | expect_false(x$visible) 109 | }) 110 | 111 | 112 | context("ENsetflowunits") 113 | test_that("setting net1 units",{ 114 | rptFile <- "net1-setunits.rpt" 115 | ENopen("Net1.inp", rptFile) 116 | before <- ENgetflowunits() 117 | ENsetflowunits("EN_AFD") 118 | after <- ENgetflowunits() 119 | ENclose() 120 | expect_false(before == after) 121 | 122 | # clean up 123 | file.remove(rptFile) 124 | }) -------------------------------------------------------------------------------- /tests/testthat/test_epanet.r: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2017, 2020 4 | # Author: Bradley J Eck and Ernesto Arandia 5 | # 6 | #*****************************************/ 7 | 8 | 9 | context("ENepanet") 10 | test_that("ENepanet all args",{ 11 | expect_silent( ENepanet("Net1.inp", "Net1.rpt", "Net1.bin") ) 12 | # clean-up 13 | file.remove("Net1.rpt") 14 | file.remove("Net1.bin") 15 | }) 16 | 17 | test_that("RENepanet null bin",{ 18 | 19 | expect_silent( ENepanet("Net1.inp", "Net1.rpt") ) 20 | # clean-up 21 | file.remove("Net1.rpt") 22 | }) 23 | 24 | test_that("retuns null invisibly",{ 25 | wv <- withVisible( ENepanet("Net1.inp", "Net1.rpt") ) 26 | expect_null(wv$value) 27 | expect_false(wv$visible) 28 | # clean-up 29 | file.remove("Net1.rpt") 30 | }) 31 | 32 | test_that("R func ENepanet bad input",{ 33 | 34 | expect_error( ENepanet(NA, NA, NA) , "inp") 35 | expect_error( ENepanet("Net1.inp", NA, NA) , "rpt") 36 | expect_error( ENepanet("Net1.inp", "Net1.rpt", NA) , "bin") 37 | 38 | }) 39 | 40 | test_that("returns error code",{ 41 | expect_error( ENepanet("Net55.inp", "Net55.rpt"), "302") 42 | }) 43 | 44 | 45 | 46 | context("save inp file") 47 | test_that("func loads",{ 48 | expect_true( is.loaded("RENsaveinpfile")) 49 | }) 50 | 51 | test_that("func works",{ 52 | ENopen("Net1.inp", "Net1.rpt") 53 | ENsaveinpfile("new.inp") 54 | expect_true( file.exists("new.inp")) 55 | ENclose() 56 | # clean-up 57 | file.remove("new.inp") 58 | }) 59 | 60 | 61 | context("get count") 62 | 63 | test_that("no crash calling on closed toolkit",{ 64 | # expect_false( getOpenflag() ) 65 | expect_error( x <- ENgetcount(0) ) 66 | }) 67 | test_that("works with character input",{ 68 | ENopen("Net3.inp","Net3.rpt") 69 | 70 | nNodes <- ENgetcount("EN_NODECOUNT") 71 | nLinks <- ENgetcount("EN_LINKCOUNT") 72 | expect_equal(nNodes, 97 ) 73 | expect_equal(nLinks, 119 ) 74 | ENclose() 75 | }) 76 | 77 | test_that("works with numeric input",{ 78 | 79 | ENopen("Net3.inp","Net3.rpt") 80 | nPatt <- ENgetcount(3) 81 | nCont <- ENgetcount(5) 82 | expect_equal(nPatt, 5 ) 83 | expect_equal(nCont, 6 ) 84 | 85 | nNodes <- ENgetcount(0 ) 86 | nLinks <- ENgetcount(2) 87 | expect_equal(nNodes, 97 ) 88 | expect_equal(nLinks, 119 ) 89 | 90 | ENclose() 91 | 92 | }) 93 | 94 | test_that("returns error code",{ 95 | 96 | ENopen("Net3.inp","Net3.rpt") 97 | expect_error( ENgetcount(555),"251") 98 | ENclose() 99 | 100 | }) 101 | 102 | test_that("error on multiple input",{ 103 | ENopen("Net3.inp","Net3.rpt") 104 | expect_error( ENgetcount(c(0,1,2))) 105 | ENclose() 106 | }) 107 | 108 | 109 | context("get version") 110 | test_that("works",{ 111 | 112 | v <- ENgetversion() 113 | expect_equal(v, as.integer(20200)) 114 | 115 | }) 116 | 117 | 118 | context("ENinit") 119 | 120 | test_that("func exists",{ 121 | expect_true( is.loaded("RENinit")) 122 | }) 123 | 124 | test_that("func works",{ 125 | ENinit(rptFile="xxx.rpt", outFile="yyy.out", unitsType="EN_LPS", headLossType="EN_DW") 126 | expect_silent(ENclose()) 127 | file.remove("xxx.rpt") 128 | }) -------------------------------------------------------------------------------- /.github/workflows/rhub.yaml: -------------------------------------------------------------------------------- 1 | # R-hub's generic GitHub Actions workflow file. It's canonical location is at 2 | # https://github.com/r-hub/actions/blob/v1/workflows/rhub.yaml 3 | # You can update this file to a newer version using the rhub2 package: 4 | # 5 | # rhub::rhub_setup() 6 | # 7 | # It is unlikely that you need to modify this file manually. 8 | 9 | name: R-hub 10 | run-name: "${{ github.event.inputs.id }}: ${{ github.event.inputs.name || format('Manually run by {0}', github.triggering_actor) }}" 11 | 12 | on: 13 | workflow_dispatch: 14 | inputs: 15 | config: 16 | description: 'A comma separated list of R-hub platforms to use.' 17 | type: string 18 | default: 'linux,windows,macos' 19 | name: 20 | description: 'Run name. You can leave this empty now.' 21 | type: string 22 | id: 23 | description: 'Unique ID. You can leave this empty now.' 24 | type: string 25 | 26 | jobs: 27 | 28 | setup: 29 | runs-on: ubuntu-latest 30 | outputs: 31 | containers: ${{ steps.rhub-setup.outputs.containers }} 32 | platforms: ${{ steps.rhub-setup.outputs.platforms }} 33 | 34 | steps: 35 | # NO NEED TO CHECKOUT HERE 36 | - uses: r-hub/actions/setup@v1 37 | with: 38 | config: ${{ github.event.inputs.config }} 39 | id: rhub-setup 40 | 41 | linux-containers: 42 | needs: setup 43 | if: ${{ needs.setup.outputs.containers != '[]' }} 44 | runs-on: ubuntu-latest 45 | name: ${{ matrix.config.label }} 46 | strategy: 47 | fail-fast: false 48 | matrix: 49 | config: ${{ fromJson(needs.setup.outputs.containers) }} 50 | container: 51 | image: ${{ matrix.config.container }} 52 | 53 | steps: 54 | - uses: r-hub/actions/checkout@v1 55 | - uses: r-hub/actions/platform-info@v1 56 | with: 57 | token: ${{ secrets.RHUB_TOKEN }} 58 | job-config: ${{ matrix.config.job-config }} 59 | - uses: r-hub/actions/setup-deps@v1 60 | with: 61 | token: ${{ secrets.RHUB_TOKEN }} 62 | job-config: ${{ matrix.config.job-config }} 63 | - uses: r-hub/actions/run-check@v1 64 | with: 65 | token: ${{ secrets.RHUB_TOKEN }} 66 | job-config: ${{ matrix.config.job-config }} 67 | 68 | other-platforms: 69 | needs: setup 70 | if: ${{ needs.setup.outputs.platforms != '[]' }} 71 | runs-on: ${{ matrix.config.os }} 72 | name: ${{ matrix.config.label }} 73 | strategy: 74 | fail-fast: false 75 | matrix: 76 | config: ${{ fromJson(needs.setup.outputs.platforms) }} 77 | 78 | steps: 79 | - uses: r-hub/actions/checkout@v1 80 | - uses: r-hub/actions/setup-r@v1 81 | with: 82 | job-config: ${{ matrix.config.job-config }} 83 | token: ${{ secrets.RHUB_TOKEN }} 84 | - uses: r-hub/actions/platform-info@v1 85 | with: 86 | token: ${{ secrets.RHUB_TOKEN }} 87 | job-config: ${{ matrix.config.job-config }} 88 | - uses: r-hub/actions/setup-deps@v1 89 | with: 90 | job-config: ${{ matrix.config.job-config }} 91 | token: ${{ secrets.RHUB_TOKEN }} 92 | - uses: r-hub/actions/run-check@v1 93 | with: 94 | job-config: ${{ matrix.config.job-config }} 95 | token: ${{ secrets.RHUB_TOKEN }} 96 | -------------------------------------------------------------------------------- /tests/testthat/test_demand.r: -------------------------------------------------------------------------------- 1 | 2 | 3 | context("ENgetdemandmodel") 4 | test_that("get demand model",{ 5 | 6 | suffix <- paste0( sample(letters, 4), collapse="") 7 | rptFile <- paste0("node-tests-", suffix,".rpt") 8 | ENopen("Net1.inp", rptFile) 9 | 10 | dmdmdl <- ENgetdemandmodel() 11 | expect_true( is.list(dmdmdl)) 12 | 13 | ENclose() 14 | 15 | file.remove(rptFile) 16 | }) 17 | 18 | context("ENsetdemandmodel") 19 | test_that("set demand model",{ 20 | suffix <- paste0( sample(letters, 4), collapse="") 21 | rptFile <- paste0("node-tests-", suffix,".rpt") 22 | ENopen("Net1.inp", rptFile) 23 | 24 | ENsetdemandmodel(model="EN_PDA", pmin=10, preq=25, pexp=1.1) 25 | 26 | dmdmdl <- ENgetdemandmodel() 27 | expect_true(is.list(dmdmdl)) 28 | expect_equal(dmdmdl$model, "EN_PDA") 29 | expect_equal(as.integer(dmdmdl$pmin), 10) 30 | expect_equal(as.integer(dmdmdl$preq), 25) 31 | expect_true(dmdmdl$pexp > 1.08) 32 | 33 | ENclose() 34 | 35 | file.remove(rptFile) 36 | }) 37 | 38 | 39 | 40 | context("Net3 node 40 existing demand") 41 | test_that("base demand",{ 42 | suffix <- paste0( sample(letters, 4), collapse="") 43 | rptFile <- paste0("node-tests-", suffix, ".rpt") 44 | ENopen("Net3.inp", rptFile) 45 | nidx <- ENgetnodeindex("40") 46 | 47 | bdmd <- ENgetbasedemand(nodeindex = nidx, demand_index = 1) 48 | expect_equal( as.integer(bdmd), 0) 49 | 50 | dname <- ENgetdemandname(nidx) 51 | expect_equal(dname, "") 52 | 53 | didx <- ENgetdemandindex(nidx, "") 54 | expect_equal(didx, 1) 55 | 56 | ENsetbasedemand(nidx, 1, 3) 57 | bdmd3 <- ENgetbasedemand(nidx) 58 | expect_equal(as.integer(bdmd3), 3) 59 | 60 | ENclose() 61 | 62 | file.remove(rptFile) 63 | }) 64 | 65 | context("Net3 node 40 adding demand") 66 | test_that("add demand",{ 67 | suffix <- paste0(sample(letters, 4), collapse="") 68 | rptFile <- paste0("node-tests-", suffix, ".rpt") 69 | ENopen("Net3.inp", rptFile) 70 | nidx <- ENgetnodeindex("40") 71 | x <- ENadddemand(nodeindex=nidx, base_demand=123, demand_pattern=3, demand_name="test") 72 | expect_null(x) 73 | 74 | num <- ENgetnumdemands(nidx) 75 | expect_equal(num,2) 76 | 77 | didx <- ENgetdemandindex(nidx, "test") 78 | expect_equal(didx, 2) 79 | dname <- ENgetdemandname(nidx, didx) 80 | expect_equal(dname, "test") 81 | 82 | ENsetdemandname(nidx, didx, suffix) 83 | dname2 <- ENgetdemandname(nidx, didx) 84 | expect_equal( dname2, suffix) 85 | 86 | didx2 <- ENgetdemandindex(nidx, suffix) 87 | expect_equal(didx2, 2) 88 | 89 | ENdeletedemand(nidx, didx) 90 | num2 <- ENgetnumdemands(nidx) 91 | expect_equal(num2,1) 92 | 93 | ENclose() 94 | file.remove(rptFile) 95 | }) 96 | 97 | context("demand patterns") 98 | test_that("get set demand patterns",{ 99 | 100 | suffix <- paste0(sample(letters, 4), collapse="") 101 | rptFile <- paste0("node-tests-", suffix, ".rpt") 102 | ENopen("Net3.inp", rptFile) 103 | 104 | # node 35 has demand pattern 4 105 | p4idx <- ENgetpatternindex("4") 106 | n35idx <- ENgetnodeindex("35") 107 | n35pat <- ENgetdemandpattern(n35idx) 108 | expect_equal(n35pat, p4idx) 109 | 110 | 111 | # assign pattern 3 to node 20 112 | n20idx <- ENgetnodeindex("20") 113 | p3idx <- ENgetpatternindex("3") 114 | ENsetdemandpattern(n20idx, demand_index=1, p3idx) 115 | x <- ENgetdemandpattern(n20idx) 116 | expect_equal(x,p3idx) 117 | 118 | ENclose() 119 | 120 | file.remove(rptFile) 121 | }) -------------------------------------------------------------------------------- /tests/testthat/test_Rtoolkit.r: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2017 4 | # Author: Ernesto Arandia & Bradley J Eck 5 | # 6 | #***************************************** 7 | 8 | 9 | 10 | context("node information") 11 | test_that("node info",{ 12 | expect_silent({ 13 | ENopen("Net3.inp","Net3.rpt") 14 | # get information about nodes (IDs, indexes, ...) 15 | nNodes <- ENgetcount("EN_NODECOUNT") 16 | #nids <- ENgetnodeid(seq(1 : nNodes)) 17 | #nind <- ENgetnodeindex(nids) 18 | #ntyp <- ENgetnodetype(nind) 19 | #nval <- ENgetnodevalue(nind, "EN_ELEVATION") 20 | #nval2 <- ENgetnodevalue(seq(1, nNodes, by=2), c("EN_ELEVATION", "EN_BASEDEMAND")) 21 | 22 | ENclose() 23 | }) 24 | }) 25 | 26 | context("link information") 27 | test_that("link info",{ 28 | expect_silent({ 29 | ENopen("Net3.inp","Net3.rpt") 30 | # get information about links 31 | nLinks <- ENgetcount("EN_LINKCOUNT") 32 | #lids <- ENgetlinkid(seq(1 : nLinks)) 33 | #lind <- ENgetlinkindex(lids) 34 | #ltyp <- ENgetlinktype(seq(1 : nLinks)) 35 | #lnodes <- ENgetlinknodes(lind) 36 | #lval <- ENgetlinkvalue(lind, c("EN_DIAMETER", "EN_LENGTH", "EN_ROUGHNESS")) 37 | 38 | ENclose() 39 | }) 40 | }) 41 | 42 | 43 | 44 | context("other network info ") 45 | test_that("net info",{ 46 | expect_silent({ 47 | ENopen("Net3.inp","Net3.rpt") 48 | # get other network information 49 | #ctrl <- ENgetcontrol(c(1,3)) 50 | funits <- ENgetflowunits() 51 | timeparam <- ENgettimeparam(c(0, 1, 2)) 52 | timeparam2 <- ENgettimeparam(c("EN_REPORTSTART", "EN_REPORTSTEP")) 53 | units <- ENgetflowunits() 54 | qtype <- ENgetqualtype() 55 | ver <- ENgetversion() 56 | 57 | ENclose() 58 | }) 59 | }) 60 | 61 | ######################################### 62 | # set new values for network parameters 63 | ######################################### 64 | 65 | context("setting controls") 66 | test_that("set controls",{ 67 | expect_silent({ 68 | ENopen("Net3.inp","Net3.rpt") 69 | # enSetControl ################## 70 | #ctrl1 <- ENgetcontrol(c(1, 3)) # get controls 1 and 3 71 | #ctrl1$level = c(3601, 17) # change control settings 72 | #setctrl1 <- ENsetcontrol(ctrl1) # set new control settings 73 | #checkctrl1 <- ENgetcontrol(c(1, 3)) # check new settings 74 | 75 | #setctrl2 <- ENsetcontrol(c(1, 3), c("EN_TIMER", "EN_LOWLEVEL"), c(118, 119), c(1, 1), c(0, 95), c(3602, 18)) 76 | #checkctrl2 <- ENgetcontrol(c(1, 3)) 77 | 78 | numctrls <- ENgetcount("EN_CONTROLCOUNT"); 79 | #ctrls <- ENgetcontrol(seq(1 : numctrls)) 80 | # selctrl <- subset(ctrls, (ctype == 0 & lindex == ENgetlinkindex("335"))) 81 | # newctrl <- selctrl 82 | # newctrl$level = 17.5 83 | # setctrl3 <- ENsetcontrol(newctrl) 84 | # checkctrl3 <- ENgetcontrol(seq(1 : numctrls)) 85 | 86 | ENclose() 87 | }) 88 | }) 89 | 90 | 91 | context("setting node values ") 92 | test_that("set node vals",{ 93 | expect_silent({ 94 | ENopen("Net3.inp","Net3.rpt") 95 | # enSetNodeValue 96 | somenodes <- c(1, 3, 5) 97 | newval <- data.frame(index = somenodes, paramcode = rep(0, 3), value = c(150, 130, 132)) 98 | #setnodeval1 <- ENsetnodevalue(newval) 99 | #nodeval1 <- ENgetnodevalue(somenodes, "EN_ELEVATION") 100 | #setnodeval2 <- ENsetnodevalue(index = somenodes, paramcode = c(0, 1, 0), value = c(151, 1, 132.5)) 101 | #nodeval2 <- ENgetnodevalue(somenodes, c(0, 1)) 102 | 103 | ENclose() 104 | }) 105 | }) 106 | 107 | context("setting link values ") 108 | test_that("set link vals",{ 109 | expect_silent({ 110 | ENopen("Net3.inp","Net3.rpt") 111 | # enSetLinkValue 112 | somelinks <- c(5, 8, 15) 113 | newlinkval <- data.frame(index = somelinks, paramcode = rep(0, 3), value = c(24, 18, 18)) 114 | #setlinkval1 <- ENsetlinkvalue(newlinkval) 115 | #linkval1 <- ENgetlinkvalue(somelinks, "EN_DIAMETER") 116 | #setlinkval2 <- ENsetlinkvalue(index = somelinks, paramcode = c(0, 2, 0), value = c(24, 115, 18)) 117 | #linkval2 <- ENgetlinkvalue(somelinks, c(0, 2)) 118 | 119 | ENclose() 120 | }) 121 | }) 122 | 123 | -------------------------------------------------------------------------------- /R/epanet.r: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2017 4 | # Author: Ernesto Arandia & Bradley J Eck 5 | # 6 | #***************************************** 7 | 8 | 9 | #' ENepanet 10 | #' 11 | #' runs a complete EPANET simulation 12 | #' 13 | #' @export 14 | #' @param inpFile name of input file 15 | #' @param rptFile name of report file (to be created) 16 | #' @param binOutFile name of optional binary output file 17 | #' @return Returns NULL invisibly; called for side effect 18 | #' @useDynLib epanet2toolkit RENepanet 19 | #' @examples 20 | #' # path to Net1.inp example file included with this package 21 | #' inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 22 | #' print(inp) 23 | #' ENepanet( inp, "Net1.rpt") 24 | #' # try opening Net1.rpt in a text editor or reading it back 25 | #' # into R with the read.rpt() function in package epanetReader 26 | #' myRpt <- epanetReader::read.rpt("Net1.rpt") 27 | #' summary(myRpt) 28 | #' # clean-up the created file 29 | #' file.remove("Net1.rpt") 30 | ENepanet <- function( inpFile, rptFile, binOutFile=""){ 31 | # arg checking 32 | if( !is.character(inpFile) ) stop("inpFile must be character") 33 | # if( !file.exists(inpFile)) stop(paste(inpFile, "does not exist")) 34 | if( !is.character(rptFile) ) stop("rptFile must be character") 35 | if( !is.character(binOutFile) ) stop("binOutFile must be character") 36 | 37 | arg <- .C("RENepanet", inpFile, rptFile, binOutFile, as.integer(-1) ) 38 | 39 | err <- arg[[4]] 40 | check_epanet_error( err ) 41 | invisible() 42 | } 43 | 44 | #' ENinit 45 | #' 46 | #' Initializes an empty EPANET network 47 | #' 48 | #' @param rptFile the name of a report file to be created (or "" if not needed). 49 | #' @param outFile the name of a binary output file to be created (or "" if not needed). 50 | #' @param unitsType the choice of flow units. One of: "EN_CFS", "EN_GPM", "EN_MGD", 51 | #' "EN_IMGD", "EN_AFD", "EN_LPS", "EN_LPM", "EN_MLD", "EN_CMH", "EN_CMD" 52 | #' @param headLossType the choice of head loss formula . One of: EN_HW, EN_DW, EN_CM 53 | #' @return Returns NULL invisibly; called for side effect 54 | #' @useDynLib epanet2toolkit RENinit 55 | #' @details This function should be called to create an empty EPANET project without 56 | #' an EPANET-formatted input file. If the 57 | #' project receives it's network data from an input file then there is no need to 58 | #' call this function; use ENopen instead. 59 | ENinit <- function( rptFile, outFile, unitsType, headLossType){ 60 | 61 | FlowUnitsEnums <-c("EN_CFS" ,"EN_GPM" ,"EN_MGD" ,"EN_IMGD" ,"EN_AFD" ,"EN_LPS" ,"EN_LPM" ,"EN_MLD" ,"EN_CMH" ,"EN_CMD") 62 | flowUnitsVal <- lookup_enum_value(FlowUnitsEnums, unitsType) 63 | 64 | HeadLossEnums <- c("EN_HW","EN_DW","EN_CM") 65 | headlossVal <- lookup_enum_value(HeadLossEnums, headLossType) 66 | 67 | arg <- .C("RENinit", rptFile, outFile, flowUnitsVal, headlossVal, as.integer(-1)) 68 | err <- arg[[5]] 69 | check_epanet_error(err) 70 | return(invisible()) 71 | } 72 | 73 | 74 | #' ENaveinpfile 75 | #' 76 | #' Saves current data to "INP" formatted text file. 77 | #' 78 | #' @return Returns NULL invisibly; called for side effect 79 | #' @param filename The file path to create 80 | #' @export 81 | #' @useDynLib epanet2toolkit RENsaveinpfile 82 | ENsaveinpfile <- function(filename){ 83 | arg <- .C("RENsaveinpfile", filename, as.integer(-1) ) 84 | err <- arg[[2]] 85 | check_epanet_error( err ) 86 | } 87 | 88 | 89 | 90 | 91 | #' Retrieve the current version number of the EPANET Toolkit. 92 | #' 93 | #' \code{ENgetversion} retrieves the current version number of the EPANET Toolkit. 94 | #' 95 | #' @export 96 | #' @useDynLib epanet2toolkit RENgetversion 97 | #' @return An integer, the Toolkit version number. 98 | #' 99 | #' @note The version number is a 5-digit integer that increases sequentially from 100 | #' 20001 with each new update of the Toolkit. 101 | #' @examples 102 | #' ENgetversion() 103 | ENgetversion <- function() { 104 | 105 | x <- .C("RENgetversion", as.integer(0), as.integer(-1)) 106 | check_epanet_error(x[[2]]) 107 | return(x[[1]]) 108 | 109 | } 110 | 111 | -------------------------------------------------------------------------------- /src/mempool.c: -------------------------------------------------------------------------------- 1 | /* 2 | ****************************************************************************** 3 | Project: OWA EPANET 4 | Version: 2.2 5 | Module: mempool.c 6 | Description: a simple fast poooled memory allocation package 7 | Authors: see AUTHORS 8 | Copyright: see AUTHORS 9 | License: see LICENSE 10 | Last Updated: 05/15/2019 11 | 12 | This module is based code by Steve Hill in Graphics Gems III, 13 | David Kirk (ed.), Academic Press, Boston, MA, 1992 14 | ****************************************************************************** 15 | */ 16 | 17 | #include 18 | 19 | #include "mempool.h" 20 | 21 | /* 22 | ** ALLOC_BLOCK_SIZE - adjust this size to suit your installation - it 23 | ** should be reasonably large otherwise you will be mallocing a lot. 24 | */ 25 | 26 | #define ALLOC_BLOCK_SIZE 64000 /*(62*1024)*/ 27 | 28 | struct MemBlock 29 | { 30 | struct MemBlock *next; // Next block 31 | char *block, // Start of block 32 | *free, // Next free position in block 33 | *end; // block + block size 34 | }; 35 | 36 | struct Mempool 37 | { 38 | struct MemBlock *first; 39 | struct MemBlock *current; 40 | }; 41 | 42 | static struct MemBlock* createMemBlock(void) 43 | { 44 | struct MemBlock* memBlock = malloc(sizeof(struct MemBlock)); 45 | if (memBlock) 46 | { 47 | memBlock->block = malloc(ALLOC_BLOCK_SIZE * sizeof(char)); 48 | if (memBlock->block == NULL) 49 | { 50 | free(memBlock); 51 | return NULL; 52 | } 53 | memBlock->free = memBlock->block; 54 | memBlock->next = NULL; 55 | memBlock->end = memBlock->block + ALLOC_BLOCK_SIZE; 56 | } 57 | return memBlock; 58 | } 59 | 60 | 61 | static void deleteMemBlock(struct MemBlock* memBlock) 62 | { 63 | free(memBlock->block); 64 | free(memBlock); 65 | } 66 | 67 | 68 | struct Mempool * mempool_create(void) 69 | { 70 | struct Mempool *mempool; 71 | mempool = (struct Mempool *)malloc(sizeof(struct Mempool)); 72 | if (mempool == NULL) return NULL; 73 | mempool->first = createMemBlock(); 74 | mempool->current = mempool->first; 75 | if (mempool->first == NULL) return NULL; 76 | return mempool; 77 | } 78 | 79 | void mempool_delete(struct Mempool *mempool) 80 | { 81 | if (mempool == NULL) return; 82 | while (mempool->first) 83 | { 84 | mempool->current = mempool->first->next; 85 | deleteMemBlock(mempool->first); 86 | mempool->first = mempool->current; 87 | } 88 | free(mempool); 89 | mempool = NULL; 90 | } 91 | 92 | void mempool_reset(struct Mempool *mempool) 93 | { 94 | mempool->current = mempool->first; 95 | mempool->current->free = mempool->current->block; 96 | } 97 | 98 | 99 | char * mempool_alloc(struct Mempool *mempool, size_t size) 100 | { 101 | char* ptr; 102 | 103 | /* 104 | ** Align to 4 byte boundary - should be ok for most machines. 105 | ** Change this if your machine has weird alignment requirements. 106 | */ 107 | size = (size + 3) & 0xfffffffc; 108 | 109 | if (!mempool->current) return NULL; 110 | ptr = mempool->current->free; 111 | mempool->current->free += size; 112 | 113 | // Check if the current block is exhausted 114 | 115 | if (mempool->current->free >= mempool->current->end) 116 | { 117 | // Is the next block already allocated? 118 | 119 | if (mempool->current->next) 120 | { 121 | // re-use block 122 | mempool->current->next->free = mempool->current->next->block; 123 | mempool->current = mempool->current->next; 124 | } 125 | else 126 | { 127 | // extend the pool with a new block 128 | mempool->current->next = createMemBlock(); 129 | if (!mempool->current->next) return NULL; 130 | mempool->current = mempool->current->next; 131 | } 132 | 133 | // set ptr to the first location in the next block 134 | 135 | ptr = mempool->current->free; 136 | mempool->current->free += size; 137 | } 138 | 139 | // Return pointer to allocated memory 140 | 141 | return ptr; 142 | } 143 | -------------------------------------------------------------------------------- /R/curves.r: -------------------------------------------------------------------------------- 1 | 2 | #' Adds a new data curve to a project. 3 | #' 4 | #' @param id The ID name of the curve to be added. 5 | #' @details The new curve contains a single data point (1.0, 1.0). 6 | #' @return null invisibly 7 | #' @export 8 | #' @useDynLib epanet2toolkit RENaddcurve 9 | ENaddcurve <- function(id){ 10 | 11 | res <- .C("RENaddcurve", id, as.integer(-1)) 12 | check_epanet_error(res[[2]]) 13 | return(invisible) 14 | } 15 | 16 | 17 | #' Deletes a data curve from a project 18 | #' 19 | #' @param index the data curve's index (starting from 1). 20 | #' @return null invisibly 21 | #' @export 22 | #' @useDynLib epanet2toolkit RENdeletecurve 23 | ENdeletecurve <- function(index){ 24 | 25 | res <- .C("RENdeletecurve", index, as.integer(-1)) 26 | check_epanet_error(res[[2]]) 27 | return(invisible()) 28 | } 29 | 30 | #' Retrieves the index of a curve given its ID name. 31 | #' 32 | #' @param id the ID name of a curve. 33 | #' @return The curve's index (starting from 1). 34 | #' @export 35 | #' @useDynLib epanet2toolkit RENgetcurveindex 36 | ENgetcurveindex <- function(id){ 37 | 38 | res <- .C("RENgetcurveindex", id, as.integer(-1), as.integer(-1)) 39 | check_epanet_error(res[[3]]) 40 | return(res[[2]]) 41 | } 42 | 43 | #' Retrieves the ID name of a curve given its index. 44 | #' 45 | #' @param index a curve's index (starting from 1). 46 | #' @return the curve's ID name. 47 | #' @export 48 | #' @useDynLib epanet2toolkit RENgetcurveid 49 | ENgetcurveid <- function(index){ 50 | 51 | buff <- strrep(" ", EN_MAXID) 52 | res <- .C("RENgetcurveid", as.integer(index), buff, as.integer(-1)) 53 | check_epanet_error(res[[3]]) 54 | return(res[[2]]) 55 | } 56 | 57 | 58 | #' Changes the ID name of a data curve given its index. 59 | #' 60 | #' @param index a data curve index (starting from 1). 61 | #' @param id the data curve's new ID name. 62 | #' @return null invisibly 63 | #' @export 64 | #' @useDynLib epanet2toolkit RENsetcurveid 65 | ENsetcurveid <- function(index, id){ 66 | 67 | res <- .C("RENsetcurveid", as.integer(index), id, as.integer(-1)) 68 | check_epanet_error(res[[3]]) 69 | return(invisible) 70 | } 71 | 72 | #' Retrieves the number of points in a curve. 73 | #' 74 | #' @param index a curve's index (starting from 1). 75 | #' @return The number of data points assigned to the curve. 76 | #' @export 77 | #' @useDynLib epanet2toolkit RENgetcurvelen 78 | ENgetcurvelen <- function(index){ 79 | 80 | res <- .C("RENgetcurvelen", as.integer(index), as.integer(-1), as.integer(-1)) 81 | check_epanet_error(res[[3]]) 82 | return(res[[2]]) 83 | } 84 | 85 | #' Retrieves a curve's type 86 | #' 87 | #' @param index a curve's index (starting from 1). 88 | #' @return the curve's type 89 | #' @export 90 | #' @useDynLib epanet2toolkit RENgetcurvetype 91 | ENgetcurvetype <- function(index){ 92 | res <- .C("RENgetcurvetype", as.integer(index), as.integer(-1), as.integer(-1)) 93 | check_epanet_error(res[[3]]) 94 | ctype <- res[[2]] 95 | return( EN_CurveType[ctype+1]) 96 | } 97 | 98 | 99 | #' Retrieves the value of a single data point for a curve. 100 | #' 101 | #' @param curveIndex a curve's index (starting from 1). 102 | #' @param pointIndex the index of a point on the curve (starting from 1). 103 | #' @return list with the point's x-value and y-value 104 | #' @export 105 | #' @useDynLib epanet2toolkit RENgetcurvevalue 106 | ENgetcurvevalue <- function(curveIndex, pointIndex){ 107 | 108 | res <- .C("RENgetcurvevalue", as.integer(curveIndex), as.integer(pointIndex), 0.0, 0.0, as.integer(-1)) 109 | check_epanet_error(res[[5]]) 110 | val <- list( x = res[[3]], 111 | y = res[[4]] ) 112 | return(val) 113 | } 114 | 115 | #' Sets the value of a single data point for a curve. 116 | #' 117 | #' @param curveIndex a curve's index (starting from 1). 118 | #' @param pointIndex the index of a point on the curve (starting from 1). 119 | #' @param x the point's new x-value. 120 | #' @param y the point's new y-value. 121 | #' @return null invisibly 122 | #' @export 123 | #' @useDynLib epanet2toolkit RENsetcurvevalue 124 | ENsetcurvevalue <- function(curveIndex, pointIndex, x, y){ 125 | 126 | res <- .C("RENsetcurvevalue", as.integer(curveIndex), as.integer(pointIndex), 127 | as.numeric(x), as.numeric(y), as.integer(-1)) 128 | check_epanet_error( res[[5]]) 129 | return(invisible()) 130 | } 131 | 132 | 133 | # NOTE - opted to not implement ENgetcurve for R as it can be built from the other funcs -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![CRAN RStudio mirror 2 | downloads](http://cranlogs.r-pkg.org/badges/epanet2toolkit)](https://cran.r-project.org/package=epanet2toolkit) 3 | [![CRAN 4 | version](http://www.r-pkg.org/badges/version/epanet2toolkit)](https://cran.r-project.org/package=epanet2toolkit) 5 | 6 | 7 | # epanet2toolkit 8 | epanet2toolkit is an R package for simulating water networks using Epanet. The 9 | package provides functions from the Epanet programmer's toolkit as R functions so 10 | that basic or customized simulations can be carried out from R. The package 11 | uses [Epanet version 2.2 from Open Water Analytics](https://github.com/OpenWaterAnalytics/EPANET/releases/tag/v2.2). 12 | This version of the R package supports much of the extensive new functionality in EPANET version 2.2. 13 | 14 | In addition to this readme page and the package manual, the paper [An R package for EPANET simulations](https://doi.org/10.1016/j.envsoft.2018.05.016) 15 | is published in _Environmental Modelling & Software_ and is also available as a [preprint](http://bradeck.net/docs/ArandiaEck2018epanet2toolkit.pdf). The conference paper [Water demand and network modelling with R](http://bradeck.net/docs/iEMSs18.pdf) gives some more in depth examples. 16 | 17 | ## Installation 18 | The package can be installed from CRAN. 19 | ``` 20 | install.packages("epanet2toolkit") 21 | ``` 22 | 23 | Or, install the development version from github.com 24 | ``` 25 | devtools::install_github("bradleyjeck\epanet2toolkit") 26 | ``` 27 | 28 | ## Getting Started 29 | After installation, the package needs to be loaded for use. 30 | ``` 31 | library(epanet2toolkit) 32 | ``` 33 | A brief introduction is available in the package help and each function has its 34 | own help page. Functions provided by the package map directly to functions in 35 | Epanet's API and integrate with the R system for handling exceptions. Thus the 36 | function ENgetnodeindex( nodeID ) provides the index corresponding to a node 37 | ID, or raises an error if such a node ID does not exist. 38 | 39 | ``` 40 | ?epanet2toolkit 41 | ?ENgetnodeindex 42 | ``` 43 | 44 | ### Running a Full Simulation 45 | The function ENepanet() runs a full simulation and writes the results to a file. 46 | A file of simulation results can be analyzed using the package [epanetReader](https://github.com/bradleyjeck/epanetReader). 47 | ``` 48 | ENepanet("Net1.inp", "Net1.rpt") 49 | ``` 50 | 51 | ### Querying Network Properties 52 | Characteristics of a network can be examined using package functions. 53 | Note that Epanet needs to be opened for use and should be closed when the analysis finishes. 54 | ``` 55 | ENopen("Net1.inp", "Net1.rpt") 56 | ENgetflowunits() 57 | ENgetqualtype() 58 | ENgetcount("EN_NODECOUNT") 59 | ENgetcount("EN_LINKCOUNT") 60 | ENgetnodeid(1) 61 | ENgetlinkid(1) 62 | ENclose() 63 | ``` 64 | ### Example Programs 65 | 66 | The US EPA website for Epanet includes example programs for a hydrant rating curve 67 | and chlorine dosage analysis. An implementation of those programs using R and epanet2toolkit 68 | are included with the package as tests: 69 | - [Hydrant Rating Example](https://github.com/bradleyjeck/epanet2toolkit/blob/master/tests/testthat/test_epanet_example_2.r) 70 | - [Chlorine Dosage Example](https://github.com/bradleyjeck/epanet2toolkit/blob/master/tests/testthat/test_epanet_example_3.r) 71 | 72 | 73 | 74 | ## Programming Notes for Package Developers 75 | 76 | Epanet provides a collection of functions known as the programmer's toolkit or 77 | API for building customized simulations. epanet2toolkit makes these functions 78 | callable from R. 79 | 80 | Functions in the Epanet API return an integer error code and provide requested 81 | values by reference. 82 | ``` 83 | int ENgetnodeindex(char *nodeID, int *nodeindex); 84 | ``` 85 | A C toolkit function such as ENgetnodeindex takes two arguments: the node 86 | ID, and a pointer to an integer variable where the requested nodeindex is 87 | stored. The function returns an integer error code. Using the C function 88 | requires allocating an integer for storing the requested node index and passing 89 | a pointer to the storage location to the function. Checking 90 | the returned error code is optional, but is good practice. 91 | 92 | epanet2toolkit integrates Epanet into R by providing two layers of 93 | wrapping. First, the existing functions of Epanet's C API are wrapped by new C 94 | functions with return type 'void' or 'SEXP' so that they can be called from R. 95 | Second, new R functions are provided to call these new C functions. The R 96 | functions provide some argument checking and also check the error codes returned 97 | by Epanet. 98 | 99 | -------------------------------------------------------------------------------- /src/enumstxt.h: -------------------------------------------------------------------------------- 1 | /* 2 | ***************************************************************************** 3 | Project: OWA EPANET 4 | Version: 2.2 5 | Module: enumstxt.h 6 | Description: text strings for enumerated data types 7 | Authors: see AUTHORS 8 | Copyright: see AUTHORS 9 | License: see LICENSE 10 | Last Updated: 06/20/2019 11 | ****************************************************************************** 12 | */ 13 | 14 | #ifndef ENUMSTXT_H 15 | #define ENUMSTXT_H 16 | #include "text.h" 17 | 18 | char *NodeTxt[] = {t_JUNCTION, 19 | t_RESERVOIR, 20 | t_TANK}; 21 | 22 | char *LinkTxt[] = {w_CV, 23 | w_PIPE, 24 | w_PUMP, 25 | w_PRV, 26 | w_PSV, 27 | w_PBV, 28 | w_FCV, 29 | w_TCV, 30 | w_GPV}; 31 | 32 | char *StatTxt[] = {t_XHEAD, 33 | t_TEMPCLOSED, 34 | t_CLOSED, 35 | t_OPEN, 36 | t_ACTIVE, 37 | t_XFLOW, 38 | t_XFCV, 39 | t_XPRESSURE, 40 | t_FILLING, 41 | t_EMPTYING, 42 | t_OVERFLOWING}; 43 | 44 | char *FormTxt[] = {w_HW, 45 | w_DW, 46 | w_CM}; 47 | 48 | char *RptFormTxt[] = {t_HW, 49 | t_DW, 50 | t_CM}; 51 | 52 | char *RptFlowUnitsTxt[] = {u_CFS, 53 | u_GPM, 54 | u_MGD, 55 | u_IMGD, 56 | u_AFD, 57 | u_LPS, 58 | u_LPM, 59 | u_MLD, 60 | u_CMH, 61 | u_CMD}; 62 | 63 | char *FlowUnitsTxt[] = {w_CFS, 64 | w_GPM, 65 | w_MGD, 66 | w_IMGD, 67 | w_AFD, 68 | w_LPS, 69 | w_LPM, 70 | w_MLD, 71 | w_CMH, 72 | w_CMD}; 73 | 74 | char *PressUnitsTxt[] = {w_PSI, 75 | w_KPA, 76 | w_METERS}; 77 | 78 | char *DemandModelTxt[] = { w_DDA, 79 | w_PDA, 80 | NULL }; 81 | 82 | char *QualTxt[] = {w_NONE, 83 | w_CHEM, 84 | w_AGE, 85 | w_TRACE}; 86 | 87 | 88 | char *SourceTxt[] = {w_CONCEN, 89 | w_MASS, 90 | w_SETPOINT, 91 | w_FLOWPACED}; 92 | 93 | char *ControlTxt[] = {w_BELOW, 94 | w_ABOVE, 95 | w_TIME, 96 | w_CLOCKTIME}; 97 | 98 | char *TstatTxt[] = {w_NONE, 99 | w_AVG, 100 | w_MIN, 101 | w_MAX, 102 | w_RANGE}; 103 | 104 | char *MixTxt[] = {w_MIXED, 105 | w_2COMP, 106 | w_FIFO, 107 | w_LIFO, 108 | NULL}; 109 | 110 | char *RptFlagTxt[] = {w_NO, 111 | w_YES, 112 | w_FULL}; 113 | 114 | char *SectTxt[] = {s_TITLE, s_JUNCTIONS, s_RESERVOIRS, 115 | s_TANKS, s_PIPES, s_PUMPS, 116 | s_VALVES, s_CONTROLS, s_RULES, 117 | s_DEMANDS, s_SOURCES, s_EMITTERS, 118 | s_PATTERNS, s_CURVES, s_QUALITY, 119 | s_STATUS, s_ROUGHNESS, s_ENERGY, 120 | s_REACTIONS, s_MIXING, s_REPORT, 121 | s_TIMES, s_OPTIONS, s_COORDS, 122 | s_VERTICES, s_LABELS, s_BACKDROP, 123 | s_TAGS, s_END, 124 | NULL}; 125 | 126 | char *Fldname[] = {t_ELEV, t_DEMAND, t_HEAD, 127 | t_PRESSURE, t_QUALITY, t_LENGTH, 128 | t_DIAM, t_FLOW, t_VELOCITY, 129 | t_HEADLOSS, t_LINKQUAL, t_LINKSTATUS, 130 | t_SETTING, t_REACTRATE, t_FRICTION, 131 | "", "", "", "", "", "", NULL}; 132 | 133 | 134 | #endif 135 | -------------------------------------------------------------------------------- /src/hash.c: -------------------------------------------------------------------------------- 1 | /* 2 | ****************************************************************************** 3 | Project: OWA EPANET 4 | Version: 2.2 5 | Module: hash.c 6 | Description: implementation of a simple hash table 7 | Authors: see AUTHORS 8 | Copyright: see AUTHORS 9 | License: see LICENSE 10 | Last Updated: 05/15/2019 11 | ****************************************************************************** 12 | */ 13 | 14 | #include 15 | #include 16 | #include "hash.h" 17 | 18 | #define HASHTABLEMAXSIZE 128000 19 | 20 | // An entry in the hash table 21 | typedef struct DataEntryStruct 22 | { 23 | char *key; 24 | int data; 25 | struct DataEntryStruct *next; 26 | } DataEntry; 27 | 28 | // Hash a string to an integer 29 | unsigned int gethash(char *str) 30 | { 31 | unsigned int hash = 5381; 32 | unsigned int retHash; 33 | int c; 34 | while ((c = *str++)) 35 | { 36 | hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ 37 | } 38 | retHash = hash % HASHTABLEMAXSIZE; 39 | return retHash; 40 | } 41 | 42 | // Produce a duplicate string 43 | char *dupstr(const char *s) 44 | { 45 | size_t size = strlen(s) + 1; 46 | char *p = malloc(size); 47 | if (p) memcpy(p, s, size); 48 | return p; 49 | } 50 | 51 | // Create a hash table 52 | HashTable *hashtable_create(void) 53 | { 54 | int i; 55 | HashTable *ht = (HashTable *) calloc(HASHTABLEMAXSIZE, sizeof(HashTable)); 56 | if (ht != NULL) 57 | { 58 | for (i = 0; i < HASHTABLEMAXSIZE; i++) ht[i] = NULL; 59 | } 60 | return ht; 61 | } 62 | 63 | // Insert an entry into the hash table 64 | int hashtable_insert(HashTable *ht, char *key, int data) 65 | { 66 | unsigned int i = gethash(key); 67 | DataEntry *entry; 68 | if ( i >= HASHTABLEMAXSIZE ) return 0; 69 | entry = (DataEntry *) malloc(sizeof(DataEntry)); 70 | if (entry == NULL) return(0); 71 | entry->key = dupstr(key); 72 | entry->data = data; 73 | entry->next = ht[i]; 74 | ht[i] = entry; 75 | return 1; 76 | } 77 | 78 | // Change the hash table's data entry for a particular key 79 | int hashtable_update(HashTable *ht, char *key, int new_data) 80 | { 81 | unsigned int i = gethash(key); 82 | DataEntry *entry; 83 | 84 | if ( i >= HASHTABLEMAXSIZE ) return NOTFOUND; 85 | entry = ht[i]; 86 | while (entry != NULL) 87 | { 88 | if ( strcmp(entry->key, key) == 0 ) 89 | { 90 | entry->data = new_data; 91 | return 1; 92 | } 93 | entry = entry->next; 94 | } 95 | return NOTFOUND; 96 | } 97 | 98 | // Delete an entry in the hash table 99 | int hashtable_delete(HashTable *ht, char *key) 100 | { 101 | unsigned int i = gethash(key); 102 | DataEntry *entry, *preventry; 103 | 104 | if ( i >= HASHTABLEMAXSIZE ) return NOTFOUND; 105 | 106 | preventry = NULL; 107 | entry = ht[i]; 108 | while (entry != NULL) 109 | { 110 | if (strcmp(entry->key, key) == 0) 111 | { 112 | if (preventry == NULL) ht[i] = entry->next; 113 | else preventry->next = entry->next; 114 | free(entry->key); 115 | free(entry); 116 | return 1; 117 | } 118 | preventry = entry; 119 | entry = entry->next; 120 | } 121 | return NOTFOUND; 122 | } 123 | 124 | // Find the data for a particular key 125 | int hashtable_find(HashTable *ht, char *key) 126 | { 127 | unsigned int i = gethash(key); 128 | DataEntry *entry; 129 | 130 | if ( i >= HASHTABLEMAXSIZE ) return NOTFOUND; 131 | entry = ht[i]; 132 | while (entry != NULL) 133 | { 134 | if ( strcmp(entry->key, key) == 0 ) 135 | { 136 | return entry->data; 137 | } 138 | entry = entry->next; 139 | } 140 | return NOTFOUND; 141 | } 142 | 143 | // Find a particular key in the hash table 144 | char *hashtable_findkey(HashTable *ht, char *key) 145 | { 146 | unsigned int i = gethash(key); 147 | DataEntry *entry; 148 | if ( i >= HASHTABLEMAXSIZE ) return NULL; 149 | entry = ht[i]; 150 | while (entry != NULL) 151 | { 152 | if ( strcmp(entry->key, key) == 0 ) return entry->key; 153 | entry = entry->next; 154 | } 155 | return NULL; 156 | } 157 | 158 | // Delete a hash table and free all of its memory 159 | void hashtable_free(HashTable *ht) 160 | { 161 | DataEntry *entry, *nextentry; 162 | int i; 163 | 164 | for (i = 0; i < HASHTABLEMAXSIZE; i++) 165 | { 166 | entry = ht[i]; 167 | while (entry != NULL) 168 | { 169 | nextentry = entry->next; 170 | free(entry->key); 171 | free(entry); 172 | entry = nextentry; 173 | } 174 | ht[i] = NULL; 175 | } 176 | free(ht); 177 | } 178 | -------------------------------------------------------------------------------- /R/options.r: -------------------------------------------------------------------------------- 1 | #***************************************** 2 | # 3 | # (C) Copyright IBM Corp. 2017 4 | # Author: Ernesto Arandia & Bradley J Eck 5 | # 6 | #***************************************** 7 | 8 | 9 | #' Retrieve the value of an analysis option. 10 | #' 11 | #' \code{ENgetoption} retrieves the value of one or more particular analysis options. 12 | #' 13 | #' @export 14 | #' @useDynLib epanet2toolkit RENgetoption 15 | #' @param optioncode A character or integer specifying the option code 16 | #' (see below). 17 | #' 18 | #' @return numeric value of the specified analysis option(s). 19 | #' 20 | #' @details Option codes consist of the following constants: 21 | #' \tabular{ll}{ 22 | #' \code{EN_TRIALS} \tab 0 \cr 23 | #' \code{EN_ACCURACY} \tab 1 \cr 24 | #' \code{EN_TOLERANCE} \tab 2 \cr 25 | #' \code{EN_EMITEXPON} \tab 3 \cr 26 | #' \code{EN_DEMANDMULT} \tab 4 27 | #' } 28 | #' 29 | #' @examples 30 | #' # path to Net1.inp example file included with this package 31 | #' inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 32 | #' ENopen( inp, "Net1.rpt") 33 | #' ENgetoption(0) 34 | #' ENgetoption("EN_TRIALS") 35 | #' ENclose() 36 | ENgetoption <- function(optioncode) { 37 | 38 | codeTable = c("EN_TRIALS", "EN_ACCURACY", "EN_TOLERANCE", "EN_EMITEXPON", "EN_DEMANDMULT") 39 | 40 | # check the arguments 41 | if( length(optioncode) != 1 ) stop("can only get one option at time") 42 | if (missing(optioncode)) { 43 | stop("Need to specify the analysis option code.") 44 | } 45 | if (is.character(optioncode)) { 46 | code <- as.integer(match(optioncode, codeTable) - 1) 47 | } 48 | else if (is.numeric(optioncode)) { 49 | code = as.integer(optioncode) 50 | } 51 | else if (is.integer(optioncode)) { 52 | code <- optioncode 53 | } 54 | else{ 55 | stop("The analysis option code must be a character string or an integer.") 56 | } 57 | if (any(is.na(code))) { 58 | stop("The analysis option code specified is incorrect.") 59 | } 60 | 61 | x <- .C("RENgetoption", code, 0.0, as.integer(-1)) 62 | check_epanet_error( x[[3]]) 63 | return( x[[2]]) 64 | } 65 | 66 | 67 | #' Set the value of a particular analysis option. 68 | #' 69 | #' \code{ENsetoption} sets the value of a particular analysis option. 70 | #' 71 | #' @export 72 | #' @useDynLib epanet2toolkit RENsetoption 73 | #' @param optioncode An integer or character vector specifying the option 74 | #' @param value numeric 75 | #' 76 | #' @details Option codes consist of the following constants: 77 | #' 78 | #' \tabular{lr}{ 79 | #' \code{EN_TRIALS} \tab 0\cr 80 | #' \code{EN_ACCURACY} \tab 1\cr 81 | #' \code{EN_TOLERANCE} \tab 2\cr 82 | #' \code{EN_EMITEXPON} \tab 3\cr 83 | #' \code{EN_DEMANDMULT} \tab 4 84 | #' } 85 | #' 86 | #' 87 | #' @examples 88 | #' # path to Net1.inp example file included with this package 89 | #' inp <- file.path( find.package("epanet2toolkit"), "extdata","Net1.inp") 90 | #' ENopen( inp, "Net1.rpt") 91 | #' ENgetoption("EN_TRIALS") 92 | #' ENsetoption("EN_TRIALS", 22) 93 | #' ENgetoption("EN_TRIALS") 94 | #' ENclose() 95 | ENsetoption <- function(optioncode, value) { 96 | 97 | codeTable = c("EN_TRIALS", "EN_ACCURACY", "EN_TOLERANCE", "EN_EMITEXPON", "EN_DEMANDMULT") 98 | 99 | # check the arguments 100 | if( length(optioncode) != 1 ) stop("can only set one option at time") 101 | if (missing(optioncode)) { 102 | stop("Need to specify the analysis option code.") 103 | } 104 | if (is.character(optioncode)) { 105 | code <- as.integer(match(optioncode, codeTable) - 1) 106 | } 107 | else if (is.numeric(optioncode)) { 108 | code = as.integer(optioncode) 109 | } 110 | else if (is.integer(optioncode)) { 111 | code <- optioncode 112 | } 113 | else{ 114 | stop("The analysis option code must be a character string or an integer.") 115 | } 116 | if (any(is.na(code))) { 117 | stop("The analysis option code specified is incorrect.") 118 | } 119 | 120 | if( length(value) != 1) stop("can only set one option at a time") 121 | if( !is.numeric(value)) stop("value must be numeric") 122 | 123 | x <- .C("RENsetoption", code, value, as.integer(-1)) 124 | check_epanet_error( x[[3]]) 125 | return( invisible()) 126 | } 127 | 128 | 129 | #' Sets flow units. 130 | #' 131 | #' @param units the choice of flow units. One of: "EN_CFS", "EN_GPM", "EN_MGD", 132 | #' "EN_IMGD", "EN_AFD", "EN_LPS", "EN_LPM", "EN_MLD", "EN_CMH", "EN_CMD" 133 | #' @returns null invisibly 134 | #' @details Flow units in liters or cubic meters implies that SI metric units 135 | #' are used for all other quantities in addition to flow. Otherwise US Customary 136 | #' units are employed. 137 | #' @useDynLib epanet2toolkit RENsetflowunits 138 | ENsetflowunits <- function(units){ 139 | FlowUnitsEnums <-c("EN_CFS" ,"EN_GPM" ,"EN_MGD" ,"EN_IMGD" ,"EN_AFD" ,"EN_LPS" ,"EN_LPM" ,"EN_MLD" ,"EN_CMH" ,"EN_CMD") 140 | flowUnitsVal <- lookup_enum_value(FlowUnitsEnums, units) 141 | x <- .C("RENsetflowunits", as.integer(flowUnitsVal), as.integer(-1)) 142 | check_epanet_error(x[[2]]) 143 | } --------------------------------------------------------------------------------