/**********************************************************
 * Version $Id: ihacres_elev_cal.cpp 1261 2011-12-16 15:12:15Z oconrad $
 *********************************************************/
///////////////////////////////////////////////////////////
//                    ihacres_elev_cal.cpp               //
//                                                       //
//                 Copyright (C) 2008 by                 //
//                     Stefan Liersch                    //
//-------------------------------------------------------//
//    e-mail:     stefan.liersch@ufz.de                  //
//                stefan.liersch@gmail.com               //
//                     2008-01-08                        //
///////////////////////////////////////////////////////////

#include "ihacres_elev_cal.h"
#include "convert_sl.h"
#include "model_tools.h"

#include <stdlib.h> // random numbers
#include <time.h>	// random numbers

// TEST OUTPUT ONLY
#include <fstream>

//---------------------------------------------------------------------

Cihacres_elev_cal::Cihacres_elev_cal()
{
	//-----------------------------------------------------
	// 1. Info...
	Set_Name(_TL("IHACRES Elevation Bands Calibration"));

	Set_Author(SG_T("copyrights (c) 2008 Stefan Liersch"));

	Set_Description(_TW("The rainfall-runoff model IHACRES."
	));

	Add_Reference(
		SG_T("Jakeman, A.J., Hornberger, G.M."), "1993",
		SG_T("How Much Complexity Is Warranted in a Rainfall-Runoff Model?"),
		SG_T("Water Resources Research, 29, No. 8, 2637-2649")
	);

	Add_Reference(
		SG_T("Kokkonen, T. S. et al."), "2003",
		SG_T("Predicting daily flows in ungauged catchments: model regionalization from catchment descriptors at the Coweeta Hydrologic Laboratory, North Carolina"),
		SG_T("Hydrological Processes, 17, 2219-2238")
	);

	Add_Reference(
		SG_T("Croke, B.F.W., Merritt, W.S., et al."), "2004",
		SG_T("A dynamic model for predicting hydrologic response to land cover changes in gauged and ungauged catchments"),
		SG_T("Journal Of Hydrology, 291(1-2), 115-131")
	);

	Parameters.Add_Table_Output(
		NULL	, "TABLEout"	, _TL("Table"),
		_TL("")
	);
	Parameters.Add_Table_Output(
		NULL	, "TABLEparms"	, _TL("Table"),
		_TL("")
	);

	///////////////////////////////////////////////////////////////////
	// FIRST TOOL DIALOG
	_CreateDialog1();
	///////////////////////////////////////////////////////////////////
}

Cihacres_elev_cal::~Cihacres_elev_cal()
{}
//---------------------------------------------------------------------

bool Cihacres_elev_cal::On_Execute()
{
	double		NSE_temp	= 0.0;
	double		NSE_max		= -9999.9;
	string		nse, nse_text;

	CSG_Parameters P;
	//std::ofstream f("_out_elev.txt");

	// Assign Parameters from first Tool Dialog
	//---------------------------------------------------------
	int eb			= Parameters("NELEVBANDS")		->asInt();
	m_nElevBands	= eb + 2; // because list starts with 2 !
	m_nsim			= Parameters("NSIM")			->asInt();
	m_Area_tot		= Parameters("AREA_tot")		->asDouble();
	m_IHAC_version	= Parameters("IHACVERS")		->asInt();
	m_StorConf		= Parameters("STORAGE")			->asInt();
	m_bSnowModule	= Parameters("SNOW_TOOL")		->asBool();
	m_obj_func		= Parameters("OBJ_FUNC")		->asInt();
	m_NSEmin		= Parameters("NSEMIN")			->asDouble();

	//---------------------------------------------------------

	//---------------------------------------------------------
	// Assign number of storages
	m_nStorages = ihacres.Assign_nStorages(m_StorConf);
	//---------------------------------------------------------

	//---------------------------------------------------------
	// Initialize pointers
	_Init_ElevBands(m_nElevBands);
	m_p_linparms	= new C_IHAC_LinearParms(m_nElevBands,m_nStorages);
	m_p_lin_lb		= new C_IHAC_LinearParms(m_nElevBands,m_nStorages);
	m_p_lin_ub		= new C_IHAC_LinearParms(m_nElevBands,m_nStorages);
	m_p_nonlinparms = new C_IHAC_NonLinearParms(m_nElevBands);
	m_p_nl_lb		= new C_IHAC_NonLinearParms(m_nElevBands);
	m_p_nl_ub		= new C_IHAC_NonLinearParms(m_nElevBands);
	//---------------------------------------------------------

	//---------------------------------------------------------
	// open second and third user dialog
	if ( _CreateDialog2() && _CreateDialog3())
	{
		//---------------------------------------------------------
		// searching the first and the last record of the time range
		ihacres.AssignFirstLastRec(*m_p_InputTable, m_first, m_last, m_date1, m_date2, m_dateField);
		m_nValues = m_last - m_first + 1;
		//---------------------------------------------------------
		
		//---------------------------------------------------------
		_Init_Pointers(m_nValues);
		//---------------------------------------------------------

		//---------------------------------------------------------
		// read input table
		_ReadInputFile();
		//---------------------------------------------------------

		//---------------------------------------------------------
		// PERFORM STREAMFLOW SIMULATION
		// FOR EACH ELEVATION BAND
		//---------------------------------------------------------
		// Convert Streamflow vector from m3/s*day-1 to mm/day
		m_p_Q_obs_mmday = model_tools::m3s_to_mmday(m_p_Q_obs_m3s, m_p_Q_obs_mmday, m_nValues, m_Area_tot);
		
		//---------------------------------------------------------
		m_pTable_parms = SG_Create_Table();
		_CreateTableParms();
		m_counter = 0;
		//---------------------------------------------------------

		///////////////////////////////////////////////////////////
		//
		//		SIMULATION
		//
		///////////////////////////////////////////////////////////
		
		// initialize random function
		srand((unsigned) time(NULL)); // using time.h

		for (int sim = 0; sim < m_nsim && Set_Progress(sim, m_nsim); sim++)
		{
			_Simulate_NonLinearModule();

			_Simulate_Streamflow();

			_Sum_Streamflow();

			m_NSE = m_NSE_lowflow = m_NSE_highflow = m_PBIAS = 0;
			_CalcEfficiency();


			// write in output table if criterion is fulfilled
			NSE_temp = ihacres._Assign_NSE_temp(m_obj_func, m_NSE, m_NSE_highflow, m_NSE_lowflow);

			if (NSE_temp > m_NSEmin)
			{
				if (NSE_temp > NSE_max)
				{
					NSE_max = NSE_temp;
					nse = convert_sl::Double2String(NSE_max).c_str();
					nse_text = "max. NSE ";
					nse_text += nse;
					Process_Set_Text(CSG_String(nse_text.c_str()));
				}

				_WriteTableParms();
			}
		}
		//---------------------------------------------------------

		m_pTable_parms->Set_Name(SG_T("ihacres_elevbands_cal"));
		Parameters("TABLEparms")->Set_Value(m_pTable_parms);

		//m_pTable = SG_Create_Table();
		//_CreateTableSim();
		//// add tables to SAGA Workspace
		//m_pTable->Set_Name("ihacres_elevBands_output");
		//Parameters("TABLEout")->Set_Value(m_pTable);

		delete[] m_p_elevbands; // sämtliche Unter-Pointer noch löschen
		delete[] m_p_pcpField;
		delete[] m_p_tmpField;
		delete[] m_p_Q_obs_m3s;
		delete[] m_p_Q_obs_mmday;
		delete[] m_p_Q_sim_mmday;
		delete m_p_linparms;
		delete m_p_nonlinparms;
		delete m_p_lin_lb;
		delete m_p_lin_ub;
		delete m_p_nl_lb;
		delete m_p_nl_ub;
		if (m_bSnowModule) {
			delete[] m_pSnowparms;
			delete[] m_pSnowparms_lb;
			delete[] m_pSnowparms_ub;
		}
		delete[] m_vq;
		delete[] m_vs;
		
		return(true);
	} // end if ( _CreateDialog2() )

		// delete[] m_p_elevbands;
		// delete[] m_p_pcpFields;
		// delete[] m_p_tmpFields;
		// delete m_p_linparms;
		// delete m_p_nonlinparms;
	return(false);
}

