///////////////////////////////////////////////////////////
//                 ihacres_cimate_scen.h                 //
//                                                       //
//                 Copyright (C) 2008 by                 //
//                     Stefan Liersch                    //
//-------------------------------------------------------//
//    e-mail:     stefan.liersch@ufz.de                  //
//                stefan.liersch@gmail.com               //
//                     2008-01-24                        //
//-------------------------------------------------------//
///////////////////////////////////////////////////////////


//*******************************************************//
//                        ToDo                           //
//-------------------------------------------------------//
// - 
//*******************************************************//

#include "ihacres_climate_scen.h"
#include "convert_sl.h"
#include <fstream>

///////////////////////////////////////////////////////////////////////
//
//		Constructor
//
///////////////////////////////////////////////////////////////////////

Cihacres_climate_scen::Cihacres_climate_scen(void)
{
	//-----------------------------------------------------
	// 1. Info...
	Set_Name("IHACRES Climate Scenarios");

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

	Set_Description("The Model IHACRES used to simulate flood events\n \n \n"
		"Reference: \n \n"
		"Jakeman, A.J. / Hornberger, G.M. (1993). \n"
		"How Much Complexity Is Warranted in a Rainfall-Runoff Model? \n"
		"Water Resources Research, (29), NO. 8 (2637-2649) \n \n"   
		"Kokkonen, T. S. et al. (2003). \n"
		"Predicting daily flows in ungauged catchments:"
		"model regionalization from catchment descriptors"
		"at the Coweeta Hydrologic Laboratory, North Carolina \n "
		"Hydrological Processes (17), 2219-2238 \n \n"
		"Croke, B. F. W., W. S. Merritt, et al. (2004).\n"
		"A dynamic model for predicting hydrologic response"
		"to land cover changes in gauged and"
		"ungauged catchments. \n"
		"Journal Of Hydrology 291(1-2): 115-131."
	);

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


	//-----------------------------------------------------
	// Create First Module Dialog
	_CreateDialog1();
	//-----------------------------------------------------
}


///////////////////////////////////////////////////////////////////////
//
//		Destructor
//
///////////////////////////////////////////////////////////////////////

Cihacres_climate_scen::~Cihacres_climate_scen(void)
{
}


///////////////////////////////////////////////////////////////////////
//
//		On_Execute()
//
///////////////////////////////////////////////////////////////////////


