1 /**********************************************************
2 * Version $Id: model_tools.cpp 911 2011-02-14 16:38:15Z reklov_w $
3 *********************************************************/
4 #include "model_tools.h"
5 #include <math.h>
6 #include <stdlib.h> // random numbers
7 //-------------------------------------------------------------------
8
9 ///////////////////////////////////////////////////////////////////////
10 //
11 // OBJECTIVE FUNCTIONS
12 //
13 ///////////////////////////////////////////////////////////////////////
14
15 //---------------------------------------------------------------------
16 // Calculate Nash-Sutcliff efficiency
17 //---------------------------------------------------------------------
CalcEfficiency(double * obs,double * sim,int nvals)18 double model_tools::CalcEfficiency(double *obs, double *sim, int nvals)
19 {
20 int i;
21
22 double sum_obsminsim_2 = 0.0;
23 double sum_obsminmean_2 = 0.0;
24 double mean_obs = 0.0;
25 //double sum_obs = 0.0; // sum of observed discharge
26
27 // calculate mean of observed time series
28 for (i = 0; i < nvals; i++)
29 mean_obs += obs[i] / nvals;
30
31 for (i = 0; i < nvals; i++)
32 {
33 sum_obsminsim_2 += pow(obs[i] - sim[i], 2.0);
34 sum_obsminmean_2 += pow(obs[i] - mean_obs, 2.0);
35 }
36
37 return (1 - sum_obsminsim_2 / sum_obsminmean_2);
38 }
39 //-------------------------------------------------------------------
40
CalcEfficiency(vector_d & obs,vector_d & sim)41 double model_tools::CalcEfficiency(vector_d &obs, vector_d &sim)
42 {
43 int i;
44
45 int nvals = obs.size();
46 double sum_obsminsim_2 = 0.0;
47 double sum_obsminmean_2 = 0.0;
48 double mean_obs = 0.0;
49 //double sum_obs = 0.0; // sum of observed discharge
50
51 // calculate mean of observed time series
52 for (i = 0; i < nvals; i++)
53 mean_obs += obs[i] / nvals;
54
55 for (i = 0; i < nvals; i++)
56 {
57 sum_obsminsim_2 += pow(obs[i] - sim[i], 2.0);
58 sum_obsminmean_2 += pow(obs[i] - mean_obs, 2.0);
59 }
60
61 return (1 - sum_obsminsim_2 / sum_obsminmean_2);
62 }
63 //-------------------------------------------------------------------
64 // Calculate Nash-Sutcliff efficiency adapted to high flow
65 // Reference:
66 // Liu and De Smedt, 2004. WetSpa Extension,
67 // A GIS-based Hydrologic Model for Flood Prediction and Watershed Management
68 // Documentation and User Manual. Brussels. Vrije Universiteit Brussel.
69
Calc_NSE_HighFlow(double * obs,double * sim,int nvals)70 double model_tools::Calc_NSE_HighFlow(double *obs, double *sim, int nvals)
71 {
72 int i;
73
74 double mean_obs = 0.0;
75 double sum_numerator = 0.0;
76 double sum_denominator = 0.0;
77
78 // calculate mean of observed time series
79 for (i = 0; i < nvals; i++)
80 mean_obs += obs[i] / nvals;
81
82 for (i = 0; i < nvals; i++)
83 {
84 sum_numerator += ( (obs[i] + mean_obs) * pow(sim[i] - obs[i], 2.0));
85 sum_denominator += ( (obs[i] + mean_obs) * pow(obs[i] - mean_obs, 2.0));
86 }
87
88 return ( 1 - sum_numerator / sum_denominator );
89 }
90 //-------------------------------------------------------------------
91
92 //-------------------------------------------------------------------
93 // Calculate Nash-Sutcliff efficiency adapted to high flow
94 // Reference:
95 // Liu and De Smedt, 2004. WetSpa Extension,
96 // A GIS-based Hydrologic Model for Flood Prediction and Watershed Management
97 // Documentation and User Manual. Brussels. Vrije Universiteit Brussel.
98
Calc_NSE_LowFlow(double * obs,double * sim,int nvals)99 double model_tools::Calc_NSE_LowFlow(double *obs, double *sim, int nvals)
100 {
101 int i;
102
103 double mean_obs = 0.0;
104 double sum_log_obsminsim_2 = 0.0;
105 double sum_log_obsminmean_2 = 0.0;
106
107 // calculate mean of observed time series
108 for (i = 0; i < nvals; i++)
109 mean_obs += obs[i] / nvals;
110
111 for (i = 0; i < nvals; i++)
112 {
113 sum_log_obsminsim_2 += pow( (log(obs[i])-log(sim[i])),2 );
114 sum_log_obsminmean_2 += pow( (log(obs[i])-log(mean_obs)),2 );
115 }
116
117 return( 1 - sum_log_obsminsim_2 / sum_log_obsminmean_2);
118 }
119 //---------------------------------------------------------------------
120
121 //---------------------------------------------------------------------
122 // Calculate PBIAS
123 //---------------------------------------------------------------------
Calc_PBIAS(double * obs,double * sim,int nvals)124 double model_tools::Calc_PBIAS(double* obs, double* sim, int nvals)
125 {
126 double sim_min_obs = 0.0;
127 double sum_obs = 0.0;
128
129 for (int i = 0; i < nvals; i++)
130 {
131 sim_min_obs += sim[i] - obs[i];
132 sum_obs += obs[i];
133 }
134
135 return(sim_min_obs * 100 / sum_obs);
136 }
137 //---------------------------------------------------------------------
138
139
140
141
142 ///////////////////////////////////////////////////////////////////////
143 //
144 // RUNOFF COEFFICIENT
145 //
146 ///////////////////////////////////////////////////////////////////////
147
148 //---------------------------------------------------------------------
149 // Calculate Runoff Coefficient
150 //---------------------------------------------------------------------
CalcRunoffCoeff(vector_d & streamflow,vector_d & precipitation)151 double model_tools::CalcRunoffCoeff(vector_d &streamflow, vector_d &precipitation)
152 {
153 // calculate runoff coefficient as stated in:
154 // Kokkonen, T. S. et al. (2003).
155 double sum_flow = 0;
156 double sum_pcp = 0;
157
158 for (unsigned int i = 0; i < streamflow.size(); i++)
159 {
160 sum_flow += streamflow[i];
161 sum_pcp += precipitation[i];
162 }
163 return (sum_flow / sum_pcp * 100);
164 }
165 //---------------------------------------------------------------------
CalcRunoffCoeff(double * streamflow,double * precipitation,int nvals)166 double model_tools::CalcRunoffCoeff(double *streamflow, double *precipitation,
167 int nvals)
168 {
169 // calculate runoff coefficient as stated in:
170 // Kokkonen, T. S. et al. (2003).
171 double sum_flow = 0;
172 double sum_pcp = 0;
173
174 for (int i = 0; i < nvals; i++)
175 {
176 sum_flow += streamflow[i];
177 sum_pcp += precipitation[i];
178 }
179 return (sum_flow / sum_pcp * 100);
180 }
181
182
183
184
185
186 ///////////////////////////////////////////////////////////////////////
187 //
188 // UNIT CONVERSION
189 //
190 ///////////////////////////////////////////////////////////////////////
191
m3s_to_mmday(double val,double area)192 double model_tools::m3s_to_mmday(double val, double area)
193 {
194 return(val * 86.4 / area);
195 }
196 //---------------------------------------------------------------------
m3s_to_mmday(double * m3s,double * mmday,int nvals,double area)197 double *model_tools::m3s_to_mmday(double *m3s, double *mmday, int nvals, double area)
198 {
199 for (int i = 0; i < nvals; i++)
200 mmday[i] = m3s[i] * 86.4 / area;
201 return(mmday);
202 }
203 //---------------------------------------------------------------------
m3s_to_mmday(vector_d & m3s,vector_d & mmday,double area)204 vector_d model_tools::m3s_to_mmday(vector_d &m3s, vector_d &mmday, double area)
205 {
206 for (unsigned int i = 0; i < m3s.size(); i++)
207 mmday[i] = m3s[i] * 86.4 / area;
208 return(mmday);
209 }
210 //---------------------------------------------------------------------
211
mmday_to_m3s(double val,double area)212 double model_tools::mmday_to_m3s(double val, double area)
213 {
214 return(val * area / 86.4);
215 }
216 //---------------------------------------------------------------------
mmday_to_m3s(double * mmday,double * m3s,int nvals,double area)217 double *model_tools::mmday_to_m3s(double *mmday, double *m3s, int nvals, double area)
218 {
219 for (int i = 0; i < nvals; i++)
220 m3s[i] = mmday[i] * area / 86.4;
221 return(m3s);
222 }
223 //---------------------------------------------------------------------
mmday_to_m3s(vector_d & mmday,vector_d & m3s,double area)224 vector_d model_tools::mmday_to_m3s(vector_d &mmday, vector_d &m3s, double area)
225 {
226 for (unsigned int i = 0; i < m3s.size(); i++)
227 m3s[i] = mmday[i] * area / 86.4;
228 return(m3s);
229 }
230
231
232
233
234
235 ///////////////////////////////////////////////////////////////////////
236 //
237 // MISC
238 //
239 ///////////////////////////////////////////////////////////////////////
240
241 //---------------------------------------------------------------------
242 // Create a random number
243 //---------------------------------------------------------------------
Random_double(double lb,double ub)244 double model_tools::Random_double(double lb, double ub)
245 {
246 // lb = lower bound, ub = upper bound
247 double random;
248
249 random = rand()/(1.+RAND_MAX);
250 random = lb + (ub - lb) * random;
251
252 return(random);
253 }
254 //-------------------------------------------------------------------
255
256 //---------------------------------------------------------------------
257 // Leap year function
258 //---------------------------------------------------------------------
LeapYear(int year)259 bool model_tools::LeapYear(int year)
260 {
261 if ( (year % 4 == 0) &&
262 (year % 100 != 0) ||
263 (year % 400 == 0) )
264 return(true);
265 else
266 return(false);
267 }
268 //-------------------------------------------------------------------
269
270
271 //---------------------------------------------------------------------
272 // Find indices of lowest values
273 //---------------------------------------------------------------------
FindLowestIndices(double * array,int nvals,int * TopIndex,int top)274 void model_tools::FindLowestIndices(double *array, int nvals, int *TopIndex, int top)
275 {
276 double min_temp = 99999999.0;
277 double x = -99999999.0;
278 int index = 0;
279
280 for (int k = 0; k < top; k++)
281 {
282 for (int j = 0; j < nvals; j++)
283 {
284 if (array[j] < min_temp && array[j] > x)
285 {
286 min_temp = array[j];
287 index = j;
288 }
289 }
290 TopIndex[k] = index;
291 x = min_temp;
292 min_temp = 99999999.0;
293 }
294 }
295
296 //---------------------------------------------------------------------
297 // Find indices of highest values
298 //---------------------------------------------------------------------
FindHighestIndices(double * array,int nvals,int * TopIndex,int top,double min)299 void model_tools::FindHighestIndices(double *array, int nvals, int *TopIndex, int top, double min)
300 {
301 double max_temp = -99999999.0;
302 double x = 99999999.0;
303 int index = 0;
304 bool exist = false;
305
306 for (int k = 0; k < top; k++)
307 {
308 for (int j = 0; j < nvals; j++)
309 {
310 if (array[j] > max_temp && array[j] < x && array[j] > min)
311 {
312 max_temp = array[j];
313 index = j;
314 exist = true;
315 }
316 }
317 if (exist)
318 {
319 TopIndex[k] = index;
320 } else {
321 TopIndex[k] = -1;
322 }
323 exist = false;
324 x = max_temp;
325 max_temp = -99999999.0;
326 }
327 }
328 //---------------------------------------------------------------------
329
330
331 //---------------------------------------------------------------------
332 // summarize arrays
333 //---------------------------------------------------------------------
SumArray(double * array,unsigned int size)334 double model_tools::SumArray(double* array, unsigned int size)
335 {
336 double sum = 0.0;
337 for (unsigned int i = 0; i < size; i++) {
338 sum += array[i];
339 }
340 return(sum);
341 }
342 //---------------------------------------------------------------------
343