//---------------------------------------------------------------------

void Cihacres_elev_cal::_Init_ElevBands(int nvals)
{
	// instantiate elevation bands
	m_p_elevbands = new Cihacres_elev_bands[nvals];

	// instantiate field numbers
	m_p_pcpField = new int[nvals];
	m_p_tmpField = new int[nvals];

	if (m_bSnowModule)
	{
		m_pSnowparms	= new CSnowParms[nvals];
		m_pSnowparms_lb	= new CSnowParms[nvals];
		m_pSnowparms_ub	= new CSnowParms[nvals];
	}

	m_vq = new double[nvals];
	m_vs = new double[nvals];
}
//---------------------------------------------------------------------

void Cihacres_elev_cal::_Init_Pointers(int nvals)
{
	m_vec_date.resize(nvals);
	m_p_Q_obs_m3s = new double[nvals];
	m_p_Q_obs_mmday = new double[nvals];
	m_p_Q_sim_mmday = new double[nvals];
	
	for (int eb = 0; eb < m_nElevBands; eb++)
	{
		m_p_elevbands[eb].m_p_pcp = new double[nvals];
		m_p_elevbands[eb].m_p_tmp = new double[nvals];
		m_p_elevbands[eb].m_p_ER = new double[nvals];
		m_p_elevbands[eb].m_p_streamflow_sim = new double[nvals];
		m_p_elevbands[eb].m_p_Tw = new double[nvals];
		m_p_elevbands[eb].m_p_WI = new double[nvals];
	
		if (m_bSnowModule) {
			m_p_elevbands[eb].m_p_SnowStorage = new double[nvals];
			m_p_elevbands[eb].m_p_MeltRate = new double[nvals];
		}
	}
}
//---------------------------------------------------------------------

void Cihacres_elev_cal::_ReadInputFile()
{
	for (int j = 0, k = m_first; j < m_nValues, k < m_last + 1; j++, k++)
	{
		m_vec_date[j].append(CSG_String(m_p_InputTable->Get_Record(k)->asString(m_dateField)));
		m_p_Q_obs_m3s[j] = m_p_InputTable->Get_Record(k)->asDouble(m_streamflowField);
		
		for (int eb = 0; eb < m_nElevBands; eb++)
		{
			m_p_elevbands[eb].m_p_pcp[j] = m_p_InputTable->Get_Record(k)->asDouble(m_p_pcpField[eb]);
			m_p_elevbands[eb].m_p_tmp[j] = m_p_InputTable->Get_Record(k)->asDouble(m_p_tmpField[eb]);
		}
	}
}
//---------------------------------------------------------------------

void Cihacres_elev_cal::_CalcSnowModule(int eb)
{
	m_p_SnowModule = new CSnowModule(m_p_elevbands[eb].m_p_tmp, m_p_elevbands[eb].m_p_pcp, m_nValues,
									m_pSnowparms[eb].T_Rain, m_pSnowparms[eb].T_Melt, m_pSnowparms[eb].DD_FAC);

	m_p_elevbands[eb].m_p_MeltRate = m_p_SnowModule->Get_MeltRate(m_p_elevbands[eb].m_p_MeltRate, m_nValues);
	m_p_elevbands[eb].m_p_SnowStorage = m_p_SnowModule->Get_SnowStorage(m_p_elevbands[eb].m_p_SnowStorage, m_nValues);

	delete m_p_SnowModule;
}
//---------------------------------------------------------------------