//---------------------------------------------------------------------
// This function is executed when the user is pressing the OK button
// in the first module dialog
//---------------------------------------------------------------------
bool Cihacres_climate_scen::On_Execute(void)
{
		//std::ofstream f("_scenario.txt");

	//-----------------------------------------------------------------
	// Assign parameters from First Module Dialog
	//-----------------------------------------------------------------
	m_pTable_Init		= Parameters("TABLE_INIT")			->asTable();
	m_api_field			= Parameters("API_FIELD")			->asInt();
	m_er_field			= Parameters("ER_FIELD")			->asInt();
	m_q_field			= Parameters("Q_FIELD")				->asInt();
	m_pTable_climate	= Parameters("TABLE_CLIMATE")		->asTable();
	m_day_field			= Parameters("DAY_FIELD")			->asInt();
	m_pcp_field			= Parameters("PCP_FIELD")			->asInt();
	m_tmp_field			= Parameters("TMP_FIELD")			->asInt();
	m_nDaysPeriod		= Parameters("N_DAYS_PERIOD")		->asInt();
	m_Area				= Parameters("AREA")				->asDouble();
	m_IHAC_version		= Parameters("IHACVERS")			->asInt();
	m_StorConf			= Parameters("STORAGE")				->asInt();
	m_bSnowModule		= Parameters("SNOW_MODULE")			->asBool();

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

	//---------------------------------------------------------
	// Assign number of storages
	m_nStorages = ihacres.Assign_nStorages(m_StorConf);
	m_p_linparms = new C_IHAC_LinearParms(1,m_nStorages);
	m_p_nonlinparms = new C_IHAC_NonLinearParms(1);
	//---------------------------------------------------------

	if ( _CreateDialog2() )
	{
		//-----------------------------------------------------------------
		// Initialize parameters and pointers
		//-----------------------------------------------------------------
		_Initialize();
		//-----------------------------------------------------------------

		//-----------------------------------------------------------------
		// Create output table
		//-----------------------------------------------------------------
		m_pTable = SG_Create_Table();
		_CreateOutputTable();
		m_counter = 0;
		//-----------------------------------------------------------------

		//-----------------------------------------------------------------
		//	SIMULATION
		//-----------------------------------------------------------------
		//f << "scenario" << ", " << "combination" << ", ";
		//for (unsigned int i = 0; i < m_nDaysPeriod+1; i++)
		//	f << i << ", ";
		//f << std::endl;

		for (unsigned int scenario = 0; scenario < m_nClimateScenarios && Set_Progress(scenario,m_nClimateScenarios); scenario++)
		{
			for (unsigned int combination = 0; combination < m_nParameterCombinations; combination++)
			{
				_Simulate(scenario, combination);

				_WriteOutputTable(scenario, combination);

				//f << scenario << ", " << combination << ", ";
				//for (unsigned int i = 0; i < m_nDaysPeriod+1; i++)
				//	f << m_p_Q_sim_mmday[i] << ", ";
				//f << std::endl;
			}
		}
		//-----------------------------------------------------------------

		//-----------------------------------------------------------------
		// Output table to SAGA-Workspace
		//-----------------------------------------------------------------
		m_pTable->Set_Name("IHACRES_Climate_Scenarios");
		Parameters("TABLEout")->Set_Value(m_pTable);
		//-----------------------------------------------------------------


		//////////////////////////////////////
		// DELETE Pointers (to destructor ?)
		//////////////////////////////////////
		delete[] m_p_Q_sim_mmday;
		delete m_pInit;
		delete[] m_pScenario;
		delete m_p_linparms;
		delete m_p_nonlinparms;
		delete[] m_pTw;
		delete[] m_pWI;
		delete[] m_pER;
		delete[] m_pMeltRate;
		//////////////////////////////////////

		return(true);
	} // end if ( _CreateDialog2() )
	return(false);
}
//---------------------------------------------------------------------



//---------------------------------------------------------------------
//		SIMULATION
//---------------------------------------------------------------------
void Cihacres_climate_scen::_Simulate(int scenario, int combination)
{
	if (m_bSnowModule)
	{
		m_pSnowModule = new CSnowModule(m_pScenario[scenario].pTMP, m_pScenario[scenario].pPCP, m_nDaysPeriod+1,
			m_snowparms.T_Rain, m_snowparms.T_Melt, m_snowparms.DD_FAC);
		m_pMeltRate = m_pSnowModule->Get_MeltRate(m_pMeltRate, m_nDaysPeriod+1);
		delete m_pSnowModule;
	}

	_Simulate_NonLinearModule(scenario, combination);
	_Simulate_Streamflow(combination);
}
//---------------------------------------------------------------------



