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