void Cihacres_elev_cal::_Simulate_NonLinearModule()
{
	double eR_init = 0.0;
	for (int eb = 0; eb < m_nElevBands; eb++)
	{
		//-------------------------------------------------------------
		// Assign random values
		//-------------------------------------------------------------
		if (m_bSnowModule)
		{
			m_pSnowparms[eb].T_Rain	= model_tools::Random_double(m_pSnowparms_lb[eb].T_Rain,m_pSnowparms_ub[eb].T_Rain);
			m_pSnowparms[eb].T_Melt	= model_tools::Random_double(m_pSnowparms_lb[eb].T_Melt,m_pSnowparms_ub[eb].T_Melt);
			m_pSnowparms[eb].DD_FAC = model_tools::Random_double(m_pSnowparms_lb[eb].DD_FAC,m_pSnowparms_ub[eb].DD_FAC);

			m_p_SnowModule = new CSnowModule(m_p_elevbands[eb].m_p_tmp, m_p_elevbands[eb].m_p_pcp, m_nValues,
				m_pSnowparms[eb].T_Rain, m_pSnowparms[eb].T_Melt, m_pSnowparms[eb].DD_FAC);

			m_p_elevbands[eb].m_p_MeltRate = m_p_SnowModule->Get_MeltRate(m_p_elevbands[eb].m_p_MeltRate, m_nValues);
			delete m_p_SnowModule;
		}
	
		m_p_nonlinparms->mp_tw[eb]	= model_tools::Random_double(m_p_nl_lb->mp_tw[eb], m_p_nl_ub->mp_tw[eb]);
		m_p_nonlinparms->mp_f[eb]	= model_tools::Random_double(m_p_nl_lb->mp_f[eb], m_p_nl_ub->mp_f[eb]);
		m_p_nonlinparms->mp_c[eb]	= model_tools::Random_double(m_p_nl_lb->mp_c[eb], m_p_nl_ub->mp_c[eb]);

		if (m_IHAC_version == 1) { // Croke etal. (2005)
			m_p_nonlinparms->mp_l[eb]= model_tools::Random_double(m_p_nl_ub->mp_l[eb],m_p_nl_ub->mp_l[eb]);
			m_p_nonlinparms->mp_p[eb]= model_tools::Random_double(m_p_nl_ub->mp_p[eb],m_p_nl_ub->mp_p[eb]);
		}

		//----------------------------------------------------------
		// calculate excess rainfall time series
		//----------------------------------------------------------
		switch(m_IHAC_version)
		{
		case 0: // Jakeman & Hornberger (1993)
			// The parameter index (fourth parameter) is zero here, because 
			// the parameter settings of the non-linear module are in all elevationbands equal.
			// If they should be different the index parameter can be used to identify the
			// corresponding elevation band.
			ihacres.CalcWetnessTimeConst(m_p_elevbands[eb].m_p_tmp, m_p_elevbands[eb].m_p_Tw,
					m_p_nonlinparms, eb, m_nValues); 
					// 0 = index (only one instance of m_p_nonlinparms)

			if (m_bSnowModule)
			{
				ihacres.CalcWetnessIndex(m_p_elevbands[eb].m_p_Tw, m_p_elevbands[eb].m_p_pcp,
					m_p_elevbands[eb].m_p_tmp, m_p_elevbands[eb].m_p_WI, 0.5, m_p_nonlinparms->mp_c[eb],
					m_bSnowModule, m_pSnowparms[eb].T_Rain, m_nValues);

				ihacres.CalcExcessRain(m_p_elevbands[eb].m_p_pcp, m_p_elevbands[eb].m_p_tmp,
					m_p_elevbands[eb].m_p_WI, m_p_elevbands[eb].m_p_ER, eR_init,
					m_p_elevbands[eb].m_sum_eRainGTpcp, m_nValues, m_bSnowModule,
					m_pSnowparms[eb].T_Rain, m_pSnowparms[eb].T_Melt,
					m_p_elevbands[eb].m_p_MeltRate);
			} else {

				ihacres.CalcWetnessIndex(m_p_elevbands[eb].m_p_Tw, m_p_elevbands[eb].m_p_pcp,
					m_p_elevbands[eb].m_p_tmp, m_p_elevbands[eb].m_p_WI, 0.5, m_p_nonlinparms->mp_c[eb],
					m_bSnowModule, 0, m_nValues);

				ihacres.CalcExcessRain(m_p_elevbands[eb].m_p_pcp, m_p_elevbands[eb].m_p_tmp,
					m_p_elevbands[eb].m_p_WI, m_p_elevbands[eb].m_p_ER, eR_init,
					m_p_elevbands[eb].m_sum_eRainGTpcp, m_nValues, m_bSnowModule,
					0,0,0);
			}
			break;
		case 1: // Croke et al. (2005)
			ihacres.CalcWetnessTimeConst_Redesign(m_p_elevbands[eb].m_p_tmp, m_p_elevbands[eb].m_p_Tw,
				m_p_nonlinparms, eb, m_nValues);	// 0 = index (only one instance of m_p_nonlinparms)

			if (m_bSnowModule)
			{
				ihacres.CalcWetnessIndex_Redesign(m_p_elevbands[eb].m_p_Tw, m_p_elevbands[eb].m_p_pcp, m_p_elevbands[eb].m_p_WI, 0.5,
					m_bSnowModule, m_pSnowparms[eb].T_Rain, m_nValues);

				ihacres.CalcExcessRain_Redesign(m_p_elevbands[eb].m_p_pcp, m_p_elevbands[eb].m_p_tmp, m_p_elevbands[eb].m_p_WI, 
					m_p_elevbands[eb].m_p_ER, eR_init, m_p_elevbands[eb].m_sum_eRainGTpcp, m_nValues, 
					m_p_nonlinparms->mp_c[eb], m_p_nonlinparms->mp_l[eb], m_p_nonlinparms->mp_p[eb],
					m_bSnowModule, m_pSnowparms[eb].T_Rain, m_pSnowparms[eb].T_Melt, m_p_elevbands[eb].m_p_MeltRate);
			} else {
				ihacres.CalcWetnessIndex_Redesign(m_p_elevbands[eb].m_p_Tw, m_p_elevbands[eb].m_p_pcp, m_p_elevbands[eb].m_p_WI, 0.5,
					m_bSnowModule, 0, m_nValues);

				ihacres.CalcExcessRain_Redesign(m_p_elevbands[eb].m_p_pcp, m_p_elevbands[eb].m_p_tmp, m_p_elevbands[eb].m_p_WI, 
					m_p_elevbands[eb].m_p_ER, eR_init, m_p_elevbands[eb].m_sum_eRainGTpcp, m_nValues, 
					m_p_nonlinparms->mp_c[eb], m_p_nonlinparms->mp_l[eb], m_p_nonlinparms->mp_p[eb],
					m_bSnowModule, 0,0,0);
			}
			break;
		} // end switch(m_IHAC_vers)
	}
}
//---------------------------------------------------------------------

void Cihacres_elev_cal::_Simulate_Streamflow()
{
	//-------------------------------------------------------------
	// Assign random values
	//-------------------------------------------------------------
	for (int eb = 0; eb < m_nElevBands; eb++)
	{
		switch(m_StorConf)
		{
		case 0: // single storage
			m_p_linparms->a[eb]	= model_tools::Random_double(m_p_lin_lb->a[eb],m_p_lin_ub->a[eb]);
			m_p_linparms->b[eb]	= model_tools::Random_double(m_p_lin_lb->b[eb],m_p_lin_ub->b[eb]);
			break;
		case 1: // two storages in parallel
			do
			{
				m_p_linparms->aq[eb] = model_tools::Random_double(m_p_lin_lb->aq[eb], m_p_lin_ub->aq[eb]);
				m_p_linparms->as[eb] = model_tools::Random_double(m_p_lin_lb->as[eb], m_p_lin_ub->as[eb]);
				m_p_linparms->bq[eb] = model_tools::Random_double(m_p_lin_lb->bq[eb], m_p_lin_ub->bq[eb]);
				// Calculate parameter m_vq to check parms aq and bq
				// Equation after Jakeman & Hornberger (1993)
				m_vq[eb] = m_p_linparms->bq[eb] / ( 1 + m_p_linparms->aq[eb] );
			}
			while (m_vq[eb] < 0.0 || m_vq[eb] > 1.0);
			m_p_linparms->bs[eb] = ihacres.Calc_Parm_BS(m_p_linparms->aq[eb], m_p_linparms->as[eb], m_p_linparms->bq[eb]);
			break;
		}
	

		//----------------------------------------------------------
		// calculate streamflow
		//----------------------------------------------------------
		switch(m_StorConf)
		{
		case 0: // single storage
			ihacres.SimStreamflowSingle(m_p_elevbands[eb].m_p_ER, m_p_Q_obs_mmday[0],
				m_p_elevbands[eb].m_p_streamflow_sim, m_delay,
				m_p_linparms->a[eb], m_p_linparms->b[eb], m_nValues);
			break;
		case 1: // two storages in parallel
			ihacres.SimStreamflow2Parallel(m_p_elevbands[eb].m_p_ER,
				m_p_elevbands[eb].m_p_streamflow_sim, m_p_Q_obs_mmday[0],
				m_p_linparms, eb, m_vq[eb], m_vs[eb], m_nValues, m_delay);
			break;
		case 2: // two storages in series
			break;
		} // end switch(m_StorConf)
	}// end for (int eb...
}
//---------------------------------------------------------------------