//---------------------------------------------------------------------
//		SIMULATE NON-LINEAR MODULE
//---------------------------------------------------------------------
void Cihacres_climate_scen::_Simulate_NonLinearModule(int scenario, int combination)
{
	unsigned int nval = m_nDaysPeriod + 1;
	double sum_eRainGTpcp;
	//----------------------------------------------------------
	// 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 equal in all equal simulations.
		// If they should be different the index parameter can be used to identify the
		// corresponding elevation band.
		ihacres.CalcWetnessTimeConst_scen(m_pScenario[scenario].pTMP, m_pTw,
				m_p_nonlinparms, 0, nval); 
				// 0 = index (only one instance of m_p_nonlinparms)

		if (m_bSnowModule)
		{
			ihacres.CalcWetnessIndex(m_pTw, m_pScenario[scenario].pPCP,
				m_pScenario[scenario].pTMP, m_pWI, m_pInit->pAPI[combination], m_p_nonlinparms->mp_c[0],
				m_bSnowModule, m_snowparms.T_Rain, nval);

			ihacres.CalcExcessRain(m_pScenario[scenario].pPCP, m_pScenario[scenario].pTMP,
				m_pWI, m_pER, m_pInit->pER[combination], sum_eRainGTpcp, nval, m_bSnowModule,
				m_snowparms.T_Rain, m_snowparms.T_Melt,
				m_pMeltRate);
		} else {

			ihacres.CalcWetnessIndex(m_pTw, m_pScenario[scenario].pPCP,
				m_pScenario[scenario].pTMP, m_pWI, m_pInit->pAPI[combination], m_p_nonlinparms->mp_c[0],
				m_bSnowModule, 0, nval);

			ihacres.CalcExcessRain(m_pScenario[scenario].pPCP, m_pScenario[scenario].pTMP,
				m_pWI, m_pER, m_pInit->pER[combination],
				sum_eRainGTpcp, nval, m_bSnowModule,
				0,0,0);
		}
		break;
	case 1: // Croke et al. (2005)
		ihacres.CalcWetnessTimeConst_Redesign(m_pScenario[scenario].pTMP, m_pTw,
			m_p_nonlinparms, 0, nval);	// 0 = index (only one instance of m_p_nonlinparms)

		if (m_bSnowModule)
		{
			ihacres.CalcWetnessIndex_Redesign(m_pTw, m_pScenario[scenario].pPCP, m_pWI, m_pInit->pAPI[combination],
				m_bSnowModule, m_snowparms.T_Rain, nval);

			ihacres.CalcExcessRain_Redesign(m_pScenario[scenario].pPCP, m_pScenario[scenario].pTMP, m_pWI, 
				m_pER, m_pInit->pER[combination],sum_eRainGTpcp, nval, 
				m_p_nonlinparms->mp_c[0], m_p_nonlinparms->mp_l[0], m_p_nonlinparms->mp_p[0],
				m_bSnowModule, m_snowparms.T_Rain, m_snowparms.T_Melt, m_pMeltRate);
		} else {
			ihacres.CalcWetnessIndex_Redesign(m_pTw, m_pScenario[scenario].pPCP, m_pWI, m_pInit->pAPI[combination],
				m_bSnowModule, 0, nval);

			ihacres.CalcExcessRain_Redesign(m_pScenario[scenario].pPCP, m_pScenario[scenario].pTMP, m_pWI, 
				m_pER, m_pInit->pER[combination],sum_eRainGTpcp, nval, 
				m_p_nonlinparms->mp_c[0], m_p_nonlinparms->mp_l[0], m_p_nonlinparms->mp_p[0],
				m_bSnowModule, 0,0,0);
		}
		break;
	} // end switch(m_IHAC_vers)
}
//---------------------------------------------------------------------



//---------------------------------------------------------------------
//		SIMULATE STREAMFLOW
//---------------------------------------------------------------------
void Cihacres_climate_scen::_Simulate_Streamflow(int combination)
{
	//----------------------------------------------------------
	unsigned int nval = m_nDaysPeriod + 1;
	double vq, vs;
	//----------------------------------------------------------
	// calculate streamflow
	//----------------------------------------------------------
	switch(m_StorConf)
	{
	case 0: // single storage
		ihacres.SimStreamflowSingle(m_pER, m_pInit->pQ_mmday[combination],
			m_p_Q_sim_mmday, m_delay,
			m_p_linparms->a[0], m_p_linparms->b[0], nval);
		break;
	case 1: // two storages in parallel
		ihacres.SimStreamflow2Parallel(m_pER,
			m_p_Q_sim_mmday, m_pInit->pQ_mmday[combination],
			m_p_linparms, 0, vq, vs, nval, m_delay);
		break;
	case 2: // two storages in series
		break;
	} // end switch(m_StorConf)
}
//---------------------------------------------------------------------



