-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathrunRSWMM.r
executable file
·235 lines (193 loc) · 11.6 KB
/
runRSWMM.r
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#runRSWMM Developed by Peter Steinberg of Herrera Environmental Consultants
#Send bugs and feature requests to: [email protected], 206-715-4492
#Version 1: December 2011
#Revision 1.1: January 1/10/2012, corrected problem in binary file reader
#General Notes
#Before editing this script do the following things:
#Move your SWMM file to a directory that can hold a lot of files
#Test that you can run your SWMM file from this directory and you haven't messed up paths to files or something
#Take your SWMM input file and replace the uncertain parameters with codes like
# $1$, $2$, $3$
#You can repeat codes if you want the optimization algorithm to repeat a parameter.
#For example, if you know 2 subcatchments should have the same infiltration rate, you
# can put the same code in for their infiltration rates and they will receive the same parameter
#Create a parameter bounds CSV file that looks like this (without the comment sign #):
# Code,Minimum,Maximum,Initial
# $1$,10,32,15
# $2$,10,31,20
# $3$,4,15,5
# $4$,2,8,7
# $5$,25,100,33
# $6$,20,75,33
# $7$,20,60,50
#Create a calibration time series data CSV that looks like this (without the comment sign #):
#Date ,(CFS)
#1/1/07 0:01,0.08
#1/1/07 0:02,0.22
#1/1/07 0:03,0.38
#1/1/07 0:04,0.54
#1/1/07 0:05,0.67
#1/1/07 0:06,0.83
#REMEMBER YOU HAVE TO USE DOUBLE BACKSLASHES FOR ALL FILENAMES##########
#You have to manually create all directories you provide. RSWMM does not make directories.
#Preliminaries: clear workspace and source the RSWMM code for a function library
rm(list=ls())
#edit this source line to reflect where you have saved RSWMM.r.
source("O:\\departments\\Water Quality\\Users\\Peter\\programs\\RSWMM\\RSWMM.r")
#If you are doing a calibration run, you need to provide the following lines
# to direct the optimizer to your files
#Calibration Data should be in a CSV with datetimes in the first column,
#and data in the second column
#The text file is assumed to have a one line header
#Call this function with the correct dateFormat for your datetimes
#the dateFormat is passed to strptime, so look for formatting information there
#for example, dates like this 1/1/07 12:00, can be read with the default dateFormat
#e.g.:
#Date ,(CFS)
#1/1/07 0:01,0.08
#1/1/07 0:02,0.22
#1/1/07 0:03,0.38
#1/1/07 0:04,0.54
#1/1/07 0:05,0.67
#1/1/07 0:06,0.83
#
calDataCSV="O:\\departments\\Water Quality\\Users\\Peter\\programs\\RSWMM\\testingData\\CalData1.csv"
#if you have a non-stadard date format, you can provide that as an argument below, but in either case
# you have to call the function that reads the calData
#getCalDataFromCSV(CSVFile=calDataCSV,dateFormat="%m/%d/%y %H:%M")
calDataObj<-getCalDataFromCSV(CSVFile=calDataCSV)
#Provide a path for the CSV containing optimization history. This is an empty file to start out.
#Make sure you have created the directories that will hold this file
optFile="O:\\departments\\Water Quality\\Users\\Peter\\programs\\RSWMM\\testingData\\Optimization History.csv"
#Provide a path for the CSV containing parameter bounds
#For ease, make your parameter bounds file in this format (without the comment symbols):
# Code,Minimum,Maximum,Initial
# $1$,10,32,15
# $2$,10,31,20
# $3$,4,15,5
# $4$,2,8,7
# $5$,25,100,33
# $6$,20,75,33
# $7$,20,60,50
parFile="O:\\departments\\Water Quality\\Users\\Peter\\programs\\RSWMM\\testingData\\Parameter Ranges 1.csv"
parametersTable=getParmeterBounds(parFile)
#Initialize the iteration count and the optimization history, in case you
#want to stop the model before the optimization function is complete. If you
# press the STOP button before the optimzation function returns, you can check your
#csv provided above or the variable optimizationHistory for intermediate results
iteration=1
optimizationHistory=data.frame()
#Select single or multiobjective optimization by setting one of the two following variables to TRUE
#Set useOptim to TRUE if you are doing single objective optimization, otherwise FALSE
useOptim=FALSE
#set useMCO to TRUE if you are doing multiobjective optimization, otherwise FALSE
useMCO=TRUE
##################################################################################
#######################Single Objective Calibration Begins Here##################
#####################################################################################
#If you are doing multi-objective optimization, this section is ignored
#Provide options for single objective optimization
#Initialize the options object
optimOpt={}
#Pick one of six methods for calibration:
# may be one of = c("Nelder-Mead", "BFGS", "CG", "L-BFGS-B", "SANN", "Brent"),
optimOpt$method ="SANN"
#Look at the documentation in RSWMM.R for the getSWMMTimeSeriesData function
#to develop a function call that returns your time series
# of interest from the SWMM binary file
# a few notes on this funtion:
#you always have to pass in headobj=headobj. This is so that you don't reread the header on every iteration
#you select an iType, which determines whether you are looking for a node, link, subcatchment, or system variable
#you provide a vIndex, which is the parameter you want to return (e.g. depth)
#you provide the nameInOutputFile. This will be the same as the node, link, or subcatchment number in the input file.
#if you are getting a system variable's results, you can leave nameInOutputFile as ""
#you should provide a function call in quotes that will subsequently be evaled in the objective function
optimOpt$functionCallToEvalForASWMMTimeSeries='getSWMMTimeSeriesData(headObj=headObj,iType=3,nameInOutputFile="",vIndex=4)'
#Put the parameter bounds and intialization in the optimization options: you shouldn't need to change these
# lines if you have imported them using RSWMM formats/functions
optimOpt$lower= c(as.vector(parametersTable["Minimum"]))$Minimum
optimOpt$upper=c(as.vector(parametersTable["Maximum"]))$Maximum
optimOpt$initial=c(as.vector(parametersTable["Initial"]))$Initial
#Provide a base name for the input/output files that are created
#RSWMM will add the necessary extensions. It also adds random text so that it is thread safe, and
# you can run more than one RSWMM.r optimization at the same time
optimOpt$baseOutputName="O:\\departments\\Water Quality\\Users\\Peter\\programs\\RSWMM\\testingData\\OptTest1\\Opt Ex1 Post"
#Provide a SWMM template file that has the replacement codes
optimOpt$SWMMTemplateFile="O:\\departments\\Water Quality\\Users\\Peter\\programs\\RSWMM\\testingData\\Example1-Post.inp"
#Provide a path to SWMM.exe. The binary file reader is written for SWMM 5.0.022. For earlier versions of SWMM,
# you would have to edit the binary file reader because the output format has changed.
optimOpt$SWMMexe="C:\\Program Files (x86)\\EPA SWMM 5.0\\SWMM5.exe"
#Look at RSWMM.R's performanceStatsAsMinimization function and select one of the performance statistics
optimOpt$performanceStat="sumOfSquaredError"
#The following function call does the optimization. It should not need any edits,
#unless you want to look at the optim function documentation and provide more specific
# control parameters.
#set the working directory in R to be the directory of the swmm template so that LID reports
#show up in the right place #this is a 1/24/2012 edit
setwd(dirname(optimOpt$SWMMTemplateFile))
if(useOptim){
out=optim(optimOpt$initial,objectiveFunction,
gr = NULL, baseOutputName= optimOpt$baseOutputName,
SWMMTemplateFile=optimOpt$SWMMTemplateFile,
SWMMexe=optimOpt$SWMMexe,
functionCallToEvalForASWMMTimeSeries=optimOpt$functionCallToEvalForASWMMTimeSeries,
performanceStat=optimOpt$performanceStat,
method = optimOpt$method,
lower = optimOpt$lower, upper = optimOpt$upper,
control = list(), hessian = FALSE)
}
#################################################################################
#########################End of Single Objective Calibration Section#############
#################################################################################
##################################################################################
######################### Start of Multiobjective Optimization ##################
#################################################################################
#If you are doing single objective optimization by setting useOptim to TRUE, this
#section is ignored.
#initialize the multiobjective optimization options object
mcoOpt={}
#Look at the documentation in RSWMM.R for the getSWMMTimeSeriesData function
#to develop a function call that returns your time series
# of interest from the SWMM binary file
# a few notes on this funtion:
#you always have to pass in headobj=headobj. This is so that you don't reread the header on every iteration
#you select an iType, which determines whether you are looking for a node, link, subcatchment, or system variable
#you provide a vIndex, which is the parameter you want to return (e.g. depth)
#you provide the nameInOutputFile. This will be the same as the node, link, or subcatchment number in the input file.
#if you are getting a system variable's results, you can leave nameInOutputFile as ""
#you should provide a function call in quotes that will subsequently be evaled in the objective function
mcoOpt$functionCallToEvalForASWMMTimeSeries='getSWMMTimeSeriesData(headObj=headObj,iType=3,nameInOutputFile="",vIndex=4)'
#Provide upper and lower bounds. No need to edit these lines if you have imported parameters using RSWMM functions/formats
mcoOpt$lower=c(as.vector(parametersTable["Minimum"]))$Minimum
mcoOpt$upper=c(as.vector(parametersTable["Maximum"]))$Maximum
#Provide path to SWMM.exe
mcoOpt$SWMMexe="C:\\Program Files (x86)\\EPA SWMM 5.0\\SWMM5.exe"
#Select one or more performance stats listed in RSWMM.R
mcoOpt$performanceStats=c("sumOfSquaredError","linearCorrelationTimesMinus1")
#Provide a base output name for SWMM input/output files
mcoOpt$baseOutputName="O:\\departments\\Water Quality\\Users\\Peter\\programs\\RSWMM\\testingData\\OptTest1\\Opt Ex1 Post"
#Provide a path to your SWMM template file with replacement codes in it
mcoOpt$SWMMTemplateFile="O:\\departments\\Water Quality\\Users\\Peter\\programs\\RSWMM\\testingData\\Example1-Post.inp"
#set the working directory in R to be the directory of the swmm template so that LID reports
#show up in the right place #this is a 1/24/2012 edit
setwd(dirname(mcoOpt$SWMMTemplateFile))
#This is the function call to NSGA2. Change this if
# you want to further control the process. (See the documentation for mco package: NSGS2 function)
if(useMCO){
library(mco)
out= nsga2(objectiveFunction,
idim=length(mcoOpt$lower),
odim=length(mcoOpt$performanceStats),
baseOutputName= mcoOpt$baseOutputName,
SWMMTemplateFile=mcoOpt$SWMMTemplateFile,
SWMMexe=mcoOpt$SWMMexe,
functionCallToEvalForASWMMTimeSeries=mcoOpt$functionCallToEvalForASWMMTimeSeries,
performanceStat=mcoOpt$performanceStats,
generations=500,
lower.bounds=as.real(mcoOpt$lower),
upper.bounds=as.real(mcoOpt$upper),
constraints=NULL)
}
##################################################################################
########################END of multiobjective optimization########################
##################################################################################