//---------------------------------------------------------------------
//		Summarize streamflow from elevation bands
//---------------------------------------------------------------------
void Cihacres_elev_cal::_Sum_Streamflow()
{
	//std::ofstream f("_cal_elev.txt");
	
	double sum = 0.0;
	for (int n = 0; n < m_nValues; n++)
	{
		for (int eb = 0; eb < m_nElevBands; eb++) {
			sum += m_p_elevbands[eb].m_p_streamflow_sim[n] * m_p_elevbands[eb].m_area / m_Area_tot;
			//f << m_p_elevbands[eb].m_p_streamflow_sim[n] << ", ");
		}
		//f << std::endl;
		m_p_Q_sim_mmday[n] = sum;
		sum = 0.0;
	}
}
//---------------------------------------------------------------------


//---------------------------------------------------------------------
//		Nash-Sutcliffe efficiency
//---------------------------------------------------------------------
void Cihacres_elev_cal::_CalcEfficiency()
{
	m_NSE			= model_tools::CalcEfficiency(m_p_Q_obs_mmday, m_p_Q_sim_mmday, m_nValues);
	m_NSE_highflow	= model_tools::Calc_NSE_HighFlow(m_p_Q_obs_mmday, m_p_Q_sim_mmday, m_nValues);
	m_NSE_lowflow	= model_tools::Calc_NSE_LowFlow(m_p_Q_obs_mmday, m_p_Q_sim_mmday, m_nValues);
	m_PBIAS			= model_tools::Calc_PBIAS(m_p_Q_obs_mmday, m_p_Q_sim_mmday, m_nValues);
}
//---------------------------------------------------------------------


/////////////////////////////////////////////////////////////////////////////
//
//							CREATE TABLES
//
/////////////////////////////////////////////////////////////////////////////

//---------------------------------------------------------------------
//		Create output table
//---------------------------------------------------------------------
void Cihacres_elev_cal::_CreateTableParms()
{
	char c[12];

	// creating the column titles
	m_pTable_parms->Add_Field("NSE",				SG_DATATYPE_Double);
	m_pTable_parms->Add_Field("NSE_high",			SG_DATATYPE_Double);
	m_pTable_parms->Add_Field("NSE_low",			SG_DATATYPE_Double);
	m_pTable_parms->Add_Field("PBIAS",				SG_DATATYPE_Double);
	//m_pTable_parms->Add_Field("eR_ovest",			SG_DATATYPE_Double);

	for (int i = 0; i < m_nElevBands; i++)
	{
		sprintf(c,"%s_%d","vq",i+1);
		m_pTable_parms->Add_Field(c,					SG_DATATYPE_Double);
		sprintf(c,"%s_%d","vs",i+1);
		m_pTable_parms->Add_Field(c,					SG_DATATYPE_Double);
		sprintf(c,"%s_%d","T(q)",i+1);
		m_pTable_parms->Add_Field(c,					SG_DATATYPE_Double);
		sprintf(c,"%s_%d","T(s)",i+1);
		m_pTable_parms->Add_Field(c,					SG_DATATYPE_Double);
		sprintf(c,"%s_%d","Tw",i+1);
		m_pTable_parms->Add_Field(c,					SG_DATATYPE_Double);
		sprintf(c,"%s_%d","f",i+1);
		m_pTable_parms->Add_Field(c,					SG_DATATYPE_Double);
		sprintf(c,"%s_%d","c",i+1);
		m_pTable_parms->Add_Field(c,					SG_DATATYPE_Double);
		if ( m_IHAC_version == 1 ) // Croke etal. (2005)
		{
			sprintf(c,"%s_%d","l",i+1);
			m_pTable_parms->Add_Field(c,				SG_DATATYPE_Double);
			sprintf(c,"%s_%d","p",i+1);
			m_pTable_parms->Add_Field(c,				SG_DATATYPE_Double);
		}
		if (m_bSnowModule)
		{
			sprintf(c,"%s_%d","T_Rain",i+1);
			m_pTable_parms->Add_Field(c,				SG_DATATYPE_Double);
			sprintf(c,"%s_%d","T_Melt",i+1);
			m_pTable_parms->Add_Field(c,				SG_DATATYPE_Double);
			sprintf(c,"%s_%d","DD_FAC",i+1);
			m_pTable_parms->Add_Field(c,				SG_DATATYPE_Double);
		}
		switch(m_StorConf)
		{
		case 0: // single
			sprintf(c,"%s_%d","a",i+1);
			m_pTable_parms->Add_Field(c,				SG_DATATYPE_Double);
			sprintf(c,"%s_%d","b",i+1);
			m_pTable_parms->Add_Field(c,				SG_DATATYPE_Double);
			break;
		case 1: // two storages in parallel
			sprintf(c,"%s_%d","aq",i+1);
			m_pTable_parms->Add_Field(c,				SG_DATATYPE_Double);
			sprintf(c,"%s_%d","as",i+1);
			m_pTable_parms->Add_Field(c,				SG_DATATYPE_Double);
			sprintf(c,"%s_%d","bq",i+1);
			m_pTable_parms->Add_Field(c,				SG_DATATYPE_Double);
			sprintf(c,"%s_%d","bs",i+1);
			m_pTable_parms->Add_Field(c,				SG_DATATYPE_Double);
			break;
		}
	}
}
//---------------------------------------------------------------------