//---------------------------------------------------------------------
//		INITIALIZE
//---------------------------------------------------------------------
void Cihacres_climate_scen::_Initialize()
{
	unsigned int nval = m_nDaysPeriod + 1;
	m_nParameterCombinations = m_pTable_Init->Get_Record_Count();
	m_nClimateScenarios = m_pTable_climate->Get_Record_Count() / m_nDaysPeriod;
	m_nScenarios = m_nParameterCombinations * m_nClimateScenarios;

	m_p_Q_sim_mmday = new double[nval];
	m_pTw			= new double[nval];
	m_pWI			= new double[nval];
	m_pER			= new double[nval];
	m_pMeltRate		= new double[nval];

	// read initial combinations (m_pTable_init)
	m_pInit = new CInit_values(m_nParameterCombinations);
	for (unsigned int i = 0; i < m_nParameterCombinations; i++)
	{
		m_pInit->pAPI[i] = m_pTable_Init->Get_Record(i)->asDouble(m_api_field);
		m_pInit->pER[i] = m_pTable_Init->Get_Record(i)->asDouble(m_er_field);
		m_pInit->pQ_mmday[i] = m_pTable_Init->Get_Record(i)->asDouble(m_q_field) * 86.4 / m_Area;
	}

	// initialize climate scenario parameters
	m_pScenario = new CScenario[m_nClimateScenarios];
	for (unsigned int i = 0; i < m_nClimateScenarios; i++)
	{
		m_pScenario[i].Inst_Scenarios(nval);
	}

	// read climate scenario data
	int count = 0;
	for (unsigned int scen = 0; scen < m_nClimateScenarios; scen++)
	{
		// set inital pcp and tmp values
		m_pScenario[scen].pPCP[0] = 0.0;
		m_pScenario[scen].pTMP[0] = 0.0;
		// assign pcp and tmp values from climate scenario input table
		for (unsigned int val = 0; val < m_nDaysPeriod; val++)
		{
			m_pScenario[scen].pPCP[val+1] = m_pTable_climate->Get_Record(count)->asDouble(m_pcp_field);
			m_pScenario[scen].pTMP[val+1] = m_pTable_climate->Get_Record(count)->asDouble(m_tmp_field);
			count++;
		}
	}
}
//---------------------------------------------------------------------





///////////////////////////////////////////////////////////////////////
//
//		CREATE TABLE
//
///////////////////////////////////////////////////////////////////////

//---------------------------------------------------------------------
void Cihacres_climate_scen::_CreateOutputTable()
{
	string fieldname;
	// creating the column titles
	m_pTable->Add_Field("Scenario",				 TABLE_FIELDTYPE_Int);
	m_pTable->Add_Field("P_Combination",		 TABLE_FIELDTYPE_Int);
	m_pTable->Add_Field("API",					 TABLE_FIELDTYPE_Double);
	m_pTable->Add_Field("ER",					 TABLE_FIELDTYPE_Double);
	m_pTable->Add_Field("Q",					 TABLE_FIELDTYPE_Double);
	for (unsigned int i = 0; i < m_nDaysPeriod; i++)
	{
		fieldname = "TS_";
		fieldname+=convert_sl::Int2String(i+1);
		m_pTable->Add_Field(fieldname.c_str(),	TABLE_FIELDTYPE_Double);
	}
}
//---------------------------------------------------------------------

void Cihacres_climate_scen::_WriteOutputTable(int scenario, int combination)
{
	int					field = 0;
	CSG_Table_Record	*pRecord;
	
	m_pTable->Add_Record();
	pRecord = m_pTable->Get_Record(m_counter);

	pRecord->Set_Value(field, scenario + 1); field++;
	pRecord->Set_Value(field, combination + 1); field++;
	pRecord->Set_Value(field, m_pInit->pAPI[combination]); field++;
	pRecord->Set_Value(field, m_pInit->pER[combination]); field++;
	pRecord->Set_Value(field, m_pInit->pQ_mmday[combination] * m_Area / 86.4); field++;

	for (unsigned int i = 1; i < m_nDaysPeriod+1; i++)
	{
		pRecord->Set_Value(field, m_p_Q_sim_mmday[i] * m_Area / 86.4);
		field++;
	}

	m_counter++;
}



///////////////////////////////////////////////////////////////////////
//
//		DIALOGS
//
///////////////////////////////////////////////////////////////////////


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

	//-----------------------------------------------------------------
	//		SCENARIO TABLES / PARAMETERS
	//-----------------------------------------------------------------
	pNode = Parameters.Add_Table(
		NULL	, "TABLE_INIT"	, _TL("Parameter Table"),
		"",
		PARAMETER_INPUT
	);
	Parameters.Add_Table_Field(
		pNode	, "API_FIELD"	, _TL("API Column"),
		"Select the column containing the initial API (Antecedent Precipitation Index) values"
	);
	Parameters.Add_Table_Field(
		pNode	, "ER_FIELD"	, _TL("ER Column"),
		"Select the column containing the initial ER (Excess rainfall) values"
	);
	Parameters.Add_Table_Field(
		pNode	, "Q_FIELD"	, _TL("Q Column"),
		"Select the column containing the initial Q (Streamflow) values"
	);

	pNode = Parameters.Add_Table(
		NULL	, "TABLE_CLIMATE"	, _TL("Climate Table"),
		"",
		PARAMETER_INPUT
	);
	Parameters.Add_Table_Field(
		pNode	, "DAY_FIELD"	, _TL("DAY Column"),
		"Select the column containing the current day"
	);
	Parameters.Add_Table_Field(
		pNode	, "PCP_FIELD"	, _TL("PCP Column"),
		"Select the column containing the PCP (Precipitation) values"
	);
	Parameters.Add_Table_Field(
		pNode	, "TMP_FIELD"	, _TL("TMP Column"),
		"Select the column containing the TMP (Temperature) values"
	);

	pNode = Parameters.Add_Value(
		NULL,	"N_DAYS_PERIOD",	_TL("Number of Days in a Simulation"),
		_TL("Number of days in a simulation period"),
		PARAMETER_TYPE_Int
	);
	//-----------------------------------------------------------------

	//-----------------------------------------------------------------
	//		MODEL PARAMETERS
	//-----------------------------------------------------------------
	s.Printf("Node0", 0);
	pNode = Parameters.Add_Node(NULL,s,"Catchment Area","");

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

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

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

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

	Parameters.Add_Choice(
		pNode	, "STORAGE"		, "Storage",
		"",
		CSG_String::Format("%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_MODULE",	_TL("Using the snow-melt module?"),
		_TL("If checked, snow-melt module is used."),
		PARAMETER_TYPE_Bool, false
	);
	//-----------------------------------------------------------------
}



//---------------------------------------------------------------------
// DIALOG 2
//---------------------------------------------------------------------