//---------------------------------------------------------------------
//		Create output table
//---------------------------------------------------------------------
void Cihacres_elev_cal::_WriteTableParms()
{
	int					field = 0;
	CSG_Table_Record	*pRecord;

	// add a new record to the table
	m_pTable_parms->Add_Record();
	pRecord	= m_pTable_parms->Get_Record(m_counter);

	// writing the data to the current row
	pRecord->Set_Value(field,m_NSE); field++;
	pRecord->Set_Value(field,m_NSE_highflow); field++;
	pRecord->Set_Value(field,m_NSE_lowflow); field++;
	pRecord->Set_Value(field,m_PBIAS); field++;
	//pRecord->Set_Value(field,m_sum_eRainGTpcp); field++;

	for (int eb = 0; eb < m_nElevBands; eb++)
	{
		pRecord->Set_Value(field,m_vq[eb]); field++;
		pRecord->Set_Value(field,m_vs[eb]); field++;
		pRecord->Set_Value(field,ihacres.Calc_TimeOfDecay(m_p_linparms->aq[eb])); field++;
		pRecord->Set_Value(field,ihacres.Calc_TimeOfDecay(m_p_linparms->as[eb])); field++;
		pRecord->Set_Value(field,m_p_nonlinparms->mp_tw[eb]); field++;
		pRecord->Set_Value(field,m_p_nonlinparms->mp_f[eb]); field++;
		pRecord->Set_Value(field,m_p_nonlinparms->mp_c[eb]); field++;
		if ( m_IHAC_version == 1 )
		{
			pRecord->Set_Value(field,m_p_nonlinparms->mp_l[eb]); field++;
			pRecord->Set_Value(field,m_p_nonlinparms->mp_p[eb]); field++;
		}
		if ( m_bSnowModule )
		{
			pRecord->Set_Value(field,m_pSnowparms[eb].T_Rain); field++;
			pRecord->Set_Value(field,m_pSnowparms[eb].T_Melt); field++;
			pRecord->Set_Value(field,m_pSnowparms[eb].DD_FAC); field++;
		}
		switch ( m_StorConf )
		{
		case 0: // single storage
			pRecord->Set_Value(field,m_p_linparms->a[eb]); field++;
			pRecord->Set_Value(field,m_p_linparms->b[eb]); field++;
			break;
		case 1:
			pRecord->Set_Value(field,m_p_linparms->aq[eb]); field++;
			pRecord->Set_Value(field,m_p_linparms->as[eb]); field++;
			pRecord->Set_Value(field,m_p_linparms->bq[eb]); field++;
			pRecord->Set_Value(field,m_p_linparms->bs[eb]); field++;
			break;
		}
	}
	m_counter++;
}
//---------------------------------------------------------------------



//---------------------------------------------------------------------
void Cihacres_elev_cal::_CreateTableSim()
{
	int i = 0; // used in function Get_Record(i)
	CSG_Table_Record	*pRecord;
	CSG_String			tmpName;
	double				sim_eb, sim;

	// creating the column titles
	m_pTable->Add_Field("Date",		SG_DATATYPE_String);
	m_pTable->Add_Field("Flow_OBS",	SG_DATATYPE_Double);

	for (int eb = 0; eb < m_nElevBands; eb++)
	{
		tmpName = SG_T("ELEVB_");
		tmpName += convert_sl::Int2String(eb+1).c_str();
		m_pTable->Add_Field(tmpName.c_str(),	SG_DATATYPE_Double);
	}
	m_pTable->Add_Field("Flow_SIM",	SG_DATATYPE_Double);

	for (int j = 0; j < m_nValues; j++)
	{
		m_pTable->Add_Record();
		pRecord = m_pTable->Get_Record(i);

		// writing the data into the rows
		pRecord->Set_Value(0,CSG_String(m_vec_date[j].c_str()));
		pRecord->Set_Value(1,m_p_Q_obs_m3s[j]);
		sim_eb = 0.0;
		sim = 0.0;
		for (int eb = 0; eb < m_nElevBands; eb++)
		{
			sim_eb = model_tools::mmday_to_m3s(m_p_elevbands[eb].m_p_streamflow_sim[j],m_p_elevbands[eb].m_area);
			//pRecord->Set_Value(3+eb,model_tools::mmday_to_m3s(m_p_elevbands[eb].m_p_streamflow_sim[j],m_p_elevbands[eb].m_area));
			pRecord->Set_Value(2+eb, sim_eb);
			sim += sim_eb;
		}
		pRecord->Set_Value(2+m_nElevBands,sim);
		i++;
	}
}


//---------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////
//
//		                          DIALOGS
//
///////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------
// DIALOG 1
//---------------------------------------------------------------------
void Cihacres_elev_cal::_CreateDialog1()
{
	CSG_Parameter	*pNode;
	CSG_String		s;

	pNode = Parameters.Add_Choice(
		NULL	, "NELEVBANDS"		, SG_T("Number of elevation bands"),
		_TL(""),
		SG_T("2|3|4|5|6|7|8|9|10")
	);

	pNode = Parameters.Add_Value(
		NULL,	"NSIM",	_TL("Number of Simulations"),
		_TL("Number of Simulations for Calibration"),
		PARAMETER_TYPE_Int,
		1000, 1, true, 10000000, true
	);

	pNode = Parameters.Add_Value(
		pNode,	"AREA_tot", _TL("Total Catchment Area [km2]"),
			_TL(""),
			PARAMETER_TYPE_Double
	);

	s.Printf(SG_T("Node1"), 1);
	pNode = Parameters.Add_Node(NULL,s,SG_T("IHACRES Version"),_TL(""));

	Parameters.Add_Choice(
		pNode	, "IHACVERS"		, SG_T("IHACRES Version"),
		_TL(""),
		CSG_String::Format(SG_T("%s|%s|"),
			_TL("Jakeman & Hornberger (1993)"),	//  0
			_TL("Croke et al. (2005) !!! not yet implemented !!!")	//	1
		)
	);

	s.Printf(SG_T("Node2"), 2);
	pNode = Parameters.Add_Node(NULL,s,SG_T("Storage Configuration"),_TL(""));

	Parameters.Add_Choice(
		pNode	, "STORAGE"		, SG_T("Storage"),
		_TL(""),
		CSG_String::Format(SG_T("%s|%s|%s|"),
			_TL("Single Storage"),			//  0
			_TL("Two Parallel Storages"),	//  1 
			_TL("Two Storages in Series !!! not yet implemented !!!")	//  2 
		)
	);

	Parameters.Add_Value(
		pNode,	"SNOW_TOOL",	_TL("Using the snow-melt module?"),
		_TL("If checked, snow-melt module is used."),
		PARAMETER_TYPE_Bool, false
	);

	s.Printf(SG_T("Node6"), 6);
	pNode = Parameters.Add_Node(NULL,s,SG_T("Nash-Sutcliffe Efficiency"),_TL(""));

	Parameters.Add_Choice(
		pNode, "OBJ_FUNC"		, SG_T("Objective Function"),
		_TL(""),
		SG_T("NSE|NSE high flow|NSE low flow")
	);

	Parameters.Add_Value(
		pNode,	"NSEMIN",	SG_T("Minimum Nash-Sutcliffe Efficiency"),
		SG_T("Minimum Nash-Sutcliffe Efficiency required to print simulation to calibration table"),
		PARAMETER_TYPE_Double,
		0.7, 0.1, true, 1.0, true
	);
}
//---------------------------------------------------------------------
// DIALOG 2
//---------------------------------------------------------------------