bool Cihacres_climate_scen::_CreateDialog2()
{
	CSG_Parameters	P;  // used to add Parameters in the second dialog
	CSG_Parameter	*pNode, *pNode1;
	CSG_String		s;

	P.Set_Name(_TL("IHACRES Climate Scenarios (Dialog 2)"));

	// Parameters of non-linear module -------------------------
	s.Printf("Node40", 40);
	pNode = P.Add_Node(NULL,s,"Non-Linear Module","");
	P.Add_Value(
		pNode,	"TwFAC",	_TL("Wetness decline time constant (Tw)"),
		_TL("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
	);
	P.Add_Value(
		pNode	, "TFAC"		, "Temperature Modulation Factor (f)",
		_TL("Temperature Modulation Factor f"),
		PARAMETER_TYPE_Double,
		1.0, 0.0001, true, 10.0, true
	);
	P.Add_Value(
		pNode,	"CFAC",	_TL("Parameter (c)"),
		_TL("Parameter (c) to fit streamflow volume"),
		PARAMETER_TYPE_Double,
		0.001, 0.0, true, 1.0, true
	);
	switch(m_IHAC_version)
	{
	case 0: // Jakeman & Hornberger (1993)
		break;
	case 1: // Croke et al. (2005)
		s.Printf("Node41", 41);
		pNode1 = P.Add_Node(pNode,s,"Soil Moisture Power Eq.","");

		P.Add_Value(
			pNode1,	"LFAC",	_TL("Parameter (l)"),
			_TL("Soil moisture index threshold"),
			PARAMETER_TYPE_Double,
			0.0, 0.0, true, 5.0, true
		);
		P.Add_Value(
			pNode1,	"PFAC",	_TL("Parameter (p)"),
			_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
		s.Printf("Node50", 50);
		pNode = P.Add_Node(NULL,s,"Linear Module","");

		P.Add_Value(
			pNode,	"AFAC",	_TL("(a)"),
			_TL(""),
			PARAMETER_TYPE_Double,
			-0.8, -0.99, true, -0.01, true
		);

		P.Add_Value(
			pNode,	"BFAC",	_TL("(b)"),
			_TL(""),
			PARAMETER_TYPE_Double,
			0.2, 0.001, true, 1.0, true
		);
		break;

	case 1: // two parallel storages
		s.Printf("Node50", 50);
		pNode = P.Add_Node(NULL,s,"Linear Module","");

		// Parameter a
		P.Add_Value(
			pNode,	"AQ",	_TL("a(q)"),
			_TL(""),
			PARAMETER_TYPE_Double,
			-0.7, -0.99, true, -0.01, true
		);
		P.Add_Value(
			pNode,	"AS",	_TL("a(s)"),
			_TL(""),
			PARAMETER_TYPE_Double,
			-0.9, -0.99, true, -0.01, true
		);

		// Parameter b
		P.Add_Value(
			pNode,	"BQ",	_TL("b(q)"),
			_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 -----------------------------

	s.Printf("Node55", 55);
	pNode = P.Add_Node(NULL,s,"Time Delay after Start of Rainfall (INTEGER)","");
		
	P.Add_Value(
		pNode,	"DELAY",	"Time Delay (Rain-Runoff)",
		"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)
	{
	s.Printf("Node60", 60);
	pNode = P.Add_Node(NULL,s,"Snow Module Parameters","");
		
		P.Add_Value(
			pNode,	"T_RAIN",	"Temperature Threshold for Rainfall",
			"Below this threshold precipitation will fall as snow",
			PARAMETER_TYPE_Double,
			-1.0, -10.0, true, 10.0, true
		);
		P.Add_Value(
			pNode,	"T_MELT",	"Temperature Threshold for Melting",
			"Above this threshold snow will start to melt",
			PARAMETER_TYPE_Double,
			1.0, -5.0, true, 10.0, true
		);
		P.Add_Value(
			pNode,	"DD_FAC",	"Day-Degree Factor",
			"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 Climate Scenarios Dialog 2")) )
	{
		// non-linear module parameters
		m_p_nonlinparms->mp_tw[0]	= P("TwFAC")		->asDouble();
		m_p_nonlinparms->mp_f[0]	= P("TFAC")			->asDouble();
		m_p_nonlinparms->mp_c[0]	= P("CFAC")			->asDouble();
		switch(m_IHAC_version)
		{
		case 0: // Jakeman & Hornberger (1993)
			break;
		case 1: // Croke et al. (2005)
			m_p_nonlinparms->mp_l[0]= P("LFAC")			->asDouble();
			m_p_nonlinparms->mp_p[0]= P("PFAC")			->asDouble();
		}

		// linear module parameters
		switch(m_nStorages)
		{
		case 1: // single storage
			m_p_linparms->a[0]		= P("AFAC")			->asDouble();
			m_p_linparms->b[0]		= P("BFAC")			->asDouble();
			break;
		case 2: // two storages
			m_p_linparms->aq[0]		= P("AQ")			->asDouble();
			m_p_linparms->bq[0]		= P("BQ")			->asDouble();
			m_p_linparms->as[0]		= P("AS")			->asDouble();
			m_p_linparms->bs[0] = ihacres.Calc_Parm_BS(m_p_linparms->aq[0],m_p_linparms->as[0],m_p_linparms->bq[0]);
			break;
		}

		m_delay						= P("DELAY")		->asInt();	

		if (m_bSnowModule)
		{
			m_snowparms.T_Rain		= P("T_RAIN")		->asDouble();
			m_snowparms.T_Melt		= P("T_MELT")		->asDouble();
			m_snowparms.DD_FAC		= P("DD_FAC")		->asDouble();
		}

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