bool Cihacres_elev_cal::_CreateDialog2()
{
	int		i;

	//std::ofstream f("_out_elev.txt");

	CSG_Parameters	P;  // used to add Parameters in the second dialog
	CSG_Parameter	*pNode, *pNode1;
	CSG_String		s;
	CSG_String		tmpNode, tmpName;

	P.Set_Name(_TL("IHACRES Elevation Bands (Dialog 2)"));
	// Input file ----------------------------------------------
	pNode = P.Add_Table(
		NULL	, "TABLE"	, _TL("IHACRES Input Table"),
		_TL(""),
		PARAMETER_INPUT
	);

	P.Add_Table_Field(
		pNode	, "DATE_Field"	, _TL("Date Column"),
		SG_T("Select the column containing the Date")
	);

	P.Add_Table_Field(
		pNode	, "DISCHARGE_Field"	, _TL("Streamflow (obs.) Column"),
		SG_T("Select the column containing the observed streamflow time series")
	);
	
	for (i = 0; i < m_nElevBands; i++)
	{
		tmpNode = convert_sl::Int2String(i+1).c_str();
		//s.Printf(tmpNode.c_str(), i);
		//pNode1 = P.Add_Node(NULL,s,SG_T("Elevation Band Input",_TL(""));

		tmpName = SG_T("PCP Column: Elevation Band: ");
		tmpName+=tmpNode;
		P.Add_Table_Field(
			pNode	, tmpName.c_str(), tmpName.c_str(),
			SG_T("Select Precipitation Column")
		);

		tmpName = SG_T("TMP Column: Elevation Band: ");
		tmpName+=tmpNode;
		P.Add_Table_Field(
			pNode	, tmpName.c_str()	, tmpName.c_str(),
			SG_T("Select Temperature Column")
		);
	}
	// Input file ----------------------------------------------

	for (i = 0; i < m_nElevBands; i++)
	{
		tmpNode = SG_T("Node");
		tmpNode+=convert_sl::Int2String(i+100).c_str();
		tmpName = SG_T("Elevation Band ");
		tmpName+=convert_sl::Int2String(i+1).c_str();

		s.Printf(tmpNode.c_str(), i+100);
		pNode = P.Add_Node(NULL,s,tmpName.c_str(),_TL(""));
		
		tmpName = SG_T("Area [km2] Elev(");
		tmpName += tmpNode;
		tmpName += _TL(")");
		P.Add_Value(
			pNode,	tmpName, _TL("Area [km2]"),
			_TL(""),
			PARAMETER_TYPE_Double
		);

		tmpName = SG_T("Mean Elevation [m.a.s.l] Elev(");
		tmpName += tmpNode;
		tmpName += _TL(")");
		P.Add_Value(
			pNode,	tmpName, _TL("Mean Elevation [m.a.s.l]"),
			_TL(""),
			PARAMETER_TYPE_Double
		);


		// Parameters of non-linear module -------------------------

		tmpNode = SG_T("Node");
		tmpNode+=convert_sl::Int2String(i+150).c_str();
		s.Printf(tmpNode.c_str(), i+150);
		pNode1 = P.Add_Node(pNode,s,SG_T("Non-Linear Tool"),_TL(""));

		tmpName = SG_T("TwFAC_lb(");
		tmpName += tmpNode;
		tmpName += _TL(")");
		P.Add_Value(
			pNode1,	tmpName,	_TL("(Tw) wetness decline time constant [lower bound]"),
			_TW("Tw is approximately the time constant, or inversely,"
			"the rate at which the catchment wetness declines in the absence of rainfall"),
			PARAMETER_TYPE_Double,
			1.0, 0.01, true, 150.0, true
		);
		tmpName = SG_T("TwFAC_ub(");
		tmpName += tmpNode;
		tmpName += _TL(")");
		P.Add_Value(
			pNode1,	tmpName,	_TL("(Tw) wetness decline time constant [upper bound]"),
			_TW("Tw is approximately the time constant, or inversely,"
			"the rate at which the catchment wetness declines in the absence of rainfall"),
			PARAMETER_TYPE_Double,
			1.0, 0.01, true, 150.0, true
			);

		tmpName = SG_T("TFAC_lb(");
		tmpName += tmpNode;
		tmpName += _TL(")");
		P.Add_Value(
			pNode1, tmpName, SG_T("(f) Temperature Modulation Factor [lower bound]"),
			_TL("Temperature Modulation Factor f"),
			PARAMETER_TYPE_Double,
			0.05, 0.0001, true, 5.0, true
		);

		tmpName = SG_T("TFAC_ub(");
		tmpName += tmpNode;
		tmpName += _TL(")");
		P.Add_Value(
			pNode1, tmpName, SG_T("(f) Temperature Modulation Factor [upper bound]"),
			_TL("Temperature Modulation Factor f"),
			PARAMETER_TYPE_Double,
			0.5, 0.0001, true, 5.0, true
		);
	
		tmpName = SG_T("CFAC_lb(");
		tmpName += tmpNode;
		tmpName += _TL(")");
		P.Add_Value(
			pNode1,tmpName,	_TL("(c) Parameter [lower bound]"),
			_TL("Parameter (c) to fit streamflow volume"),
			PARAMETER_TYPE_Double,
			0.001, 0.0, true, 1.0, true
		);
		tmpName = SG_T("CFAC_ub(");
		tmpName += tmpNode;
		tmpName += _TL(")");
		P.Add_Value(
			pNode1,tmpName,	_TL("(c) Parameter [upper bound]"),
			_TL("Parameter (c) to fit streamflow volume"),
			PARAMETER_TYPE_Double,
			0.01, 0.0, true, 1.0, true
		);

		switch(m_IHAC_version)
		{
		case 0: // Jakeman & Hornberger (1993)
			break;
		case 1: // Croke et al. (2005)
			tmpNode = SG_T("Node");
			tmpNode+=convert_sl::Int2String(i+200).c_str();
			s.Printf(tmpNode.c_str(), i+200);
			pNode1 = P.Add_Node(pNode,s,SG_T("Soil Moisture Power Eq."),_TL(""));

			tmpName = SG_T("LFAC_lb(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName, _TL("Parameter (l) [lower bound]"),
				_TL("Soil moisture index threshold"),
				PARAMETER_TYPE_Double,
				0.0, 0.0, true, 5.0, true
			);
			tmpName = SG_T("LFAC_ub(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName, _TL("Parameter (l) [upper bound]"),
				_TL("Soil moisture index threshold"),
				PARAMETER_TYPE_Double,
				0.0, 0.0, true, 5.0, true
			);

			tmpName = SG_T("PFAC_lb(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName,	_TL("Parameter (p) [lower bound]"),
				_TL("non-linear response term"),
				PARAMETER_TYPE_Double,
				0.0, 0.0, true, 5.0, true
			);
			tmpName = SG_T("PFAC_ub(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName,	_TL("Parameter (p) [upper bound]"),
				_TL("non-linear response term"),
				PARAMETER_TYPE_Double,
				0.0, 0.0, true, 5.0, true
			);
			break;
		}
		// Parameters of non-linear module -------------------------

		// Parameters of linear module -----------------------------
		switch(m_StorConf)
		{
		case 0: // single storage
			tmpNode = SG_T("Node");
			tmpNode+=convert_sl::Int2String(i+250).c_str();
			s.Printf(tmpNode.c_str(), i+250);
			pNode1 = P.Add_Node(pNode,s,SG_T("Linear Tool"),_TL(""));

			tmpName = SG_T("AFAC_lb(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName,	_TL("(a) [lower bound]"),
				_TL(""),
				PARAMETER_TYPE_Double,
				-0.8, -0.99, true, -0.01, true
			);
			tmpName = SG_T("AFAC_ub(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName,	_TL("(a) [upper bound]"),
				_TL(""),
				PARAMETER_TYPE_Double,
				-0.8, -0.99, true, -0.01, true
			);

			tmpName = SG_T("BFAC_lb(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName,	_TL("(b) [lower bound]"),
				_TL(""),
				PARAMETER_TYPE_Double,
				0.2, 0.001, true, 1.0, true
			);
			tmpName = SG_T("BFAC_ub(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName,	_TL("(b) [upper bound]"),
				_TL(""),
				PARAMETER_TYPE_Double,
				0.2, 0.001, true, 1.0, true
			);
			break;

		case 1: // two parallel storages
			tmpNode = SG_T("Node");
			tmpNode+=convert_sl::Int2String(i+250).c_str();
			s.Printf(tmpNode.c_str(), i+250);
			pNode1 = P.Add_Node(pNode,s,SG_T("Linear Tool"),_TL(""));

			// Parameter a

			tmpName = SG_T("AQ_lb(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName,	_TL("a(q) [lower bound]"),
				_TL(""),
				PARAMETER_TYPE_Double,
				-0.7, -0.99, true, -0.01, true
			);
			tmpName = SG_T("AQ_ub(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName,	_TL("a(q) [upper bound]"),
				_TL(""),
				PARAMETER_TYPE_Double,
				-0.7, -0.99, true, -0.01, true
			);

			tmpName = SG_T("AS_lb(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName,	_TL("a(s) [lower bound]"),
				_TL(""),
				PARAMETER_TYPE_Double,
				-0.9, -0.99, true, -0.01, true
			);
			tmpName = SG_T("AS_ub(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName,	_TL("a(s) [upper bound]"),
				_TL(""),
				PARAMETER_TYPE_Double,
				-0.9, -0.99, true, -0.01, true
			);

			// Parameter b

			tmpName = SG_T("BQ_lb(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName,	_TL("b(q) [lower bound]"),
				_TL(""),
				PARAMETER_TYPE_Double,
				0.0, 0.0, true, 1.0, true
			);
			tmpName = SG_T("BQ_ub(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName,	_TL("b(q) [upper bound]"),
				_TL(""),
				PARAMETER_TYPE_Double,
				0.0, 0.0, true, 1.0, true
			);
			break;

		case 2: // two storages in series
			break;
		} // end switch (storconf)
		// Parameters of linear module -----------------------------

		tmpNode = SG_T("Node");
		tmpNode+=convert_sl::Int2String(i+300).c_str();
		s.Printf(tmpNode.c_str(), i+300);
		pNode1 = P.Add_Node(pNode,s,SG_T("Time Delay after Start of Rainfall (INTEGER)"),_TL(""));
			
		tmpName = SG_T("DELAY(");
			tmpName += tmpNode;
			tmpName += _TL(")");
		P.Add_Value(
			pNode1,	tmpName,	SG_T("Time Delay (Rain-Runoff)"),
			SG_T("The delay after the start of rainfall, before the discharge starts to rise."),
			PARAMETER_TYPE_Int,
			0, 1, true, 100, true
		);

		// snow module parameters ----------------------------------
		if (m_bSnowModule)
		{
			tmpNode = SG_T("Node");
			tmpNode+=convert_sl::Int2String(i+350).c_str();
			s.Printf(tmpNode.c_str(), i+350);
			pNode1 = P.Add_Node(pNode,s,SG_T("Snow Tool Parameters"),_TL(""));
			
			tmpName = SG_T("T_RAIN_lb(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName,	SG_T("Temperature Threshold for Rainfall [lower bound]"),
				SG_T("Below this threshold precipitation will fall as snow"),
				PARAMETER_TYPE_Double,
				-1.0, -10.0, true, 10.0, true
			);
			tmpName = SG_T("T_RAIN_ub(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName,	SG_T("Temperature Threshold for Rainfall [upper bound]"),
				SG_T("Below this threshold precipitation will fall as snow"),
				PARAMETER_TYPE_Double,
				-1.0, -10.0, true, 10.0, true
			);

			tmpName = SG_T("T_MELT_lb(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName,	SG_T("Temperature Threshold for Melting [lower bound]"),
				SG_T("Above this threshold snow will start to melt"),
				PARAMETER_TYPE_Double,
				1.0, -5.0, true, 10.0, true
			);
			tmpName = SG_T("T_MELT_ub(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName,	SG_T("Temperature Threshold for Melting [upper bound]"),
				SG_T("Above this threshold snow will start to melt"),
				PARAMETER_TYPE_Double,
				1.0, -5.0, true, 10.0, true
			);

			tmpName = SG_T("DD_FAC_lb(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName,	SG_T("Day-Degree Factor [lower bound]"),
				SG_T("Day-Degree Factor depends on catchment characteristics"),
				PARAMETER_TYPE_Double,
				0.7, 0.7, true, 9.2, true
			);
			tmpName = SG_T("DD_FAC_ub(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			P.Add_Value(
				pNode1,	tmpName,	SG_T("Day-Degree Factor [upper bound]"),
				SG_T("Day-Degree Factor depends on catchment characteristics"),
				PARAMETER_TYPE_Double,
				0.7, 0.7, true, 9.2, true
			);
		}
		// snow module parameters ----------------------------------
	}	
	
	if( SG_UI_Dlg_Parameters(&P, _TL("IHACRES Distributed Input Dialog 2")) )
	{
		// input table
		m_p_InputTable		= P("TABLE")				->asTable();
		// field numbers
		m_dateField			= P("DATE_Field")			->asInt();
		m_streamflowField	= P("DISCHARGE_Field")		->asInt();
		for (int i = 0; i < m_nElevBands; i++)
		{
			tmpNode = convert_sl::Int2String(i+1).c_str();
			
			// get precipitation column of Elevation Band[i]
			tmpName = SG_T("PCP Column: Elevation Band: ");
			tmpName+=tmpNode;
			m_p_pcpField[i]			= P(tmpName)		->asInt();

			// get temperature column of Elevation Band[i]
			tmpName = SG_T("TMP Column: Elevation Band: ");
			tmpName+=tmpNode;
			m_p_tmpField[i]			= P(tmpName)		->asInt();

			tmpNode = SG_T("Node");
			tmpNode+=convert_sl::Int2String(i+100).c_str();

			// get area[km2] of Elevation Band[i]
			tmpName = SG_T("Area [km2] Elev(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			m_p_elevbands[i].m_area	= P(tmpName)		->asDouble();

			// get mean elevation of Elevation Band[i]
			tmpName = SG_T("Mean Elevation [m.a.s.l] Elev(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			m_p_elevbands[i].m_mean_elev =P(tmpName)	->asDouble();


			// non-linear module parameters
			tmpNode = SG_T("Node");
			tmpNode+=convert_sl::Int2String(i+150).c_str();
			// get Tw
			tmpName = SG_T("TwFAC_lb(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			m_p_nl_lb->mp_tw[i]			= P(tmpName)	->asDouble();

			tmpName = SG_T("TwFAC_ub(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			m_p_nl_ub->mp_tw[i]			= P(tmpName)	->asDouble();

			// get f
			tmpName = SG_T("TFAC_lb(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			m_p_nl_lb->mp_f[i]			= P(tmpName)	->asDouble();

			tmpName = SG_T("TFAC_ub(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			m_p_nl_ub->mp_f[i]			= P(tmpName)	->asDouble();

			// get c
			tmpName = SG_T("CFAC_lb(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			m_p_nl_lb->mp_c[i]			= P(tmpName)	->asDouble();

			tmpName = SG_T("CFAC_ub(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			m_p_nl_ub->mp_c[i]			= P(tmpName)	->asDouble();

			switch(m_IHAC_version)
			{
			case 0: // Jakeman & Hornberger (1993)
				break;
			case 1: // Croke et al. (2005)
				tmpNode = SG_T("Node");
				tmpNode+=convert_sl::Int2String(i+200).c_str();
				// get l
				tmpName = SG_T("LFAC_lb(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_p_nl_lb->mp_l[i]= P(tmpName)	->asDouble();

				tmpName = SG_T("LFAC_ub(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_p_nl_ub->mp_l[i]= P(tmpName)	->asDouble();

				// get p
				tmpName = SG_T("PFAC_lb(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_p_nl_lb->mp_p[i]= P(tmpName)	->asDouble();

				tmpName = SG_T("PFAC_ub(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_p_nl_ub->mp_p[i]= P(tmpName)	->asDouble();
			}

			// linear module parameters
			switch(m_nStorages)
			{
			case 1: // single storage
				tmpNode = SG_T("Node");
				tmpNode+=convert_sl::Int2String(i+250).c_str();
				// get a
				tmpName = SG_T("AFAC_lb(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_p_lin_lb->a[i]		= P(tmpName)	->asDouble();

				tmpName = SG_T("AFAC_ub(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_p_lin_ub->a[i]		= P(tmpName)	->asDouble();

				// get b
				tmpName = SG_T("BFAC_lb(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_p_lin_lb->b[i]		= P(tmpName)	->asDouble();

				tmpName = SG_T("BFAC_ub(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_p_lin_ub->b[i]		= P(tmpName)	->asDouble();
				break;
			case 2: // two storages
				tmpNode = SG_T("Node");
				tmpNode+=convert_sl::Int2String(i+250).c_str();
				// get aq
				tmpName = SG_T("AQ_lb(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_p_lin_lb->aq[i]		= P(tmpName)	->asDouble();

				tmpName = SG_T("AQ_ub(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_p_lin_ub->aq[i]		= P(tmpName)	->asDouble();

				// get bq
				tmpName = SG_T("BQ_lb(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_p_lin_lb->bq[i]		= P(tmpName)	->asDouble();

				tmpName = SG_T("BQ_ub(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_p_lin_ub->bq[i]		= P(tmpName)	->asDouble();

				// get as
				tmpName = SG_T("AS_lb(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_p_lin_lb->as[i]		= P(tmpName)	->asDouble();

				tmpName = SG_T("AS_ub(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_p_lin_ub->as[i]		= P(tmpName)	->asDouble();
				break;
			}

			// get delay
			tmpNode = SG_T("Node");
			tmpNode+=convert_sl::Int2String(i+300).c_str();
			tmpName = SG_T("DELAY(");
			tmpName += tmpNode;
			tmpName += _TL(")");
			m_delay		= P(tmpName)					->asInt();

			if (m_bSnowModule)
			{
				tmpNode = SG_T("Node");
				tmpNode+=convert_sl::Int2String(i+350).c_str();

				tmpName = SG_T("T_RAIN_lb(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_pSnowparms_lb[i].T_Rain	= P(tmpName)	->asDouble();

				tmpName = SG_T("T_RAIN_ub(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_pSnowparms_ub[i].T_Rain	= P(tmpName)	->asDouble();

				tmpName = SG_T("T_MELT_lb(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_pSnowparms_lb[i].T_Melt	= P(tmpName)	->asDouble();

				tmpName = SG_T("T_MELT_ub(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_pSnowparms_ub[i].T_Melt	= P(tmpName)	->asDouble();

				tmpName = SG_T("DD_FAC_lb(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_pSnowparms_lb[i].DD_FAC	= P(tmpName)	->asDouble();

				tmpName = SG_T("DD_FAC_ub(");
				tmpName += tmpNode;
				tmpName += _TL(")");
				m_pSnowparms_ub[i].DD_FAC	= P(tmpName)	->asDouble();
			}

		} // end for (int i = 0; i < m_nSubbasins; i++)

		return(true);
	}
	return(false);
}

//---------------------------------------------------------------------
// DIALOG 3
//---------------------------------------------------------------------

bool Cihacres_elev_cal::_CreateDialog3()
{
	CSG_String		s;
	CSG_Parameters	P;  // used to add Parameters in the second dialog
	CSG_Parameter	*pNode;

	//	Dialog design
	P.Set_Name(_TL("Choose Time Range"));

	s.Printf(SG_T("Node1"), 1);
	pNode = P.Add_Node(NULL,s,SG_T("Time Range"),_TL(""));

	s.Printf(SG_T("FDAY") , 1-1);
	P.Add_String(pNode,s,_TL("First Day"),_TL(""),
				 m_p_InputTable->Get_Record(0)->asString(m_dateField));

	s.Printf(SG_T("LDAY") , 1-2);
	P.Add_String(pNode,s,_TL("Last Day"),_TL(""),
				 m_p_InputTable->Get_Record(m_p_InputTable->Get_Count()-1)->asString(m_dateField));

	if( SG_UI_Dlg_Parameters(&P, _TL("Choose Time Range")) )
	{
		///////////////////////////////////////////////////////////////
		//
		//                ASSIGN DATA FROM SECOND DIALOG
		//
		///////////////////////////////////////////////////////////////
		m_date1		= P(CSG_String::Format(SG_T("FDAY"),m_dateField).c_str())->asString();
		m_date2		= P(CSG_String::Format(SG_T("LDAY"),m_streamflowField).c_str())->asString();
		return(true);
	}
	return(false);
}
