#include "StreamTemperature.h"

//Refactor to document code:
//Note: Consider Refactor to replace use of Sun et al. (2015) East and West bank with Chen et al. (1998) Left and Right bank inputs
//Note: Sun et al. (2015) used East and West designation; see their Figure 3A
//Note: Chen et al. (1998) use Left and Right designation (facing upstream!); see Figure 4, Table 2 and 3
//Note: Code minimally explained by Abdi et al. (2019); Sources include: 
//Note: ... a) DHSVM 3.1.2 CanopyShading.c functions by Ning Sun and RBM.f by John Yearsly
//Note: ... For temp1 to temp11 variables, try to identify if they are in the Heat Source, HFlux, or other model code
//Note: Build code in Debug mode and find conversion errors for fixing: _Ty to unsigned_int64; size_t to int
//Note: Consider refactor to place all for TotalDist loops, and all for TotalTime loops, together in order to reduce computation time
//Note: Refactor to explore why this LOAD MODEL VARIABLES appears twice in code; // START - LOAD MODEL VARIABLES & SETUP INITAL CONDITIONS

//References:
//Chen, Y. D., Carsel, R. F., McCutcheon, S. C., & Nutter, W. L. (1998). Stream Temperature Simulation of Forested Riparian Areas: I. Watershed-Scale Model Development. Journal of Environmental Engineering, 124(4), 304-315. https://ascelibrary.org/doi/abs/10.1061/%28ASCE%290733-9372%281998%29124%3A4%28304%29
//Shuttleworth, J. W. (1993). Evaporation. In D. R. Maidment (Ed.), Handbook of Hydrology (pp. 4.1-4.5.3). New York: McGraw-Hill.
//Sun, N., Yearsley, J., Voisin, N., & Lettenmaier, D. P. (2015). A spatially distributed model for the assessment of land use impacts on stream temperature in small urban watersheds. Hydrological Processes, 29(10), 2331-2345. http://dx.doi.org/10.1002/hyp.10363

StreamTemperature::StreamTemperature(Inputs* input, SolarCalculation* solarCal) : input(input), solarCal(solarCal)
{
	//CR_calcMethod = 1: Solution Method=Crank-Nicolson
	//CR_calcMethod = 2: Solution Method=Explicit finite difference, 
	//CR_calcMethod = 3: Solution Method=HEC-RAS based method, 
	//CR_calcMethod = 4: Solution Method=Rung-Kutta

	calculation = int(input->CoolRiverVariables["CR_calcMethod"]); 
}
void StreamTemperature::clear()
{
	solarSW_Dir_LI2D.clear();
	solarSW_Diff_LI2D.clear();
	aitTemp_LI2D.clear();
	rela_humidity_LI2D.clear();
	windSp_LI2D.clear();
	cloudiness_LI2D.clear();
	hourlyTime.clear();
	SWreflVec.clear();
	adjustedDirSW_E.clear();
	adjustedDirSW_W.clear();
	adjustedDiffSW_E.clear();
	adjustedDiffSW_W.clear();
	atmLW.clear();
	lcLW.clear();
	backLW.clear();
	latent.clear();
	sensible.clear();
	bed.clear();
	BankH_E_LI.clear();
	TreeH_E_LI.clear();
	BankH_W_LI.clear();
	TreeH_W_LI.clear();
	BuildH_E_LI.clear();
	BuildH_W_LI.clear();
	CanDist_E_LI.clear();
	CanDist_W_LI.clear();
	BanDist_E_LI.clear();
	BanDist_W_LI.clear();
	BuildDist_E_LI.clear();
	BuildDist_W_LI.clear();
	Buff_E_LI.clear();
	Buff_W_LI.clear();
	elev_LI.clear();
	StrAzimuth_LI.clear();
	colNum_Dist.clear();
	rowNum_Dist.clear();
	LongValue_Dist.clear();
	latValue_Dist.clear();
	SolAzimuth_LI.clear();
	SolAltitude_LI.clear();
	SF_LI.clear();
	SkyToView_LI.clear();
	secWidth_LI.clear();
	secDepth_LI.clear();
	secSlope_LI.clear();
	secArea_LI.clear();
	Z_LI.clear();
	heat_flux_2D.clear();
	SWDir_2D.clear();
	SWDiff_2D.clear();
	SW_2D.clear();
	LW_2D.clear();
	atmLW_2D.clear();
	LCLW_2D.clear();
	backLW_2D.clear();
	Latent_2D.clear();
	Sensible_2D.clear();
	Bed_2D.clear();
	T.clear(); // T: temperature array

	fluxxx.clear();
	tNew.clear();
	Flux_Total.clear();
	Flux_Conduction.clear();
	Flux_Evaporation.clear();
	Flux_Convection.clear();
	FLux_AtmLW.clear();
	Flux_LCLW.clear();
	Flux_BackLW.clear();
	Flux_LW.clear();
	Flux_DirSW.clear();
	Flux_DiffSW.clear();
	Flux_SW.clear();

	depth_Uns.clear();

	hour_Flux_Total.clear();
	hour_Flux_Conduction.clear();
	hour_Flux_Evaporation.clear();
	hour_Flux_Convection.clear();
	hour_FLux_AtmLW.clear();
	hour_Flux_LCLW.clear();
	hour_Flux_BackLW.clear();
	hour_Flux_LW.clear();
	hour_Flux_DirSW.clear();
	hour_Flux_DiffSW.clear();
}

void StreamTemperature::skyViewE()
{
	VSAEast.resize(TotalDist);
	TSAEast.resize(TotalDist);
	BSAEast.resize(TotalDist);
	SkyV_E.resize(TotalDist);
	// VSA in the calculations, Eq. #8 in Sun et al., (2015) the answer would be in radians
	for (int i = 0; i < TotalDist; i++) {
		// VSA in the calculations, Eq. #8 in Sun et al., (2015) the answer would be in radians
		double VSA_Temp;
		if (max(BanDist_E_LI[i], CanDist_E_LI[i]) == 0) {
			VSA_Temp = 0;
		}
		else {
			VSA_Temp = atan((BankH_E_LI[i] + TreeH_E_LI[i]) / max(BanDist_E_LI[i], CanDist_E_LI[i]));
		}
		VSAEast[i] = VSA_Temp;

		double TSA_Temp;
		if (min(BanDist_E_LI[i], CanDist_E_LI[i]) == 0) {
			TSA_Temp = 0;
		}
		else {
			TSA_Temp = atan(BankH_E_LI[i] / min(BanDist_E_LI[i], CanDist_E_LI[i]));
		}
		TSAEast[i] = TSA_Temp;

		double BSA_Temp;
		if (max(BanDist_E_LI[i], BuildDist_E_LI[i]) == 0) {
			BSA_Temp = 0;
		}
		else {
			BSA_Temp = atan((BankH_E_LI[i] + BuildH_E_LI[i]) / max(BanDist_E_LI[i], BuildDist_E_LI[i]));
		}
		BSAEast[i] = BSA_Temp;

		double MaxSky = maxValue(VSA_Temp, TSA_Temp, BSA_Temp);

		double Sky_Temp = (180 - (2 * MaxSky)) / 180;
		SkyV_E[i] = Sky_Temp;
	}
}

void StreamTemperature::skyViewW()
{

	VSAWest.resize(TotalDist);
	TSAWest.resize(TotalDist);
	BSAWest.resize(TotalDist);
	SkyV_W.resize(TotalDist);
	// VSA in the calculations, Eq. #8 in Sun et al., (2015) the answer would be in radians
	for (int i = 0; i < TotalDist; i++)
	{
		// VSA in the calculations, Eq. #8 in Sun et al., (2015) the answer would be in radians
		double VSA_Temp;
		if (max(BanDist_W_LI[i], CanDist_W_LI[i]) == 0)
		{
			VSA_Temp = 0;
		}
		else
		{
			VSA_Temp = atan((BankH_W_LI[i] + TreeH_W_LI[i]) / max(BanDist_W_LI[i], CanDist_W_LI[i]));
		}
		VSAWest[i] = VSA_Temp;

		double TSA_Temp;
		if (min(BanDist_W_LI[i], CanDist_W_LI[i]) == 0)
		{
			TSA_Temp = 0;
		}
		else
		{
			TSA_Temp = atan(BankH_W_LI[i] / min(BanDist_W_LI[i], CanDist_W_LI[i]));
		}
		TSAWest[i] = TSA_Temp;

		double BSA_Temp;
		if (max(BanDist_W_LI[i], BuildDist_W_LI[i]) == 0)
		{
			BSA_Temp = 0;
		}
		else
		{
			BSA_Temp = atan((BankH_W_LI[i] + BuildH_W_LI[i]) / max(BanDist_W_LI[i], BuildDist_W_LI[i]));
		}
		BSAWest[i] = BSA_Temp;
		double MaxSky = maxValue(VSA_Temp, TSA_Temp, BSA_Temp);
		double Sky_Temp = (180 - (2 * MaxSky)) / 180;
		SkyV_W[i] = Sky_Temp;
	}
}

// Calculating the sky view factor adjusted by riparian vegetation buffer considering Eastern info
void StreamTemperature::netSolarDiffRadE(const vector<double>& SolDiffSW, int timeStep)
{
	adjustedDiffSW_E.clear();
	adjustedDiffSW_E.resize(TotalDist);
	switch (SolvingMethod) {
		case 1: {
			for (int i = 0; i < TotalDist; i++)
			{
				//adjustedDiffSW_E in the calculations, Eq. #8 in Sun et al., 2015 for East side
				adjustedDiffSW_E[i] = SolDiffSW[timeStep] * SkyV_E[i] * (1 - SWreflVec[timeStep]);
			}
			break;
		}
		case 2: {
			// Using the fix coverage values
			for (int i = 0; i < TotalDist; i++)
			{

				adjustedDiffSW_E[i] = SolDiffSW[timeStep] * (1 - SF_LI[i]) * (1 - SWreflVec[timeStep]);
			}
			break;
		}
		default: {
			cout << "Wrong shortwave radiation methodology. Stop model and select other option." << endl;
		}
	}
}

// Calculating the sky view factor adjusted by riparian vegetation buffer considering Western info
void StreamTemperature::netSolarDiffRadW(const vector<double>& SolDiffSW, int timeStep)
{
	adjustedDiffSW_W.clear();
	adjustedDiffSW_W.resize(TotalDist);
	switch (SolvingMethod) {
		case 1: {
			for (int i = 0; i < TotalDist; i++)
			{

				//adjustedDiffSW_W in the calculations, Eq. #8 in Sun et al., 2015 for East side
				adjustedDiffSW_W[i] = SolDiffSW[timeStep] * SkyV_W[i] * (1 - SWreflVec[timeStep]);
			}
			break;
		}
		case 2: {
			// Using the fix coverage values
			for (int i = 0; i < TotalDist; i++)
			{

				adjustedDiffSW_W[i] = SolDiffSW[timeStep] * (1 - SF_LI[i]) * (1 - SWreflVec[timeStep]);
			}
			break;
		}
		default: {
			cout << "Wrong shortwave radiation methodology. Stop model and select other option." << endl;
		}
	}
}

// Calculating the effective shading width for East side
double StreamTemperature::effectiveShadingE(const vector<double>& SolDirE, int dist, int ts)
{

	// considering the (-1) to get a correct answer for "i*cols + j" in SlopeCal class i as the row number and j as the col number
	int col = int(colNum_Dist[dist] - 1); 
	// considering the (-1) to get a correct answer for "i*cols + j" in SlopeCal class i as the row number and j as the col number
	int row = int(rowNum_Dist[dist] - 1); 
	//int totCols = SpaData->getcols();
	int totCols = input->getcols();
	int MapPixel_ID = row * totCols + col;

	slope = input->SlopeGround_rad[MapPixel_ID]; //The answers for slope and aspect are in radian
	aspect = input->AspectGround_N_0_rad[MapPixel_ID];

	double delta1;
	double delta2;
	double avgPath;
	double solarPhi;
	double shadowLengthE;
	double extinctCoeff;
	double effShadowLengthE;

	double Canbuffer = Buff_E_LI[dist];

	//Eq. #3 in Sun et al., (2015)
	if (SolAltitude_LI[ts] == 0)
	{
		shadowLengthE = 0;
	} // I used the 5 just as an example! I need to make a solid argument about the threshold!
	else
	{
		double MaxSky = maxValue(VSAEast[dist], BSAEast[dist], TSAEast[dist]);
		if (VSAEast[dist] == MaxSky)
		{
			shadowLengthE = (BankH_E_LI[dist] + TreeH_E_LI[dist]) *
				fabs(sin((SolAzimuth_LI[ts]) - StrAzimuth_LI[dist]) / tan(SolAltitude_LI[ts]));
		}
		else if (BSAEast[dist] == MaxSky)
		{
			shadowLengthE = (BankH_E_LI[dist] + BuildH_E_LI[dist]) *
				fabs(sin((SolAzimuth_LI[ts]) - StrAzimuth_LI[dist]) / tan(SolAltitude_LI[ts]));
		}
		else
		{
			shadowLengthE = (BankH_E_LI[dist]) *
				fabs(sin((SolAzimuth_LI[ts]) - StrAzimuth_LI[dist]) / tan(SolAltitude_LI[ts]));
		}
	}

	/* Now I am going to calculate the delta1 and delta2 to calcualte the amount of effective shading
	Eq. #4 & 5 in Sun et al., 2015*/

	if (SolAltitude_LI[ts] == 0)
	{
		delta1 = -(BankH_E_LI[dist] + secWidth_LI[dist]);
	} // I used the 5 just as an example! I need to make a solid argument about the threshold!
	else
	{
		double MaxSky = maxValue(VSAEast[dist], BSAEast[dist], TSAEast[dist]);
		if (VSAEast[dist] == MaxSky)
		{
			delta1 = ((BankH_E_LI[dist] + TreeH_E_LI[dist]) *
				fabs(sin((SolAzimuth_LI[ts]) - StrAzimuth_LI[dist]) / tan(SolAltitude_LI[ts]))) -
				(BankH_E_LI[dist] + secWidth_LI[dist]);
		}
		else if (BSAEast[dist] == MaxSky)
		{
			delta1 = ((BankH_E_LI[dist] + BuildH_E_LI[dist]) *
				fabs(sin((SolAzimuth_LI[ts]) - StrAzimuth_LI[dist]) / tan(SolAltitude_LI[ts]))) -
				(BankH_E_LI[dist] + secWidth_LI[dist]);
		}
		else
		{
			delta1 = (BankH_E_LI[dist] *
				fabs(sin((SolAzimuth_LI[ts]) - StrAzimuth_LI[dist]) / tan(SolAltitude_LI[ts]))) -
				(BankH_E_LI[dist] + secWidth_LI[dist]);
		}
	}
	if (SolAltitude_LI[ts] == 0)
	{
		delta2 = -(secWidth_LI[dist]);
	}
	else
	{
		double MaxSky = maxValue(VSAEast[dist], BSAEast[dist], TSAEast[dist]);
		if (VSAEast[dist] == MaxSky)
		{
			delta2 = ((BankH_E_LI[dist] + TreeH_E_LI[dist]) *
				fabs(sin((SolAzimuth_LI[ts]) - StrAzimuth_LI[dist]) / tan(SolAltitude_LI[ts]))) -
				(secWidth_LI[dist]);
		}
		else if (BSAEast[dist] == MaxSky)
		{
			delta2 = ((BankH_E_LI[dist] + BuildH_E_LI[dist]) *
				fabs(sin((SolAzimuth_LI[ts]) - StrAzimuth_LI[dist]) / tan(SolAltitude_LI[ts]))) -
				(secWidth_LI[dist]);
		}
		else
		{
			delta2 = (BankH_E_LI[dist] *
				fabs(sin((SolAzimuth_LI[ts]) - StrAzimuth_LI[dist]) / tan(SolAltitude_LI[ts]))) -
				(secWidth_LI[dist]);
		}
	}

	solarPhi = (cos(SolAltitude_LI[ts]) * fabs(sin(SolAzimuth_LI[ts] - StrAzimuth_LI[dist])));

	/* calculating the radiation extinction coefficient which is estimated as a function of LAI.
	Reference: http://onlinelibrary.wiley.com/doi/10.1111/j.1752-1688.2010.00423.x/abstract;  DeWalle (2010) */

	//Eq. #1 in Sun et al., (2015) and Sridhar et al. (2004)

	// The next two variables for calculating the extinction coefficient should be shortwave instead longwave based on the following paper
	double abovVegRadiation = SolDirE[ts] * (1 - SWreflVec[ts]) * ((sin(slope) * cos(SolAltitude_LI[ts]) * cos(SolAzimuth_LI[ts] - aspect)) + (cos(slope) * sin(SolAltitude_LI[ts])));

	double vegRadiation = SolDirE[ts] * (1 - SWreflVec[ts]); // Direct shortwave radiation based on the Sridhar et al. 2004 ---> Eqn. 6 & 8

	// Link address to Sridhar et al. (2004):
	//http://onlinelibrary.wiley.com/doi/10.1111/j.1752-1688.2004.tb01019.x/abstract
	// Calculating the extinction coefficient based on (DeWalle, 2010 --> Eqn. 2)
	// DeWalle (2010): http://onlinelibrary.wiley.com/doi/10.1111/j.1752-1688.2010.00423.x/abstract
	if (vegRadiation <= 0 || abovVegRadiation <= 0)
		extinctCoeff = 0;
	else
		extinctCoeff = -(log(abovVegRadiation / vegRadiation) / CanopyLAI);

	// calculating the overhanging shade (like I3 in Ning Sun's work using following methodology:
	// http://ascelibrary.org/doi/abs/10.1061/%28ASCE%290733-9372%281998%29124%3A4%28304%29

	double overHangW_E = 0;
	double canDens = input->CoolRiverVariables["CR_canDensity"];
	if (((0.1 * TreeH_E_LI[dist]) - CanDist_E_LI[dist]) < secWidth_LI[dist])
	{
		overHangW_E = ((0.1 * TreeH_E_LI[dist]) - CanDist_E_LI[dist]) * canDens;
	}
	else
	{
		overHangW_E = secWidth_LI[dist] * canDens;
	}

	// calculating of the average path (Lavg) based on the table 1 of  Sun et al., (2015)
	// (1) No shade
	if (VSAEast[dist] > max(TSAEast[dist], BSAEast[dist]))
	{
		if ((delta1 <= 0.0) && (delta2 <= 0.0))
		{
			avgPath = 0;
		}
		// (2) Partial shade, sun above buffer canopy
		else if ((delta1 <= 0.0) && (delta2 <= Canbuffer))
		{
			avgPath = ((0.5 * delta2) / solarPhi);
		}
		// (3) Partial shade, sun below buffer canopy
		else if ((delta1 <= 0.0) && (delta2 > Canbuffer))
		{
			avgPath = ((0.5 * Canbuffer) / solarPhi);
		}
		// (4) Full shade, sun above buffer canopy
		else if ((delta1 > 0.0) && (delta2 <= Canbuffer))
		{
			avgPath = ((0.5 * (delta1 + delta2)) / solarPhi);
		}
		// (5) Full shade, sun partially below buffer canopy
		else if ((delta1 <= Canbuffer) && (delta2 > Canbuffer))
		{
			avgPath = ((0.5 * (delta1 + Canbuffer)) / solarPhi);
		}
		// (6) Full shade, sun entirely below buffer canopy
		else if ((delta1 > Canbuffer) && (delta2 > Canbuffer))
		{
			avgPath = (Canbuffer / solarPhi);
		}
		//Eq. #6 in Sun et al., (2015)
		// The shadow length as the initial value for shadow (Eq. #6 in Sun et al., 2015) for Eastern side
		if (shadowLengthE < CanDist_E_LI[dist])
		{
			effShadowLengthE = 0;
		}
		else
		{
			effShadowLengthE = ((shadowLengthE - CanDist_E_LI[dist] - overHangW_E) *
				(1 - exp(-(extinctCoeff * avgPath))));
		}
	}
	else
	{
		if (shadowLengthE < BuildDist_E_LI[dist])
		{
			effShadowLengthE = 0;
		}
		effShadowLengthE = shadowLengthE - BuildDist_E_LI[dist] - overHangW_E;
	}

	return effShadowLengthE;
}

// Calculating the effective shading width for West side
double StreamTemperature::effectiveShadingW(const vector<double>& SolDirW, int dist, int ts)
{

	// considering the (-1) to get a correct answer for "i*cols + j" in SlopeCal class i as the row number and j as the col number
	int col = int(colNum_Dist[dist] - 1); 
	// considering the (-1) to get a correct answer for "i*cols + j" in SlopeCal class i as the row number and j as the col number
	int row = int(rowNum_Dist[dist] - 1);
	int totCols = input->getcols();
	int MapPixel_ID = row * totCols + col;

	slope = input->SlopeGround_rad[MapPixel_ID]; //The answers for slope and aspect are in radian
	aspect = input->AspectGround_N_0_rad[MapPixel_ID];

	double delta1;
	double delta2;
	double avgPath;
	double solarPhi;
	double shadowLengthW;
	double extinctCoeff;
	double effShadowLengthW;

	double Canbuffer = Buff_W_LI[dist];

	//Eq. #3 in Sun et al., (2015)
	if (SolAltitude_LI[ts] == 0)
	{
		shadowLengthW = 0;
	} // I used the 5 just as an example! I need to make a solid argument about the threshold!
	else
	{
		double MaxSky = maxValue(VSAWest[dist], BSAWest[dist], TSAWest[dist]);
		if (VSAWest[dist] == MaxSky)
		{
			shadowLengthW = (BankH_W_LI[dist] + TreeH_W_LI[dist]) *
				fabs(sin((SolAzimuth_LI[ts]) - StrAzimuth_LI[dist]) / tan(SolAltitude_LI[ts]));
		}
		else if (BSAWest[dist] == MaxSky)
		{
			shadowLengthW = (BankH_W_LI[dist] + BuildH_W_LI[dist]) *
				fabs(sin((SolAzimuth_LI[ts]) - StrAzimuth_LI[dist]) / tan(SolAltitude_LI[ts]));
		}
		else
		{
			shadowLengthW = (BankH_W_LI[dist]) *
				fabs(sin((SolAzimuth_LI[ts]) - StrAzimuth_LI[dist]) / tan(SolAltitude_LI[ts]));
		}
	}

	/* Now I am going to calculate the delta1 and delta2 to calcualte the amount of effective shading
	Eq. #4 & 5 in Sun et al., 2015*/

	if (SolAltitude_LI[ts] == 0)
	{
		delta1 = -(BankH_W_LI[dist] + secWidth_LI[dist]);
	} // I used the 5 just as an example! I need to make a solid argument about the threshold!
	else
	{
		double MaxSky = maxValue(VSAWest[dist], BSAWest[dist], TSAWest[dist]);
		if (VSAWest[dist] == MaxSky)
		{
			delta1 = ((BankH_W_LI[dist] + TreeH_W_LI[dist]) *
				fabs(sin((SolAzimuth_LI[ts]) - StrAzimuth_LI[dist]) / tan(SolAltitude_LI[ts]))) -
				(BankH_W_LI[dist] + secWidth_LI[dist]);
		}
		else if (BSAWest[dist] == MaxSky)
		{
			delta1 = ((BankH_W_LI[dist] + BuildH_W_LI[dist]) *
				fabs(sin((SolAzimuth_LI[ts]) - StrAzimuth_LI[dist]) / tan(SolAltitude_LI[ts]))) -
				(BankH_W_LI[dist] + secWidth_LI[dist]);
		}
		else
		{
			delta1 = ((BankH_W_LI[dist]) *
				fabs(sin((SolAzimuth_LI[ts]) - StrAzimuth_LI[dist]) / tan(SolAltitude_LI[ts]))) -
				(BankH_W_LI[dist] + secWidth_LI[dist]);
		}
	}
	if (SolAltitude_LI[ts] == 0)
	{
		delta2 = -(secWidth_LI[dist]);
	}
	else
	{
		double MaxSky = maxValue(VSAWest[dist], BSAWest[dist], TSAWest[dist]);
		if (VSAWest[dist] == MaxSky)
		{
			delta2 = ((BankH_W_LI[dist] + TreeH_W_LI[dist]) *
				fabs(sin((SolAzimuth_LI[ts]) - StrAzimuth_LI[dist]) / tan(SolAltitude_LI[ts]))) -
				(secWidth_LI[dist]);
		}
		else if (BSAWest[dist] == MaxSky)
		{
			delta2 = ((BankH_W_LI[dist] + BuildH_W_LI[dist]) *
				fabs(sin((SolAzimuth_LI[ts]) - StrAzimuth_LI[dist]) / tan(SolAltitude_LI[ts]))) -
				(secWidth_LI[dist]);
		}
		else
		{
			delta2 = ((BankH_W_LI[dist]) *
				fabs(sin((SolAzimuth_LI[ts]) - StrAzimuth_LI[dist]) / tan(SolAltitude_LI[ts]))) -
				(secWidth_LI[dist]);
		}
	}

	solarPhi = (cos(SolAltitude_LI[ts]) * fabs(sin(SolAzimuth_LI[ts] - StrAzimuth_LI[dist])));

	/* calculating the radiation extinction coefficient which is estimated as a function of LAI.
	Reference: http://onlinelibrary.wiley.com/doi/10.1111/j.1752-1688.2010.00423.x/abstract;  DeWalle (2010) */

	//Eq. #1 in Sun et al., (2015) and Sridhar et al. (2004)

	// The next two variables for calculating the extinction coefficient should be shortwave instead longwave based on the following paper
	double abovVegRadiation = SolDirW[ts] * (1 - SWreflVec[ts]) * ((sin(slope) * cos(SolAltitude_LI[ts]) * cos(SolAzimuth_LI[ts] - aspect)) + (cos(slope) * sin(SolAltitude_LI[ts])));

	double vegRadiation = SolDirW[ts] * (1 - SWreflVec[ts]); // Direct shortwave radiation based on the Sridhar et al. 2004 ---> Eqn. 6 & 8

	// Link address to Sridhar et al. (2004):
	//http://onlinelibrary.wiley.com/doi/10.1111/j.1752-1688.2004.tb01019.x/abstract
	// Calculating the extinction coefficient based on (DeWalle, 2010 --> Eqn. 2)
	// DeWalle (2010): http://onlinelibrary.wiley.com/doi/10.1111/j.1752-1688.2010.00423.x/abstract
	if (vegRadiation <= 0 || abovVegRadiation <= 0) {
		extinctCoeff = 0;
	}
	else {
		extinctCoeff = -(log(abovVegRadiation / vegRadiation) / CanopyLAI);
	}
	// calculating the overhanging shade (like I3 in Ning Sun's work using following methodology:
	// http://ascelibrary.org/doi/abs/10.1061/%28ASCE%290733-9372%281998%29124%3A4%28304%29

	double overHangW_W = 0;
	double canDens = input->CoolRiverVariables["CR_canDensity"];
	if (((0.1 * TreeH_W_LI[dist]) - CanDist_W_LI[dist]) < secWidth_LI[dist]) {
		overHangW_W = ((0.1 * TreeH_W_LI[dist]) - CanDist_W_LI[dist]) * canDens;
	}
	else {
		overHangW_W = secWidth_LI[dist] * canDens;
	}

	// calculating of the average path (Lavg) based on the table 1 of  Sun et al., (2015)
	// (1) No shade
	if (VSAWest[dist] > max(TSAWest[dist], BSAWest[dist])) {
		if ((delta1 <= 0.0) && (delta2 <= 0.0))	{
			avgPath = 0;
		}
		// (2) Partial shade, sun above buffer canopy
		else if ((delta1 <= 0.0) && (delta2 <= Canbuffer)) {
			avgPath = ((0.5 * delta2) / solarPhi);
		}
		// (3) Partial shade, sun below buffer canopy
		else if ((delta1 <= 0.0) && (delta2 > Canbuffer)) {
			avgPath = ((0.5 * Canbuffer) / solarPhi);
		}
		// (4) Full shade, sun above buffer canopy
		else if ((delta1 > 0.0) && (delta2 <= Canbuffer)) {
			avgPath = ((0.5 * (delta1 + delta2)) / solarPhi);
		}
		// (5) Full shade, sun partially below buffer canopy
		else if ((delta1 <= Canbuffer) && (delta2 > Canbuffer)) {
			avgPath = ((0.5 * (delta1 + Canbuffer)) / solarPhi);
		}
		// (6) Full shade, sun entirely below buffer canopy
		else if ((delta1 > Canbuffer) && (delta2 > Canbuffer)) {
			avgPath = (Canbuffer / solarPhi);
		}
		//Eq. #6 in Sun et al., (2015)
		// The shadow length as the initial value for shadow (Eq. #6 in Sun et al., 2015) for Eastern side
		if (shadowLengthW < CanDist_W_LI[dist]) {
			effShadowLengthW = 0;
		}
		else {
			effShadowLengthW = ((shadowLengthW - CanDist_W_LI[dist] - overHangW_W) *
				(1 - exp(-(extinctCoeff * avgPath))));
		}
	}
	else {
		if (shadowLengthW < BuildDist_W_LI[dist]) {
			effShadowLengthW = 0;
		}
		effShadowLengthW = shadowLengthW - BuildDist_W_LI[dist] - overHangW_W;
	}

	return effShadowLengthW;
}

// Fresnel's Reflectivity
void StreamTemperature::solarReflectivity()
{
	double n = 1.333;
	vector<double> solarZ(TotalTime + 1); // USED FOR HOURLY BASED
	//solarCal is pointer to SolarCalculation
	solarZ = solarCal->getSolZenith();

	//vector<double> SWreflVecTemp;
	SWreflVec.resize(TotalTime + 1);
	for (int i = 0; i < TotalTime; i++) {
		//solarZenith = solarCal->getSolZenith(i);
		double alpha_rad = solarZ[i];
		if (alpha_rad < M_PI / 2)	{
			double beta_rad = asin(sin(double(alpha_rad / n)));
			double a = pow((tan(alpha_rad - beta_rad)), 2);
			double b = pow((tan(alpha_rad + beta_rad)), 2);
			double c = pow((sin(alpha_rad - beta_rad)), 2);
			double d = pow((sin(alpha_rad + beta_rad)), 2);
			double a_deg = a * (180 / M_PI);
			double b_deg = b * (180 / M_PI);
			double c_deg = c * (180 / M_PI);
			double d_deg = d * (180 / M_PI);
			SWrefl = 0.5 * ((a_deg / b_deg) + (c_deg / d_deg));
		}
		else {
			SWrefl = 1;
		}
		SWreflVec[i] = SWrefl;
	}
}

void StreamTemperature::adjustedDirRadE(const vector<double>& DirSW, int timeStep)
{
	/* calcluating the MapPixel_ID for getAspect function to get access the desired cell of the domain. */
	int col; // considering the (-1) to get a correct answer for "i*cols + j" in SlopeCal class i as the row number and j as the col number
	int row; // considering the (-1) to get a correct answer for "i*cols + j" in SlopeCal class i as the row number and j as the col number
	int MapPixel_ID;
	int totCols = input->getcols();

	double effWidth;
	adjustedDirSW_E.clear();
	adjustedDirSW_E.resize(TotalDist);

	switch (SolvingMethod) {
		case 1: {

			// matrix1 would be direct solar radiation
			adjustedDirSW_E.resize(TotalDist);
			for (int i = 0; i < TotalDist; i++) {

				col = int(colNum_Dist[i] - 1);
				row = int(rowNum_Dist[i] - 1);
				MapPixel_ID = row * totCols + col;
				slope = input->SlopeGround_rad[MapPixel_ID]; //The answers for slope and aspect are in radian
				aspect = input->AspectGround_N_0_rad[MapPixel_ID];

				double topoEffect = (sin(slope) * cos(SolAltitude_LI[timeStep]) * cos((SolAltitude_LI[timeStep]) - aspect)) +
					cos(slope) * sin(SolAltitude_LI[timeStep]);
				if (topoEffect < 0) {
					topoEffect = 0;
				}
				effWidth = effectiveShadingE(DirSW, i, timeStep);
				adjustedDirSW_E[i] = DirSW[timeStep] * (1 - SWreflVec[timeStep]) * topoEffect * (1 - (effWidth / secWidth_LI[i]));
				if (effWidth > secWidth_LI[i]) {
					adjustedDirSW_E[i] = 0;
				}
			}
			break;
		}
		case 2: {
			// matrix1 would be direct solar radiation
			adjustedDirSW_E.resize(TotalDist);
			for (int i = 0; i < TotalDist; i++) {
				adjustedDirSW_E[i] = DirSW[timeStep] * (1 - SF_LI[i]) * (1 - SWreflVec[timeStep]);
			}
			break;
		}
		default: {
			cout << "Wrong shortwave radiation methodology. Stop model and select other option." << endl;
		}
	}
}

void StreamTemperature::adjustedDirRadW(const vector<double>& DirSW, int timeStep)
{

	/* calcluating the MapPixel_ID for getAspect function to get access the desired cell of the domain. */
	int col; // considering the (-1) to get a correct answer for "i*cols + j" in SlopeCal class i as the row number and j as the col number
	int row; // considering the (-1) to get a correct answer for "i*cols + j" in SlopeCal class i as the row number and j as the col number
	int MapPixel_ID;
	int totCols = input->getcols();

	double effWidth;
	adjustedDirSW_W.clear();
	adjustedDirSW_W.resize(TotalDist);

	switch (SolvingMethod) {
		case 1: {
			// matrix1 would be direct solar radiation
			adjustedDirSW_W.resize(TotalDist);
			for (int i = 0; i < TotalDist; i++) {

				col = int(colNum_Dist[i] - 1);
				row = int(rowNum_Dist[i] - 1);
				MapPixel_ID = row * totCols + col;
				slope = input->SlopeGround_rad[MapPixel_ID]; //The answers for slope and aspect are in radian
				aspect = input->AspectGround_N_0_rad[MapPixel_ID];

				double topoEffect = (sin(slope) * cos(SolAltitude_LI[timeStep]) * cos((SolAltitude_LI[timeStep]) - aspect)) +
					cos(slope) * sin(SolAltitude_LI[timeStep]);
				if (topoEffect < 0) {
					topoEffect = 0;
				}
				effWidth = effectiveShadingW(DirSW, i, timeStep);
				adjustedDirSW_W[i] = DirSW[timeStep] * (1 - SWreflVec[timeStep]) * topoEffect * (1 - (effWidth / secWidth_LI[i]));
				if (effWidth > secWidth_LI[i]) {
					adjustedDirSW_W[i] = 0;
				}
			}
			break;
		}
		case 2: {
			// matrix1 would be direct solar radiation
			adjustedDirSW_W.resize(TotalDist);
			for (int i = 0; i < TotalDist; i++) {
				adjustedDirSW_W[i] = DirSW[timeStep] * (1 - SF_LI[i]) * (1 - SWreflVec[timeStep]);
			}
			break;
		}
		default: {
			cout << "Wrong shortwave radiation methodology. Stop model and select other option." << endl;
		}
	}
}

void StreamTemperature::longWaveRadiation(const vector<double>& airTemperature,
	const vector<double>& relHumidity,
	const vector<double>& cloadinessCoeff,
	const vector<double>& streamTemp, int timeStep)
{
	double SBConst = 0.000000056696; // Stefan-Boltzman constant, 5.6696*10-8 (kg�s-3�K-4)

	atmLW.resize(TotalDist);
	lcLW.resize(TotalDist);
	backLW.resize(TotalDist);

	switch (SolvingMethod) {
		case 1: {
			// solving based on the calculated sky view factor
			for (int i = 0; i < TotalDist; i++) {
				//VaporPressure_Saturated_kPa (kPa) as Tetens' formula in Eq 4.2.2 Shuttleworth (1993), e_kPa=0.6108*exp[(17.27*T_C)/(237.3+T_C)]
				double VaporPressure_Saturated_kPa = 0.6108 * exp((17.27 * airTemperature[timeStep]) / (airTemperature[timeStep] + 237.3));
				double VaporPressure_Actual_kPa = (relHumidity[timeStep] / 100) * VaporPressure_Saturated_kPa;

				double emis = 1.72 * pow(((VaporPressure_Actual_kPa) / (airTemperature[timeStep] + 273.2)), (1.0 / 7.0)) * (1 + (0.22 * (pow(cloadinessCoeff[timeStep], 2))));
				if (emis > 0.96) {
					emis = 0.96;
				}
				//term1W = 0.96 * 0.84 * SBConst * pow((airTemp_C + 273.2), 4) * min(TSAWest, VSAWest);
				atmLW[i] = 0.96 * emis * SBConst * pow((airTemperature[timeStep] + 273.2), 4) * SkyV_E[i];
				// Land cover longwave radiation
				lcLW[i] = 0.96 * (1 - SkyV_E[i]) * 0.96 * SBConst * pow((airTemperature[timeStep] + 273.2), 4);

				backLW[i] = -0.96 * SBConst * pow((streamTemp[i] + 273.2), 4);
			}
			break;
		}
		case 2: {
			for (int i = 0; i < TotalDist; i++) {
				//VaporPressure_Saturated_kPa (kPa) as Tetens' formula in Eq 4.2.2 Shuttleworth (1993), e_kPa=0.6108*exp[(17.27*T_C)/(237.3+T_C)]
				double VaporPressure_Saturated_kPa = 0.6108 * exp((17.27 * airTemperature[timeStep]) / (airTemperature[timeStep] + 237.3));
				double VaporPressure_Actual_kPa = (relHumidity[timeStep] / 100) * VaporPressure_Saturated_kPa;

				double emis = 1.72 * pow(((VaporPressure_Actual_kPa) / (airTemperature[timeStep] + 273.2)), (1.0 / 7.0)) * (1 + (0.22 * (pow(cloadinessCoeff[timeStep], 2))));
				if (emis > 0.96) {
					emis = 0.96;
				}
				//term1W = 0.96 * 0.84 * SBConst * pow((airTemp_C + 273.2), 4) * min(TSAWest, VSAWest);
				atmLW[i] = 0.96 * emis * SBConst * pow((airTemperature[timeStep] + 273.2), 4) * SkyToView_LI[i];
				// Land cover longwave radiation
				lcLW[i] = 0.96 * (1 - SkyToView_LI[i]) * 0.96 * SBConst * pow((airTemperature[timeStep] + 273.2), 4);

				backLW[i] = -0.96 * SBConst * pow((streamTemp[i] + 273.2), 4);
			}
			break;
		}
		default: {
			cout << "Wrong longwave radiation methodology. Stop model and select other option." << endl;
		}
	}
	for (int i = 0; i < TotalDist; i++) {
		atmLW_2D[i][timeStep] = atmLW[i];
		LCLW_2D[i][timeStep] = lcLW[i];
		backLW_2D[i][timeStep] = backLW[i];
		LW_2D[i][timeStep] = atmLW_2D[i][timeStep] + LCLW_2D[i][timeStep] + backLW_2D[i][timeStep];
	}

	atmLW.clear();
	lcLW.clear();
	backLW.clear();
}

void StreamTemperature::latentHeat(const vector<double>& airTemperature,
	const vector<double>& relHumidity,
	const vector<double>& streamTemp,
	const vector<double>& windSp, int timeStep)
{

	double c_air = 1004;	 // heat capacity of air (J/kg deg C)
	double rho_air = 1.2041; // density of air at 20 deg C (kg/m^3)

	latent.resize(TotalDist);

	// <<<<<<<<< Evaporation section >>>>>>>>
	for (int i = 0; i < TotalDist; i++) {
		double L_e = 1000000 * (2.501 - (0.002361 * streamTemp[i])); // Calculate the latent heat of vaporization J/kg
		// Calculate the slope of the saturated vapor pressure curve at a given air temperature
		//VaporPressure_Saturated_kPa (kPa) as Tetens' formula in Eq 4.2.2 Shuttleworth (1993), e_kPa=0.6108*exp[(17.27*T_C)/(237.3+T_C)]
		double VaporPressure_Saturated_kPa = 0.6108 * exp((17.27 * airTemperature[timeStep]) / (airTemperature[timeStep] + 237.3));
		double VaporPressure_Actual_kPa = (relHumidity[timeStep] / 100) * VaporPressure_Saturated_kPa;
		double s = (4100 * VaporPressure_Saturated_kPa) / (pow((237 + airTemperature[timeStep]), 2)); //kPa / deg C
		// Calculate the aerodynamic resistance
		double r_a = 245 / ((0.54 * windSp[timeStep]) + 0.5); //[s / m]

		// Calculate air pressure
		// z = elevation of station where met data was obtained
		double Pa = 101.3 - (0.0105 * elev_LI[i]);
		// Calculate psychrometric constant(kPa / deg C) (based on air pressure(Pa), (value should be adjusted for different site elevations),
		//ratio of water to dry air = .622, and the latent heat of water vaporization = 2.45E6 [J / kg deg C])
		double psy = (c_air * Pa) / (0.622 * 2450000);
		// Calculate the Penman open water evaporation
		//double E = ((s * (((swDir[timeStep] + swDiff[timeStep]) * (1 - SWreflVec[timeStep])) + atmLW_2D[i][timeStep] + LCLW_2D[i][timeStep] + backLW_2D[i][timeStep])) / (1000 * L_e*(s + psy)))
		//	+ ((c_air*rho_air*psy*(VaporPressure_Saturated_kPa - VaporPressure_Actual_kPa)) / (1000 * L_e*r_a*(s + psy)));
		double E = ((s * (SW_2D[i][timeStep] + LW_2D[i][timeStep])) / (1000 * L_e * (s + psy))) +
			((c_air * rho_air * psy * (VaporPressure_Saturated_kPa - VaporPressure_Actual_kPa)) / (1000 * L_e * r_a * (s + psy)));

		latent[i] = (-rho_water * L_e * E);
	}

	for (int i = 0; i < TotalDist; i++) {
		Latent_2D[i][timeStep] = latent[i];
	}

	latent.clear();
}

void StreamTemperature::sensibleHeat(const vector<double>& airTemperature,
	const vector<double>& streamTemp,
	const vector<double>& windSp,
	const vector<double>& relHumidity, int timeStep)
{

	int method = int(input->CoolRiverVariables["CR_sensMethod"]);
	double c_air = 1004;	 // (J / kg deg C) value for the heat capacity of air
	double rho_air = 1.2041; // (kg / m ^ 3) value for the density of air at 20 deg C

	double vaporLatHeat = 2499500;		   // latent heat of vaporization (Joules�kg-1)
	double empiricalConst = 0.00000000159; // empirical constant, (s�m-1�mb-1)

	sensible.resize(TotalDist);

	switch (method)
	{
	case 1:
		for (int i = 0; i < TotalDist; i++) {
			double z_veg = 0.25;	 // (m)  height of vegetation around stream
			double zd = 0.7 * z_veg; // zero - plane displacement, m
			double z0 = 0.1 * z_veg; //roughness height, m
			double DH_DM = 1;		 // ratio of diffusivity of sensible heat to diffusivity
			// of momentum, m2 / s(1 under stable conditions)
			double k = 0.4;																				   //dimensionless constant
			double KH = DH_DM * c_air * rho_air * ((pow(k, 2)) / (pow((log((elev_LI[i] - zd) / z0)), 2))); // (J / C deg m3)
			sensible[i] = -KH * windSp[timeStep] * (streamTemp[i] - airTemperature[timeStep]);			   // W / m2
		}
		break;

	case 2:
		for (int i = 0; i < TotalDist; i++)	{
			//Saturated vapor pressure
			double ews = 0.61275 * exp((17.27 * streamTemp[i]) / (237.3 + streamTemp[i])); //kPa
			//Actual vapor pressure
			double ewa = (relHumidity[timeStep] / 100.0) * ews; //kPa
			//Avoiding zero value for (ews-ewa) used in denominator of Br
			if (ewa == ews) {
				ewa = 0.999 * (ews);
			}
			double Pa1 = 101.3 * pow(((293 - (0.0065 * elev_LI[i])) / 293), 5.256);
			//Br is Bowen Ratio, and method is from Glose et al., (2017), Eq. 22: https://doi.org/10.1016/j.envsoft.2017.02.021
			// Sun et al., (2015): https://doi.org/10.1002/hyp.10363 (see the supplementary materials for the other form of the Br definition)
			double Br = 0.00061 * Pa1 * ((streamTemp[i] - airTemperature[timeStep]) / (ews - ewa));
			sensible[i] = Br * Latent_2D[i][timeStep];
		}
		break;

	case 3:
		// Ning Sun's methodology
		for (int i = 0; i < TotalDist; i++)	{
			//Saturated vapor pressure
			double ews = 0.61275 * exp((17.27 * streamTemp[i]) / (237.3 + streamTemp[i])); //kPa
			//Actual vapor pressure
			double ewa = (relHumidity[timeStep] / 100.0) * ews; //kPa
			//Avoiding zero value for (ews-ewa) used in denominator of Br
			if (ewa == ews) {
				ewa = 0.999 * (ews);
			}
			double Pa1 = 101.3 * pow(((293 - (0.0065 * elev_LI[i])) / 293), 5.256);
			//Br is Bowen Ratio, and method is from Glose et al., (2017), Eq. 22: https://doi.org/10.1016/j.envsoft.2017.02.021
			// Sun et al., (2015): https://doi.org/10.1002/hyp.10363 (see the supplementary materials for the other form of the Br definition)
			double Br = 0.00061 * Pa1 * ((streamTemp[i] - airTemperature[timeStep]) / (ews - ewa));
			sensible[i] = Br * rho_water * vaporLatHeat * empiricalConst * windSp[timeStep] * (airTemperature[timeStep] - streamTemp[i]);
		}
		break;

	default:
		cout << "Wrong sensible heat methodology. Stop model and select other option." << endl;
	}

	for (int i = 0; i < TotalDist; i++) {
		Sensible_2D[i][timeStep] = sensible[i];
	}

	sensible.clear();
}

void StreamTemperature::bedSediment(const vector<vector<double>>& Wp,
	const vector<vector<double>>& Width_B,
	const vector<double>& Ksed_index,
	const vector<double>& streamTemp,
	const vector<double>& bedTemp,
	const vector<double>& depthMeas, int timeStep)
{
	//double tempSurface = surTemperature(ts);
	// streamTemp and sedimentTemp should be based on Celsius
	bed.resize(TotalDist);
	for (int i = 0; i < TotalDist; i++) {
		bed[i] = ((Wp[i][timeStep] / Width_B[i][timeStep]) * (-Ksed_index[i] * ((streamTemp[i] - bedTemp[timeStep]) / depthMeas[i])));
	}

	for (int i = 0; i < TotalDist; i++) {
		Bed_2D[i][timeStep] = bed[i];
	}
	bed.clear();
}

//StreamTemperature::avgTemperature function called from SimulationCoordinator
//Note: CoolRiver functions mainly managed from the call to StreamTemperature::avgTemperature
void StreamTemperature::avgTemperature() {

	//TotalTime is input->SimulationTimePeriod_timeSteps, number of time steps for 
	//Note: TotalTime should align with rows of RiverTimeSeries.csv, RiverSWTimeSeries.csv and RiverGWTimeSeries.csv
	//Note: Consider refactor conceptual error of presuming TotalTime = number of hours simulated, when it is really number of time steps
	TotalTime = input->SimulationTimePeriod_timeSteps;

	TotalDist = int(input->CoolRiverVariables["CR_totDist"]);
	vector<double> timeMod;
	vector<double> distMod;

	//For Loop to through TotalTime at increment of 1 hr
	for (int i = 1; i <= TotalTime; i++) {
		timeMod.push_back(i); 
	}

	//For Loop to through TotalDist at increment of 1 m
	for (int i = 1; i <= TotalDist; i++) {
		distMod.push_back(i);
	}
	//Note: Consider refactor conceptual error of presuming TotalTime = number of hours simulated, when it is really number of time steps
	int timeSteps = TotalTime;
	int nodes = TotalDist;
	//dt is deltaTime as integer 
	int dt = int(*max_element(timeMod.begin(), timeMod.end()) / (TotalTime - 1));

	//Command Prompt Notification
	cout << "Interpolating river longitudinal data in space..." << endl;

	//dischargeCount constructor assigned get_Q_count groundwater discharge data
	const int dischargeCount = input->get_Q_count();
	vector<double> distanceQ, flow_temp_1;
	vector<double> discharge_LI1;
	vector<vector<double>> timeDischarge;
	vector<double> BedTn;

	//For Loop through length of input->GW_Q_cms1 container map, where x holds constant reference to map
	for (auto const& x : input->GW_Q_cms1) {
		//distanceQ vector adds x.first, 1st element in x map
		distanceQ.push_back(x.first);
		//timeDischarge vector adds x.second, 2nd element in x map
		timeDischarge.push_back(x.second);
	}

	vector<vector<double>> discharge_time;
	//discharge_time vector resized to TotalDist
	discharge_time.resize(TotalDist);

	//For Loop through TotalTime at increment of 1 hr
	for (int i = 0; i < TotalTime; i++)	{
		//flow_temp_1 vector cleared
		flow_temp_1.clear();
		//For Loop through timeDischarge, which was sized to TotalDist
		for (int k = 0; k < timeDischarge.size(); k++) {
			//flow_temp_1 is river temperature at timeStep=1 for all locations
			flow_temp_1.push_back(timeDischarge[k].at(i));
		}
		//discharge_LI1 vector cleared
		discharge_LI1.clear();
		//For Loop assigning x to each member of distMod; distMod sized to TotalDist
		for (double x : distMod) {
			//Call interpolate function, sending distanceQ, flow_temp_1, x, true and return y
			double y = interpolate(distanceQ, flow_temp_1, x, true);
			//discharge_LI1 vector assigned y value
			discharge_LI1.push_back(y);
		}
		//For Loop incrementing j through TotalDist
		for (int j = 0; j < TotalDist; j++)	{
			//discharge_time[j] along distance j resized to TotalTime
			discharge_time[j].resize(TotalTime);
			//Note: j variable is distance, i variable is time
			//Note: discharge_time array has each row as location along the stream and each column as a different time
			discharge_time[j][i] = (discharge_LI1[j]); 
		}
	}
	
	//For Loop through length of input->GW_T_C1 container map, where x holds constant reference to map
	vector<double> distanceQ_T_C;
	for (auto const& x : input->GW_T_C1) {
			distanceQ_T_C.push_back(x.first);
		    BedTn.push_back(x.second[0]);
	}
	
	vector<double> BedTn_LI;
	//For Loop through length of distMod vector, where x holds constant reference to vector
	for (double x : distMod) {
		double y = interpolate(distanceQ_T_C, BedTn, x, true);
		BedTn_LI.push_back(y);
	}

	//************************************************
	//Note: Section of code reads in surface water data
	vector<double> locations;
	vector<vector<double>> inflow_Discharge(TotalDist, vector<double>(TotalTime));
	vector<vector<double>> inflow_Temp(TotalDist, vector<double>(TotalTime));

	//For Loop through length of SW_Q_cms1 container map, where x holds constant reference to map
	for (auto const& x : input->SW_Q_cms1) {
		locations.push_back(x.first);
		inflow_Discharge[x.first] = x.second;
	}

	//For Loop through length of SW_T_C1 container map, where x holds constant reference to map
	for (auto const& x : input->SW_T_C1) {
		inflow_Temp[x.first] = x.second;
	}

	// ***************************** DONE **************************
	// Reading in the morphology data from input file

	int knownSectionCount = int(input->StationDistanceMorphology.size());
	vector<double> secDistance, secArea, secWidth, secDepth, secDischarge, colNum, rowNum, LongValue, latValue, secSlope, Z;

	for (int i = 0; i < knownSectionCount; i++) {
		double temp1, temp2, temp3, temp4, temp6, temp7, temp8, temp9, temp10, temp11;
		temp1 = input->StationDistanceMorphology[i];
		temp2 = input->AreaR_m2[i];
		temp3 = input->WidthR_m[i];
		temp4 = input->DepthR_m[i];
		temp6 = input->ColRiver[i];
		temp7 = input->RowRiver[i];
		temp8 = input->LongitudeR_frac[i];
		temp9 = input->LatitudeR_frac[i];
		if (temp1 != NODATA) {
			secDistance.push_back(temp1);
		}
		if (temp2 != NODATA) {
			secArea.push_back(temp2);
		}
		if (temp3 != NODATA) {
			secWidth.push_back(temp3);
		}
		if (temp4 != NODATA) {
			secDepth.push_back(temp4);
		}
		if (temp6 != NODATA) {
			colNum.push_back(temp6);
		}
		if (temp7 != NODATA) {
			rowNum.push_back(temp7);
		}
		if (temp8 != NODATA) {
			LongValue.push_back(temp8);
		}
		if (temp9 != NODATA) {
			latValue.push_back(temp9);
		}
		temp10 = input->SlopeR_f[i];
		if (temp10 != NODATA) {
			secSlope.push_back(temp10);
		}
		temp11 = input->ZRiver_m[i];
		if (temp11 != NODATA) {
			Z.push_back(temp11);
		}
	}

	vector<double> discharge_LI;

	// Interpolate
	for (double x : distMod) {
		double y = interpolate(secDistance, secWidth, x, true);
		secWidth_LI.push_back(y);
	}
	for (double x : distMod) {
		double y = interpolate(secDistance, secDepth, x, true);
		secDepth_LI.push_back(y);
	}
	for (int i = 0; i < secDistance.size(); i++) {
		secDischarge.push_back(inflow_Discharge.at(locations.at(0)).at(0));
	}
	for (double x : distMod) {
		double y = interpolate(secDistance, secDischarge, x, true);
		discharge_LI.push_back(y); // interpolation of stream discharge at each location where dimensions were measured to each model node
	}
	for (double x : distMod) {
		double y = interpolate(secDistance, secSlope, x, true);
		secSlope_LI.push_back(y);
	}
	for (double x : distMod) {
		double y = interpolate(secDistance, secArea, x, true);
		secArea_LI.push_back(y);
	}
	for (double x : distMod) {
		double y = interpolate(secDistance, Z, x, true);
		Z_LI.push_back(y);
	}

	colNum_Dist.resize(TotalDist);
	rowNum_Dist.resize(TotalDist);
	LongValue_Dist.resize(TotalDist);
	latValue_Dist.resize(TotalDist);

	int valuei = secDistance.size() - 2;
	// this way, I will consider the coordinates of the previous known point for the set of locations up to next known point, in the morphology input file
	for (int i = (TotalDist - 1); i >= 0; i--) {
		if (distMod[i] >= int(secDistance[valuei])) {
			colNum_Dist[i] = colNum[valuei];
			rowNum_Dist[i] = rowNum[valuei];
			LongValue_Dist[i] = LongValue[valuei];
			latValue_Dist[i] = latValue[valuei];
		}
		if (distMod[i] <= int(secDistance[valuei])) {
			valuei--;
		}
	}

	cout << "Interpolating river temporal data in time..." << endl;

	//vector<vector<double>> discharge_time(TotalDist, vector<double>(TotalTime));

	// This needs to be done

	// ======================= Sediment Data ========================
	double sedDataCount = input->StationDistanceBedData.size() - 1;
	vector<double> DistBedMeas, BedDepthMeas, BedT0, K_sedType_LI;
	vector<double> BedDepthMeas_LI;
	vector<string> BedSedType;
	for (int i = 0; i <= sedDataCount; i++) {
		double temp1 = input->StationDistanceBedData[i];
		if (temp1 != NODATA) {
			DistBedMeas.push_back(temp1);
			BedDepthMeas.push_back(input->DepthMesurments[i]);
			BedSedType.push_back(input->TypeOfRiver[i]);
		}
	}

	// Interpolate
	for (double x : distMod) {
		double y = interpolate(DistBedMeas, BedDepthMeas, x, true);
		BedDepthMeas_LI.push_back(y);
	}

	vector<double> convertedCode;
	// Determine the sediment thermal conductivity (values from Lapham, 1989)
	for (int i = 0; i <= sedDataCount; i++) {
		string tempType = BedSedType[i];
		if (tempType == "clay") {
			convertedCode.push_back(0.84);
		}
		else if (tempType == "sand") {
			convertedCode.push_back(1.2);
		}
		else if (tempType == "gravel") {
			convertedCode.push_back(1.4);
		}
		else if (tempType == "cobbles") {
			convertedCode.push_back(2.5);
		}
	}

	// operating the NEAREST interpolation!
	DistBedMeas[0] = 1;
	K_sedType_LI = interp1(DistBedMeas, convertedCode, distMod); // thermal conductivity of sediment, W/mC

	vector<double> tempBedT;
	tempBedT.push_back(BedTn[1]);
	tempBedT.push_back(BedTn[1]);

	vector<double> sedimentTime_LI;
	vector<double> sedimentDist_LI;
	vector<double> xValsTotalTime;

	//vector<double> xValsTotalDist;
	//for (int i = 1; i <= TotalTime; i++) xValsTotalTime.push_back((double)i);
	//for (int i = 1; i <= TotalDist; i++) xValsTotalDist.push_back((double)i);
	// Interpolate
	//for (double x : xValsTotalTime)

	double firstDate = 0;
	double lastDate = timeSteps - 1;
	vector<double> time_dis;
	time_dis.push_back(firstDate);
	time_dis.push_back(lastDate);

	vector<double> timeMod_temp;
	for (int i = 1; i <= TotalTime + 1; i++) {
		timeMod_temp.push_back(i);
	}
	for (double x : timeMod_temp) {
		double y = interpolate(time_dis, tempBedT, x, true);
		sedimentTime_LI.push_back(y);
	}
	for (double x : distMod) {
		double y = interpolate(time_dis, tempBedT, x, true);
		sedimentDist_LI.push_back(y);
	}

	// ==============================================

	// ================== read in the shading percentage condition input file
	vector<double> DistanceSP_Temp, SF_Temp, SkyView_Temp;
	double ShadingPerDist = input->StationDistanceShadingPercent.size();

	for (int i = 1; i <= ShadingPerDist - 2; i++) {
		double temp1, temp2, temp3;
		temp1 = input->StationDistanceShadingPercent[i];
		if (temp1 != NODATA) {
			DistanceSP_Temp.push_back(temp1);
		}
		temp2 = input->ShadeFactorR_f[i];
		if (temp2 != NODATA) {
			SF_Temp.push_back(input->ShadeFactorR_f[i]);
		}
		temp3 = input->ViewToSkyR_f[i];
		if (temp3 != NODATA) {
			SkyView_Temp.push_back(temp3);
		}
	}

	for (double x : distMod) {
		double y = interpolate(DistanceSP_Temp, SkyView_Temp, x, true);
		SkyToView_LI.push_back(y);
	}
	for (double x : distMod) {
		double y = interpolate(DistanceSP_Temp, SF_Temp, x, true);
		SF_LI.push_back(y);
	}

	// =============== Read in the shading data ======
	double ShadingDist = input->StationDistanceShading.size() - 2;
	vector<double> Distance_Temp, BankH_E_Temp, TreeH_E_Temp, BankH_W_Temp, TreeH_W_Temp, BuildH_E_Temp,
		BuildH_W_Temp, CanDist_E_Temp, CanDist_W_Temp, BanDist_E_Temp, BanDist_W_Temp, BuildDist_E_Temp,
		BuildDist_W_Temp, Buff_E_Temp, Buff_W_Temp, StrAzimuth_Temp, elev_temp;

	for (int i = 0; i <= ShadingDist; i++) {
		double temp1 = input->StationDistanceShading[i];
		if (temp1 != NODATA) {
			Distance_Temp.push_back(temp1);
			BankH_E_Temp.push_back(input->EastBankHR_m[i]);
			TreeH_E_Temp.push_back(input->EastTreeHR_m[i]);
			BankH_W_Temp.push_back(input->WestBankHR_m[i]);
			TreeH_W_Temp.push_back(input->WestTreeHR_m[i]);
			BuildH_E_Temp.push_back(input->EastBuildingHR_m[i]);
			BuildH_W_Temp.push_back(input->WestBuildingHR_m[i]);
			CanDist_E_Temp.push_back(input->EastCanDistR_m[i]);
			CanDist_W_Temp.push_back(input->WestCanDistR_m[i]);
			BanDist_E_Temp.push_back(input->EastBankDistR_m[i]);
			BanDist_W_Temp.push_back(input->WestBankDistR_m[i]);
			BuildDist_E_Temp.push_back(input->EastBuildingDistR_m[i]);
			BuildDist_W_Temp.push_back(input->WestBuildingDistR_m[i]);
			Buff_E_Temp.push_back(input->EastBufferWR_m[i]);
			Buff_W_Temp.push_back(input->WestBufferWR_m[i]);
			elev_temp.push_back(input->ElevationR_m[i]);
			StrAzimuth_Temp.push_back(input->StreamAzimuthR_deg[i]);
		}
	}

	// Interpolate
	for (double x : distMod) {
		double y = interpolate(Distance_Temp, BankH_E_Temp, x, true);
		BankH_E_LI.push_back(y);
	}
	for (double x : distMod) {
		double y = interpolate(Distance_Temp, TreeH_E_Temp, x, true);
		TreeH_E_LI.push_back(y);
	}
	for (double x : distMod) {
		double y = interpolate(Distance_Temp, BankH_W_Temp, x, true);
		BankH_W_LI.push_back(y);
	}
	for (double x : distMod) {
		double y = interpolate(Distance_Temp, TreeH_W_Temp, x, true);
		TreeH_W_LI.push_back(y);
	}
	for (double x : distMod) {
		double y = interpolate(Distance_Temp, CanDist_E_Temp, x, true);
		CanDist_E_LI.push_back(y);
	}
	for (double x : distMod) {
		double y = interpolate(Distance_Temp, CanDist_W_Temp, x, true);
		CanDist_W_LI.push_back(y);
	}
	for (double x : distMod) {
		double y = interpolate(Distance_Temp, BanDist_E_Temp, x, true);
		BanDist_E_LI.push_back(y);
	}
	for (double x : distMod) {
		double y = interpolate(Distance_Temp, BanDist_W_Temp, x, true);
		BanDist_W_LI.push_back(y);
	}
	for (double x : distMod) {
		double y = interpolate(Distance_Temp, BuildDist_E_Temp, x, true);
		BuildDist_E_LI.push_back(y);
	}
	for (double x : distMod) {
		double y = interpolate(Distance_Temp, BuildDist_W_Temp, x, true);
		BuildDist_W_LI.push_back(y);
	}
	for (double x : distMod) {
		double y = interpolate(Distance_Temp, Buff_E_Temp, x, true);
		Buff_E_LI.push_back(y);
	}
	for (double x : distMod) {
		double y = interpolate(Distance_Temp, Buff_W_Temp, x, true);
		Buff_W_LI.push_back(y);
	}
	for (double x : distMod) {
		double y = interpolate(Distance_Temp, elev_temp, x, true);
		elev_LI.push_back(y);
	}
	for (double x : distMod) {
		double y = interpolate(Distance_Temp, StrAzimuth_Temp, x, true);
		StrAzimuth_LI.push_back(y);
	}

	// I considered 10 meter in average for each building. Therefore, I copy the height of the building to 5m up and
	// 5m down stream along the river.
	BuildH_E_LI.resize(TotalDist);
	BuildH_W_LI.resize(TotalDist);

	for (int i = 0; i < Distance_Temp.size(); i++) {
		if (i == (Distance_Temp.size() - 1)) {
			BuildH_E_LI[Distance_Temp[i] - 5] = BuildH_E_Temp[i];
			BuildH_E_LI[Distance_Temp[i] - 4] = BuildH_E_Temp[i];
			BuildH_E_LI[Distance_Temp[i] - 3] = BuildH_E_Temp[i];
			BuildH_E_LI[Distance_Temp[i] - 2] = BuildH_E_Temp[i];
			BuildH_E_LI[Distance_Temp[i] - 1] = BuildH_E_Temp[i];

			BuildH_W_LI[Distance_Temp[i] - 5] = BuildH_W_Temp[i];
			BuildH_W_LI[Distance_Temp[i] - 4] = BuildH_W_Temp[i];
			BuildH_W_LI[Distance_Temp[i] - 3] = BuildH_W_Temp[i];
			BuildH_W_LI[Distance_Temp[i] - 2] = BuildH_W_Temp[i];
			BuildH_W_LI[Distance_Temp[i] - 1] = BuildH_W_Temp[i];
		}
		else if (i == 0)
		{
			BuildH_E_LI[Distance_Temp[i]] = BuildH_E_Temp[i];
			BuildH_E_LI[Distance_Temp[i] + 5] = BuildH_E_Temp[i];
			BuildH_E_LI[Distance_Temp[i] + 4] = BuildH_E_Temp[i];
			BuildH_E_LI[Distance_Temp[i] + 3] = BuildH_E_Temp[i];
			BuildH_E_LI[Distance_Temp[i] + 2] = BuildH_E_Temp[i];
			BuildH_E_LI[Distance_Temp[i] + 1] = BuildH_E_Temp[i];

			BuildH_W_LI[Distance_Temp[i]] = BuildH_W_Temp[i];
			BuildH_W_LI[Distance_Temp[i] + 5] = BuildH_W_Temp[i];
			BuildH_W_LI[Distance_Temp[i] + 4] = BuildH_W_Temp[i];
			BuildH_W_LI[Distance_Temp[i] + 3] = BuildH_W_Temp[i];
			BuildH_W_LI[Distance_Temp[i] + 2] = BuildH_W_Temp[i];
			BuildH_W_LI[Distance_Temp[i] + 1] = BuildH_W_Temp[i];
		}
		else
		{
			if (Distance_Temp[i] > 5 && Distance_Temp[i] < BuildH_E_LI.size() - 5)
			{
				BuildH_E_LI[Distance_Temp[i]] = BuildH_E_Temp[i];
				BuildH_E_LI[Distance_Temp[i] - 5] = BuildH_E_Temp[i];
				BuildH_E_LI[Distance_Temp[i] - 4] = BuildH_E_Temp[i];
				BuildH_E_LI[Distance_Temp[i] - 3] = BuildH_E_Temp[i];
				BuildH_E_LI[Distance_Temp[i] - 2] = BuildH_E_Temp[i];
				BuildH_E_LI[Distance_Temp[i] - 1] = BuildH_E_Temp[i];
				BuildH_E_LI[Distance_Temp[i] + 1] = BuildH_E_Temp[i];
				BuildH_E_LI[Distance_Temp[i] + 2] = BuildH_E_Temp[i];
				BuildH_E_LI[Distance_Temp[i] + 3] = BuildH_E_Temp[i];
				BuildH_E_LI[Distance_Temp[i] + 4] = BuildH_E_Temp[i];
				BuildH_E_LI[Distance_Temp[i] + 5] = BuildH_E_Temp[i];

				BuildH_W_LI[Distance_Temp[i]] = BuildH_W_Temp[i];
				BuildH_W_LI[Distance_Temp[i] - 5] = BuildH_W_Temp[i];
				BuildH_W_LI[Distance_Temp[i] - 4] = BuildH_W_Temp[i];
				BuildH_W_LI[Distance_Temp[i] - 3] = BuildH_W_Temp[i];
				BuildH_W_LI[Distance_Temp[i] - 2] = BuildH_W_Temp[i];
				BuildH_W_LI[Distance_Temp[i] - 1] = BuildH_W_Temp[i];
				BuildH_W_LI[Distance_Temp[i] + 1] = BuildH_W_Temp[i];
				BuildH_W_LI[Distance_Temp[i] + 2] = BuildH_W_Temp[i];
				BuildH_W_LI[Distance_Temp[i] + 3] = BuildH_W_Temp[i];
				BuildH_W_LI[Distance_Temp[i] + 4] = BuildH_W_Temp[i];
				BuildH_W_LI[Distance_Temp[i] + 5] = BuildH_W_Temp[i];
			}
		}
	}

	// LAI value
	CanopyLAI = input->InputXml["LeafAreaIndex_Tree_m2pm2"];

	// Calculate width - depth - discharge relationship
	//Assumes stream cross section is a triangle and calculates the angle between the depth and the edge
	//Channel geometry calculations from Baker et al. (2018) https://doi.org/10.1002/hyp.13226 he importance of incorporating diurnally fluctuating stream discharge in stream temperature energy balance models
	//Baker et al. (2018) Eq 1 and 2 give depth and width for triangular channel cross-section at varying discharge for bank side angle of theta. They state temperature is insenstive to use of triangular vs rectangular channel geometry.

	//Heat flux calculations from Glose et al. (2017) http://dx.doi.org/10.1016/j.envsoft.2017.02.021, Stream heat budget modeling with HFLUX
	// 
	//Baker, E. A., Lautz, L. K., Kelleher, C. A., & McKenzie, J. M. (2018). The importance of incorporating diurnally fluctuating stream discharge in stream temperature energy balance models. Hydrological Processes, 32(18), 2901-2914. doi:https://doi.org/10.1002/hyp.13226
	//Glose, A., Lautz, L. K., & Baker, E. A. (2017). Stream heat budget modeling with HFLUX: Model development, evaluation, and applications across contrasting sites and seasons. Environmental Modelling and Software, 92, 213-228. doi:10.1016/j.envsoft.2017.02.021

	int number = TotalDist;
	vector<float> theta(number);
	for (int i = 0; i < nodes; i++) {
		theta[i] = (atan(secDepth_LI[i] / (0.5 * secWidth_LI[i])));
	}
	vector<double> n_s;
	n_s.resize(TotalDist);
	// calculates the manning number divided by the slope^1/2 which will be used as a constant at each location along the stream
	for (int i = 0; i < nodes; i++) {
		if ((calculation == 1) || (calculation == 4)) {
			//appears this equation uses a fixed bed slope
			n_s[i] = (((pow(0.25, (2.0 / 3.0))) * (pow(2, (5.0 / 3.0))) * (pow(cos(theta[i]), (2.0 / 3.0))) * (pow(tan(theta[i]), (5.0 / 3.0))) *
				(pow(secDepth_LI[i], (8.0 / 3.0)))) /
				(2 * discharge_LI[i]));
			//Note: Consider refactor to create trapezoidal channel, and replace above equation for triangular as one single type of channel
			//n_s[i] = input->CoolRiverVariables["CR_roughness"];
		}
		if ((calculation == 2) || (calculation == 3)) {
			n_s[i] = input->CoolRiverVariables["CR_roughness"];
		}
	}

	// Set discharge
	if (calculation == 1) {
		discharge_time.resize(TotalDist);
		for (int i = 0; i < TotalDist; i++) {
			discharge_time[i].resize(TotalTime);
			for (int j = 0; j < TotalTime; j++) {
				discharge_time[i][j] = inflow_Discharge[0][0]; // each row is a location along the stream and each column is a different time
			}
		}

		// Calculate depth through time and space for triangular cross section
		depth_total.resize(nodes);
		for (int i = 0; i < nodes; i++) {
			depth_total[i].resize(TotalTime);
			for (int j = 0; j < TotalTime; j++) {
				depth_total[i][j] = pow(((2.0 * n_s[i] * discharge_time[i][j]) / ((pow(0.25, (2.0 / 3.0))) * (pow(2.0, (5.0 / 3.0)))
					* (pow(cos(theta[i]), (2.0 / 3.0))) * (pow(tan(theta[i]), (5.0 / 3.0))))), (3.0 / 8.0));
				//Note: Consider refactor to create trapezoidal channel, and replace above equation for triangular as one single type of channel
				//depth_total[i][j] = secDepth_LI[i];
			}
		}

		// Calculate width through time and space for triangular cross section
		width_total.resize(nodes);
		for (int i = 0; i < nodes; i++) {
			width_total[i].resize(TotalTime);
			for (int j = 0; j < TotalTime; j++) {
				width_total[i][j] = 2.0 * tan(theta[i]) * (pow(((2.0 * n_s[i] * discharge_time[i][j]) / ((pow(0.25, (2.0 / 3.0)))
					* (pow(2.0, (5.0 / 3.0))) * (pow(cos(theta[i]), (2.0 / 3.0))) * (pow(tan(theta[i]), (5.0 / 3.0))))), (3.0 / 8.0)));
				//Note: Consider refactor to create trapezoidal channel, and replace above equation for triangular as one single type of channel
				//width_total[i][j] = secWidth_LI[i];
			}
		}

		// Calculate cross sectional area through time and space for triangular cross section
		area_total.resize(nodes);
		for (int i = 0; i < nodes; i++) {
			area_total[i].resize(TotalTime);
			for (int j = 0; j < TotalTime; j++) {
				area_total[i][j] = 0.5 * depth_total[i][j] * width_total[i][j];
				//Note: Consider refactor to create trapezoidal channel, and replace above equation for triangular as one single type of channel
				//area_total[i][j] = (width_total[i][j] * depth_total[i][j]) + (pow(depth_total[i][j],2)* Z_LI[i]);
			}
		}

		// Calculate wetted perimeter through time and space for triangular cross section
		wp_total.resize(nodes);
		for (int i = 0; i < nodes; i++) {
			wp_total[i].resize(TotalTime);
			for (int j = 0; j < TotalTime; j++) {
				wp_total[i][j] = 2.0 * (depth_total[i][j] / cos(theta[i]));
				//Note: Consider refactor to create trapezoidal channel, and replace above equation for triangular as one single type of channel
				//wp_total[i][j] = width_total[i][j] + (2 * depth_total[i][j]) * pow((1 + pow(Z_LI[i],2)),0.5);
			}
		}
	}
	double endTimeCount = input->WindSpd_mps.size();

	// ===============   UNSTEADY STATE   ===============
	//dx_Interval_m (m) is computational interval in streamwise distance x
	dx_Interval_m = input->CoolRiverVariables["CR_interval_dx"];
	//If dx_Interval_m <= 0 then warn and abort simulation
	if (dx_Interval_m <= 0) {
		cerr << "CR_interval_dx must be > 0. Got " << dx_Interval_m << ". Aborting.\n";
		abort();
	}
	//dtime_Interval_min (min) defined from HydroPlusConfig.xml element CR_interval_dt
	//Note: Reza Abdi suggested this is interpreted as seconds for unsteady model, as minutes for steady
	dtime_Interval_min = input->CoolRiverVariables["CR_interval_dt"]; 
	//If dtime_Interval_min <= 0 then warn and abort simulation
	if (dtime_Interval_min <= 0) {
		cerr << "CR_interval_dt must be > 0 minutes. Got " << dtime_Interval_min << ". Aborting.\n";
		abort();
	}
	//if calculation = 3 or 1 then it is a steady state calculation (calculation = 1 is steady state, = 3 is HEC-RAS, = 2 is unsteady)
	if ((calculation == 3) || (calculation == 1)) {
		//dtime_Interval_min is redefined for steady state simulation based on HydroPlusConfig.xml key CR_interval_dt, which has units of minutes
		dtime_Interval_min = input->CoolRiverVariables["CR_interval_dt"];
		//TotalTime_min converts TotalTime from hour to minute
		//Note: Consider refactor conceptual error of presuming TotalTime = number of hours simulated, when it is really number of time steps
		TotalTime_min = TotalTime * 60;
		//TotalTime_min further adjusted based on CR_interval_dt (computational stability parameter, given as minutes per time step); 
		// Adjusting by (60 / dtime_Interval_min) to create additional time steps if CR_interval_dt < 60 min or interval of hour time step 
		TotalTime_min = TotalTime_min * (60.0 / dtime_Interval_min);
		TotalDist_stable = (TotalDist / dx_Interval_m);
	}

	//calculation = 2 is unsteady state
	if (calculation == 2) {
		//Note: Consider refactor conceptual error of presuming TotalTime = number of hours simulated, when it is really number of time steps
		TotalTime_min = TotalTime * 60;
		if (dtime_Interval_min < 60) {
			TotalTime_min = TotalTime_min * (60.0 / dtime_Interval_min);
		}

		TotalDist_stable = (TotalDist / dx_Interval_m);
	}

	//control on output time step (minutes)
	//calculation = 1 is steady state, 	calculation = 3 is steady state with HEC-RAS inputs
	if ((calculation == 1 || calculation == 3) && (input->CoolRiverVariables["CR_Minute_output"] == 1)) {
		double temp = 0;
		for (int i = 0; i < endTimeCount * 60; i++) {
			hourlyTime_min.push_back(temp);
			temp = temp + 1;
		}
		double temp1 = 0;
		for (int i = 0; i < endTimeCount; i++) {
			hourlyTime.push_back(temp1);
			temp1 = temp1 + 2;
		}
	}
	//calculation = 2 is unsteady state
	else if (calculation == 2) {
		double temp = 0;
		for (int i = 0; i < endTimeCount; i++) {
			hourlyTime.push_back(temp);
			temp = temp + 7200;
		}
	}
	else {
		double temp = 0;
		for (int i = 0; i < endTimeCount; i++) {
			hourlyTime.push_back(temp);
			temp = temp + 2;
			//cout << temp << endl;
		}
	}


	hourlyTime[endTimeCount - 1] = TotalTime_min;
	// ==================================================

	//tsTotalHourly is defined by input file Radiation.csv
	const int tsTotalHourly = input->Radiation_Shortwave_Direct_Wpm2.size();
	vector<double> solarSW_Dir, solarSW_Diff, airTemp_C, real_humidity, windSp, cloudiness, obs_xo, hourList, sedTemp;

	for (int i = 0; i < tsTotalHourly; i++) {
		double temp1, temp2, temp3, temp4, temp5, temp6, temp8, temp9;
		temp1 = input->Radiation_Shortwave_Direct_Wpm2[i];
		temp2 = input->Radiation_Shortwave_Diffuse_Wpm2[i];
		//temp3 (C) is air temperature, in deg C
		temp3 = input->Tair_C[i]; 
		//Humidity_Per (%) is relative humidity
		temp4 = input->Humidity_Per[i];
		//WindSpd_mps (m/s) is wind speed
		temp5 = input->WindSpd_mps[i];
		//Cloudiness_F (fraction) is cloud cover
		temp6 = input->Cloudiness_F[i];
		temp8 = stod(input->SimulationTime_HMS[i]);
		//Sediment_T_C (C) is sediment temperature in deg C
		temp9 = input->Sediment_T_C[i];

		solarSW_Dir.push_back(temp1);
		solarSW_Diff.push_back(temp2);
		airTemp_C.push_back(temp3);
		real_humidity.push_back(temp4);
		windSp.push_back(temp5);
		cloudiness.push_back(temp6);
		//obs_xo.push_back(temp7);
		hourList.push_back(temp8);
		sedTemp.push_back(temp9);
	}
	obs_xo = input->SW_T_C1[0];
	vector<double> solarSW_Dir_LI, solarSW_Diff_LI, airTemp_LI_C, real_humidity_LI, windSp_LI, cloudiness_LI,
		hourList_LI, sedTemp_LI;

	for (int i = 0; i < tsTotalHourly; i++) {
		solarSW_Dir_LI.push_back(solarSW_Dir[i]);
		solarSW_Diff_LI.push_back(solarSW_Diff[i]);
		airTemp_LI_C.push_back(airTemp_C[i]);
		real_humidity_LI.push_back(real_humidity[i]);
		windSp_LI.push_back(windSp[i]);
		cloudiness_LI.push_back(cloudiness[i]);
		obs_xo_LI.push_back(obs_xo[i]);
		hourList_LI.push_back(hourList[i]);
		sedTemp_LI.push_back(sedTemp[i]);
	}

	// ================== Solar Azimuth and Altitude =====================

	vector<double> SolAzimuth_Temp, SolAltitude_Temp;
	for (int i = 0; i < tsTotalHourly; i++)
	{
		//solarCal is pointer to SolarCalculation
		SolAzimuth_Temp.push_back(solarCal->getSolAzimuth(i));
		//solarCal is pointer to SolarCalculation
		SolAltitude_Temp.push_back(solarCal->getSolAltitude(i));
	}

	for (int i = 0; i < tsTotalHourly; i++)
	{
		SolAzimuth_LI.push_back(SolAzimuth_Temp[i]);
		SolAltitude_LI.push_back(SolAltitude_Temp[i]);
	}

	// ==================================================

	// I put this function here to make sure that the code has the required vectors for unsteady calculations for
	// solar reflectivity.
	solarReflectivity();

	// ===============   UNSTEADY STATE   ===============

	vector<int> timeMod_min;
	vector<double> xVals_min;
	for (int i = 0; i < TotalTime_min; i++)
	{
		timeMod_min.push_back(i);
	}
	// Interpolate
	/*if (input->CoolRiverVariables["CR_Minute_output"] == 1) {

		double temp = 0;
		for (int i = 0; i < endTimeCount; i++) {
			hourlyTime_Steady.push_back(temp);
			temp = temp + 2;
			//cout << temp << endl;
		}
	}*/
	for (int i = 1; i <= TotalTime_min; i++)
		xVals_min.push_back((double)i);
	for (double x : xVals_min)
	{
		double y = interpolate(hourlyTime, inflow_Discharge.at(locations.at(0)), x, true);
		Q_minBased.push_back(y);

	}
	for (double x : xVals_min)
	{
		double y = interpolate(hourlyTime, obs_xo_LI, x, true);
		Tobs_minBased.push_back(y);
	}
	inflow_Rate.resize(TotalDist_stable);
	inflow_Temp_Uns.resize(TotalDist_stable);
	for (int i = 0; i < TotalDist_stable; i++)
	{
		inflow_Rate[i].resize(TotalTime_min);
		inflow_Temp_Uns[i].resize(TotalTime_min);
	}
	int inflow_loc1 = locations[1] / dx_Interval_m;
	int inflow_loc2 = locations[2] / dx_Interval_m;
	for (int j = 0; j < TotalTime_min; j++)
	{
		for (int i = 1; i < locations.size(); i++)
		{
			double inflow_Q_val = interpolate(hourlyTime, inflow_Discharge.at(locations.at(i)), (double)(j + 1), true);
			/* Infloe_Q_C */
			inflow_Rate[locations.at(i) / dx_Interval_m][j] = inflow_Q_val;
			double inflow_T_C_val = interpolate(hourlyTime, inflow_Temp.at(locations.at(i)), (double)(j + 1), true);
			/* Inflow_T_C */
			inflow_Temp_Uns[locations.at(i) / dx_Interval_m][j] = inflow_T_C_val;
		}
	}

	vector<double> DirSW_Uns, DiffSW_Uns, airTemp_Uns, RH_Uns, Cloadiness_Uns, wndSpd_Uns, sedimentTime_LI_Uns, sedTemp_Uns;
	for (double x : xVals_min)
	{
		double y = interpolate(hourlyTime, solarSW_Dir_LI, x, true);
		DirSW_Uns.push_back(y);
	}
	for (double x : xVals_min)
	{
		double y = interpolate(hourlyTime, solarSW_Diff_LI, x, true);
		DiffSW_Uns.push_back(y);
	}
	for (double x : xVals_min)
	{
		double y = interpolate(hourlyTime, airTemp_LI_C, x, true);
		airTemp_Uns.push_back(y);
	}
	for (double x : xVals_min)
	{
		double y = interpolate(hourlyTime, real_humidity_LI, x, true);
		RH_Uns.push_back(y);
	}
	for (double x : xVals_min)
	{
		double y = interpolate(hourlyTime, cloudiness_LI, x, true);
		Cloadiness_Uns.push_back(y);
	}
	for (double x : xVals_min)
	{
		double y = interpolate(hourlyTime, windSp_LI, x, true);
		wndSpd_Uns.push_back(y);
	}
	for (double x : xVals_min)
	{
		double y = interpolate(hourlyTime, sedimentTime_LI, x, true);
		sedimentTime_LI_Uns.push_back(y);
	}
	for (double x : xVals_min)
	{
		double y = interpolate(hourlyTime, sedTemp_LI, x, true);
		sedTemp_Uns.push_back(y);
	}
	hyp_Slope_Uns.resize(TotalDist_stable);
	knownSectionCount = secDistance.size();
	vector<double> elevation_calc(knownSectionCount);
	vector<double> elevation_LI, elevation_Uns;
	elevation_calc[0] = elev_LI[0];
	for (int i = 1; i < knownSectionCount; i++)
	{
		elevation_calc[i] = elevation_calc[i - 1] - (secSlope[i - 1] * (secDistance[i] - secDistance[i - 1]));
	}
	for (double x : distMod)
	{
		double y = interpolate(secDistance, elevation_calc, x, true);
		elevation_LI.push_back(y);
	}

	int counter_unsteady = 0;
	for (int i = 0; i <= TotalDist_stable; i++)
	{
		Z_unsteady.push_back(Z_LI[counter_unsteady]);
		n_unsteady.push_back(n_s[counter_unsteady]);
		s_unsteady.push_back(secSlope_LI[counter_unsteady]); // Bed slope
		discharge_Unsteady.push_back(discharge_LI1[counter_unsteady]);
		BedTn_LI_Uns.push_back(BedTn_LI[counter_unsteady]);
		width_unsteady.push_back(secWidth_LI[counter_unsteady]);
		elevation_Uns.push_back(elevation_LI[counter_unsteady]);
		counter_unsteady = (counter_unsteady + dx_Interval_m) - 1;
		if (calculation == 3)
		{
			if (i == 0)
			{
				i = 1;
			}
			counter_unsteady = i * dx_Interval_m;
			if (counter_unsteady == ((TotalDist_stable - 1) * dx_Interval_m))
			{
				counter_unsteady--;
			}
		}
	}
	for (int i = 1; i < TotalDist_stable - 1; i++)
	{
		hyp_Slope_Uns[i] = (elevation_Uns[i - 1] - elevation_Uns[i]) / dx_Interval_m;
	}
	hyp_Slope_Uns[0] = hyp_Slope_Uns[1];

	////inflow_Temp & inflow_Discharge
	//inflow_Rate.resize(TotalDist_stable);
	//inflow_Temp.resize(TotalDist_stable);
	//for (int i = 0; i < TotalDist_stable; i++) {
	//	inflow_Rate[i].resize(TotalTime_min);
	//	inflow_Temp[i].resize(TotalTime_min);
	//}
	//int inflow_loc1 = locations[1] / dx_Interval_m;
	//int inflow_loc2 = locations[2] / dx_Interval_m;
	//for (int j = 0; j < TotalTime_min; j++) {
	//	inflow_Rate[inflow_loc1][j] = inflow_Q_2_min[j];
	//	inflow_Temp[inflow_loc1][j] = inflow_temp_2_temp[j];
	//	inflow_Rate[inflow_loc2][j] = inflow_Q_3_min[j];
	//	inflow_Temp[inflow_loc2][j] = inflow_temp_3_temp[j];
	//}

	Q_GW.resize(TotalDist_stable);
	Temp_GW.resize(TotalDist_stable);
	for (int i = 0; i < TotalDist_stable - 2; i++)
	{
		Q_GW[i] = discharge_Unsteady[i + 1] - discharge_Unsteady[i];
		if (Q_GW[i] < 0)
		{
			Q_GW[i] = Q_GW[i - 1];
		} // to avoid negative values caused by interpolation
	}
	Q_GW[TotalDist_stable - 2] = Q_GW[TotalDist_stable - 3];
	for (int i = 0; i < TotalDist_stable; i++)
	{
		if (i == 0)
		{
			Temp_GW[i] = sedimentDist_LI[i * dx_Interval_m];
		}
		else
		{
			Temp_GW[i] = sedimentDist_LI[(i * dx_Interval_m) - 1];
		}
	}

	//for (int i = 1; i <= TotalTime_min; i++) xVals_min.push_back((double)i);
	// Interpolate
	for (double x : xVals_min)
	{
		double y = interpolate(hourlyTime, SWreflVec, x, true);
		SWreflVec_Uns.push_back(y);
	}
	for (double x : xVals_min)
	{
		double y = interpolate(hourlyTime, SolAzimuth_LI, x, true);
		SolAzimuth_LI_Uns.push_back(y);
	}
	for (double x : xVals_min)
	{
		double y = interpolate(hourlyTime, SolAltitude_LI, x, true);
		SolAltitude_LI_Uns.push_back(y);
	}

	// SUBSTRATE CONDUCTION
	vector<double> conductivity, particleSize, embeddedness;
	vector<double> conductivity_LI, particleSize_LI, embeddedness_LI;
	//vector<string> BedSedType;
	for (int i = 0; i <= sedDataCount; i++)
	{
		conductivity.push_back(input->HorizontalBedConnectivity[i] / 1000); // to convert from mm/s to m/s
		particleSize.push_back(input->BedParticleSize[i]);
		embeddedness.push_back(input->Embeddedness[i]);
	}

	// Interpolate
	for (double x : distMod)
	{
		double y = interpolate(DistBedMeas, conductivity, x, true);
		conductivity_LI.push_back(y);
	}
	for (double x : distMod)
	{
		double y = interpolate(DistBedMeas, particleSize, x, true);
		particleSize_LI.push_back(y);
	}
	for (double x : distMod)
	{
		double y = interpolate(DistBedMeas, embeddedness, x, true);
		embeddedness_LI.push_back(y);
	}

	int counter_uns = 0;
	for (int i = 0; i < TotalDist_stable; i++)
	{
		conductivity_Uns.push_back(conductivity_LI[counter_uns]);
		particleSize_Uns.push_back(particleSize_LI[counter_uns]);
		embeddedness_Uns.push_back(embeddedness_LI[counter_uns]);

		counter_uns = (counter_uns + dx_Interval_m) - 1;
	}

	vector<double> Flux_Total_Time(TotalDist_stable);
	vector<double> Flux_Conduction_Time(TotalDist_stable);
	vector<double> Flux_Convection_Time(TotalDist_stable);
	vector<double> FLux_AtmLW_Time(TotalDist_stable);
	vector<double> Flux_Evaporation_Time(TotalDist_stable);
	vector<double> Flux_LCLW_Time(TotalDist_stable);
	vector<double> Flux_BackLW_Time(TotalDist_stable);
	vector<double> Flux_LW_Time(TotalDist_stable);
	vector<double> Flux_DirSW_Time(TotalDist_stable);
	vector<double> Flux_DiffSW_Time(TotalDist_stable);
	vector<double> Flux_SW_Time(TotalDist_stable);
	vector<double> Delta_T(TotalDist_stable);
	vector<double> depth_Uns_temp(TotalDist_stable);

	vector<double> Nodes_Uns;
	for (int i = 0; i < TotalDist_stable; i++)
	{
		Nodes_Uns.push_back(i * dx_Interval_m);
	}
	Nodes_Uns[0] = 1;

	cout << "Computing river node volumes, discharge, and groundwater inflow..." << endl;
	// ====================================================================================
	// STEP 1: compute volumes of each reservoir (node) in the model

	vector<vector<double>> volume(TotalDist, vector<double>(TotalTime));
	// set volume at first node
	// LAR Project
	if (calculation == 1) {
		for (int i = 0; i < TotalTime; i++) {
			volume[0][i] = (distMod[1] - distMod[0]) * area_total[0][i];
		}
		for (int i = 1; i < (TotalDist - 1); i++) {
			for (int j = 0; j < TotalTime; j++) {
				volume[i][j] = area_total[i][j] * (((distMod[i + 1] + distMod[i]) / 2) - ((distMod[i] + distMod[i - 1]) / 2));
			}
		}
		// set volume at last node
		for (int i = 0; i < TotalTime; i++) {
			volume[(nodes - 1)][i] = (distMod[(nodes - 1)] - distMod[(nodes - 2)]) * area_total[(nodes - 1)][i];
		}
	}
	// STEP 2: compute discharge rates at reservoir edges using linear
	//interpolation(n - values are upstream of node n values)

	vector<vector<double>> Q_half((TotalDist + 1), vector<double>(TotalTime));

	Q_half.resize(TotalDist + 1);
	for (int i = 0; i <= TotalDist; i++)
	{
		Q_half[i].resize(TotalTime);
	}

	// this 2D vector should have (nodes+1) row and TotalTime column
	// extrapolate backwards to get discharge rate at upstream edge of stream (half a node upstream from first node)
	for (int i = 0; i < TotalTime; i++)
	{
		Q_half[0][i] = (((2.0 * discharge_time[0][i]) - discharge_time[1][i]) + discharge_time[0][i]) / 2.0;
	}
	// linearly interpolate to get discharge rates at node boundaries
	for (int i = 1; i < TotalDist; i++)
	{
		for (int j = 0; j < TotalTime; j++)
		{
			Q_half[i][j] = (discharge_time[i][j] + discharge_time[(i - 1)][j]) / 2.0;
		}
	}
	// extrapolate forwards to get discharge rate at downstream edge of stream (half a node downstream from last node)
	for (int i = 0; i < TotalTime; i++)
	{
		Q_half[nodes][i] = (((2.0 * discharge_time[(nodes - 1)][i]) - discharge_time[(nodes - 2)][i]) + discharge_time[(nodes - 1)][i]) / 2.0;
	}

	// STEP 3: compute lateral groundwater discharge rates to each node based on longtudinal changes in streamflow
	vector<vector<double>> Q_L(TotalDist, vector<double>(TotalTime));
	for (int i = 0; i < TotalDist; i++)
	{
		for (int j = 0; j < TotalTime; j++)
		{
			Q_L[i][j] = Q_half[i + 1][j] - Q_half[i][j];
		}
	}

	// STEP 4: unit conversions so all discharge rates are in m3 / min;
	// note that all inputs are x are in m, T are in deg C, and Q or Q_L are in m3 / s

	vector<vector<double>> Q_half_min((TotalDist + 1), vector<double>(TotalTime));
	vector<vector<double>> Q_L_min(TotalDist, vector<double>(TotalTime));
	int TotalDist_dummy = 5;
	int TotalTime_dummy = 5;

	if ((calculation == 2) || (calculation == 4) || (calculation == 1))
	{
		//vector<vector<double>> Q_L_min(TotalDist, vector<double>(TotalTime));
		//vector<vector<double>> Q_half_min((TotalDist+1), vector<double>(TotalTime));
		Q_half_min.resize(TotalDist + 1);
		for (int i = 0; i < (TotalDist + 1); i++)
		{
			Q_half_min[i].resize(TotalTime);
		}
		Q_L_min.resize(TotalDist);
		for (int i = 0; i < TotalDist; i++)
		{
			Q_L_min[i].resize(TotalTime);
		}
		for (int i = 0; i < (TotalDist + 1); i++)
		{
			for (int j = 0; j < TotalTime; j++)
			{
				Q_half_min[i][j] = Q_half[i][j] * 60.0;
			}
		}
		for (int i = 0; i < TotalDist; i++)
		{
			for (int j = 0; j < TotalTime; j++)
			{
				Q_L_min[i][j] = Q_L[i][j] * 60.0;
			}
		}
	}
	else
	{
		//vector<vector<double>> Q_L_min(TotalDist_dummy, vector<double>(TotalTime_dummy));
		//vector<vector<double>> Q_half_min((TotalDist_dummy + 1), vector<double>(TotalTime_dummy));

		Q_half_min.resize(TotalDist_dummy + 1);
		for (int i = 0; i < (TotalDist_dummy + 1); i++)
		{
			Q_half_min[i].resize(TotalTime_dummy);
		}
		Q_L_min.resize(TotalDist_dummy);
		for (int i = 0; i < TotalDist_dummy; i++)
		{
			Q_L_min[i].resize(TotalTime_dummy);
		}
		for (int i = 0; i < (TotalDist_dummy + 1); i++)
		{
			for (int j = 0; j < TotalTime_dummy; j++)
			{
				Q_half_min[i][j] = Q_half[i][j] * 60.0;
			}
		}
		for (int i = 0; i < TotalDist_dummy; i++)
		{
			for (int j = 0; j < TotalTime_dummy; j++)
			{
				Q_L_min[i][j] = Q_L[i][j] * 60.0;
			}
		}
	}

	//Note: Consider refactor needed to introduce Hyporheic Exchange for calculation method 1
	/*
	if (calculation == 1) {
		dx_Interval_m = pm->get_dx();
		dx_Interval_m = pm->get_dx();
		TotalDist_stable = (TotalDist / dx_Interval_m);
		HyporheicExchange_CN.resize(TotalDist_stable);
		//wp_total.resize(TotalDist_stable);
		for (int i = 0; i < TotalDist_stable; i++) {
			HyporheicExchange_CN[i].resize(TotalTime);
			wp_total[i].resize(TotalTime);
			for (int i = 0; i < TotalDist_stable; i++) {
				for (int j = 0; j < TotalTime; j++) {
					// Ratio Conductivity of dominant substrate
					Dummy3 = conductivity_Uns[i] * (1.0 - embeddedness_Uns[i]);
					// Ratio Conductivity of sand - low range
					Dummy4 = 0.01 * embeddedness_Uns[i];
					// True horizontal conductivity (m / s)
					HorCond1 = Dummy3 + Dummy4;

					// Ratio Size of dominant substrate
					Dummy3 = particleSize_Uns[i] * (1.0 - embeddedness_Uns[i]);
					// Ratio Conductivity of sand - low range
					Dummy4 = 0.062 * embeddedness_Uns[i];
					// Estimated Porosity
					//Porosity[TotalDist_stable][t] = 0.3683 * pow((Dummy1 + Dummy2), (-0.0641));

					// Calculate head at top(ho) and bottom(hL) of reach
					double ho, hL;
					if (flag_BC == 1) {
						ho = hyp_Slope_Uns[i] * dx_Interval_m;
						hL = 0;
					}
					else {
						ho = depth_total[i - 1][1] + hyp_Slope_Uns[i] * dx_Interval_m;
						hL = depth_total[i][1];
					}

					// Calculate Hyporheic Flows

					HyporheicExchange_CN[i][j] = abs(wp_total[i][j] * HorCond1 * (pow(ho, 2.0) - pow(hL, 2.0)) / (2.0 * dx_Interval_m));
					HyporheicExchange_CN[i][j] = hyp_Slope_Uns[i] * wp_total[i][j] * HorCond1 * (ho - hL);
					//if (HyporheicExchange_CN[i][j] > Q[1][i]) {
					  //  HyporheicExchange_CN[i][j] = Q[1][i];
				   // }
				}
			}
		}
	}
	*/

	if (calculation == 1) {
		cout << "Numerical method: Crank-Nicolson..." << endl;
	}
	if (calculation == 2) {
		cout << "Numerical method: Finite Difference..." << endl;
	}
	if (calculation == 3) {
		cout << "Numerical method: HEC-RAS coupling..." << endl;
	}
	if (calculation == 4) {
		cout << "Numerical method: Runge-Kutta..." << endl;
	}

	// ====================================================================================================================
	// Applying the HecRas outputs as the input data as an alternative for calculating the temperature on steady flow state
	// Jan. 18
	// First, reading in the input data from the HecRasData file

	//int	HeatTime = 0;
	//int	TravelTime = 0;
	int Rotation = 0;
	// Periodic Boundary Condition
	int PBC_On = input->CoolRiverVariables["CR_PBC"];

	int HecRasCount = input->getCount();
	vector<double> dist_HR, Q_HR, MinChElev_HR, WSElev_HR, VelChnl_HR, FlowArea_HR, TopWidth_HR, WSSlope_HR, WP_HR;

	for (int i = 0; i < HecRasCount; i++)
	{
		double temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
		temp1 = input->downStreamDist[i] * 1000; // To convert form km to m
		temp2 = input->totalQ[i];
		temp3 = input->chElev[i];
		temp3 = input->chElev[i];
		temp4 = input->waterSurElev[i];
		temp5 = input->velChnl[i];
		temp6 = input->xArea[i];
		temp7 = input->topWidth[i];
		temp8 = input->waterSurSlope[i];
		temp9 = input->wettedPerimeter[i];

		dist_HR.push_back(temp1);
		Q_HR.push_back(temp2);
		MinChElev_HR.push_back(temp3);
		WSElev_HR.push_back(temp4);
		VelChnl_HR.push_back(temp5);
		FlowArea_HR.push_back(temp6);
		TopWidth_HR.push_back(temp7);
		WSSlope_HR.push_back(temp8);
		WP_HR.push_back(temp9);
	}

	// Interpolating the input data
	for (double x : distMod)
	{
		double y = interpolate(dist_HR, Q_HR, x, true);
		Q_HR_LI.push_back(y);
	}
	for (double x : distMod)
	{
		double y = interpolate(dist_HR, MinChElev_HR, x, true);
		MinChElev_HR_LI.push_back(y);
	}
	for (double x : distMod)
	{
		double y = interpolate(dist_HR, WSElev_HR, x, true);
		WSElev_HR_LI.push_back(y);
	}
	for (double x : distMod)
	{
		double y = interpolate(dist_HR, VelChnl_HR, x, true);
		VelChnl_HR_LI.push_back(y);
	}
	for (double x : distMod)
	{
		double y = interpolate(dist_HR, FlowArea_HR, x, true);
		FlowArea_HR_LI.push_back(y);
	}
	for (double x : distMod)
	{
		double y = interpolate(dist_HR, TopWidth_HR, x, true);
		TopWidth_HR_LI.push_back(y);
	}
	for (double x : distMod)
	{
		double y = interpolate(dist_HR, WSSlope_HR, x, true);
		WSSlope_HR_LI.push_back(y);
	}
	for (double x : distMod)
	{
		double y = interpolate(dist_HR, WP_HR, x, true);
		WP_HR_LI.push_back(y);
	}

	dtime_Interval_min = input->CoolRiverVariables["CR_interval_dt"];
	int PBC_loopNR = input->CoolRiverVariables["CR_PBC_loopNR"] * 60;
	PBC_loopNR = PBC_loopNR * (60.0 / dtime_Interval_min);
	vector<double> inflow_T0_HR;

	Q_Inflow_HR.resize(TotalDist_stable);
	T_Inflow_HR.resize(TotalDist_stable);
	for (int i = 0; i < TotalDist_stable; i++)
	{
		Q_Inflow_HR[i].resize(TotalTime);
		T_Inflow_HR[i].resize(TotalTime);
	}
	for (int j = 0; j < TotalTime; j++)
	{
		for (int i = 0; i < locations.size(); i++) {
			Q_Inflow_HR[locations.at(i) / dx_Interval_m][j] = inflow_Discharge[locations.at(i)][j];
			T_Inflow_HR[locations.at(i) / dx_Interval_m][j] = inflow_Temp[locations.at(i)][j];
		}
	}
	// ======================================================

	// START - LOAD MODEL VARIABLES & SETUP INITAL CONDITIONS
	cout << "Obtaining boundary and initial conditions..." << endl;

	DeltaT_HR.resize(TotalDist_stable);

	// Finite difference target sections

	int TotalDist_stable_HR = TotalDist_stable - 1;

	Porosity.resize(TotalDist_stable);
	for (int i = 0; i < TotalDist_stable; i++)
		Porosity[i].resize(TotalTime_min);

	int TotalTime_min_HR = 0;
	int TotalTime_HR = 0;
	int TotalDist_HR = 0;
	if (calculation == 3)
	{
		//TotalTime_min_HR = TotalTime_min;
		TotalTime_HR = TotalTime;
		TotalDist_HR = TotalDist;
		Porosity.resize(TotalDist_stable);
		for (int i = 0; i < TotalDist_stable; i++)
			Porosity[i].resize(TotalTime_HR);
	}
	else
	{
		TotalTime_min_HR = 1;
		TotalDist_HR = 1;
	}

	FluxTotal_HR.resize(TotalDist_stable);
	DeltaTotal_HR.resize(TotalDist_stable);
	HeatFluxADR_Temperature_C.resize(TotalDist_stable);
	DepthALL_HR.resize(TotalDist_stable);
	DepthAvgALL_HR.resize(TotalDist_stable);
	AreaALL_HR.resize(TotalDist_stable);
	VelocityALL_HR.resize(TotalDist_stable);
	WidthALL_HR.resize(TotalDist_stable);
	HeatFluxRetentionTime_p_dt.resize(TotalDist_stable);
	Pw_ALL_HR.resize(TotalDist_stable);
	WSElev_ALL_HR.resize(TotalDist_stable);
	Q_Str_HR.resize(TotalDist_stable);
	HyporheicExchange_HR.resize(TotalDist_stable);
	Dispersion_HR.resize(TotalDist_stable);
	FluxConduction_HR.resize(TotalDist_stable);
	for (int i = 0; i < TotalDist_stable; i++)
	{
		FluxTotal_HR[i].resize(TotalTime_HR);
		DeltaTotal_HR[i].resize(TotalTime_HR);
		HeatFluxADR_Temperature_C[i].resize(TotalTime_HR);
		DepthALL_HR[i].resize(TotalTime_HR);
		DepthAvgALL_HR[i].resize(TotalTime_HR);
		AreaALL_HR[i].resize(TotalTime_HR);
		VelocityALL_HR[i].resize(TotalTime_HR);
		WidthALL_HR[i].resize(TotalTime_HR);
		HeatFluxRetentionTime_p_dt[i].resize(TotalTime_HR);
		Pw_ALL_HR[i].resize(TotalTime_HR);
		WSElev_ALL_HR[i].resize(TotalTime_HR);
		Q_Str_HR[i].resize(TotalTime_HR);
		HyporheicExchange_HR[i].resize(TotalTime_HR);
		Dispersion_HR[i].resize(TotalTime_HR);
		FluxConduction_HR[i].resize(TotalTime_HR);
	}

	Flux_Evaporation_HR.resize(TotalDist_HR);
	Flux_Conduction_HR.resize(TotalDist_HR);
	Flux_Convection_HR.resize(TotalDist_HR);
	FLux_AtmLW_HR.resize(TotalDist_HR);
	Flux_LCLW_HR.resize(TotalDist_HR);
	Flux_BackLW_HR.resize(TotalDist_HR);
	Flux_LW_HR.resize(TotalDist_HR);
	Flux_DirSW_HR.resize(TotalDist_HR);
	Flux_DiffSW_HR.resize(TotalDist_HR);
	Flux_SW_HR.resize(TotalDist_HR);
	Flux_Total_HRdist.resize(TotalDist_HR);
	Temp_HRdist.resize(TotalDist_HR);
	for (int i = 0; i < TotalDist_HR; i++)
	{
		Flux_Evaporation_HR[i].resize(TotalTime_HR);
		Flux_Conduction_HR[i].resize(TotalTime_HR);
		Flux_Convection_HR[i].resize(TotalTime_HR);
		FLux_AtmLW_HR[i].resize(TotalTime_HR);
		Flux_LCLW_HR[i].resize(TotalTime_HR);
		Flux_BackLW_HR[i].resize(TotalTime_HR);
		Flux_LW_HR[i].resize(TotalTime_HR);
		Flux_DirSW_HR[i].resize(TotalTime_HR);
		Flux_DiffSW_HR[i].resize(TotalTime_HR);
		Flux_SW_HR[i].resize(TotalTime_HR);
		Flux_Total_HRdist[i].resize(TotalTime_HR);
		Temp_HRdist[i].resize(TotalTime_HR);
	}

	Flux_Evaporation_Nodes.resize(TotalDist_stable);
	Flux_Conduction_Nodes.resize(TotalDist_stable);
	Flux_Convection_Nodes.resize(TotalDist_stable);
	FLux_AtmLW_Nodes.resize(TotalDist_stable);
	Flux_LCLW_Nodes.resize(TotalDist_stable);
	Flux_BackLW_Nodes.resize(TotalDist_stable);
	Flux_LW_Nodes.resize(TotalDist_stable);
	Flux_DirSW_Nodes.resize(TotalDist_stable);
	Flux_DiffSW_Nodes.resize(TotalDist_stable);
	Flux_SW_Nodes.resize(TotalDist_stable);
	for (int i = 0; i < (TotalDist_stable); i++)
	{
		Flux_Evaporation_Nodes[i].resize(TotalTime_HR);
		Flux_Conduction_Nodes[i].resize(TotalTime_HR);
		Flux_Convection_Nodes[i].resize(TotalTime_HR);
		FLux_AtmLW_Nodes[i].resize(TotalTime_HR);
		Flux_LCLW_Nodes[i].resize(TotalTime_HR);
		Flux_BackLW_Nodes[i].resize(TotalTime_HR);
		Flux_LW_Nodes[i].resize(TotalTime_HR);
		Flux_DirSW_Nodes[i].resize(TotalTime_HR);
		Flux_DiffSW_Nodes[i].resize(TotalTime_HR);
		Flux_SW_Nodes[i].resize(TotalTime_HR);
	}

	calcT_Temp.resize(TotalDist_stable);

	// ======================================================

	int distanceHR = TotalDist;
	vector<double> Hec_Dist;
	int counterHR = 0;

	if (calculation == 3)
	{
		for (int i = 0; i < TotalTime; i++)
		{

			while (distanceHR > 0)
			{
				Hec_Dist.push_back(TotalDist - distanceHR);

				WidthALL_HR[counterHR][i] = TopWidth_HR_LI[counterHR * dx_Interval_m];
				DepthALL_HR[counterHR][i] = WSElev_HR_LI[counterHR * dx_Interval_m] - MinChElev_HR_LI[counterHR * dx_Interval_m];
				DepthAvgALL_HR[counterHR][i] = FlowArea_HR_LI[counterHR * dx_Interval_m] / TopWidth_HR_LI[counterHR * dx_Interval_m];
				Q_Str_HR[counterHR][i] = Q_HR_LI[counterHR * dx_Interval_m];
				VelocityALL_HR[counterHR][i] = VelChnl_HR_LI[counterHR * dx_Interval_m];
				AreaALL_HR[counterHR][i] = FlowArea_HR_LI[counterHR * dx_Interval_m];
				HeatFluxRetentionTime_p_dt[counterHR][i] = dx_Interval_m / VelChnl_HR_LI[counterHR * dx_Interval_m];
				//Pw_ALL_HR[counterHR][i] = secWidth_LI[counterHR * dx_Interval_m] + 2.0 * DepthALL_HR[counterHR][0] * sqrt(1.0 + pow(Z_LI[counterHR * dx_Interval_m], 2.0));
				Pw_ALL_HR[counterHR][i] = WP_HR_LI[counterHR * dx_Interval_m];
				WSElev_ALL_HR[counterHR][i] = WSElev_HR_LI[counterHR * dx_Interval_m] + (WSSlope_HR_LI[counterHR * dx_Interval_m] * ((TotalDist - distanceHR) - Hec_Dist[counterHR]));

				distanceHR = distanceHR - dx_Interval_m;
				counterHR++;
			}
			distanceHR = TotalDist;
			Hec_Dist.resize(0);
			counterHR = 0;
		}
	}

	// ================== SW calculation condition
	SolvingMethod = input->CoolRiverVariables["CR_SWMethod"];
	if (SolvingMethod == 1) {
		cout << endl << "Solving radiation flux based on sky view and bank factors..." << endl;
	}
	if (SolvingMethod == 2) {
		cout << "Solving radiation flux based on shade factors..." << endl;
	}
	// =============================================
	SedimentMethod = input->CoolRiverVariables["CR_Sediment_method"];
	if (SedimentMethod == 1) {
		cout << "Solving sediment flux based on RBM model..." << endl;
	}
	if (SedimentMethod == 2) {
		cout << "Solving sediment flux based on Heat Source model..." << endl;
	}
	// For the Crank-Nicolson method
	int TotalDist_CN = 0;
	int TotalTime_CN = 0;
	int TotalTime_CN_Uns = 0;
	if (calculation == 1) {
		TotalDist_CN = TotalDist;
		TotalTime_CN = TotalTime;
		TotalTime_Uns_CN = TotalTime * 60;
	}
	else {
		TotalDist_CN = 1;
		TotalTime_CN = 1;
	}
	SWDir_2D.resize(TotalDist_CN);
	SWDiff_2D.resize(TotalDist_CN);
	SW_2D.resize(TotalDist_CN);
	atmLW_2D.resize(TotalDist_CN);
	LCLW_2D.resize(TotalDist_CN);
	backLW_2D.resize(TotalDist_CN);
	LW_2D.resize(TotalDist_CN);
	Latent_2D.resize(TotalDist_CN);
	Sensible_2D.resize(TotalDist_CN);
	Bed_2D.resize(TotalDist_CN);
	heat_flux_2D.resize(TotalDist_CN);
	for (int i = 0; i < TotalDist_CN; i++)
	{
		SWDir_2D[i].resize(TotalTime_CN);
		SWDiff_2D[i].resize(TotalTime_CN);
		SW_2D[i].resize(TotalTime_CN);
		atmLW_2D[i].resize(TotalTime_CN);
		LCLW_2D[i].resize(TotalTime_CN);
		backLW_2D[i].resize(TotalTime_CN);
		LW_2D[i].resize(TotalTime_CN);
		Latent_2D[i].resize(TotalTime_CN);
		Sensible_2D[i].resize(TotalTime_CN);
		Bed_2D[i].resize(TotalTime_CN);
		heat_flux_2D[i].resize(TotalTime_CN);
	}
	// ANALYSING THE ENTERIOR RESULTS AND VECTOR - REZA
	vector<vector<double>> a_c(TotalDist_CN, vector<double>(TotalTime_CN));
	vector<vector<double>> b_c(TotalDist_CN, vector<double>(TotalTime_CN));
	vector<vector<double>> c_c(TotalDist_CN, vector<double>(TotalTime_CN));
	vector<vector<double>> o(TotalDist_CN, vector<double>(TotalTime_CN));
	vector<vector<double>> p(TotalDist_CN, vector<double>(TotalTime_CN)); // intermediate matrices to get b
	vector<vector<double>> q(TotalDist_CN, vector<double>(TotalTime_CN));
	vector<vector<double>> o_c(TotalDist_CN, vector<double>(TotalTime_CN));
	vector<vector<double>> p_c(TotalDist_CN, vector<double>(TotalTime_CN));
	vector<vector<double>> q_c(TotalDist_CN, vector<double>(TotalTime_CN));
	vector<vector<double>> d(TotalDist_CN, vector<double>(TotalTime_CN));
	vector<vector<double>> g(TotalDist_CN, vector<double>(TotalTime_CN)); // Pre - allocate g, k, and m arrays
	vector<vector<double>> k(TotalDist_CN, vector<double>(TotalTime_CN));
	vector<vector<double>> m(TotalDist_CN, vector<double>(TotalTime_CN));
	vector<vector<double>> A(TotalDist_CN, vector<double>(TotalDist_CN + 1)); // the last column is for Solving linear equations with Gaussian elimination
	vector<vector<double>> a(TotalDist_CN, vector<double>(TotalTime_CN));
	vector<vector<double>> b(TotalDist_CN, vector<double>(TotalTime_CN));
	vector<vector<double>> c(TotalDist_CN, vector<double>(TotalTime_CN));

	// ===================================================================

	// required for Crank-Nicolson method
	int startingHour = input->CoolRiverVariables["startingHour"];

	double initialT = inflow_Temp.at(locations.at(0)).at(0); // set initial temperature condition
	//int TotalTimeMin = TotalTime * 60;

	vector<int> timeRepeatedHour;
	vector<double> initialT_T0(TotalDist);

	//required for Runge-Kutta method
	int TotalDist_RK = 0;
	int TotalTime_RK = 0;
	if (calculation == 4)
	{
		TotalDist_RK = TotalDist;
		TotalTime_RK = TotalTime;
	}
	else
	{
		TotalDist_RK = 1;
		TotalTime_RK = 1;
	}
	vector<vector<double>> T_k1(TotalDist_RK, vector<double>(TotalTime_RK)); // pre-allocate arrays for temperature at intermediate times
	vector<vector<double>> heat_flux_k1(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> heat_flux_k2(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> u1(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> v1(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> s1(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> m1(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> k1(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> u2(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> v2(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> s2(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> m2(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> k2(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> SWDir_2D_k2(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> SWDiff_2D_k2(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> SW_2D_k2(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> atmLW_2D_k2(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> LCLW_2D_k2(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> backLW_2D_k2(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> LW_2D_k2(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> Latent_2D_k2(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> Sensible_2D_k2(TotalDist_RK, vector<double>(TotalTime_RK));
	vector<vector<double>> Bed_2D_k2(TotalDist_RK, vector<double>(TotalTime_RK));

	int TotalDist_FD = 0;
	int TotalTime_FD = 0;
	if (calculation == 2)
	{
		TotalDist_FD = TotalDist;
		TotalTime_FD = TotalTime;
		TotalTime_Uns_FD = TotalTime * 60;
	}
	else
	{
		TotalDist_FD = 1;
		TotalTime_FD = 1;
		TotalTime_Uns_FD = 1;
	}

	Flux_Total.resize(TotalDist_FD);
	Flux_Conduction.resize(TotalDist_FD);
	Flux_Evaporation.resize(TotalDist_FD);
	Flux_Convection.resize(TotalDist_FD);
	FLux_AtmLW.resize(TotalDist_FD);
	Flux_LCLW.resize(TotalDist_FD);
	Flux_BackLW.resize(TotalDist_FD);
	Flux_LW.resize(TotalDist_FD);
	Flux_DirSW.resize(TotalDist_FD);
	Flux_DiffSW.resize(TotalDist_FD);
	Flux_SW.resize(TotalDist_FD);
	T_Uns.resize(TotalDist_FD);
	Pw_unsteady1.resize(TotalDist_FD);
	width_UnsTotal1.resize(TotalDist_FD);
	depth_AvgUns1.resize(TotalDist_FD);
	Hyporheic_Exchange1.resize(TotalDist_FD);
	Rh_unsteady1.resize(TotalDist_FD);
	depth_Uns.resize(TotalDist_FD);
	for (int i = 0; i < TotalDist_FD; i++)
	{
		Flux_Total[i].resize(TotalTime_Uns_FD);
		Flux_Conduction[i].resize(TotalTime_Uns_FD);
		Flux_Evaporation[i].resize(TotalTime_Uns_FD);
		Flux_Convection[i].resize(TotalTime_Uns_FD);
		FLux_AtmLW[i].resize(TotalTime_Uns_FD);
		Flux_LCLW[i].resize(TotalTime_Uns_FD);
		Flux_BackLW[i].resize(TotalTime_Uns_FD);
		Flux_LW[i].resize(TotalTime_Uns_FD);
		Flux_DirSW[i].resize(TotalTime_Uns_FD);
		Flux_DiffSW[i].resize(TotalTime_Uns_FD);
		Flux_SW[i].resize(TotalTime_Uns_FD);
		T_Uns[i].resize(TotalTime_Uns_FD);
		Pw_unsteady1[i].resize(TotalTime_Uns_FD);
		width_UnsTotal1[i].resize(TotalTime_Uns_FD);
		Hyporheic_Exchange1[i].resize(TotalTime_Uns_FD);
		depth_AvgUns1[i].resize(TotalTime_Uns_FD);
		Rh_unsteady1[i].resize(TotalTime_Uns_FD);
		depth_Uns[i].resize(TotalTime_Uns_FD);
	}

	hour_Flux_Total.resize(TotalDist_stable);
	hour_Flux_Conduction.resize(TotalDist_stable);
	hour_Flux_Evaporation.resize(TotalDist_stable);
	hour_Flux_Convection.resize(TotalDist_stable);
	hour_FLux_AtmLW.resize(TotalDist_stable);
	hour_Flux_LCLW.resize(TotalDist_stable);
	hour_Flux_BackLW.resize(TotalDist_stable);
	hour_Flux_LW.resize(TotalDist_stable);
	hour_Flux_DirSW.resize(TotalDist_stable);
	hour_Flux_DiffSW.resize(TotalDist_stable);
	hour_Flux_SW.resize(TotalDist_stable);
	hour_T_Uns.resize(TotalDist_stable);
	hour_depth_Uns.resize(TotalDist_stable);
	hour_Pw_unsteady.resize(TotalDist_stable);
	hour_width_UnsTotal.resize(TotalDist_stable);
	hour_depth_AvgUns.resize(TotalDist_stable);
	hour_Hyporheic_Exchange.resize(TotalDist_stable);
	hour_Rh_unsteady.resize(TotalDist_stable);
	for (int i = 0; i < TotalDist_stable; i++)
	{
		hour_Flux_Total[i].resize(TotalTime);
		hour_Flux_Conduction[i].resize(TotalTime);
		hour_Flux_Evaporation[i].resize(TotalTime);
		hour_Flux_Convection[i].resize(TotalTime);
		hour_FLux_AtmLW[i].resize(TotalTime);
		hour_Flux_LCLW[i].resize(TotalTime);
		hour_Flux_BackLW[i].resize(TotalTime);
		hour_Flux_LW[i].resize(TotalTime);
		hour_Flux_DirSW[i].resize(TotalTime);
		hour_Flux_DiffSW[i].resize(TotalTime);
		hour_Flux_SW[i].resize(TotalTime);
		hour_T_Uns[i].resize(TotalTime);
		hour_depth_Uns[i].resize(TotalTime);
		hour_depth_Uns[i].resize(TotalTime);
		hour_Pw_unsteady[i].resize(TotalTime);
		hour_width_UnsTotal[i].resize(TotalTime);
		hour_depth_AvgUns[i].resize(TotalTime);
		hour_Hyporheic_Exchange[i].resize(TotalTime);
		hour_Rh_unsteady[i].resize(TotalTime);
	}

	int counterSec = 0;
	int counterWriter = 0;
	int counterHourly = 0;
	int minCounter = 60 / dtime_Interval_min;
	// Calculating the sky view factors for the East and West banks and the magnitude of the TSA, VSA & BSA
	skyViewE();
	skyViewW();

	switch (calculation) {
		case 1: {
			vector<vector<double>>().swap(T_k1);
			vector<vector<double>>().swap(heat_flux_k1);
			vector<vector<double>>().swap(heat_flux_k2);
			vector<vector<double>>().swap(u1);
			vector<vector<double>>().swap(v1);
			vector<vector<double>>().swap(s1);
			vector<vector<double>>().swap(m1);
			vector<vector<double>>().swap(k1);
			vector<vector<double>>().swap(u2);
			vector<vector<double>>().swap(v2);
			vector<vector<double>>().swap(s2);
			vector<vector<double>>().swap(m2);
			vector<vector<double>>().swap(k2);
			vector<vector<double>>().swap(SWDir_2D_k2);
			vector<vector<double>>().swap(SWDiff_2D_k2);
			vector<vector<double>>().swap(SW_2D_k2);
			vector<vector<double>>().swap(atmLW_2D_k2);
			vector<vector<double>>().swap(LCLW_2D_k2);
			vector<vector<double>>().swap(backLW_2D_k2);
			vector<vector<double>>().swap(LW_2D_k2);
			vector<vector<double>>().swap(Latent_2D_k2);
			vector<vector<double>>().swap(Sensible_2D_k2);
			vector<vector<double>>().swap(Bed_2D_k2);

			// STEP 5 : Calculate coefficients of the tridiagonal matrix(a, b, c)
			//  and set coefficients at the boundaries. Use a, b and c to create the A matrix.
			//   Note that a, b and c are constant in time as long as Q, volume, and Q_L are constant with time.
			//   ===================> Solving the Crank-Nicolson method
			// coefficient matrices
			// pieces of equation for the future temperature

			// increment a counter each time assembly executes
			static long long cn_assemble_calls = 0;
			++cn_assemble_calls;

			for (int i = 0; i < TotalDist; i++) {
				for (int j = 0; j < (TotalTime - 1); j++) {
					a[i][j] = (-dt * Q_half_min[i][j + 1]) / (4.0 * volume[i][0]);	// sub-diagonal: coefficients of Tn - 1
					o[i][j] = (dt * Q_half_min[i][j + 1]) / ((4.0 * volume[i][0])); // intermediate steps to get b
					p[i][j] = (dt * Q_half_min[i + 1][j + 1]) / ((4.0 * volume[i][0]));
					q[i][j] = (dt * Q_L_min[i][j + 1]) / ((2.0 * volume[i][0]));
					b[i][j] = 1.0 + o[i][j] - p[i][j] + q[i][j];					// diagonal: coefficients of Tn
					c[i][j] = (dt * Q_half_min[i + 1][j + 1]) / (4 * volume[i][0]); // super-diagonal: coefficients of Tn+1
				}
				// for last values since we don't know the future we just reuse the last known
				a[i][TotalTime - 1] = (-dt * Q_half_min[i][TotalTime - 1]) / (4.0 * volume[i][0]); // sub-diagonal: coefficients of Tn-1
				o[i][TotalTime - 1] = (dt * Q_half_min[i][TotalTime - 1]) / ((4.0 * volume[i][0]));
				p[i][TotalTime - 1] = (dt * Q_half_min[i + 1][TotalTime - 1]) / ((4.0 * volume[i][0]));
				q[i][TotalTime - 1] = (dt * Q_L_min[i][TotalTime - 1]) / ((2.0 * volume[i][0]));
				b[i][TotalTime - 1] = 1.0 + o[i][TotalTime - 1] - p[i][TotalTime - 1] + q[i][TotalTime - 1];	  // diagonal: coefficients of Tn
				c[i][TotalTime - 1] = (dt * Q_half_min[i + 1][TotalTime - 1]) / (4.0 * volume[i][TotalTime - 1]); // super-diagonal: coefficients of Tn+1
			}
			// pieces of equation for the current temperature to make d(new)
			for (int i = 0; i < TotalDist; i++) {
				for (int j = 0; j < TotalTime; j++) {
					a_c[i][j] = (-dt * Q_half_min[i][j]) / (4 * volume[i][0]);	// sub-diagonal: coefficients of Tn - 1
					o_c[i][j] = (dt * Q_half_min[i][j]) / ((4 * volume[i][0])); // intermediate steps to get b
					p_c[i][j] = (dt * Q_half_min[i + 1][j]) / ((4 * volume[i][0]));
					q_c[i][j] = (dt * Q_L_min[i][j]) / ((2 * volume[i][0]));
					b_c[i][j] = 1.0 + o_c[i][j] - p_c[i][j] + q_c[i][j];		  // diagonal: coefficients of Tn
					c_c[i][j] = (dt * Q_half_min[i + 1][j]) / (4 * volume[i][0]); // super-diagonal: coefficients of Tn+1
				}
			}

			// STEP 6: Calculate right hand side(d).
			// The values for d are temperature - dependent, so they change each time step.
			// Once d is computed, use that d value and the
			// matrix A to solve for the temperature for each time step.



			// set temperatures for first time step at input values
			T.resize(TotalDist);
			for (int i = 0; i < TotalDist; i++) {
				T[i].resize(TotalTime);
				T[i][0] = initialT;
			}
			for (int i = 0; i < TotalDist; i++) {
				initialT_T0[i] = initialT;
			}

			// Shortwave calculation for the first time step:
			solarReflectivity();

			adjustedDirRadE(solarSW_Dir_LI, 0);	  // preparing the adjustedDirSW_E vector
			adjustedDirRadW(solarSW_Dir_LI, 0);	  // preparing the adjustedDirSW_W vector
			netSolarDiffRadE(solarSW_Diff_LI, 0); // preparing the adjustedDiffSW_E vector
			netSolarDiffRadW(solarSW_Diff_LI, 0); // preparing the adjustedDiffSW_W vector

			// Insert values for first time step.
			for (int i = 0; i < TotalDist; i++) {
				if (hourList_LI[0] >= 0 && hourList_LI[0] < 12) {
					SWDir_2D[i][0] = adjustedDirSW_E[i];
					SWDiff_2D[i][0] = adjustedDiffSW_E[i];
				}
				else {
					SWDir_2D[i][0] = adjustedDirSW_W[i];
					SWDiff_2D[i][0] = adjustedDiffSW_W[i];
				}
				SW_2D[i][0] = SWDir_2D[i][0] + SWDiff_2D[i][0];
			}

			// Longwave radiation for the first time step
			longWaveRadiation(airTemp_LI_C, real_humidity_LI, cloudiness_LI, initialT_T0, 0);
			// latent heat in the fist time step
			latentHeat(airTemp_LI_C, real_humidity_LI, initialT_T0, windSp_LI, 0);
			// Sensible heat for the first time step
			sensibleHeat(airTemp_LI_C, initialT_T0, windSp_LI, real_humidity_LI, 0);
			// Stream Bed heat for the first time step
			bedSediment(wp_total, width_total, K_sedType_LI, initialT_T0, sedimentTime_LI, BedDepthMeas_LI, 0);

			//// Insert values for first time step.
			for (int i = 0; i < TotalDist; i++) {
				heat_flux_2D[i][0] = (SW_2D[i][0] + LW_2D[i][0] + Latent_2D[i][0] + Sensible_2D[i][0] + Bed_2D[i][0]) * 60;
			}

			for (int i = 0; i < TotalDist; i++) {
				for (int j = 0; j < TotalTime; j++) {
					g[i][j] = 1.0 + a_c[i][j] + c_c[i][j] - q_c[i][j];
					if (Q_L_min[i][j] < 0) {
						k[i][j] = 0;
					}
					else {
						k[i][j] = ((dt * Q_L_min[i][j]) / volume[i][j]);
					}
				}
			}

			// ========================== main calculations ======================
			//For timeStep to TotalTime
			for (int timeStep = 0; timeStep < TotalTime - 1; ++timeStep) {

				//timeStep_next = timeStep + 1
				const int timeStep_next = timeStep + 1; 

				//Flor i to TotalDist build m[i][timeStep]
				for (int i = 0; i < TotalDist; ++i) {
					m[i][timeStep] = (dt * (width_total[i][timeStep] * heat_flux_2D[i][timeStep])
						/ (rho_water * c_water) / area_total[i][timeStep]);
				}

				// ---- Build RHS d[*, timeStep] ----
				// Upper boundary (i = 0)
				d[0][timeStep] =
					(g[0][timeStep] * T[0][timeStep])
					+ (o_c[0][timeStep] * obs_xo_LI[timeStep])
					- (p_c[0][timeStep] * T[1][timeStep])
					+ (k[0][timeStep] * sedimentDist_LI[0])
					+ m[0][timeStep]
					- (a_c[0][timeStep] * obs_xo_LI[timeStep + 1]);

				// Interior
				for (int i = 1; i < TotalDist - 1; ++i) {
					d[i][timeStep] =
						(g[i][timeStep] * T[i][timeStep])
						+ (o_c[i][timeStep] * T[i - 1][timeStep])
						- (p_c[i][timeStep] * T[i + 1][timeStep])
						+ (k[i][timeStep] * sedimentDist_LI[i])
						+ m[i][timeStep];
				}

				// Lower boundary (i = TotalDist - 1), your Neumann form
				d[TotalDist - 1][timeStep] =
					(g[TotalDist - 1][timeStep] * T[TotalDist - 1][timeStep])
					+ (o_c[TotalDist - 1][timeStep] * T[TotalDist - 2][timeStep])
					- (p_c[TotalDist - 1][timeStep] * T[TotalDist - 1][timeStep])
					+ (k[TotalDist - 1][timeStep] * sedimentDist_LI[TotalDist - 1])
					+ m[TotalDist - 1][timeStep];

				// ---- Build tri-diagonal slices for THIS time step ----
				vector<double> sub(TotalDist, 0.0), diag(TotalDist, 0.0), sup(TotalDist, 0.0);
				vector<double> rhs(TotalDist, 0.0), x_local;

				// First row
				diag[0] = b[0][timeStep];
				sup[0] = c[0][timeStep];
				rhs[0] = d[0][timeStep];

				// Interior rows
				for (int i = 1; i < TotalDist - 1; ++i) {
					sub[i] = a[i][timeStep];
					diag[i] = b[i][timeStep];
					sup[i] = c[i][timeStep];
					rhs[i] = d[i][timeStep];
				}

				// Last row (fold super-diagonal into diagonal for Neumann)
				sub[TotalDist - 1] = a[TotalDist - 1][timeStep];
				diag[TotalDist - 1] = b[TotalDist - 1][timeStep] + c[TotalDist - 1][timeStep];
				rhs[TotalDist - 1] = d[TotalDist - 1][timeStep];

				//Thomas_Numerical_Solver is a tri-diagonal system solver: sub/diag/sup * x = rhs ----
				Thomas_Numerical_Solver(sub, diag, sup, rhs, x_local);

				//For i to TotalDist
				for (int i = 0; i < TotalDist; ++i) {
					//T[i][timeStep_next] = x_local[i] updated
					T[i][timeStep_next] = x_local[i];
					initialT_T0[i] = x_local[i];
				}

				// =============================== Gaussian elimination for Ax=B linear equation done! ==========================
				// =============================== Next time step (timeStep+1) calculations
				adjustedDirRadE(solarSW_Dir_LI, (timeStep + 1));	// preparing the adjustedDirSW_E vector
				adjustedDirRadW(solarSW_Dir_LI, (timeStep + 1));	// preparing the adjustedDirSW_W vector
				netSolarDiffRadE(solarSW_Diff_LI, (timeStep + 1)); // preparing the adjustedDiffSW_E vector
				netSolarDiffRadW(solarSW_Diff_LI, (timeStep + 1)); // preparing the adjustedDiffSW_W vector
				//Update SWDir_2D SWDiff_2D for East and West exposure for next time step
				for (int i = 0; i < TotalDist; ++i) {
					//If hourList_LI[timeStep_next] >= 0 && hourList_LI[timeStep_next] < 12, then East exposure
					if (hourList_LI[timeStep_next] >= 0 && hourList_LI[timeStep_next] < 12) {
						SWDir_2D[i][timeStep_next] = adjustedDirSW_E[i];
						SWDiff_2D[i][timeStep_next] = adjustedDiffSW_E[i];
					}
					//Else >=12, then West exposure
					else {
						SWDir_2D[i][timeStep_next] = adjustedDirSW_W[i];
						SWDiff_2D[i][timeStep_next] = adjustedDiffSW_W[i];
					}
					//SW_2D[i][timeStep_next] = SWDir_2D[i][timeStep_next] + SWDiff_2D[i][timeStep_next]; combine direct and diffuse
					SW_2D[i][timeStep_next] = SWDir_2D[i][timeStep_next] + SWDiff_2D[i][timeStep_next];
				}

				longWaveRadiation(airTemp_LI_C, real_humidity_LI, cloudiness_LI, initialT_T0, (timeStep + 1));
				// latent heat in the fist time step
				latentHeat(airTemp_LI_C, real_humidity_LI, initialT_T0, windSp_LI, (timeStep + 1));
				// Sensible heat for the first time step
				sensibleHeat(airTemp_LI_C, initialT_T0, windSp_LI, real_humidity_LI, (timeStep + 1));
				// Stream Bed heat for the first time step
				bedSediment(wp_total, width_total, K_sedType_LI, initialT_T0, sedimentTime_LI, BedDepthMeas_LI, (timeStep + 1));

				for (int i = 0; i < TotalDist; i++) {
					heat_flux_2D[i][(timeStep + 1)] = (SW_2D[i][(timeStep + 1)] + LW_2D[i][(timeStep + 1)] + Latent_2D[i][(timeStep + 1)] +
						Sensible_2D[i][(timeStep + 1)] + Bed_2D[i][(timeStep + 1)]) *
						60;
				}
				//Note: This Xterm output code for regular use, and should not be removed
				//If modulus timeStep and 25% of TotalTime equals zero, then write output to Xterm window to update user
				if (timeStep % int(0.25 * TotalTime) == 0) {
					cout << "Simulating time step " << timeStep + 1 << " of " << TotalTime << endl;
				}
				//If timeStep equals TotalTime, using modulus operator, then write output to Xterm window to update user
				else if (timeStep + 1 == TotalTime) {
					cout << "Simulating time step " << timeStep + 1 << " of " << TotalTime << endl;
				}
			}

			//2D vectors used for writing minutely_outputs
			if (input->CoolRiverVariables["CR_Minute_output"] == 1) {
				t_minBased.resize(TotalDist_CN);
				SWDir_2D_min.resize(TotalDist_CN);//198
				SWDiff_2D_min.resize(TotalDist_CN);
				SW_2D_min.resize(TotalDist_CN);
				atmLW_2D_min.resize(TotalDist_CN);
				LCLW_2D_min.resize(TotalDist_CN);
				backLW_2D_min.resize(TotalDist_CN);
				LW_2D_min.resize(TotalDist_CN);
				Latent_2D_min.resize(TotalDist_CN);
				Sensible_2D_min.resize(TotalDist_CN);
				Bed_2D_min.resize(TotalDist_CN);
				heat_flux_2D_min.resize(TotalDist_CN);
				for (int i = 0; i < TotalDist_CN; i++) {
					t_minBased[i].resize(TotalTime_Uns_CN);
					SWDir_2D_min[i].resize(TotalTime_Uns_CN);//2880
					SWDiff_2D_min[i].resize(TotalTime_Uns_CN);
					SW_2D_min[i].resize(TotalTime_Uns_CN);
					atmLW_2D_min[i].resize(TotalTime_Uns_CN);
					LCLW_2D_min[i].resize(TotalTime_Uns_CN);
					backLW_2D_min[i].resize(TotalTime_Uns_CN);
					LW_2D_min[i].resize(TotalTime_Uns_CN);
					Latent_2D_min[i].resize(TotalTime_Uns_CN);
					Sensible_2D_min[i].resize(TotalTime_Uns_CN);
					Bed_2D_min[i].resize(TotalTime_Uns_CN);
					heat_flux_2D_min[i].resize(TotalTime_Uns_CN);
				}

				//Intializing vectors to store minutely_values
				vector < double > t_min(TotalTime * 60);
				vector < double > heat_flux_min(TotalTime * 60);
				vector < double > SWDir_min(TotalTime * 60);
				vector < double > SWDiff_min(TotalTime * 60);
				vector < double > SW_min(TotalTime * 60);
				vector < double > LW_min(TotalTime * 60);
				vector < double > atmLW_min(TotalTime * 60);
				vector < double > LCLW_min(TotalTime * 60);
				vector < double > backLW_min(TotalTime * 60);
				vector < double > Latent_min(TotalTime * 60);
				vector < double > Sensible_min(TotalTime * 60);
				vector < double > Bed_min(TotalTime * 60);

				//function which generates minutely_outputs
				for (int j = 0; j < TotalDist; j++) {
					t_min = minute(T, j);
					heat_flux_min = minute(heat_flux_2D, j);
					SWDir_min = minute(SWDir_2D, j);
					SWDiff_min = minute(SWDiff_2D, j);
					SW_min = minute(SW_2D, j);
					LW_min = minute(LW_2D, j);
					atmLW_min = minute(atmLW_2D, j);
					LCLW_min = minute(LCLW_2D, j);
					backLW_min = minute(backLW_2D, j);
					Latent_min = minute(Latent_2D, j);
					Sensible_min = minute(Sensible_2D, j);
					Bed_min = minute(Bed_2D, j);

					//Interpolating minutely_outputs
					for (double x = 0; x < (TotalTime * 60); x++) {
						double y = interpolate(hourlyTime, t_min, x, true);
						t_minBased[j][x] = y;
					}
					for (double x = 0; x < (TotalTime * 60); x++) {
						double y = interpolate(hourlyTime, heat_flux_min, x, true);
						heat_flux_2D_min[j][x] = y;
					}

					for (double x = 0; x < (TotalTime * 60); x++) {
						double y = interpolate(hourlyTime, SWDir_min, x, true);
						SWDir_2D_min[j][x] = y;
					}
					for (double x = 0; x < (TotalTime * 60); x++) {
						double y = interpolate(hourlyTime, SWDiff_min, x, true);
						SWDiff_2D_min[j][x] = y;
					}
					for (double x = 0; x < (TotalTime * 60); x++) {
						double y = interpolate(hourlyTime, SW_min, x, true);
						SW_2D_min[j][x] = y;
					}
					for (double x = 0; x < (TotalTime * 60); x++) {
						double y = interpolate(hourlyTime, LW_min, x, true);
						LW_2D_min[j][x] = y;
					}
					for (double x = 0; x < (TotalTime * 60); x++) {
						double y = interpolate(hourlyTime, atmLW_min, x, true);
						atmLW_2D_min[j][x] = y;
					}
					for (double x = 0; x < (TotalTime * 60); x++) {
						double y = interpolate(hourlyTime, LCLW_min, x, true);
						LCLW_2D_min[j][x] = y;
					}
					for (double x = 0; x < (TotalTime * 60); x++) {
						double y = interpolate(hourlyTime, backLW_min, x, true);
						backLW_2D_min[j][x] = y;
					}
					for (double x = 0; x < (TotalTime * 60); x++) {
						double y = interpolate(hourlyTime, Latent_min, x, true);
						Latent_2D_min[j][x] = y;
					}
					for (double x = 0; x < (TotalTime * 60); x++) {
						double y = interpolate(hourlyTime, Sensible_min, x, true);
						Sensible_2D_min[j][x] = y;
					}
					for (double x = 0; x < (TotalTime * 60); x++) {
						double y = interpolate(hourlyTime, Bed_min, x, true);
						Bed_2D_min[j][x] = y;
					}
				}
			}

			cout << "... Crank-Nicolson modeling methodology is complete." << endl;

			break;
		}
		case 2: {

			// Removing the required vectors for case 1 and 2 to reduce the amount of memory usage
			vector<vector<double>>().swap(T_k1);
			vector<vector<double>>().swap(heat_flux_k1);
			vector<vector<double>>().swap(heat_flux_k2);
			vector<vector<double>>().swap(u1);
			vector<vector<double>>().swap(v1);
			vector<vector<double>>().swap(s1);
			vector<vector<double>>().swap(m1);
			vector<vector<double>>().swap(k1);
			vector<vector<double>>().swap(u2);
			vector<vector<double>>().swap(v2);
			vector<vector<double>>().swap(s2);
			vector<vector<double>>().swap(m2);
			vector<vector<double>>().swap(k2);
			vector<vector<double>>().swap(SWDir_2D_k2);
			vector<vector<double>>().swap(SWDiff_2D_k2);
			vector<vector<double>>().swap(SW_2D_k2);
			vector<vector<double>>().swap(atmLW_2D_k2);
			vector<vector<double>>().swap(LCLW_2D_k2);
			vector<vector<double>>().swap(backLW_2D_k2);
			vector<vector<double>>().swap(LW_2D_k2);
			vector<vector<double>>().swap(Latent_2D_k2);
			vector<vector<double>>().swap(Sensible_2D_k2);
			vector<vector<double>>().swap(Bed_2D_k2);

			vector<vector<double>>().swap(a_c);
			vector<vector<double>>().swap(b_c);
			vector<vector<double>>().swap(c_c);
			vector<vector<double>>().swap(o);
			vector<vector<double>>().swap(p);
			vector<vector<double>>().swap(q);
			vector<vector<double>>().swap(o_c);
			vector<vector<double>>().swap(p_c);
			vector<vector<double>>().swap(q_c);
			vector<vector<double>>().swap(d);
			vector<vector<double>>().swap(g);
			vector<vector<double>>().swap(k);
			vector<vector<double>>().swap(m);
			vector<vector<double>>().swap(A);
			vector<vector<double>>().swap(a);
			vector<vector<double>>().swap(b);
			vector<vector<double>>().swap(c);

			// Calculating the unsteady state using the McCormick and Explicit Finite Difference methodologies
			// Using the formulation form Boyd & Kasper (2003)
			// www.oregon.gov/deq/FilterDocs/heatsourcemanual.pdf

			// ======================================================
			// START - LOAD MODEL VARIABLES & SETUP INITAL CONDITIONS
			cout << "Obtaining boundary and initial conditions..." << endl;
			Q.resize(2);
			Temp_unsteady.resize(2);

			for (int i = 0; i < (2); i++) {
				Q[i].resize(TotalDist_stable + 1);
				Temp_unsteady[i].resize(TotalDist_stable + 1);
			}
			depth_unsteady.resize(TotalDist_stable);
			AreaX.resize(TotalDist_stable);
			velocity_unsteady.resize(TotalDist_stable);

			for (int i = 0; i < TotalDist_stable; i++) {
				depth_unsteady[i].resize(2);
				AreaX[i].resize(2);
				velocity_unsteady[i].resize(2);
			}
			Pw_unsteady.resize(TotalDist_stable);
			width_UnsTotal.resize(TotalDist_stable);
			depth_AvgUns.resize(TotalDist_stable);
			Hyporheic_Exchange.resize(TotalDist_stable);
			Rh_unsteady.resize(TotalDist_stable);
			Flag_SkipNode.resize(TotalDist_stable);

			// ======================================================
			// Sky to view and TSA, VSA & BSA adjusted to unsteady dx

			if (SolvingMethod == 1) {
				SkyToView_UnsE.resize(TotalDist_stable);
				SkyToView_UnsW.resize(TotalDist_stable);
				int count_uns = 0;
				for (int i = 0; i < TotalDist_stable; i++) {
					SkyToView_UnsE[i] = SkyV_E[count_uns];
					SkyToView_UnsW[i] = SkyV_W[count_uns];
					count_uns = (count_uns + dx_Interval_m) - 1;
				}
			}
			else {
				SkyToView_UnsE.resize(TotalDist_stable);
				SkyToView_UnsW.resize(TotalDist_stable);
				SF_LI_Uns.resize(TotalDist_stable);
				int count_uns = 0;
				for (int i = 0; i < TotalDist_stable; i++) {
					SkyToView_UnsE[i] = SkyToView_LI[count_uns];
					SkyToView_UnsW[i] = SkyToView_LI[count_uns];
					SF_LI_Uns[i] = SF_LI[count_uns];

					count_uns = (count_uns + dx_Interval_m) - 1;
				}
			}

			// ======================================================
			Node_Uns = 0;
			double distance;
			distance = TotalDist;
			time_Uns = 0;
			flag_BC = 1;

			Q_In.resize(TotalDist_stable);
			T_In.resize(TotalDist_stable);
			for (int i = 0; i < TotalDist_stable; i++) {
				Q_In[i].resize(TotalTime_min);
				T_In[i].resize(TotalTime_min);
			}

			for (int i = 0; i < TotalDist_stable; i++) {
				for (int j = 0; j < TotalTime_min; j++) {
					Q_In[i][j] = inflow_Rate[i][j];
					T_In[i][j] = inflow_Temp_Uns[i][j];
				}
			}

			while (distance >= 0) {

				initialConditions(Node_Uns);

				distance = distance - dx_Interval_m;
				Node_Uns++;
				flag_BC = 0;
			}

			// ======================================================
			// END LOAD MODEL VARIABLES & SETUP INITAL CONDITIONS

			// ======================================================
			// START MACCORMICK HEAT/MASS TRANSFER MODELS

			if ((calculation == 2) && input->CoolRiverVariables["CR_Minute_output"] == 1) {
				double temp = 0;
				for (int i = 0; i < endTimeCount * 60; i++) {
					hourlyTime_unSteady.push_back(temp);
					temp = temp + 1;
				}
			}

			for (int Time_min = 0; Time_min < TotalTime_min; Time_min++) {

				hydroStability();
				// ===========================================================
				// Reset Counters, Flags
				Node_Uns = 0;
				flag_BC = 1;
				distance = TotalDist;
				T_unsTemporary.resize(TotalDist_stable + 1);
				// ===========================================================

				while (distance > 0) {
					hydraulics(Node_Uns, Time_min);

					adjustedDirRadE_Uns(DirSW_Uns, Time_min, Node_Uns);
					adjustedDirRadW_Uns(DirSW_Uns, Time_min, Node_Uns);
					netSolarDiffRadE_Uns(DiffSW_Uns, Time_min, Node_Uns);
					netSolarDiffRadW_Uns(DiffSW_Uns, Time_min, Node_Uns);

					if (startingHour >= 0 && startingHour < 12) {
						DirSW_Uns_temp = DirSW_UnsE;
						DiffSW_Uns_temp = DiffSW_UnsE;
					}
					else {
						DirSW_Uns_temp = DirSW_UnsW;
						DiffSW_Uns_temp = DiffSW_UnsW;
					}
					SW_Uns = DiffSW_Uns_temp + DirSW_Uns_temp;

					longWaveRadiation_Uns(airTemp_Uns, RH_Uns, Cloadiness_Uns, Time_min, Node_Uns);
					latentHeat_Uns(airTemp_Uns, RH_Uns, wndSpd_Uns, Time_min, Node_Uns);
					sensibleHeat_Uns(airTemp_Uns, wndSpd_Uns, RH_Uns, Time_min, Node_Uns);
					//bedSediment_Uns(K_sedType_LI, sedTemp_Uns, depth_AvgUns, Time_min, Node_Uns);

					if (SedimentMethod == 1) {
						bedSediment_Uns(K_sedType_LI, sedTemp_Uns, depth_AvgUns, Time_min, Node_Uns);
					}
					if (SedimentMethod == 2) {
						bedSedimentHS(sedTemp_Uns, Time_min, Node_Uns);
					}

					Flux_Total_Time[Node_Uns] = SW_Uns + LW_Uns + latent_Uns + Sensible_Uns + bed_Uns;
					Flux_Conduction_Time[Node_Uns] = bed_Uns;
					Flux_Evaporation_Time[Node_Uns] = latent_Uns;
					Flux_Convection_Time[Node_Uns] = Sensible_Uns;
					FLux_AtmLW_Time[Node_Uns] = LW_Atm_Uns;
					Flux_LCLW_Time[Node_Uns] = LW_LC_Uns;
					Flux_BackLW_Time[Node_Uns] = LW_Back_Uns;
					Flux_LW_Time[Node_Uns] = LW_Atm_Uns + LW_LC_Uns + LW_Back_Uns;
					Flux_DirSW_Time[Node_Uns] = DirSW_Uns_temp;
					Flux_DiffSW_Time[Node_Uns] = DiffSW_Uns_temp;
					Flux_SW_Time[Node_Uns] = SW_Uns;

					//Boyd and Kasper(2003).Analytical methods for dynamic open channel heat and mass transfer : Methodology for heat source model version 7.0 (TMDL Tools Updated - 2007).Retrieved from Portland, OR.
					//Delta_T (C/s) is 3rd RHS in Eq 2-119 of Boyd and Kasper (2003), a heat flux reaction term
					Delta_T[Node_Uns] = Flux_Total_Time[Node_Uns] / (depth_AvgUns[Node_Uns] * rho_water * c_water);

					flag_BC = 0;
					distance = distance - dx_Interval_m;
					Node_Uns = Node_Uns + 1;
				}

				McCormick_Temp1(Delta_T, Time_min);
				McCormick_Temp2(Delta_T, Time_min);

				// Reset flags
				for (int i = 0; i < TotalDist_stable; i++) {
					Q[0][i] = Q[1][i];
					AreaX[i][0] = AreaX[i][1];
					depth_unsteady[i][0] = depth_unsteady[i][1];
					depth_Uns_temp[i] = depth_unsteady[i][1];
				}
				if (counterSec % minCounter == 0) {
					// writing the results
					for (double x = 0; x < TotalDist; x++) {
						double y = interpolate(Nodes_Uns, Flux_Total_Time, x, true);
						Flux_Total[x][counterWriter] = y;
					}
					for (double x = 0; x < TotalDist; x++) {
						double y = interpolate(Nodes_Uns, Flux_Conduction_Time, x, true);
						Flux_Conduction[x][counterWriter] = y;
					}
					for (double x = 0; x < TotalDist; x++) {
						double y = interpolate(Nodes_Uns, Flux_Evaporation_Time, x, true);
						Flux_Evaporation[x][counterWriter] = y;
					}
					for (double x = 0; x < TotalDist; x++) {
						double y = interpolate(Nodes_Uns, Flux_Convection_Time, x, true);
						Flux_Convection[x][counterWriter] = y;
					}
					for (double x = 0; x < TotalDist; x++) {
						double y = interpolate(Nodes_Uns, FLux_AtmLW_Time, x, true);
						FLux_AtmLW[x][counterWriter] = y;
					}
					for (double x = 0; x < TotalDist; x++) {
						double y = interpolate(Nodes_Uns, Flux_LCLW_Time, x, true);
						Flux_LCLW[x][counterWriter] = y;
					}
					for (double x = 0; x < TotalDist; x++) {
						double y = interpolate(Nodes_Uns, Flux_BackLW_Time, x, true);
						Flux_BackLW[x][counterWriter] = y;
					}
					for (double x = 0; x < TotalDist; x++) {
						double y = interpolate(Nodes_Uns, Flux_LW_Time, x, true);
						Flux_LW[x][counterWriter] = y;
					}
					for (double x = 0; x < TotalDist; x++) {
						double y = interpolate(Nodes_Uns, Flux_DirSW_Time, x, true);
						Flux_DirSW[x][counterWriter] = y;
					}
					for (double x = 0; x < TotalDist; x++) {
						double y = interpolate(Nodes_Uns, Flux_DiffSW_Time, x, true);
						Flux_DiffSW[x][counterWriter] = y;
					}
					for (double x = 0; x < TotalDist; x++) {
						double y = interpolate(Nodes_Uns, Flux_SW_Time, x, true);
						Flux_SW[x][counterWriter] = y;
					}
					for (double x = 0; x < TotalDist; x++) {
						double y = interpolate(Nodes_Uns, T_unsTemporary, x, true);
						T_Uns[x][counterWriter] = y;
					}
					for (double x = 0; x < TotalDist; x++) {
						double y = interpolate(Nodes_Uns, Pw_unsteady, x, true);
						Pw_unsteady1[x][counterWriter] = y;
					}
					for (double x = 0; x < TotalDist; x++) {
						double y = interpolate(Nodes_Uns, width_UnsTotal, x, true);
						width_UnsTotal1[x][counterWriter] = y;
					}
					for (double x = 0; x < TotalDist; x++) {
						double y = interpolate(Nodes_Uns, depth_Uns_temp, x, true);
						depth_Uns[x][counterWriter] = y;
					}
					for (double x = 0; x < TotalDist; x++) {
						double y = interpolate(Nodes_Uns, depth_AvgUns, x, true);
						depth_AvgUns1[x][counterWriter] = y;
					}
					for (double x = 0; x < TotalDist; x++) {
						double y = interpolate(Nodes_Uns, Hyporheic_Exchange, x, true);
						Hyporheic_Exchange1[x][counterWriter] = y;
					}
					for (double x = 0; x < TotalDist; x++) {
						double y = interpolate(Nodes_Uns, Rh_unsteady, x, true);
						Rh_unsteady1[x][counterWriter] = y;
					}

					counterWriter++;
				}

				if (counterSec % (60 * minCounter) == 0) {
					for (int i = 0; i < TotalDist_stable; i++) {
						hour_Flux_Total[i][counterHourly] = Flux_Total_Time[i];
						hour_Flux_Conduction[i][counterHourly] = Flux_Conduction_Time[i];
						hour_Flux_Evaporation[i][counterHourly] = Flux_Evaporation_Time[i];
						hour_Flux_Convection[i][counterHourly] = Flux_Convection_Time[i];
						hour_FLux_AtmLW[i][counterHourly] = FLux_AtmLW_Time[i];
						hour_Flux_LCLW[i][counterHourly] = Flux_LCLW_Time[i];
						hour_Flux_BackLW[i][counterHourly] = Flux_BackLW_Time[i];
						hour_Flux_LW[i][counterHourly] = Flux_LW_Time[i];
						hour_Flux_DirSW[i][counterHourly] = Flux_DirSW_Time[i];
						hour_Flux_DiffSW[i][counterHourly] = Flux_DiffSW_Time[i];
						hour_Flux_SW[i][counterHourly] = Flux_SW_Time[i];
						hour_T_Uns[i][counterHourly] = T_unsTemporary[i];
						hour_depth_Uns[i][counterHourly] = depth_Uns_temp[i];
						hour_Pw_unsteady[i][counterHourly] = Pw_unsteady[i];
						hour_width_UnsTotal[i][counterHourly] = width_UnsTotal[i];
						hour_depth_AvgUns[i][counterHourly] = depth_AvgUns[i];
						hour_Hyporheic_Exchange[i][counterHourly] = Hyporheic_Exchange[i];
						hour_Rh_unsteady[i][counterHourly] = Rh_unsteady[i];
					}
					counterHourly++;
				}

				counterSec++;
				if (counterSec >= (60 * (60 / dtime_Interval_min))) {
					startingHour++;
					counterSec = 0;
				}
				if (startingHour >= 24) {
					startingHour = 0;
				}
				//Note: This Xterm output code for regular use, and should not be removed
				//If modulus TotalTime_min and 20% of TotalTime_min equals zero, then write output to Xterm window to update user
				if (Time_min % int(0.25 * TotalTime_min) == 0) {
					cout << "Simulating time step " << Time_min + 1 << " of " << TotalTime_min << endl;
				}
				//If Time_min equals TotalTime_min, using modulus operator, then write output to Xterm window to update user
				else if (Time_min + 1 == TotalTime_min) {
					cout << "Simulating time step " << Time_min + 1 << " of " << TotalTime_min << endl;
				}
			}
			//2D vectors used for writing minutely_outputs
			if (input->CoolRiverVariables["CR_Minute_output"] == 1) {
				t_minBased.resize(TotalDist_FD);
				SWDir_2D_min.resize(TotalDist_FD);
				SWDiff_2D_min.resize(TotalDist_FD);
				SW_2D_min.resize(TotalDist_FD);
				atmLW_2D_min.resize(TotalDist_FD);
				LCLW_2D_min.resize(TotalDist_FD);
				backLW_2D_min.resize(TotalDist_FD);
				LW_2D_min.resize(TotalDist_FD);
				Latent_2D_min.resize(TotalDist_FD);
				Sensible_2D_min.resize(TotalDist_FD);
				Bed_2D_min.resize(TotalDist_FD);
				heat_flux_2D_min.resize(TotalDist_FD);
				Pw_unsteady_2D_min.resize(TotalDist_FD);
				width_UnsTotal_2D_min.resize(TotalDist_FD);
				depth_AvgUns_2D_min.resize(TotalDist_FD);
				Hyporheic_Exchange_2D_min.resize(TotalDist_FD);
				Rh_unsteady_2D_min.resize(TotalDist_FD);
				for (int i = 0; i < TotalDist_FD; i++) {
					t_minBased[i].resize(TotalTime_Uns_FD);
					SWDir_2D_min[i].resize(TotalTime_Uns_FD);
					SWDiff_2D_min[i].resize(TotalTime_Uns_FD);
					SW_2D_min[i].resize(TotalTime_Uns_FD);
					atmLW_2D_min[i].resize(TotalTime_Uns_FD);
					LCLW_2D_min[i].resize(TotalTime_Uns_FD);
					backLW_2D_min[i].resize(TotalTime_Uns_FD);
					LW_2D_min[i].resize(TotalTime_Uns_FD);
					Latent_2D_min[i].resize(TotalTime_Uns_FD);
					Sensible_2D_min[i].resize(TotalTime_Uns_FD);
					Bed_2D_min[i].resize(TotalTime_Uns_FD);
					heat_flux_2D_min[i].resize(TotalTime_Uns_FD);
					Pw_unsteady_2D_min[i].resize(TotalTime_Uns_FD);
					width_UnsTotal_2D_min[i].resize(TotalTime_Uns_FD);
					depth_AvgUns_2D_min[i].resize(TotalTime_Uns_FD);
					Hyporheic_Exchange_2D_min[i].resize(TotalTime_Uns_FD);
					Rh_unsteady_2D_min[i].resize(TotalTime_Uns_FD);
				}
				//Intializing vectors to store minutely_values
				for (int i = 0; i < TotalDist_stable; i++) {
					vector < double > t_min(TotalTime * 60);
					vector < double > heat_flux_min(TotalTime * 60);
					vector < double > SWDir_min(TotalTime * 60);
					vector < double > SWDiff_min(TotalTime * 60);
					vector < double > SW_min(TotalTime * 60);
					vector < double > LW_min(TotalTime * 60);
					vector < double > atmLW_min(TotalTime * 60);
					vector < double > LCLW_min(TotalTime * 60);
					vector < double > backLW_min(TotalTime * 60);
					vector < double > Latent_min(TotalTime * 60);
					vector < double > Sensible_min(TotalTime * 60);
					vector < double > Bed_min(TotalTime * 60);
					vector < double > Pw_unsteady_min(TotalTime * 60);
					vector < double > width_UnsTotal_min(TotalTime * 60);
					vector < double > depth_AvgUns_min(TotalTime * 60);
					vector < double > Hyporheic_Exchange_min(TotalTime * 60);
					vector < double > Rh_unsteady_min(TotalTime * 60);
					//function which generates minutely_outputs
					for (int j = 0; j < TotalDist_stable; j++)
					{
						t_min = minute(hour_T_Uns, j);
						heat_flux_min = minute(hour_Flux_Total, j);
						SWDir_min = minute(hour_Flux_DirSW, j);
						SWDiff_min = minute(hour_Flux_DiffSW, j);
						SW_min = minute(hour_Flux_SW, j);
						LW_min = minute(hour_Flux_LW, j);
						atmLW_min = minute(hour_FLux_AtmLW, j);
						LCLW_min = minute(hour_Flux_LCLW, j);
						backLW_min = minute(hour_Flux_BackLW, j);
						Latent_min = minute(hour_Flux_Evaporation, j);
						Sensible_min = minute(hour_Flux_Convection, j);
						Bed_min = minute(hour_Flux_Conduction, j);
						Pw_unsteady_min = minute(hour_Pw_unsteady, j);
						width_UnsTotal_min = minute(hour_width_UnsTotal, j);
						depth_AvgUns_min = minute(hour_depth_AvgUns, j);
						Hyporheic_Exchange_min = minute(hour_Hyporheic_Exchange, j);
						Rh_unsteady_min = minute(hour_Rh_unsteady, j);


						for (double x = 0; x < TotalTime * 60; x++) {
							double y = interpolate(hourlyTime_unSteady, t_min, x, true);
							t_minBased[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime_unSteady, heat_flux_min, x, true);
							heat_flux_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime_unSteady, SWDir_min, x, true);
							SWDir_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime_unSteady, SWDiff_min, x, true);
							SWDiff_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime_unSteady, SW_min, x, true);
							SW_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime_unSteady, LW_min, x, true);
							LW_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime_unSteady, atmLW_min, x, true);
							atmLW_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime_unSteady, LCLW_min, x, true);
							LCLW_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime_unSteady, backLW_min, x, true);
							backLW_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime_unSteady, Latent_min, x, true);
							Latent_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime_unSteady, Sensible_min, x, true);
							Sensible_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime_unSteady, Bed_min, x, true);
							Bed_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime_unSteady, Pw_unsteady_min, x, true);
							Pw_unsteady_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime_unSteady, width_UnsTotal_min, x, true);
							width_UnsTotal_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime_unSteady, depth_AvgUns_min, x, true);
							depth_AvgUns_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime_unSteady, Hyporheic_Exchange_min, x, true);
							Hyporheic_Exchange_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime_unSteady, Rh_unsteady_min, x, true);
							Rh_unsteady_2D_min[j][x] = y;
						}
					}
				}
			}
			break;
		}
		case 3: {

			// Removing the required vectors for case 1 and 2 to reduce the amount of memory usage
			vector<vector<double>>().swap(T_k1);
			vector<vector<double>>().swap(heat_flux_k1);
			vector<vector<double>>().swap(heat_flux_k2);
			vector<vector<double>>().swap(u1);
			vector<vector<double>>().swap(v1);
			vector<vector<double>>().swap(s1);
			vector<vector<double>>().swap(m1);
			vector<vector<double>>().swap(k1);
			vector<vector<double>>().swap(u2);
			vector<vector<double>>().swap(v2);
			vector<vector<double>>().swap(s2);
			vector<vector<double>>().swap(m2);
			vector<vector<double>>().swap(k2);
			vector<vector<double>>().swap(SWDir_2D_k2);
			vector<vector<double>>().swap(SWDiff_2D_k2);
			vector<vector<double>>().swap(SW_2D_k2);
			vector<vector<double>>().swap(atmLW_2D_k2);
			vector<vector<double>>().swap(LCLW_2D_k2);
			vector<vector<double>>().swap(backLW_2D_k2);
			vector<vector<double>>().swap(LW_2D_k2);
			vector<vector<double>>().swap(Latent_2D_k2);
			vector<vector<double>>().swap(Sensible_2D_k2);
			vector<vector<double>>().swap(Bed_2D_k2);

			vector<vector<double>>().swap(a_c);
			vector<vector<double>>().swap(b_c);
			vector<vector<double>>().swap(c_c);
			vector<vector<double>>().swap(o);
			vector<vector<double>>().swap(p);
			vector<vector<double>>().swap(q);
			vector<vector<double>>().swap(o_c);
			vector<vector<double>>().swap(p_c);
			vector<vector<double>>().swap(q_c);
			vector<vector<double>>().swap(d);
			vector<vector<double>>().swap(g);
			vector<vector<double>>().swap(k);
			vector<vector<double>>().swap(m);
			vector<vector<double>>().swap(A);
			vector<vector<double>>().swap(a);
			vector<vector<double>>().swap(b);
			vector<vector<double>>().swap(c);

			// ======================================================
			// Sky to view and TSA, VSA & BSA adjusted to unsteady dx

			if (SolvingMethod == 1)
			{
				SkyToView_UnsE.resize(TotalDist_stable);
				SkyToView_UnsW.resize(TotalDist_stable);
				int count_uns = 0;
				for (int i = 0; i < TotalDist_stable; i++)
				{
					if (i == (TotalDist_stable - 1))
					{
						count_uns = (i * dx_Interval_m) - 1;
					}
					else
					{
						count_uns = i * dx_Interval_m;
					}

					SkyToView_UnsE[i] = SkyV_E[count_uns];
					SkyToView_UnsW[i] = SkyV_W[count_uns];
				}
			}
			else
			{
				SkyToView_UnsE.resize(TotalDist_stable);
				SkyToView_UnsW.resize(TotalDist_stable);
				SF_LI_Uns.resize(TotalDist_stable);
				int count_uns = 0;
				for (int i = 0; i < TotalDist_stable; i++)
				{
					if (i == (TotalDist_stable - 1))
					{
						count_uns = (i * dx_Interval_m) - 1;
					}
					else
					{
						count_uns = i * dx_Interval_m;
					}

					SkyToView_UnsE[i] = SkyToView_LI[count_uns];
					SkyToView_UnsW[i] = SkyToView_LI[count_uns];
					SF_LI_Uns[i] = SF_LI[count_uns];
				}
			}

			// ======================================================
			//Node_HR = 0;
			//double distance_HR;
			//distance_HR = TotalDist;
			//time_HR = 0;
			flag_BC = 1;
			HyporheicVelocity_HR.resize(TotalDist_stable);

			// ======================================================

			//for (int i = 0; i < TotalTime_min; i++) {
			for (int i = 0; i < TotalTime; i++)
			{
				for (int theNode_HR = 0; theNode_HR < TotalDist_stable_HR; theNode_HR++)
				{
					// Find hyporheic fluxes
					// Ratio Conductivity of dominant substrate
					double Dummy1 = conductivity_Uns[theNode_HR] * (1.0 - embeddedness_Uns[theNode_HR]);
					// Ratio Conductivity of sand - low range
					double Dummy2 = 0.00002 * embeddedness_Uns[theNode_HR];
					// True horizontal conductivity (m / s)
					double HorCond = Dummy1 + Dummy2;

					// Ratio Size of dominant substrate
					Dummy1 = particleSize_Uns[theNode_HR] * (1.0 - embeddedness_Uns[theNode_HR]);
					// Ratio Conductivity of sand - low range
					Dummy2 = 0.062 * embeddedness_Uns[theNode_HR];
					// Estimated Porosity
					Porosity[theNode_HR][i] = (0.3683 * pow((Dummy1 + Dummy2), (-0.0641)));

					// Calculate head at top(ho) and bottom(hL) of reach
					double ho, hL;
					if (theNode_HR < (TotalDist_stable_HR - 1))
					{
						hL = WSElev_ALL_HR[theNode_HR + 1][i];
					}
					else
					{
						hL = WSElev_HR_LI[((theNode_HR + 1) * dx_Interval_m) - 1];
					}
					ho = WSElev_ALL_HR[theNode_HR][i];

					// Try new equation for calculating Hyporheic Exchange Flow, without squaring ho and hL, and without porosity
					HyporheicExchange_HR[theNode_HR][i] = abs(ho - hL) * Pw_ALL_HR[theNode_HR][i] * HorCond * (ho - hL) / dx_Interval_m;

					// I turned this section off. There was no reason to keep it! Reza, Feb. 20

					//if (HyporheicExchange_HR[theNode_HR][i] > Q_Str_HR[theNode_HR][i]) {
					//	HyporheicExchange_HR[theNode_HR][i] = Q_Str_HR[theNode_HR][i];
					//}
					//if (abs(HyporheicExchange_HR[theNode_HR][i]) > 0) {
					//	HyporheicVelocity_HR[theNode_HR] = (HyporheicExchange_HR[theNode_HR][i] / 3600.0) / ((ho - hL) * Pw_ALL_HR[theNode_HR][i] * Porosity[theNode_HR][TotalTime]);   // m/hr

					//}
					//else {
					//	HyporheicVelocity_HR[theNode_HR] = 0;
					//}
					//HyporheicExchange_HR[theNode_HR][i] = abs(HyporheicExchange_HR[theNode_HR][i]);

					// finding dispersion coefficient
					// Calculate dispersion using equations copied from SubMcCormick1
					double Shear_Velocity;
					double SlopeWS = (hL - ho) / dx_Interval_m;
					if (SlopeWS <= 0)
					{
						Shear_Velocity = VelocityALL_HR[theNode_HR][i];
					}
					else
					{
						Shear_Velocity = sqrt(9.8 * DepthALL_HR[theNode_HR][i] * SlopeWS);
					}
					// Changed 0.011 to 0.06 in below eqn to account for natural (not straight) streams
					Dispersion_HR[theNode_HR][i] = (0.06 * pow(VelocityALL_HR[theNode_HR][i], 2.0) * pow(WidthALL_HR[theNode_HR][i], 2.0)) / (DepthALL_HR[theNode_HR][i] * Shear_Velocity);
					if ((Dispersion_HR[theNode_HR][i] * pow((dtime_Interval_min / dx_Interval_m), 2.0)) > 0.5)
					{
						Dispersion_HR[theNode_HR][i] = (0.45 * pow(dx_Interval_m, 2.0)) / dtime_Interval_min;
					}

					// Updating the stream temperature in the 1st cross section (theNode = 0) w/ the observed temperature for boundary condition
					if (flag_BC == 1)
					{
						//HeatFluxADR_Temperature_C[theNode_HR][i] = inflow_T0_HR[i];
						HeatFluxADR_Temperature_C[theNode_HR][i] = inflow_Temp.at(locations[0])[i];
					}

					flag_BC = 0;
					theDistance_HR = theDistance_HR - dx_Interval_m;
				}
				flag_BC = 1;
			}

			// For debugging purpose
			//for (int i = 0; i < 100; i++) {
			//	Hyporheic_Exchange_HR.push_back(HyporheicExchange_HR[i][1]);
			//}

			//for (int i = 0; i < TotalDist_stable_HR; i++) { Pw_HR_1D.push_back(Pw_ALL_HR[i][1]); }
			//average_PW_HR = accumulate(Pw_HR_1D.begin(), Pw_HR_1D.end(), 0.0) / Pw_HR_1D.size();
			//averageHor_Con_HR = accumulate(Hor_Con_HR.begin(), Hor_Con_HR.end(), 0.0) / Hor_Con_HR.size();
			//averageHor_ho_HR = accumulate(ho_HR.begin(), ho_HR.end(), 0.0) / ho_HR.size();
			//averageHor_hl_HR = accumulate(hl_HR.begin(), hl_HR.end(), 0.0) / hl_HR.size();

			// Updated heat calculations
			//for (int timeStep = 0; timeStep < TotalTime_min; timeStep++) {
			for (int timeStep = 0; timeStep < TotalTime; timeStep++)
			{

				//TravelTime = 0;

				for (int theNode = 0; theNode <= TotalDist_stable_HR; theNode++)
				{
					if (theNode == 0) {
						if (PBC_On == 1) {
							if ((timeStep != 0) && (timeStep % PBC_loopNR != 0)) {
								HeatFluxADR_Temperature_C[theNode][timeStep] = HeatFluxADR_Temperature_C[TotalDist_stable_HR - 1][timeStep - 1];
							}
						}
					}

					adjustedDirRadE_Uns(solarSW_Dir_LI, timeStep, theNode);
					adjustedDirRadW_Uns(solarSW_Dir_LI, timeStep, theNode);
					netSolarDiffRadE_Uns(solarSW_Diff_LI, timeStep, theNode);
					netSolarDiffRadW_Uns(solarSW_Diff_LI, timeStep, theNode);

					if (startingHour >= 0 && startingHour < 12) {
						DirSW_Uns_temp = DirSW_UnsE;
						DiffSW_Uns_temp = DiffSW_UnsE;
					}
					else {
						DirSW_Uns_temp = DirSW_UnsW;
						DiffSW_Uns_temp = DiffSW_UnsW;
					}

					SW_Uns = DiffSW_Uns_temp + DirSW_Uns_temp;

					longWaveRadiation_Uns(airTemp_LI_C, real_humidity_LI, cloudiness_LI, timeStep, theNode);
					latentHeat_Uns(airTemp_LI_C, real_humidity_LI, windSp_LI, timeStep, theNode);
					sensibleHeat_Uns(airTemp_LI_C, windSp_LI, real_humidity_LI, timeStep, theNode);
					//option 1 for bed*******************************************************
					//bedSediment_HR(K_sedType_LI, sedTemp_Uns, DepthAvgALL_HR, timeStep, theNode);

					Flux_Total_Time[theNode] = SW_Uns + LW_Uns + latent_Uns + Sensible_Uns;

					//Flux_Conduction_Time[theNode] = bed_Uns;
					Flux_Evaporation_Time[theNode] = latent_Uns; //LatentE
					Flux_Convection_Time[theNode] = Sensible_Uns; //SensibleE
					FLux_AtmLW_Time[theNode] = LW_Atm_Uns;
					Flux_LCLW_Time[theNode] = LW_LC_Uns; //LandcoverLW
					Flux_BackLW_Time[theNode] = LW_Back_Uns; //WaterBack2Sky_LW
					Flux_LW_Time[theNode] = LW_Atm_Uns + LW_LC_Uns + LW_Back_Uns; //TotalLW
					Flux_DirSW_Time[theNode] = DirSW_Uns_temp; //DirectSW
					Flux_DiffSW_Time[theNode] = DiffSW_Uns_temp; //DiffuseSW
					Flux_SW_Time[theNode] = SW_Uns; //TotalSW

					//DeltaTime_Interval used to compute and retention time, based on SUNY ESF MS thesis of Jill Crispell, then PhD of Reza Abdi 
					DeltaT_HR[theNode] = (Flux_Total_Time[theNode] * dtime_Interval_min) / (DepthAvgALL_HR[theNode][timeStep] * rho_water * c_water);

					DeltaTotal_HR[theNode][timeStep] = DeltaT_HR[theNode];

					ConductionFlux_HR(Porosity, sedTemp_LI, timeStep, theNode, Rotation);
					FluxTotal_HR[theNode][timeStep] = Flux_Total_Time[theNode];
					Flux_Conduction_Time[theNode] = FluxConduction_HR[theNode][timeStep];

					double HeatFluxAdvection_C_p_dt = 0;
					double HeatFluxDispersion_C_p_dt = 0;
					double HeatFluxAD_Temperature_C;
					if (theNode != 0) {
						//Algorithm is developed for HEC-RAS applications of i-Tree CoolRiver following the logic presented by Abdi et al, 2020a, building on Abdi and Endreny, 2019
						//Abdi, Endreny and Nowak, 2020a. A model to integrate urban river thermal cooling in river restoration. Journal of Environmental Management, 258, 110023. doi:https://doi.org/10.1016/j.jenvman.2019.110023
						//Abdi and Endreny, 2019. A River Temperature Model to Assist Managers in Identifying Thermal Pollution Causes and Solutions. Water, 11(5). doi:10.3390/w11051060
						//Eq 1 in Abdi et al. 2020a contains advection, dispersion and reaction terms (heat flux Rh and lateral inflows Ri), similar to Eq 1 in Abdi and Endreny 2019, but for T rather than dT/dt
						//Eq 1 in Abdi et al. 2020a defines advection as dt(V*[(Tup-T)/dx]) to get units of C, temperature
						//Eq 4 in Abdi et al. 2020a should have Q rather than Qup in numerator of 1st RHS term
						//Eq 6 in Abdi et al. 2020a should have no denominator, removing Qa + Qb + Qc, where a = tributary inflow, b = groundwater inflow, and c = hyporheic inflow
						//Eq 3 in Abdi et al. 2020a properly divides into Eq 4 and Eq 6 only if Eq 6 removes the denominator, recognizing it must divide later by Qtotal

						//Eq 4 in Abdi et al. 2020a defines advection and dispersion as the transport of heat flux within a certain channel interval and retention time
						//Eq 4 in Abdi et al. 2020a defines retention time dtr as the inverse of velocity V for the channel interval length dx 
						//Eq 5 in Abdi et al. 2020a defines Rh2 as the heat flux based advection and dispersion, with both re-written from their formulation in Eq 1 to use heat flux terms

						//HeatFluxAdvection_C_p_dt is 1st RHS in Eq 5 of Abdi et al. 2020a
						HeatFluxAdvection_C_p_dt = (FluxTotal_HR[theNode][timeStep] + FluxConduction_HR[theNode][timeStep]) / (rho_water * c_water * DepthALL_HR[theNode][timeStep]);

						//HeatFluxDispersion_C_p_dt is 2nd RHS in Eq 5 of Abdi et al. 2020a
						HeatFluxDispersion_C_p_dt = -1 * Dispersion_HR[theNode][timeStep] * (((FluxTotal_HR[theNode][timeStep] + FluxConduction_HR[theNode][timeStep]) / (rho_water * c_water * DepthALL_HR[theNode][timeStep] * VelocityALL_HR[theNode][timeStep]) - ((FluxTotal_HR[theNode - 1][timeStep] + FluxConduction_HR[theNode - 1][timeStep]) / (rho_water * c_water * DepthALL_HR[theNode - 1][timeStep] * VelocityALL_HR[theNode - 1][timeStep]))) / dx_Interval_m);

						//HeatFluxAD_Temperature_C is 1st bracketed RHS term numerator in Eq 4 of Abdi et al. 2020a, without Qup
						//HeatFluxAD_Temperature_C represents advection and dispersion terms of heat flux
						HeatFluxAD_Temperature_C = HeatFluxADR_Temperature_C[theNode - 1][timeStep] + (HeatFluxAdvection_C_p_dt + HeatFluxDispersion_C_p_dt) * HeatFluxRetentionTime_p_dt[theNode][timeStep];

						//HeatFluxADR_Temperature_C is LHS of Eq 4 in Abdi et al. 2020a, with Qup replacing Q in numerator of 1st RHS term
						//HeatFluxADR_Temperature_C combines inflow reaction term Ri2 with HeatFluxAD_Temperature_C advection dispersion term
						//Ri2 is from Eq 6, but without the denominator Qa + Qb + Qc, which is replaced by Qtotal in Eq 4 as properly derived from Eq 3
						HeatFluxADR_Temperature_C[theNode][timeStep] = (HeatFluxAD_Temperature_C * (Q_Str_HR[theNode][timeStep] - HyporheicExchange_HR[theNode][timeStep] - Q_GW[theNode] - Q_Inflow_HR[theNode][timeStep]) +
							Q_Inflow_HR[theNode][timeStep] * T_Inflow_HR[theNode][timeStep] + HyporheicExchange_HR[theNode][timeStep] * BedTn_LI_Uns[theNode] +
							Q_GW[theNode] * Temp_GW[theNode]) /
							Q_Str_HR[theNode][timeStep];
					}

					//transforming the 2D vector (variable time space) Temp1_HRsize to 1D vector (space, fixed time), which will be used for other distances
					for (int counter = 0; counter < TotalDist_stable; counter++) {
						calcT_Temp[counter] = HeatFluxADR_Temperature_C[counter][timeStep];
					}

					if ((HeatFluxADR_Temperature_C[theNode][timeStep] > 50) || (HeatFluxADR_Temperature_C[theNode][timeStep] < 0)) {
						cout << "Model is unstable.  There could be a variety of reasons for this." << endl;
						cout << "Check your input data, or try decreasing time step and/or increasing distance step." << endl;
					}

					Rotation = Rotation + 1;
				}

				for (int count = 0; count < TotalDist_stable_HR; count++) {
					Flux_Evaporation_Nodes[count][timeStep] = Flux_Evaporation_Time[count];
					Flux_Conduction_Nodes[count][timeStep] = Flux_Conduction_Time[count];
					Flux_Convection_Nodes[count][timeStep] = Flux_Convection_Time[count];
					FLux_AtmLW_Nodes[count][timeStep] = FLux_AtmLW_Time[count];
					Flux_LCLW_Nodes[count][timeStep] = Flux_LCLW_Time[count];
					Flux_BackLW_Nodes[count][timeStep] = Flux_BackLW_Time[count];
					Flux_LW_Nodes[count][timeStep] = Flux_LW_Time[count];
					Flux_DirSW_Nodes[count][timeStep] = Flux_DirSW_Time[count];
					Flux_DiffSW_Nodes[count][timeStep] = Flux_DiffSW_Time[count];
					Flux_SW_Nodes[count][timeStep] = Flux_SW_Time[count];
				}


				for (double x = 0; x < TotalDist; x++) {
					double y = interpolate(Nodes_Uns, Flux_Total_Time, x, true);
					Flux_Total_HRdist[x][timeStep] = y;
				}

				for (double x = 0; x < TotalDist; x++) {
					double y = interpolate(Nodes_Uns, Flux_Evaporation_Time, x, true);
					Flux_Evaporation_HR[x][timeStep] = y;
				}

				for (double x = 0; x < TotalDist; x++) {
					double y = interpolate(Nodes_Uns, Flux_Conduction_Time, x, true);
					Flux_Conduction_HR[x][timeStep] = y;
				}

				for (double x = 0; x < TotalDist; x++) {
					double y = interpolate(Nodes_Uns, Flux_Convection_Time, x, true);
					Flux_Convection_HR[x][timeStep] = y;
				}

				for (double x = 0; x < TotalDist; x++) {
					double y = interpolate(Nodes_Uns, FLux_AtmLW_Time, x, true);
					FLux_AtmLW_HR[x][timeStep] = y;
				}

				for (double x = 0; x < TotalDist; x++) {
					double y = interpolate(Nodes_Uns, Flux_LCLW_Time, x, true);
					Flux_LCLW_HR[x][timeStep] = y;
				}

				for (double x = 0; x < TotalDist; x++) {
					double y = interpolate(Nodes_Uns, Flux_BackLW_Time, x, true);
					Flux_BackLW_HR[x][timeStep] = y;
				}

				for (double x = 0; x < TotalDist; x++) {
					double y = interpolate(Nodes_Uns, Flux_LW_Time, x, true);
					Flux_LW_HR[x][timeStep] = y;
				}

				for (double x = 0; x < TotalDist; x++) {
					double y = interpolate(Nodes_Uns, Flux_DirSW_Time, x, true);
					Flux_DirSW_HR[x][timeStep] = y;
				}

				for (double x = 0; x < TotalDist; x++) {
					double y = interpolate(Nodes_Uns, Flux_DiffSW_Time, x, true);
					Flux_DiffSW_HR[x][timeStep] = y;
				}

				for (double x = 0; x < TotalDist; x++) {
					double y = interpolate(Nodes_Uns, Flux_SW_Time, x, true);
					Flux_SW_HR[x][timeStep] = y;
				}

				for (double x = 0; x < TotalDist; x++) {
					double y = interpolate(Nodes_Uns, calcT_Temp, x, true);
					Temp_HRdist[x][timeStep] = y;
				}

				Rotation = 0;
				startingHour++;
				if (startingHour > 24) {
					startingHour = 0;
				}

				//Note: This Xterm output code for regular use, and should not be removed
				//If modulus timeStep and 25% of TotalTime equals zero, then write output to Xterm window to update user
				if (timeStep % int(0.25 * TotalTime) == 0) {
					cout << "Simulating time step " << timeStep + 1 << " of " << TotalTime << endl;
				}
				//If timeStep equals TotalTime, using modulus operator, then write output to Xterm window to update user
				else if (timeStep + 1 == TotalTime) {
					cout << "Simulating time step " << timeStep + 1 << " of " << TotalTime << endl;
				}
			}

			if (input->CoolRiverVariables["CR_Minute_output"] == 1) {
				t_minBased.resize(TotalDist_stable);
				SWDir_2D_min.resize(TotalDist_stable);//396
				SWDiff_2D_min.resize(TotalDist_stable);
				SW_2D_min.resize(TotalDist_stable);
				atmLW_2D_min.resize(TotalDist_stable);
				LCLW_2D_min.resize(TotalDist_stable);
				backLW_2D_min.resize(TotalDist_stable);
				LW_2D_min.resize(TotalDist_stable);
				Latent_2D_min.resize(TotalDist_stable);
				Sensible_2D_min.resize(TotalDist_stable);
				Bed_2D_min.resize(TotalDist_stable);
				heat_flux_2D_min.resize(TotalDist_stable);
				delta_2D_min.resize(TotalDist_stable);
				depthAvgALL_2D_min.resize(TotalDist_stable);
				AreaALL_2D_min.resize(TotalDist_stable);
				VelocityALL_2D_min.resize(TotalDist_stable);
				WidthALL_2D_min.resize(TotalDist_stable);
				RetentionT_2D_min.resize(TotalDist_stable);
				Pw_ALL_2D_min.resize(TotalDist_stable);
				WSElev_ALL_2D_min.resize(TotalDist_stable);
				Q_Str_2D_min.resize(TotalDist_stable);
				HyporheicExchange_2D_min.resize(TotalDist_stable);
				Dispersion_2D_min.resize(TotalDist_stable);
				FluxConduction_2D_min.resize(TotalDist_stable);
				FluxTotal_HR.resize(TotalDist_stable);
				for (int i = 0; i < TotalDist_stable; i++) {
					t_minBased[i].resize(TotalTime * 60);
					SWDir_2D_min[i].resize(TotalTime * 60);//2880
					SWDiff_2D_min[i].resize(TotalTime * 60);
					SW_2D_min[i].resize(TotalTime * 60);
					atmLW_2D_min[i].resize(TotalTime * 60);
					LCLW_2D_min[i].resize(TotalTime * 60);
					backLW_2D_min[i].resize(TotalTime * 60);
					LW_2D_min[i].resize(TotalTime * 60);
					Latent_2D_min[i].resize(TotalTime * 60);
					Sensible_2D_min[i].resize(TotalTime * 60);
					Bed_2D_min[i].resize(TotalTime * 60);
					heat_flux_2D_min[i].resize(TotalTime * 60);
					delta_2D_min[i].resize(TotalTime * 60);
					depthAvgALL_2D_min[i].resize(TotalTime * 60);
					AreaALL_2D_min[i].resize(TotalTime * 60);
					VelocityALL_2D_min[i].resize(TotalTime * 60);
					WidthALL_2D_min[i].resize(TotalTime * 60);
					RetentionT_2D_min[i].resize(TotalTime * 60);
					Pw_ALL_2D_min[i].resize(TotalTime * 60);
					WSElev_ALL_2D_min[i].resize(TotalTime * 60);
					Q_Str_2D_min[i].resize(TotalTime * 60);
					HyporheicExchange_2D_min[i].resize(TotalTime * 60);
					Dispersion_2D_min[i].resize(TotalTime * 60);
					FluxConduction_2D_min[i].resize(TotalTime * 60);
				}

				for (int i = 0; i < TotalDist_stable; i++) {
					vector < double > t_min(TotalTime * 60);
					vector < double > heat_flux_min(TotalTime * 60);
					vector < double > SWDir_min(TotalTime * 60);
					vector < double > SWDiff_min(TotalTime * 60);
					vector < double > SW_min(TotalTime * 60);
					vector < double > LW_min(TotalTime * 60);
					vector < double > atmLW_min(TotalTime * 60);
					vector < double > LCLW_min(TotalTime * 60);
					vector < double > backLW_min(TotalTime * 60);
					vector < double > Latent_min(TotalTime * 60);
					vector < double > Sensible_min(TotalTime * 60);
					vector < double > Bed_min(TotalTime * 60);
					vector < double > delta_min(TotalTime * 60);
					vector < double > depthAvgALL_min(TotalTime * 60);
					vector < double > AreaALL_min(TotalTime * 60);
					vector < double > VelocityALL_min(TotalTime * 60);
					vector < double > WidthALL_min(TotalTime * 60);
					vector < double > RetentionT_min(TotalTime * 60);
					vector < double > Pw_ALL_min(TotalTime * 60);
					vector < double > WSElev_ALL_min(TotalTime * 60);
					vector < double > Q_Str_min(TotalTime * 60);
					vector < double > HyporheicExchange_min(TotalTime * 60);
					vector < double > Dispersion_min(TotalTime * 60);
					vector < double > FluxConduction_min(TotalTime * 60);
					for (int j = 0; j < TotalDist_stable; j++)
					{
						t_min = minute(HeatFluxADR_Temperature_C, j);
						heat_flux_min = minute(FluxTotal_HR, j);
						SWDir_min = minute(Flux_DirSW_Nodes, j);
						SWDiff_min = minute(Flux_DiffSW_Nodes, j);
						SW_min = minute(Flux_SW_Nodes, j);
						LW_min = minute(Flux_LW_Nodes, j);
						atmLW_min = minute(FLux_AtmLW_Nodes, j);
						LCLW_min = minute(Flux_LCLW_Nodes, j);
						backLW_min = minute(Flux_BackLW_Nodes, j);
						Latent_min = minute(Flux_Evaporation_Nodes, j);
						Sensible_min = minute(Flux_Convection_Nodes, j);
						Bed_min = minute(Flux_Conduction_Nodes, j);

						if (input->CoolRiverVariables["CR_Extended"] == 1)
						{

							delta_min = minute(DeltaTotal_HR, j);
							depthAvgALL_min = minute(DepthAvgALL_HR, j);
							AreaALL_min = minute(AreaALL_HR, j);
							VelocityALL_min = minute(VelocityALL_HR, j);
							WidthALL_min = minute(WidthALL_HR, j);
							RetentionT_min = minute(HeatFluxRetentionTime_p_dt, j);
							Pw_ALL_min = minute(Pw_ALL_HR, j);
							WSElev_ALL_min = minute(WSElev_ALL_HR, j);
							Q_Str_min = minute(Q_Str_HR, j);
							HyporheicExchange_min = minute(HyporheicExchange_HR, j);
							Dispersion_min = minute(Dispersion_HR, j);
							FluxConduction_min = minute(FluxConduction_HR, j);
						}

						for (double x = 0; x < (TotalTime * 60); x++) {

							double y = interpolate(hourlyTime, t_min, x, true);
							t_minBased[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, heat_flux_min, x, true);
							heat_flux_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, SWDir_min, x, true);
							SWDir_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, SWDiff_min, x, true);
							SWDiff_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, SW_min, x, true);
							SW_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, LW_min, x, true);
							LW_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, atmLW_min, x, true);
							atmLW_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, LCLW_min, x, true);
							LCLW_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, backLW_min, x, true);
							backLW_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, Latent_min, x, true);
							Latent_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, Sensible_min, x, true);
							Sensible_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, Bed_min, x, true);
							Bed_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, delta_min, x, true);
							delta_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, depthAvgALL_min, x, true);
							depthAvgALL_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, AreaALL_min, x, true);
							AreaALL_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, VelocityALL_min, x, true);
							VelocityALL_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, WidthALL_min, x, true);
							WidthALL_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, RetentionT_min, x, true);
							RetentionT_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, Pw_ALL_min, x, true);
							Pw_ALL_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, WSElev_ALL_min, x, true);
							WSElev_ALL_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, Q_Str_min, x, true);
							Q_Str_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, HyporheicExchange_min, x, true);
							HyporheicExchange_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, Dispersion_min, x, true);
							Dispersion_2D_min[j][x] = y;
						}
						for (double x = 0; x < (TotalTime * 60); x++) {
							double y = interpolate(hourlyTime, FluxConduction_min, x, true);
							FluxConduction_2D_min[j][x] = y;
						}
					}

				}
			}
			// For Debugging purpose*******************************************
			//for (int i = 0; i < 12; i++) {
			//  for (int j = 0; j < 96; j++) {
			//      tempNodesDebugg[i][j] = HeatFluxADR_Temperature_C[nodeDebugg[i]][j];
			//  }

			//}
			cout << "... HEC-RAS based simulation process is done!" << endl;
			break;
		}
		case 4: {

			vector<vector<double>>().swap(a_c);
			vector<vector<double>>().swap(b_c);
			vector<vector<double>>().swap(c_c);
			vector<vector<double>>().swap(o);
			vector<vector<double>>().swap(p);
			vector<vector<double>>().swap(q);
			vector<vector<double>>().swap(o_c);
			vector<vector<double>>().swap(p_c);
			vector<vector<double>>().swap(q_c);
			vector<vector<double>>().swap(d);
			vector<vector<double>>().swap(g);
			vector<vector<double>>().swap(k);
			vector<vector<double>>().swap(m);
			vector<vector<double>>().swap(A);
			vector<vector<double>>().swap(a);
			vector<vector<double>>().swap(b);
			vector<vector<double>>().swap(c);

			// STEP 6: Pre-allocate arrays used in iterative solution and set
			// initial and boundary temperature conditions.
			// ===================> Solving the Runge-Kutta method

			// set temperatures for first time step at input values
			T.resize(TotalDist);
			for (int i = 0; i < TotalDist; i++)
			{
				T[i].resize(TotalTime);
				T[i][0] = initialT;
			}
			for (int i = 0; i < TotalTime; i++)
			{
				T[0][i] = obs_xo_LI[i];
			} // set boundary temperature condition

			initialT_T0.clear();
			initialT_T0.resize(TotalDist);
			for (int i = 0; i < TotalDist; i++)
			{
				initialT_T0[i] = initialT;
			}
			// Insert R - values for first time step.
			// Shortwave calculation for the first time step:
			solarReflectivity();
			adjustedDirRadE(solarSW_Dir_LI, 0);	  // preparing the adjustedDirSW_E vector
			adjustedDirRadW(solarSW_Dir_LI, 0);	  // preparing the adjustedDirSW_W vector
			netSolarDiffRadE(solarSW_Diff_LI, 0); // preparing the adjustedDiffSW_E vector
			netSolarDiffRadW(solarSW_Diff_LI, 0); // preparing the adjustedDiffSW_W vector
			// Longwave radiation for the first time step
			longWaveRadiation(airTemp_LI_C, real_humidity_LI, cloudiness_LI, initialT_T0, 0);
			// latent heat in the fist time step
			latentHeat(airTemp_LI_C, real_humidity_LI, initialT_T0, windSp_LI, 0);
			// Sensible heat for the first time step
			sensibleHeat(airTemp_LI_C, initialT_T0, windSp_LI, real_humidity_LI, 0);
			// Stream Bed heat for the first time step
			bedSediment(wp_total, width_total, K_sedType_LI, initialT_T0, sedimentTime_LI, BedDepthMeas_LI, 0);

			// ============ Time managing for East/West side of the stream bor allocating shortwave radiation correctly ===========

			minToHour(startingHour, TotalTime, timeRepeatedHour);

			// =======================================================================
			// Insert values for first time step.

			// Insert values for first time step.

			for (int i = 0; i < TotalDist; i++)
			{
				if (timeRepeatedHour[0] >= 0 && timeRepeatedHour[0] < 12)
				{
					SWDir_2D[i][0] = adjustedDirSW_E[i];
					SWDiff_2D[i][0] = adjustedDiffSW_E[i];
				}
				else
				{
					SWDir_2D[i][0] = adjustedDirSW_W[i];
					SWDiff_2D[i][0] = adjustedDiffSW_W[i];
				}
			}

			// Step 7: Calculate stream temperature using a second order Runge-Kutta method.
			// Change in temperature with respect to time is calculated at intermediate timesteps as defined by k1, which is
			// used to determine temperature at the intermediate time step. k1 is then used to calculate change in temperature to the next
			// time step, or k2.  Temperature at the future timestep is solved using k1 and k2.

			for (int timeStep = 0; timeStep < TotalTime; timeStep++)
			{
				if (timeStep == (TotalTime - 1))
				{
				}
				else
				{
					// Insert heat flux for k1 at n=2:r-1
					// =============================== Next time step (timeStep) calculations
					adjustedDirRadE(solarSW_Dir_LI, timeStep);	  // preparing the adjustedDirSW_E vector
					adjustedDirRadW(solarSW_Dir_LI, timeStep);	  // preparing the adjustedDirSW_W vector
					netSolarDiffRadE(solarSW_Diff_LI, timeStep); // preparing the adjustedDiffSW_E vector
					netSolarDiffRadW(solarSW_Diff_LI, timeStep); // preparing the adjustedDiffSW_W vector
					// Longwave radiation for the first time step
					longWaveRadiation(airTemp_LI_C, real_humidity_LI, cloudiness_LI, initialT_T0, timeStep);
					// latent heat in the fist time step
					latentHeat(airTemp_LI_C, real_humidity_LI, initialT_T0, windSp_LI, timeStep);
					// Sensible heat for the first time step
					sensibleHeat(airTemp_LI_C, initialT_T0, windSp_LI, real_humidity_LI, timeStep);
					// Stream Bed heat for the first time step
					bedSediment(wp_total, width_total, K_sedType_LI, initialT_T0, sedimentTime_LI, BedDepthMeas_LI, timeStep);
					// ================================ Creating the "heat_flux_k1" 2D vector
					// ========= Time managing for East/West side of the stream for allocating shortwave radiation correctly ========

					// Insert values for first time step.

					for (int i = 0; i < TotalDist; i++)
					{

						if (timeRepeatedHour[timeStep] >= 0 && timeRepeatedHour[timeStep] < 12)
						{
							SWDir_2D[i][timeStep] = adjustedDirSW_E[i];
							SWDiff_2D[i][timeStep] = adjustedDiffSW_E[i];
						}
						else
						{
							SWDir_2D[i][timeStep] = adjustedDirSW_W[i];
							SWDiff_2D[i][timeStep] = adjustedDiffSW_W[i];
						}
						SW_2D[i][timeStep] = SWDir_2D[i][timeStep] + SWDiff_2D[i][timeStep];

						heat_flux_k1[i][timeStep] = SW_2D[i][timeStep] + LW_2D[i][timeStep] + Latent_2D[i][timeStep] + Sensible_2D[i][timeStep] + Bed_2D[i][timeStep];
					}

					for (int i = 1; i <= (TotalDist - 2); i++)
					{
						u1[i][timeStep] = (Q_half_min[i][timeStep] / volume[i][0]) * (0.5 * T[(i - 1)][timeStep] - 0.5 * T[i][timeStep]);
						v1[i][timeStep] = (Q_half_min[(i + 1)][timeStep] / volume[i][0]) * (0.5 * T[i][timeStep] - 0.5 * T[(i + 1)][timeStep]);
						s1[i][timeStep] = (Q_L_min[i][timeStep] / volume[i][0]) * (sedimentDist_LI[i] - T[i][timeStep]);
						m1[i][timeStep] = (width_total[i][timeStep] * heat_flux_k1[i][timeStep]) / ((rho_water * c_water)) / area_total[i][timeStep];
						k1[i][timeStep] = u1[i][timeStep] + v1[i][timeStep] + s1[i][timeStep] + m1[i][timeStep];
					}

					// T(r,t) is assumed to be T(r-1,t)
					// for i = TotalDist
					u1[nodes - 1][timeStep] = (Q_half_min[nodes - 1][timeStep] / volume[nodes - 1][0]) * (0.5 * T[(nodes - 2)][timeStep] - 0.5 * T[nodes - 1][timeStep]);
					v1[nodes - 1][timeStep] = (Q_half_min[nodes - 1][timeStep] / volume[nodes - 1][0]) * (0.5 * T[nodes - 1][timeStep] - 0.5 * T[nodes - 1][timeStep]);
					s1[nodes - 1][timeStep] = (Q_L_min[nodes - 1][timeStep] / volume[nodes - 1][0]) * (sedimentDist_LI[nodes - 1] - T[nodes - 1][timeStep]);
					m1[nodes - 1][timeStep] = (width_total[nodes - 1][timeStep] * heat_flux_k1[nodes - 1][timeStep]) / ((rho_water * c_water)) / area_total[nodes - 1][timeStep];
					k1[nodes - 1][timeStep] = u1[nodes - 1][timeStep] + v1[nodes - 1][timeStep] + s1[nodes - 1][timeStep] + m1[nodes - 1][timeStep];

					// Calculate temperature based on k1
					T_k1[0][timeStep] = obs_xo_LI[timeStep]; // set boundary temperature condition
					for (int i = 1; i < TotalDist; i++)
					{
						T_k1[i][timeStep] = T[i][timeStep] + (dt * k1[i][timeStep]);
					}

					initialT_T0.clear();
					initialT_T0.resize(TotalDist);
					for (int i = 0; i < TotalDist; i++)
					{
						initialT_T0[i] = T_k1[i][timeStep];
					}

					// *****************CHECKING THE RESULTS OF K1 - START
					float averageTK1 = accumulate(initialT_T0.begin(), initialT_T0.end(), 0.0) / initialT_T0.size();
					cout << "*** The Average of the T_K1:  " << averageTK1 << endl;
					// *****************CHECKING THE RESULTS OF K1 - END

					// Calculate k2 ===========> Insert R - values for k2 *****************************************
					adjustedDirRadE(solarSW_Dir_LI, timeStep);	  // preparing the adjustedDirSW_E vector
					adjustedDirRadW(solarSW_Dir_LI, timeStep);	  // preparing the adjustedDirSW_W vector
					netSolarDiffRadE(solarSW_Diff_LI, timeStep); // preparing the adjustedDiffSW_E vector
					netSolarDiffRadW(solarSW_Diff_LI, timeStep); // preparing the adjustedDiffSW_W vector
					// Longwave radiation for the first time step
					longWaveRadiation(airTemp_LI_C, real_humidity_LI, cloudiness_LI, initialT_T0, timeStep);
					// latent heat in the fist time step
					latentHeat(airTemp_LI_C, real_humidity_LI, initialT_T0, windSp_LI, timeStep);
					// Sensible heat for the first time step
					sensibleHeat(airTemp_LI_C, initialT_T0, windSp_LI, real_humidity_LI, timeStep);
					// Stream Bed heat for the first time step
					bedSediment(wp_total, width_total, K_sedType_LI, initialT_T0, sedimentTime_LI, BedDepthMeas_LI, timeStep);

					// Insert values for first time step.

					for (int i = 0; i < TotalDist; i++)
					{
						if (timeRepeatedHour[timeStep] >= 0 && timeRepeatedHour[timeStep] < 12)
						{
							SWDir_2D_k2[i][timeStep] = adjustedDirSW_E[i];
							SWDiff_2D_k2[i][timeStep] = adjustedDiffSW_E[i];
						}
						else
						{
							SWDir_2D_k2[i][timeStep] = adjustedDirSW_W[i];
							SWDiff_2D_k2[i][timeStep] = adjustedDiffSW_W[i];
						}
						SW_2D_k2[i][timeStep] = SWDir_2D_k2[i][timeStep] + SWDiff_2D_k2[i][timeStep];
						//atmLW_2D_k2[i][timeStep] = atmLW_2D[i][timeStep];
						//LCLW_2D_k2[i][timeStep] = LCLW_2D[i][timeStep];
						//backLW_2D_k2[i][timeStep] = backLW[i];
						LW_2D_k2[i][timeStep] = LW_2D[i][timeStep];
						Latent_2D_k2[i][timeStep] = Latent_2D[i][timeStep];
						Sensible_2D_k2[i][timeStep] = Sensible_2D[i][timeStep];
						Bed_2D_k2[i][timeStep] = Bed_2D[i][timeStep];

						heat_flux_k2[i][timeStep] = SW_2D_k2[i][timeStep] + LW_2D_k2[i][timeStep] + Latent_2D_k2[i][timeStep] + Sensible_2D_k2[i][timeStep] + Bed_2D_k2[i][timeStep];
					}

					// T(r,t) is assumed to be T(r-1,t)
					for (int i = 1; i <= (TotalDist - 2); i++)
					{
						u2[i][timeStep] = (Q_half_min[i][(timeStep + 1)] / volume[i][0]) * (0.5 * T_k1[(i - 1)][timeStep] - 0.5 * T_k1[i][timeStep]);
						v2[i][timeStep] = (Q_half_min[(i + 1)][(timeStep + 1)] / volume[i][0]) * (0.5 * T_k1[i][timeStep] - 0.5 * T_k1[(i + 1)][timeStep]);
						s2[i][timeStep] = (Q_L_min[i][(timeStep + 1)] / volume[i][0]) * (sedimentDist_LI[i] - T_k1[i][timeStep]);
						m2[i][timeStep] = (width_total[i][timeStep] * heat_flux_k2[i][timeStep]) / ((rho_water * c_water)) / area_total[i][timeStep];
						k2[i][timeStep] = u2[i][timeStep] + v2[i][timeStep] + s2[i][timeStep] + m2[i][timeStep];
					}

					u2[nodes - 1][timeStep] = (Q_half_min[nodes - 1][(timeStep + 1)] / volume[nodes - 1][0]) * (0.5 * T_k1[(nodes - 2)][timeStep] - 0.5 * T_k1[nodes - 1][timeStep]);
					v2[nodes - 1][timeStep] = (Q_half_min[nodes][(timeStep + 1)] / volume[nodes - 1][0]) * (0.5 * T_k1[nodes - 1][timeStep] - 0.5 * T_k1[nodes - 1][timeStep]);
					s2[nodes - 1][timeStep] = (Q_L_min[nodes - 1][(timeStep + 1)] / volume[nodes - 1][0]) * (sedimentDist_LI[nodes - 1] - T_k1[nodes - 1][timeStep]);
					m2[nodes - 1][timeStep] = (width_total[nodes - 1][timeStep] * heat_flux_k2[nodes - 1][timeStep]) / ((rho_water * c_water)) / area_total[nodes - 1][timeStep];
					k2[nodes - 1][timeStep] = u2[nodes - 1][timeStep] + v2[nodes - 1][timeStep] + s2[nodes - 1][timeStep] + m2[nodes - 1][timeStep];

					// Calculate temperature at next timestep for each node
					initialT_T0.clear();
					initialT_T0.resize(TotalDist);
					for (int i = 1; i < TotalDist; i++)
					{
						T[i][(timeStep + 1)] = T[i][timeStep] + (dt * (0.5 * k1[i][timeStep] + 0.5 * k2[i][timeStep]));
					}
					for (int i = 0; i < TotalDist; i++)
					{
						initialT_T0[i] = T[i][timeStep + 1];
					}

					float averageT = accumulate(initialT_T0.begin(), initialT_T0.end(), 0.0) / initialT_T0.size();
					//cout << "*** The Average of the initialT_T0:  " << averageT << endl;

					// Insert R-values for future time step
					// =============================== Next time step (timeStep+1) calculations
					adjustedDirRadE(solarSW_Dir_LI, (timeStep + 1));	// preparing the adjustedDirSW_E vector
					adjustedDirRadW(solarSW_Dir_LI, (timeStep + 1));	// preparing the adjustedDirSW_W vector
					netSolarDiffRadE(solarSW_Diff_LI, (timeStep + 1)); // preparing the adjustedDiffSW_E vector
					netSolarDiffRadW(solarSW_Diff_LI, (timeStep + 1)); // preparing the adjustedDiffSW_W vector
					// Longwave radiation for the first time step
					longWaveRadiation(airTemp_LI_C, real_humidity_LI, cloudiness_LI, initialT_T0, (timeStep + 1));
					// latent heat in the fist time step
					latentHeat(airTemp_LI_C, real_humidity_LI, initialT_T0, windSp_LI, (timeStep + 1));
					// Sensible heat for the first time step
					sensibleHeat(airTemp_LI_C, initialT_T0, windSp_LI, real_humidity_LI, (timeStep + 1));
					// Stream Bed heat for the first time step
					bedSediment(wp_total, width_total, K_sedType_LI, initialT_T0, sedimentTime_LI, BedDepthMeas_LI, (timeStep + 1));

					// Insert values for first time step.
					//vector<vector<double>> heat_flux_2D, SWDir_2D, SWDiff_2D, SW_2D, LW_2D, atmLW_2D, LCLW_2D, backLW_2D, Latent_2D, Sensible_2D, Bed_2D;
					for (int i = 0; i < TotalDist; i++)
					{
						if (timeRepeatedHour[timeStep] >= 0 && timeRepeatedHour[timeStep] < 12)
						{
							SWDir_2D[i][(timeStep + 1)] = adjustedDirSW_E[i];
							SWDiff_2D[i][(timeStep + 1)] = adjustedDiffSW_E[i];
						}
						else
						{
							SWDir_2D[i][(timeStep + 1)] = adjustedDirSW_W[i];
							SWDiff_2D[i][(timeStep + 1)] = adjustedDiffSW_W[i];
						}
					}
					//Note: This Xterm output code for regular use, and should not be removed
					//If modulus timeStep and 25% of TotalTime equals zero, then write output to Xterm window to update user
					if (timeStep % int(0.25 * TotalTime) == 0) {
						cout << "Simulating time step " << timeStep + 1 << " of " << TotalTime << endl;
					}
					//If timeStep equals TotalTime, using modulus operator, then write output to Xterm window to update user
					else if (timeStep + 1 == TotalTime) {
						cout << "Simulating time step " << timeStep + 1 << " of " << TotalTime << endl;
					}
				}
			}
			cout << "... Runge-Kutta modeling methodology is complete." << endl;
			for (int i = 0; i < TotalDist; i++)
			{
				for (int j = 0; j < TotalTime; j++)
				{
					SW_2D[i][j] = SWDir_2D[i][j] + SWDiff_2D[i][j];
					heat_flux_2D[i][j] = SW_2D[i][j] + LW_2D[i][j] + Latent_2D[i][j] + Sensible_2D[i][j] + Bed_2D[i][j];
				}
			}
			break;
		}
		default: {
			cout << "Wrong modeling methodology code! Check the methodology code and try again." << endl;
			break;
		}
	}
}

//function to write out minutely time step outputs
vector<double> StreamTemperature::minute(vector<vector<double>>& yData, int k) {
	//for (int i = 0; i < TotalDist; i++) {
	//creating vectors of T_temp hour and t_minute as generic vector name for all variables
	vector < double > T_temp(TotalTime + 1);
	vector < double > t_minute(TotalTime * 60);
	for (int j = 0; j < TotalTime; j++) {
		//j is total time as hours, k is minutely steps within each j
		T_temp[j] = yData[k][j];
	}
	for (int j = 0; j < TotalTime; j++) {
		//f is slope, used in interpolation function, fraction of hours per minute
		double f = ((T_temp[j] - T_temp[j + 1]) / 59);
		//loop through 60 minutes
		for (int i = 0; i < 60; i++) {
			//interpolation function using slope f for each minute
			double min = (T_temp[j]) - (((i + 1) - 1) * (f));
			t_minute[j * 60 + i] = min;
			}
	}
	return t_minute;
}



//   Returns interpolated value at x from parallel arrays ( xData, yData )
//   Assumes that xData has at least two elements, is sorted and is strictly monotonic increasing
//   boolean argument extrapolate determines behaviour beyond ends of array (if needed)

double StreamTemperature::interpolate(vector<double>& xData, vector<double>& yData, double x, bool extrapolate)
{
	int size = int(xData.size());
	//only when the minutely is equal to 1 do we return yData, which are minutely values
	if ((input->CoolRiverVariables["CR_Minute_output"] == 1) && (yData.size() == TotalTime * 60)) {

		return yData[x];
	}
	else {

		int i = 0;				  // find left end of interval for interpolation
		if (x >= xData[size - 2]) // special case: beyond right end
		{
			i = size - 2;
		}
		else
		{
			while (x > xData[i + 1])
				i++;
		}
		double xL = xData[i], yL = yData[i], xR = xData[i + 1], yR = yData[i + 1]; // points on either side (unless beyond ends)
		if (!extrapolate)														   // if beyond ends of array and not extrapolating
		{
			if (x < xL)
				yR = yL;
			if (x > xR)
				yL = yR;
		}

		double dydx = (yR - yL) / (xR - xL); // gradient
		return yL + dydx * (x - xL);		 // linear interpolation
	}
}

//======================================================================

void StreamTemperature::minToHour(int startH, int size, vector<int>& dateHTemp)
{
	double value1 = size / 60.0;  // 3100 / 60 = 51.6 ====> example
	int value1_f = int(floor(value1)); // 51
	int full = value1_f * 60;
	int extra = size - (value1_f * 60);

	dateHTemp.resize(size);
	int j = 1;
	int z = 0;
	int counter = startH;
	for (int hour = 0; hour < value1_f; hour++)
	{
		for (int i = 0; i <= 59; i++)
		{
			dateHTemp[i + (z * 60)] = counter;
		}
		z = z + 1;
		counter = counter + 1;
		if (counter > 23)
		{
			counter = counter - 24;
		}
	}

	for (int i = 0; i < extra; i++)
	{
		dateHTemp[(full + i)] = counter;
	}
}

//Thomas tridiagonal solver: a (sub), b (diag), c (super), rhs -> x
void StreamTemperature::Thomas_Numerical_Solver(const vector<double>& a, vector<double> b, const vector<double>& c, const vector<double>& rhs, vector<double>& x)
{
	const int n = (int)b.size();
	vector<double> d(rhs); // working copy of rhs

	// forward sweep
	for (int i = 1; i < n; ++i) {
		const double m = a[i] / b[i - 1];
		b[i] -= m * c[i - 1];
		d[i] -= m * d[i - 1];
	}
	// back substitution
	x.resize(n);
	x[n - 1] = d[n - 1] / b[n - 1];
	for (int i = n - 2; i >= 0; --i) x[i] = (d[i] - c[i] * x[i + 1]) / b[i];
}


// ================================= solving the linear equation using Gaussian elimination for Ax=B linear equation
vector<double> StreamTemperature::gauss(vector<vector<double>>& A)
{
	int n = int(A.size());

	for (int i = 0; i < n; i++)
	{
		// Search for maximum in this column
		double maxEl = abs(A[i][i]);
		int maxRow = i;
		for (int k = i + 1; k < n; k++)
		{
			if (abs(A[k][i]) > maxEl)
			{
				maxEl = abs(A[k][i]);
				maxRow = k;
			}
		}

		// Swap maximum row with current row (column by column)
		for (int k = i; k < n + 1; k++)
		{
			double tmp = A[maxRow][k];
			A[maxRow][k] = A[i][k];
			A[i][k] = tmp;
		}

		// Make all rows below this one 0 in current column
		for (int k = i + 1; k < n; k++)
		{
			double c = -A[k][i] / A[i][i];
			for (int j = i; j < n + 1; j++)
			{
				if (i == j)
				{
					A[k][j] = 0;
				}
				else
				{
					A[k][j] += c * A[i][j];
				}
			}
		}
	}

	// Solve equation Ax=b for an upper triangular matrix A
	vector<double> c = vector<double>(n);
	for (int i = n - 1; i >= 0; i--)
	{
		c.at(i) = A[i][n] / A[i][i];
		for (int k = i - 1; k >= 0; k--)
		{
			A[k][n] -= A[k][i] * c.at(i);
		}
	}
	return c;
}

double StreamTemperature::maxValue(double x, double y, double z)
{
	double Maximum = x;
	if (y > Maximum)
	{
		Maximum = y;
	}
	if (z > Maximum)
	{
		Maximum = z;
	}

	return Maximum;
}

vector<double> StreamTemperature::interp1(vector<double>& x, vector<double>& y, vector<double>& x_new)
{
	// Nearest interpolation for the y_new vector based on the distances in x and x_new and also based on the values in y
	vector<double> y_new;
	y_new.resize(x_new.size());
	int counter = 0;
	for (int i = 0; i < x_new.size(); i++)
	{
		double up_dist = x_new[i] - x[counter];
		double down_dist = x[counter + 1] - x_new[i];
		if (down_dist < up_dist)
		{
			y_new[i] = y[counter + 1];
		}
		else
		{
			y_new[i] = y[counter];
		}
		if (x_new[i] >= x[counter + 1])
		{
			counter++;
		}
	}
	return y_new;
}

void StreamTemperature::initialConditions(int Node)
{

	// Set Flow Initial Conditions
	if (flag_BC == 1)
	{
		Q[0][Node] = Q_minBased[time_Uns];
	}
	else
	{
		Q[0][Node] = Q[0][Node - 1] + Q_In[Node - 1][time_Uns] + Q_GW[Node - 1];
	}
	Q[1][Node] = Q[0][Node];
	// ======================================================
	// Set Temperature Initial Conditions
	Temp_unsteady[0][Node] = Tobs_minBased[time_Uns];
	Temp_unsteady[1][Node] = Temp_unsteady[0][Node];
	// ======================================================
	// Calculate Initial Condition Hydraulics
	if (Node != TotalDist_stable)
	{

		if (s_unsteady[Node] <= 0)
		{
			cout << "Slope cannot be less than or equal to zero unless you enter a control depth." << endl;
		}

		if (flag_BC == 1)
		{
			depth_unsteady[Node][0] = 1.0;
		}
		else
		{
			depth_unsteady[Node][0] = depth_unsteady[Node - 1][0];
		}

		if (Q[0][Node] < 0.0071)
		{
			// Channel is going dry
			//cout << "The channel is going dry. " << endl;
			Flag_SkipNode[Node] = 1;
		}
		else
		{
			// Channel has sufficient flow
			Flag_SkipNode[Node] = 0;
		}

		double Q_Est = Q[0][Node];

		if (Flag_SkipNode[Node] == 0)
		{
			double Converge = 100000.0;
			double dy = 0.01;
			double D_Est = depth_unsteady[Node][0];
			double A_Est = AreaX[Node][0];
			double Fy = 0;
			double Fyy = 0;
			double dFy;
			double thed;

			int Count_Iterations = 0;
			int passCode = 0;

			while (passCode == 0)
			{
				if (D_Est == 0)
				{
					D_Est = 10.0;
				}
				A_Est = D_Est * (width_unsteady[Node] + Z_unsteady[Node] * D_Est);
				Pw_unsteady[Node] = width_unsteady[Node] + 2.0 * D_Est * sqrt(1.0 + pow(Z_unsteady[Node], 2.0));
				if (Pw_unsteady[Node] <= 0)
				{
					Pw_unsteady[Node] = 0.00001;
				}
				Rh_unsteady[Node] = A_Est / Pw_unsteady[Node];
				Fy = A_Est * pow(Rh_unsteady[Node], (2.0 / 3.0)) - (n_unsteady[Node]) * Q_Est / sqrt(s_unsteady[Node]);
				thed = D_Est + dy;
				A_Est = thed * (width_unsteady[Node] + Z_unsteady[Node] * thed);
				Pw_unsteady[Node] = width_unsteady[Node] + 2.0 * thed * sqrt(1 + pow(Z_unsteady[Node], 2.0));
				if (Pw_unsteady[Node] <= 0)
				{
					Pw_unsteady[Node] = 0.00001;
				}
				Rh_unsteady[Node] = A_Est / Pw_unsteady[Node];
				Fyy = A_Est * pow(Rh_unsteady[Node], (2.0 / 3.0)) - (n_unsteady[Node]) * Q_Est / sqrt(s_unsteady[Node]);
				dFy = (Fyy - Fy) / dy;
				if (dFy == 0)
				{
					dFy = 0.99;
				}
				thed = D_Est - Fy / dFy;
				D_Est = thed;
				if ((D_Est < 0) || (D_Est > 1000000000000) || (Count_Iterations > 1000))
				{
					srand(int(time(0)));
					double r = rand() % 1000;
					D_Est = 10.0 * r; // Randomly reseed initial value and step
					Converge = 10.0;
					Count_Iterations = 0;
				}
				dy = 0.01;
				Converge = abs(Fy / dFy);
				if (Converge < 0.001)
				{
					passCode++;
				}
				Count_Iterations = Count_Iterations + 1;
			}
			depth_unsteady[Node][0] = D_Est;
			AreaX[Node][0] = A_Est;
			velocity_unsteady[Node][0] = Q[0][Node] / AreaX[Node][0];
			width_UnsTotal[Node] = width_unsteady[Node] + 2.0 * Z_unsteady[Node] * depth_unsteady[Node][0];
			// Celerity(Node) = theVelocity(Node, 0) + Sqr(9.8 * theDepth(Node, 0))
		}
		else
		{
			Q_Est = 0;
			depth_unsteady[Node][0] = 0;
			AreaX[Node][0] = 0;
			Pw_unsteady[Node] = 0;
			Rh_unsteady[Node] = 0;
			width_UnsTotal[Node] = 0;
			depth_AvgUns[Node] = 0;
			velocity_unsteady[Node][0] = 0;
			Q[0][Node] = 0;
			// Celerity(Node) = 0
		}
	}
}

void StreamTemperature::hydroStability()
{
	double dummy;
	double maxdt = 100000.0;
	int theDistance = TotalDist;
	int Node = 0;

	for (int i = 0; i < TotalDist; i += dx_Interval_m)
	{
		if (theDistance >= 0)
		{
			dummy = dx_Interval_m / (velocity_unsteady[Node][0] + sqrt(9.80 * depth_unsteady[Node][0]));
			if (dummy < maxdt)
			{
				maxdt = dummy;
			}
			dummy = pow(Rh_unsteady[Node], (4.0 / 3.0)) / (9.8 * velocity_unsteady[Node][0] * pow(n_unsteady[Node], 2.0));
			if (dummy < maxdt)
			{
				maxdt = dummy;
			}

			theDistance = theDistance - dx_Interval_m;
			Node++;
		}
		if (maxdt < dtime_Interval_min)
		{
			cout << "The selected dt for the unsteady calculation is not stable!! " << endl;
			cout << "The dt should be considered equal to: " << maxdt << " as the max alovable dt. " << endl;
		}
	}
}

void StreamTemperature::hydraulics(int Node, int t)
{

	double Q_In_0, Q_In_1, Q_Out_0;

	// ======================================================
	// Calculate Initial Condition Hydraulics
	if (flag_BC == 1)
	{
		Q[0][Node] = Q_minBased[t];
		Q_In_0 = Q[0][Node];
		Q_In_1 = Q[1][Node];
		Q_Out_0 = Q[0][Node];
		Temp_unsteady[0][Node] = Tobs_minBased[t];
	}
	else
	{
		Q_In_0 = Q[0][Node - 1];
		Q_In_1 = Q[1][Node - 1];
		Q_Out_0 = Q[0][Node];
	}

	// ======================================================
	// Calculate flow volumes in reaches for both times

	double EvapVol = evap_Rate * width_UnsTotal[Node] * dx_Interval_m;
	double Mix = Q_In[Node][t] + Q_GW[Node] - EvapVol;
	double V_In_0 = (Mix + Q_In_0) * dtime_Interval_min;
	if (V_In_0 < 0)
	{
		V_In_0 = 0;
	}
	double V_In_1 = (Mix + Q_In_1) * dtime_Interval_min;
	if (V_In_1 < 0)
	{
		V_In_1 = 0;
	}
	double V_Out_0 = Q_Out_0 * dtime_Interval_min;
	if (V_Out_0 < 0)
	{
		V_Out_0 = 0;
	}
	// ======================================================

	double Q_Est = Mix + Q_In_1;
	if (Q_Est < 0.0071)
	{
		// Channel is going dry
		//cout << "The channel is going dry. " << endl;
		Flag_SkipNode[Node] = 1;
	}
	else
	{
		// Channel has sufficient flow
		Flag_SkipNode[Node] = 0;
	}

	// ======================================================
	// Start Flow Routing

	if (flag_BC == 1)
	{
		depth_unsteady[Node][0] = 1;
	}
	else
	{
		depth_unsteady[Node][0] = depth_unsteady[Node - 1][0];
	}

	int passCode = 0;
	double Converge = 100000.0;
	if (Flag_SkipNode[Node] == 0)
	{
		double dy = 0.01;
		double D_Est = depth_unsteady[Node][0];
		double A_Est = AreaX[Node][0];
		int Count_Iterations = 0;

		while (passCode == 0)
		{
			if (D_Est == 0)
			{
				D_Est = 10.0;
			}
			A_Est = D_Est * (width_unsteady[Node] + Z_unsteady[Node] * D_Est);
			Pw_unsteady[Node] = width_unsteady[Node] + 2.0 * D_Est * sqrt(1.0 + pow(Z_unsteady[Node], 2.0));
			if (Pw_unsteady[Node] <= 0)
			{
				Pw_unsteady[Node] = 0.00001;
			}
			Rh_unsteady[Node] = AreaX[Node][0] / Pw_unsteady[Node];
			double Fy = A_Est * pow(Rh_unsteady[Node], (2.0 / 3.0)) - (n_unsteady[Node]) * Q_Est / sqrt(s_unsteady[Node]);
			double thed = D_Est + dy;
			A_Est = thed * (width_unsteady[Node] + Z_unsteady[Node] * thed);
			Pw_unsteady[Node] = width_unsteady[Node] + 2.0 * thed * sqrt(1 + pow(Z_unsteady[Node], 2.0));
			if (Pw_unsteady[Node] <= 0)
			{
				Pw_unsteady[Node] = 0.00001;
			}
			Rh_unsteady[Node] = AreaX[Node][0] / Pw_unsteady[Node];
			double Fyy = A_Est * pow(Rh_unsteady[Node], (2.0 / 3.0)) - (n_unsteady[Node]) * Q_Est / sqrt(s_unsteady[Node]);
			double dFy = (Fyy - Fy) / dy;
			if (dFy == 0)
			{
				dFy = 0.99;
			}
			thed = D_Est - Fy / dFy;
			D_Est = thed;
			if ((D_Est < 0) || (D_Est > 1000000000000) || (Count_Iterations > 1000))
			{
				// Newton-Raphson didn't converge on a solution
				// need to reseed initial guess and restart method
				srand(time(0));
				//double r = rand() % 1;
				double r = ((double)rand() / (RAND_MAX)) + 1;
				D_Est = 0.1 * r; // Randomly reseed initial value and step
				Converge = 10.0;
				Count_Iterations = 0;
			}
			dy = 0.01;
			Converge = abs(Fy / dFy);
			if (Converge < 0.0001)
			{
				passCode++;
			}
			Count_Iterations = Count_Iterations + 1;
		}
		// Newton-Raphson has determined wetted depth, width, XArea, velocity at current time
		depth_unsteady[Node][0] = D_Est;
		AreaX[Node][0] = A_Est;
		velocity_unsteady[Node][0] = Q_Est / AreaX[Node][0];
		width_UnsTotal[Node] = width_unsteady[Node] + 2.0 * Z_unsteady[Node] * depth_unsteady[Node][0];
		depth_AvgUns[Node] = AreaX[Node][0] / width_UnsTotal[Node];
	}
	else
	{
		Q_Est = 0;
		depth_unsteady[Node][1] = 0;
		AreaX[Node][1] = 0;
		Pw_unsteady[Node] = 0;
		Rh_unsteady[Node] = 0;
		width_UnsTotal[Node] = 0;
		depth_AvgUns[Node] = 0;
		velocity_unsteady[Node][0] = 0;
		Q[1][Node] = 0;
	}

	if (Flag_SkipNode[Node] == 0)
	{
		if (flag_BC == 1)
		{
			// Start - Boundary Condition
			depth_unsteady[Node][1] = depth_unsteady[Node][0];
			Q[1][Node] = Q[0][Node];
			AreaX[Node][1] = AreaX[Node][0];
			velocity_unsteady[Node][1] = Q[1][Node] / AreaX[Node][1];
		}
		else
		{
			/* Explicit Hydraulic Method
			Depth finding is from Analytical Methods for Dynamic Open Channel Heat and Mass Transfer by Boyd& Kasper (2003),
				Section 3.3.2 Explicit Finite Difference Method. Equation numbers are from this document, which is for Heat Source Model.
				Document at: www.oregon.gov/deq/FilterDocs/heatsourcemanual.pdf

				The depth finding uses the following steps :

				1. Determine stability condition for each distance step ‘i’ for the time step ‘t’ using the Courant (3 - 30) and friction stability equations(3 - 31).For each time ‘t’ calculate the smallest dt value for all segments ‘i’.
				2. Solve for dw(i, t) using the finite difference form of the continuity equation(3 - 26)
				3. Calculate the friction slope(Sf) from equation(3 - 28)
				4. Solve for U(i, t) using the finite difference form of the conservation of momentum equation (3 - 29) 
				5. Calculate Q(t) as a function of dw(i, t) and U(i, t)

			The depth finding uses the St.Venant equations in a three point central difference approximation.

			Eq 3-13, Continuity Equation(form 2) (Bedient and Huber 1992). This is re-written in algebraic form below.
			ddw / dt + dw * dU / dx + ddw / dx = 0

			Eq 3-14, Momentum Equation(Bedient and Huber 1992). This is re-written in algebraic form below.
			dU / dt + U * dU / dx + g * ddw / dx = g * (So - Sf)

			Variables are : dw = average water depth(m), U = average velocity(m / s), Sf = channel water surface friction slope(unitless), 
			g = gravity, t = time(s), x = longitudinal distance(m), So = channel bed slope(unitless), Q = channel discharge(m ^ 3 / s)

			Derivation of algebraic equations:
				
				Eq 3-25
				dU/dx = [U(i+1,t-1) - U(i-1,t-1)]/(2*dx)
				dU/dt = [U(i,t-1) - U(i,t)]/dt
				ddw/dx = [dw(i+1,t-1) - dw(i-1,t-1)]/(2*dx)
				ddw/dt = [dw(i,t-1) - dw(i,t)]/dt

				Substitution of Eq 3-25 into Continuity Eq 3-13 yields:
				[dw(i,t-1) - dw(i,t)]/dt + dw(i,t-1) * [U(i+1,t-1) - U(i-1,t-1)]/(2*dx) + U(i,t-1) * [dw(i+1,t-1) - dw(i-1,t-1)]/(2*dx) = 0

				Eq 3-26, Finite Difference Form of the Continuity Equation
				dw(i,t) = dw(i,t-1) + dt/(2*dx) * [dw(i,t-1) * [U(i-1,t+1) - U(i+1,t-1)] + U(i,t-1) * [dw(i-1,t-1) - dw(i+1,t-1)]

				Eq 3-27,  Finite Difference Form of the Conservation of Momentum Equation (3-14)
				U(i,t) = U(i,t-1) + dt/(2*dx) * U(i,t-1) * [U(i+1,t+1) - U(i-1,t-1)] + (dt*g)/(2*dx)* [dw(i+1,t-1) - dw(i-1,t-1)] - dt * g * (So-Sf)

				Eq 3-28, for a trapezoidal channel where U = [U(i+1,t-1) - U(i-1,t-1)]/2
				Sf = (U^2*n^2)/(A/Pw)^(4/3) = ((([U(i+1,t-1) - U(i-1,t-1)]/2)^2 * n^2) / ((dw(i,t)* [Wb+Z*dw(i,t)])/(Wb+2*dw(i,t)*(1+Z)^0.5)^(4/3)))

				Substitution of Eq 3-28 into Eq 3-27 yields:
				Eq 3-29 final finite difference form of the Conservation of Momentum Equation
				U(i,t) = U(i,t-1) + dt/(2*dx) * U(i,t-1) * [U(i+1,t-1) - U(i-1,t-1)] + (dt * g)/(2*dx) * [dw(i+1,t-1) - dw(i-1,t-1)] -
					dt*g * (So - ((([U(i+1,t-1) - U(i-1,t-1)]/2)^2 * n^2) / ((dw(i,t)* [Wb+Z*dw(i,t)])/(Wb+2*dw(i,t)*(1+Z)^0.5)^(4/3))))

			*/

			//define variables for depth, width, velocity for time and space, allowing for finite differencing
			double dR, WR, vR;
			if (Node == (TotalDist_stable - 1))
			{
				dR = depth_unsteady[Node][0];
				WR = width_UnsTotal[Node];
				vR = velocity_unsteady[Node][0];
			}
			else
			{
				dR = depth_unsteady[Node + 1][0];
				WR = width_UnsTotal[Node + 1];
				vR = velocity_unsteady[Node + 1][0];
			}
			//define depth, width, depth for offset nodes, and define bed and surface slopes
			double dL = depth_unsteady[Node - 1][0];
			double dM = depth_unsteady[Node][0];
			double Wm = width_UnsTotal[Node];
			double WL = width_UnsTotal[Node - 1];
			double vL = velocity_unsteady[Node - 1][0];
			double vM = velocity_unsteady[Node][0];
			double So = s_unsteady[Node];
			double Sf;

			/*Solve for channel water depth using Eq 3-26 from Boyd and Kasper (2003) 
			Eq 3 - 26, Finite Difference Form of the Continuity Equation
				dw(i, t) = dw(i, t - 1) + dt / (2 * dx) * [dw(i, t - 1) * [U(i - 1, t + 1) - U(i + 1, t - 1)] + U(i, t - 1) * [dw(i - 1, t - 1) - dw(i + 1, t - 1)]
			*/
			dM = dM + (dtime_Interval_min / (2.0 * dx_Interval_m)) * (dM * (vL - vR) + vM * (dL - dR));
			
			//Compute River cross-section area, wetted perimeter, and hydraulic radius for trapezoidal channel
			//Eq 3-3, 3-4, 3-5 from Boyd and Kasper (2003)
			AreaX[Node][1] = dM * (width_unsteady[Node] + Z_unsteady[Node] * dM);
			Pw_unsteady[Node] = width_unsteady[Node] + 2.0 * dM * sqrt(1.0 + pow(Z_unsteady[Node], 2.0));
			Rh_unsteady[Node] = AreaX[Node][1] / Pw_unsteady[Node];

			/*Solve for friction slope using Eq 3-28 from Boyd & Kasper (2003)
			Eq 3-28, for a trapezoidal channel where U = [U(i+1,t-1) - U(i-1,t-1)]/2
				Sf = (U^2*n^2)/(A/Pw)^(4/3) = ((([U(i+1,t-1) - U(i-1,t-1)]/2)^2 * n^2) / ((dw(i,t)* [Wb+Z*dw(i,t)])/(Wb+2*dw(i,t)*(1+Z)^0.5)^(4/3)))
			*/
			Sf = (((pow((vR + vL), 2.0)) / 2.0) * (pow(n_unsteady[Node], 2.0))) / pow(Rh_unsteady[Node], (4.0 / 3.0));

			/*Solve for velocity using Eq 3-27 from Boyd & Kasper (2003)
			Eq 3-27,  Finite Difference Form of the Conservation of Momentum Equation (3-14)
				U(i,t) = U(i,t-1) + dt/(2*dx) * U(i,t-1) * [U(i+1,t+1) - U(i-1,t-1)] + (dt*g)/(2*dx)* [dw(i+1,t-1) - dw(i-1,t-1)] - dt * g * (So-Sf)
			*/ 
			double A = vM + (dtime_Interval_min / (2.0 * dx_Interval_m)) * vM * (vR - vL);
			double B = ((dtime_Interval_min * 9.8 / (2.0 * dx_Interval_m)) * (dR - dL)) - (dtime_Interval_min * 9.8 * (So - Sf));
			velocity_unsteady[Node][1] = A + B;

			// Calculate flow as a function of velocity and depth
			double Converge = 100000.0;
			double Q_Est = Mix + Q_In_1;

			if (Q_Est < 0.0071)
			{
				// Channel is going dry
				cout << "The channel is going dry. Stop Model Run and Change Input Data. " << endl;
				Flag_SkipNode[Node] = 1;
			}
			else
			{
				// Channel has sufficient flow
				Flag_SkipNode[Node] = 0;
			}

			//Newton-Raphson root finding algorithm to estimate depth, from Boyd and Kasper (2003) page 75
			if (Flag_SkipNode[Node] == 0)
			{
				double dy = 0.01;
				int Count_Iterations = 0;
				double D_Est = depth_unsteady[Node][1];
				double A_Est = AreaX[Node][1];
				double Fy, thed, Fyy, dFy;
				int passCode1 = 0;
				while (passCode1 == 0)
				{
					if (D_Est == 0)
					{
						//Initial guess of depth (m)
						D_Est = 10.0;
					}
					//Compute River cross-section area and wetted perimeter for trapezoidal channel
					//Eq 3-4, 3-5 from Boyd and Kasper (2003)
					A_Est = D_Est * (width_unsteady[Node] + Z_unsteady[Node] * D_Est);
					Pw_unsteady[Node] = width_unsteady[Node] + 2.0 * D_Est * sqrt(1.0 + pow(Z_unsteady[Node], 2.0));
					if (Pw_unsteady[Node] <= 0)
					{
						Pw_unsteady[Node] = 0.00001;
					}
					//Compute River cross-section hydraulic radius for trapezoidal channel
					//Eq 3-3 from Boyd and Kasper (2003)
					Rh_unsteady[Node] = AreaX[Node][0] / Pw_unsteady[Node];

					//Manning Eq as root function of depth, Fy, used in Newton-Raphson
					Fy = A_Est * pow(Rh_unsteady[Node], (2.0 / 3.0)) - (n_unsteady[Node]) * Q_Est / sqrt(s_unsteady[Node]);

					//Adjust variables in Manning Eq for use in first derivative of Manning Eq
					thed = D_Est + dy;
					A_Est = thed * (width_unsteady[Node] + Z_unsteady[Node] * thed);
					Pw_unsteady[Node] = width_unsteady[Node] + 2.0 * thed * sqrt(1 + pow(Z_unsteady[Node], 2.0));
					if (Pw_unsteady[Node] <= 0)
					{
						Pw_unsteady[Node] = 0.00001;
					}
					Rh_unsteady[Node] = AreaX[Node][0] / Pw_unsteady[Node];

					//First derivative of Manning Eq as root function of depth, Fy, used in Newton-Raphson
					Fyy = A_Est * pow(Rh_unsteady[Node], (2.0 / 3.0)) - (n_unsteady[Node]) * Q_Est / sqrt(s_unsteady[Node]);

					dFy = (Fyy - Fy) / dy;
					if (dFy == 0)
					{
						dFy = 0.99;
					}

					//Newton-Raphson equation to compute updated estimate of depth
					thed = D_Est - Fy / dFy;
					D_Est = thed;

					if ((D_Est < 0) || (D_Est > 1000000000000) || (Count_Iterations > 1000))
					{
						srand(time(0));
						//double r = rand() % 10;
						double r = ((double)rand() / (RAND_MAX)) + 1;
						D_Est = 0.1 * r; // Randomly reseed initial value and step
						Converge = 10.0;
						Count_Iterations = 0;
					}
					dy = 0.01;
					Converge = abs(Fy / dFy);
					if (Converge < 0.0001)
					{
						passCode1++;
					}
					Count_Iterations = Count_Iterations + 1;
				}
				depth_unsteady[Node][1] = D_Est;
				AreaX[Node][1] = A_Est;
				width_UnsTotal[Node] = width_unsteady[Node] + 2.0 * Z_unsteady[Node] * depth_unsteady[Node][1];
				depth_AvgUns[Node] = AreaX[Node][1] / width_UnsTotal[Node];
				Q[1][Node] = velocity_unsteady[Node][1] * AreaX[Node][1];
			}
			else
			{
				Q_Est = 0;
				depth_unsteady[Node][1] = 0;
				AreaX[Node][1] = 0;
				Pw_unsteady[Node] = 0;
				Rh_unsteady[Node] = 0;
				width_UnsTotal[Node] = 0;
				depth_AvgUns[Node] = 0;
				velocity_unsteady[Node][0] = 0;
				Q[1][Node] = 0;
			}
		}
	}

	// ======================================================
	// Calc hyporheic flow in cell Q(0,1)
	if (Flag_SkipNode[Node] == 0)
	{
		// Ratio Conductivity of dominant substrate
		double Dummy1 = conductivity_Uns[Node] * (1.0 - embeddedness_Uns[Node]);
		// Ratio Conductivity of sand - low range
		double Dummy2 = 0.01 * embeddedness_Uns[Node];
		// True horizontal conductivity (m / s)
		double HorCond = Dummy1 + Dummy2;

		// Ratio Size of dominant substrate
		Dummy1 = particleSize_Uns[Node] * (1.0 - embeddedness_Uns[Node]);
		// Ratio Conductivity of sand - low range
		Dummy2 = 0.062 * embeddedness_Uns[Node];
		// Estimated Porosity
		//Porosity = 0.3683 * pow((Dummy1 + Dummy2), (-0.0641));

		// Calculate head at top(ho) and bottom(hL) of reach
		double ho, hL;
		if (flag_BC == 1)
		{
			ho = hyp_Slope_Uns[Node] * dx_Interval_m;
			hL = 0;
		}
		else
		{
			ho = depth_unsteady[Node - 1][1] + hyp_Slope_Uns[Node] * dx_Interval_m;
			hL = depth_unsteady[Node][1];
		}
		// Calculate Hyporheic Flows
		//Hyporheic_Exchange[Node] = abs(Porosity * Pw_unsteady[Node] * HorCond * (pow(ho, 2.0) - pow(hL, 2.0)) / (2.0 * dx_Interval_m));
		Hyporheic_Exchange[Node] = hyp_Slope_Uns[Node] * Pw_unsteady[Node] * HorCond * (ho - hL);
		if (Hyporheic_Exchange[Node] > Q[1][Node])
		{
			Hyporheic_Exchange[Node] = Q[1][Node];
		}

		// Calculate tendency to stratify
		Froude_Densiometric = (sqrt(1.0 / 9.8 * 0.000001)) * ((dx_Interval_m * Q[1][Node]) / (depth_unsteady[Node][1] * AreaX[Node][1] * dx_Interval_m));
	}
	else
	{
		// No Flow in Channel
		Hyporheic_Exchange[Node] = 0;
		Froude_Densiometric = 0;
		Temp_unsteady[0][Node] = 0;
	}
}

//Algorithm developed from Boyd and Kasper (2003), Eq 2-119 to 2-120 as first approximation of slope for heat-energy transfer
//Boyd and Kasper (2003). Analytical methods for dynamic open channel heat and mass transfer: Methodology for heat source model version 7.0 (TMDL Tools Updated-2007). Retrieved from Portland, OR.
void StreamTemperature::McCormick_Temp1(const vector<double>& delta_t, int time)
{
	// =======================================================
	// Calc Forward Difference "S1" of MacCormick Method
	// Calculate temperature (first estimate)
	//  T(t,i) = Stream tempertaure
	//  t = time
	//  i = simulation node
	// =======================================================

	int Flag_BC = 1;
	double dummy = 0;
	double T0, T1, T2;
	double Shear_Velocity;
	double Dummy1, Dummy2;
	int Node = 0;
	dispersion.resize(TotalDist_stable);
	S1.resize(TotalDist_stable);

	T_trib_shift.resize(2);
	for (int i = 0; i < 2; i++)
	{
		T_trib_shift[i].resize(TotalDist_stable + 1);
	}

	while (TotalDist - (Node * dx_Interval_m) > 0)
	{
		if (Flag_BC == 0)
		{
			if (Flag_SkipNode[Node] == 0)
			{
				//T_trib_shift (C) is LHS of Eq 3 from Abdi and Endreny, 2019.
				//Abdi and Endreny (2019). A River Temperature Model to Assist Managers in Identifying Thermal Pollution Causes and Solutions.Water, 11(5).doi:10.3390 / w11051060
				T_trib_shift[0][Node] = 0;
				mixing(Node, dummy, time);
				if (TotalDist - ((Node + 1) * dx_Interval_m) > 0)
				{
					//T0 (C) is Twi-1 from Eq 2-119 of Boyd and Kasper (2003), and contains Ri inflow mixing from Eq 3 of Endreny and Abdi (2019)
					T0 = Temp_unsteady[0][Node - 1] + T_trib_shift[0][Node];
					//T1 is Twi from Eq 2-119 of Boyd and Kasper (2003)
					T1 = Temp_unsteady[0][Node];
					//T1 is Twi+1 from Eq 2-119 of Boyd and Kasper (2003)
					T2 = Temp_unsteady[0][Node + 1];
				}
				else
				{
					//T0 (C) is Twi-1 from Eq 2-119 of Boyd and Kasper (2003), and contains Ri inflow mixing from Eq 3 of Endreny and Abdi (2019)
					T0 = Temp_unsteady[0][Node - 1] + T_trib_shift[0][Node];
					//T1 is Twi from Eq 2-119 of Boyd and Kasper (2003)
					T1 = Temp_unsteady[0][Node];
					//T1 is Twi+1 from Eq 2-119 of Boyd and Kasper (2003)
					T2 = Temp_unsteady[0][Node];
				}
				if (s_unsteady[Node] <= 0)
				{
					Shear_Velocity = velocity_unsteady[Node][1];
				}
				else
				{
					Shear_Velocity = sqrt(9.8 * depth_unsteady[Node][1] * s_unsteady[Node]);
				}
				dispersion[Node] = (0.011 * pow(velocity_unsteady[Node][1], 2.0) * pow(width_UnsTotal[Node], 2.0)) / (depth_unsteady[Node][1] * Shear_Velocity);
				if ((dispersion[Node] * pow((dtime_Interval_min / dx_Interval_m), 2.0)) > 0.5)
				{
					dispersion[Node] = (0.45 * pow(dx_Interval_m, 2.0)) / dtime_Interval_min;
				}
				//Dummy1 (C/s) is advection as 1st RHS term in Eq 2-119 of Boyd and Kasper (2003)
				Dummy1 = -velocity_unsteady[Node][1] * (T1 - T0) / dx_Interval_m;
				//Dummy1 (C/s) is dispersion as 2nd RHS term in Eq 2-119 of Boyd and Kasper (2003)
				Dummy2 = dispersion[Node] * (T2 - 2.0 * T1 + T0) / pow(dx_Interval_m, 2.0);
				//S1 (C/s) is LHS term in Eq 2-119 of Boyd and Kasper (2003), where delta_t is 3rd RHS term for heat flux reaction
				S1[Node] = Dummy1 + Dummy2 + delta_t[Node];
				//Temp_unsteady is LHS term in Eq 2-120 of Boyd and Kasper (2003), with three RHS terms
				Temp_unsteady[1][Node] = Temp_unsteady[0][Node] + S1[Node] * dtime_Interval_min;
			}
			else
			{
				//Temp_unsteady is LHS term in Eq 2-120 of Boyd and Kasper (2003), with one RHS term
				Temp_unsteady[1][Node] = Temp_unsteady[0][Node];
			}
		}
		else
		{
			//Temp_unsteady is LHS term in Eq 2-120 of Boyd and Kasper (2003), with one RHS term
			Temp_unsteady[1][Node] = Tobs_minBased[time];
		}
		Flag_BC = 0;
		Node = Node + 1;
	}

	//Temp_unsteady[1][TotalDist_stable] = Temp_unsteady[1][TotalDist_stable - 1];
}

//Algorithm developed from Boyd and Kasper (2003), Eq 2-121 to 2-122 as second approximation of slope for heat-energy transfer
//Boyd and Kasper (2003). Analytical methods for dynamic open channel heat and mass transfer: Methodology for heat source model version 7.0 (TMDL Tools Updated-2007). Retrieved from Portland, OR.
void StreamTemperature::McCormick_Temp2(const vector<double>& delta_t, int time)
{

	// =======================================================
	// Calc Backward Difference "S2" of MacCormick Method
	// =======================================================

	int Flag_BC = 1;
	int Node = 0;
	int dummy = 1;
	double T0, T1, T2;
	double Dummy1, Dummy2;

	S2.resize(TotalDist_stable);

	while (TotalDist - (Node * dx_Interval_m) > 0)
	{
		if (Flag_BC == 0)
		{
			T_trib_shift[1][Node] = 0;
			mixing(Node, dummy, time);
			if (Flag_SkipNode[Node] == 0)
			{
				if (TotalDist - ((Node + 1) * dx_Interval_m) > 0)
				{
					T0 = Temp_unsteady[1][Node - 1] + T_trib_shift[1][Node];
					T1 = Temp_unsteady[1][Node];
					T2 = Temp_unsteady[1][Node + 1];
				}
				else
				{
					T0 = Temp_unsteady[1][Node - 1] + T_trib_shift[1][Node];
					T1 = Temp_unsteady[1][Node];
					T2 = Temp_unsteady[1][Node];
				}

				// ===================================================
				// Final MacCormick Finite Difference Calc.
				// ===================================================
				Dummy1 = -velocity_unsteady[Node][1] * (T1 - T0) / dx_Interval_m;
				Dummy2 = dispersion[Node] * (T2 - 2.0 * T1 + T0) / pow(dx_Interval_m, 2.0);
				S2[Node] = Dummy1 + Dummy2 + delta_t[Node];
				Temp_unsteady[1][Node] = Temp_unsteady[0][Node] + ((S1[Node] + S2[Node]) / 2.0) * dtime_Interval_min;
			}
			else
			{
				Temp_unsteady[1][Node] = Temp_unsteady[0][Node];
			}
		}
		if ((Temp_unsteady[1][Node] > 50) || (Temp_unsteady[1][Node] < 0))
		{
			cout << "Model is unstable.  There could be a variety of reasons for this." << endl;
			cout << "Check your input data, or try decreasing time step and/or increasing distance step." << endl;
		}
		Flag_BC = 0;
		Node = Node + 1;
	}
	Node = 0;
	while (TotalDist - (Node * dx_Interval_m) > -dx_Interval_m)
	{
		Temp_unsteady[0][Node] = Temp_unsteady[1][Node];
		T_unsTemporary[Node] = Temp_unsteady[1][Node];
		Node = Node + 1;
	}
}
//Algorithm to create term Ri in Eq 1 and 3 of Abdi and Endreny, 2019, A River Temperature Model to Assist Managers in Identifying Thermal Pollution Causes and Solutions. Water, 11(5). doi:10.3390/w11051060
//N.B. Eq 1 should represent Ri as Ri/dt, to maintain units of dC/dt [T/t], given Eq 3 is units of C [T]. 
void StreamTemperature::mixing(int Node, int Dummy, int t)
{
	// Temperatures from mass transfer processes

	double Q_up, T_up, T_mix;

	if (Q[1][Node] > 0)
	{
		Q_up = Q[Dummy][Node - 1];
		//T_up is upstream temperature (C) enter node
		T_up = Temp_unsteady[Dummy][Node - 1];
	}
	else
	{
		//Q_up is upstream flow (m^3/dt) entering node
		Q_up = 0;
	}

	if (Q_up > 0)
	{
		//Algorithm developed within Abdi and Endreny, 2019. 
		//Abdi and Endreny, 2019. A River Temperature Model to Assist Managers in Identifying Thermal Pollution Causes and Solutions. Water, 11(5). doi:10.3390/w11051060
		//T_mix (C) is 1st RHS term of Eq 3 from Abdi and Endreny, 2019, as temperature rather than delta temperature
		//Note Eq 3 is computing Ri as units of dT, or change in temperature by subtracting 2nd RHS. T_mix is the updated temperature
		T_mix = ((Q_In[Node][t] * T_In[Node][t]) + (T_up * Q_up) + (BedTn_LI_Uns[Node] * Hyporheic_Exchange[Node]) + (Q_GW[Node] * Temp_GW[Node])) /
			(Q_GW[Node] + Hyporheic_Exchange[Node] + Q_up + Q_In[Node][t]);

		//T_trib_shift (C) is the Ri term from LHS of Eq 3, as change in temperature, dT, and this is sent to Boyd and Casper (McCormick algorithm
		T_trib_shift[Dummy][Node] = T_mix - T_up;
	}
}

void StreamTemperature::adjustedDirRadE_Uns(const vector<double>& DirSW, int timeStep, int Node)
{
	/* calcluating the MapPixel_ID for getAspect function to get access the desired cell of the domain. */
	int col; // considering the (-1) to get a correct answer for "i*cols + j" in SlopeCal class i as the row number and j as the col number
	int row; // considering the (-1) to get a correct answer for "i*cols + j" in SlopeCal class i as the row number and j as the col number
	int MapPixel_ID;
	int totCols = input->getcols();

	int NodeTemp;
	if (Node == 0) {
		NodeTemp = 0;
	}
	else {
		NodeTemp = (Node * dx_Interval_m) - 1;
	}

	double effWidth;
	DirSW_UnsE = 0;

	double topoEffect = 0;
	switch (SolvingMethod) {
		case 1: {
			col = int(colNum_Dist[NodeTemp] - 1);
			row = int(rowNum_Dist[NodeTemp] - 1);
			MapPixel_ID = row * totCols + col;
			slope = input->SlopeGround_rad[MapPixel_ID]; //The answers for slope and aspect are in radian
			aspect = input->AspectGround_N_0_rad[MapPixel_ID];

			topoEffect = (sin(slope) * cos(SolAltitude_LI_Uns[timeStep]) * cos((SolAltitude_LI_Uns[timeStep]) - aspect)) +
				cos(slope) * sin(SolAltitude_LI_Uns[timeStep]);
			if (topoEffect < 0) {
				topoEffect = 0;
			}
			effWidth = effectiveShadingE_Uns(DirSW, Node, timeStep);
			DirSW_UnsE = DirSW[timeStep] * (1 - SWreflVec_Uns[timeStep]) * topoEffect * (1 - (effWidth / width_UnsTotal[Node]));
			if (effWidth > width_UnsTotal[Node]) {
				DirSW_UnsE = 0;
			}

			break;
		}
		case 2: {
			if (calculation == 2) {
				DirSW_UnsE = DirSW[timeStep] * (1 - SF_LI_Uns[Node]) * (1 - SWreflVec_Uns[timeStep]);
			}
			if (calculation == 3) {
				DirSW_UnsE = DirSW[timeStep] * (1 - SF_LI_Uns[Node]) * (1 - SWreflVec[timeStep]);
			}

			break;
		}
		default: {
			cout << "Wrong shortwave radiation methodology. Stop model and select other option." << endl;
		}
	}
}

void StreamTemperature::adjustedDirRadW_Uns(const vector<double>& DirSW, int timeStep, int Node)
{
	/* calcluating the MapPixel_ID for getAspect function to get access the desired cell of the domain. */
	int col; // considering the (-1) to get a correct answer for "i*cols + j" in SlopeCal class i as the row number and j as the col number
	int row; // considering the (-1) to get a correct answer for "i*cols + j" in SlopeCal class i as the row number and j as the col number
	int MapPixel_ID;
	int totCols = input->getcols();

	int NodeTemp;
	if (Node == 0) {
		NodeTemp = 0;
	}
	else {
		NodeTemp = int((Node * dx_Interval_m) - 1);
	}

	double effWidth;
	DirSW_UnsW = 0;

	double topoEffect = 0;
	switch (SolvingMethod) {
		case 1: {
			col = int(colNum_Dist[NodeTemp] - 1);
			row = int(rowNum_Dist[NodeTemp] - 1);
			MapPixel_ID = row * totCols + col;
			//The units for slope and aspect are radian
			slope = input->SlopeGround_rad[MapPixel_ID];
			aspect = input->AspectGround_N_0_rad[MapPixel_ID];

			topoEffect = (sin(slope) * cos(SolAltitude_LI_Uns[timeStep]) * cos((SolAltitude_LI_Uns[timeStep]) - aspect)) +
				cos(slope) * sin(SolAltitude_LI_Uns[timeStep]);
			if (topoEffect < 0)
			{
				topoEffect = 0;
			}
			effWidth = effectiveShadingW(DirSW, Node, timeStep);
			DirSW_UnsW = DirSW[timeStep] * (1 - SWreflVec_Uns[timeStep]) * topoEffect * (1 - (effWidth / width_UnsTotal[Node]));
			if (effWidth > width_UnsTotal[Node])
			{
				DirSW_UnsW = 0;
			}

			break;
		}
		case 2: {
			if (calculation == 2)
			{
				DirSW_UnsW = DirSW[timeStep] * (1 - SF_LI_Uns[Node]) * (1 - SWreflVec_Uns[timeStep]);
			}
			if (calculation == 3)
			{
				DirSW_UnsW = DirSW[timeStep] * (1 - SF_LI_Uns[Node]) * (1 - SWreflVec[timeStep]);
			}

			break;
		}
		default: {
			cout << "Wrong shortwave radiation methodology. Stop model and select other option." << endl;
		}
	}
}

double StreamTemperature::effectiveShadingE_Uns(const vector<double>& SolDirE, int Node, int ts)
{
	int NodeTemp;
	if (Node == 0)
	{
		NodeTemp = 0;
	}
	else
	{
		NodeTemp = int((Node * dx_Interval_m) - 1);
	}
	// to get access the correct location in the vectors based on the dx of
	// unsteady state.

	 // considering the (-1) to get a correct answer for "i*cols + j" in SlopeCal class i as the row number and j as the col number
	int col = int(colNum_Dist[NodeTemp] - 1);
	// considering the (-1) to get a correct answer for "i*cols + j" in SlopeCal class i as the row number and j as the col number
	int row = int(rowNum_Dist[NodeTemp] - 1); 
	int totCols = input->getcols();
	int MapPixel_ID = row * totCols + col;

	slope = input->SlopeGround_rad[MapPixel_ID]; //The answers for slope and aspect are in radian
	aspect = input->AspectGround_N_0_rad[MapPixel_ID];

	double delta1;
	double delta2;
	double avgPath;
	double solarPhi;
	double shadowLengthE;
	double extinctCoeff;
	double effShadowLengthE;

	double Canbuffer = Buff_E_LI[NodeTemp];

	//Eq. #3 in Sun et al., (2015)
	if (SolAltitude_LI_Uns[ts] == 0)
	{
		shadowLengthE = 0;
	} // I used the 5 just as an example! I need to make a solid argument about the threshold!
	else
	{
		double MaxSky = maxValue(VSAEast[NodeTemp], BSAEast[NodeTemp], TSAEast[NodeTemp]);
		if (VSAEast[NodeTemp] == MaxSky)
		{
			shadowLengthE = (BankH_E_LI[NodeTemp] + TreeH_E_LI[NodeTemp]) *
				fabs(sin((SolAzimuth_LI_Uns[ts]) - StrAzimuth_LI[NodeTemp]) / tan(SolAltitude_LI_Uns[ts]));
		}
		else if (BSAEast[NodeTemp] == MaxSky)
		{
			shadowLengthE = (BankH_E_LI[NodeTemp] + BuildH_E_LI[NodeTemp]) *
				fabs(sin((SolAzimuth_LI_Uns[ts]) - StrAzimuth_LI[NodeTemp]) / tan(SolAltitude_LI_Uns[ts]));
		}
		else
		{
			shadowLengthE = (BankH_E_LI[NodeTemp]) *
				fabs(sin((SolAzimuth_LI_Uns[ts]) - StrAzimuth_LI[NodeTemp]) / tan(SolAltitude_LI_Uns[ts]));
		}
	}

	/* Now I am going to calculate the delta1 and delta2 to calcualte the amount of effective shading
	Eq. #4 & 5 in Sun et al., 2015*/

	if (SolAltitude_LI_Uns[ts] == 0)
	{
		delta1 = -(BankH_E_LI[NodeTemp] + width_UnsTotal[Node]);
	} // I used the 5 just as an example! I need to make a solid argument about the threshold!
	else
	{
		double MaxSky = maxValue(VSAEast[NodeTemp], BSAEast[NodeTemp], TSAEast[NodeTemp]);
		if (VSAEast[NodeTemp] == MaxSky)
		{
			delta1 = ((BankH_E_LI[NodeTemp] + TreeH_E_LI[NodeTemp]) *
				fabs(sin((SolAzimuth_LI_Uns[ts]) - StrAzimuth_LI[NodeTemp]) / tan(SolAltitude_LI_Uns[ts]))) -
				(BankH_E_LI[NodeTemp] + width_UnsTotal[Node]);
		}
		else if (BSAEast[NodeTemp] == MaxSky)
		{
			delta1 = ((BankH_E_LI[NodeTemp] + BuildH_E_LI[NodeTemp]) *
				fabs(sin((SolAzimuth_LI_Uns[ts]) - StrAzimuth_LI[NodeTemp]) / tan(SolAltitude_LI_Uns[ts]))) -
				(BankH_E_LI[NodeTemp] + width_UnsTotal[Node]);
		}
		else
		{
			delta1 = (BankH_E_LI[NodeTemp] *
				fabs(sin((SolAzimuth_LI_Uns[ts]) - StrAzimuth_LI[NodeTemp]) / tan(SolAltitude_LI_Uns[ts]))) -
				(BankH_E_LI[NodeTemp] + width_UnsTotal[Node]);
		}
	}
	if (SolAltitude_LI_Uns[ts] == 0)
	{
		delta2 = -(width_UnsTotal[Node]);
	}
	else
	{
		double MaxSky = maxValue(VSAEast[NodeTemp], BSAEast[NodeTemp], TSAEast[NodeTemp]);
		if (VSAEast[NodeTemp] == MaxSky)
		{
			delta2 = ((BankH_E_LI[NodeTemp] + TreeH_E_LI[NodeTemp]) *
				fabs(sin((SolAzimuth_LI_Uns[ts]) - StrAzimuth_LI[NodeTemp]) / tan(SolAltitude_LI_Uns[ts]))) -
				(width_UnsTotal[Node]);
		}
		else if (BSAEast[NodeTemp] == MaxSky)
		{
			delta2 = ((BankH_E_LI[NodeTemp] + BuildH_E_LI[NodeTemp]) *
				fabs(sin((SolAzimuth_LI_Uns[ts]) - StrAzimuth_LI[NodeTemp]) / tan(SolAltitude_LI_Uns[ts]))) -
				(width_UnsTotal[Node]);
		}
		else
		{
			delta2 = (BankH_E_LI[NodeTemp] *
				fabs(sin((SolAzimuth_LI_Uns[ts]) - StrAzimuth_LI[NodeTemp]) / tan(SolAltitude_LI_Uns[ts]))) -
				(width_UnsTotal[Node]);
		}
	}

	solarPhi = (cos(SolAltitude_LI_Uns[ts]) * fabs(sin(SolAzimuth_LI_Uns[ts] - StrAzimuth_LI[NodeTemp])));

	/* calculating the radiation extinction coefficient which is estimated as a function of LAI.
	Reference: http://onlinelibrary.wiley.com/doi/10.1111/j.1752-1688.2010.00423.x/abstract;  DeWalle (2010) */

	//Eq. #1 in Sun et al., (2015) and Sridhar et al. (2004)

	// The next two variables for calculating the extinction coefficient should be shortwave instead longwave based on the following paper
	double abovVegRadiation = SolDirE[ts] * (1 - SWreflVec_Uns[ts]) * ((sin(slope) * cos(SolAltitude_LI_Uns[ts]) * cos(SolAzimuth_LI_Uns[ts] - aspect)) + (cos(slope) * sin(SolAltitude_LI_Uns[ts])));

	double vegRadiation = SolDirE[ts] * (1 - SWreflVec_Uns[ts]); // Direct shortwave radiation based on the Sridhar et al. 2004 ---> Eqn. 6 & 8

	// Link address to Sridhar et al. (2004):
	//http://onlinelibrary.wiley.com/doi/10.1111/j.1752-1688.2004.tb01019.x/abstract
	// Calculating the extinction coefficient based on (DeWalle, 2010 --> Eqn. 2)
	// DeWalle (2010): http://onlinelibrary.wiley.com/doi/10.1111/j.1752-1688.2010.00423.x/abstract
	if (vegRadiation <= 0 || abovVegRadiation <= 0)
		extinctCoeff = 0;
	else
		extinctCoeff = -(log(abovVegRadiation / vegRadiation) / CanopyLAI);

	// calculating the overhanging shade (like I3 in Ning Sun's work using following methodology:
	// http://ascelibrary.org/doi/abs/10.1061/%28ASCE%290733-9372%281998%29124%3A4%28304%29

	double overHangW_E = 0;
	double canDens = input->CoolRiverVariables["CR_canDensity"];
	if (((0.1 * TreeH_E_LI[NodeTemp]) - CanDist_E_LI[NodeTemp]) < width_UnsTotal[Node])
	{
		overHangW_E = ((0.1 * TreeH_E_LI[NodeTemp]) - CanDist_E_LI[NodeTemp]) * canDens;
	}
	else
	{
		overHangW_E = width_UnsTotal[Node] * canDens;
	}

	// calculating of the average path (Lavg) based on the table 1 of  Sun et al., (2015)
	// (1) No shade
	if (VSAEast[NodeTemp] > max(TSAEast[NodeTemp], BSAEast[NodeTemp])) {
		if ((delta1 <= 0.0) && (delta2 <= 0.0))	{
			avgPath = 0;
		}
		// (2) Partial shade, sun above buffer canopy
		else if ((delta1 <= 0.0) && (delta2 <= Canbuffer)) {
			avgPath = ((0.5 * delta2) / solarPhi);
		}
		// (3) Partial shade, sun below buffer canopy
		else if ((delta1 <= 0.0) && (delta2 > Canbuffer)) {
			avgPath = ((0.5 * Canbuffer) / solarPhi); 
		}
		// (4) Full shade, sun above buffer canopy
		else if ((delta1 > 0.0) && (delta2 <= Canbuffer)) {
			avgPath = ((0.5 * (delta1 + delta2)) / solarPhi);
		}
		// (5) Full shade, sun partially below buffer canopy
		else if ((delta1 <= Canbuffer) && (delta2 > Canbuffer)) {
			avgPath = ((0.5 * (delta1 + Canbuffer)) / solarPhi);
		}
		// (6) Full shade, sun entirely below buffer canopy
		else if ((delta1 > Canbuffer) && (delta2 > Canbuffer)) {
			avgPath = (Canbuffer / solarPhi);
		}
		//Eq. #6 in Sun et al., (2015)
		// The shadow length as the initial value for shadow (Eq. #6 in Sun et al., 2015) for Eastern side
		if (shadowLengthE < CanDist_E_LI[NodeTemp]) {
			effShadowLengthE = 0;
		}
		else {
			effShadowLengthE = ((shadowLengthE - CanDist_E_LI[NodeTemp] - overHangW_E) *
				(1 - exp(-(extinctCoeff * avgPath))));
		}
	}
	else {
		if (shadowLengthE < BuildDist_E_LI[NodeTemp]) {
			effShadowLengthE = 0;
		}
		effShadowLengthE = shadowLengthE - BuildDist_E_LI[NodeTemp] - overHangW_E;
	}

	return effShadowLengthE;
}

double StreamTemperature::effectiveShadingW_Uns(const vector<double>& SolDirW, int Node, int ts)
{
	int NodeTemp;
	if (Node == 0) {
		NodeTemp = 0;
	}
	else {
		NodeTemp = (Node * dx_Interval_m) - 1;
	}
	// to get access the correct location in the vectors based on the dx of
	// unsteady state.

	int col = colNum_Dist[NodeTemp] - 1; // considering the (-1) to get a correct answer for "i*cols + j" in SlopeCal class i as the row number and j as the col number
	int row = rowNum_Dist[NodeTemp] - 1; // considering the (-1) to get a correct answer for "i*cols + j" in SlopeCal class i as the row number and j as the col number
	int totCols = input->getcols();
	int MapPixel_ID = row * totCols + col;

	slope = input->SlopeGround_rad[MapPixel_ID]; //The answers for slope and aspect are in radian
	aspect = input->AspectGround_N_0_rad[MapPixel_ID];

	double delta1;
	double delta2;
	double avgPath;
	double solarPhi;
	double shadowLengthW;
	double extinctCoeff;
	double effShadowLengthW;

	double Canbuffer = Buff_W_LI[NodeTemp];

	//Eq. #3 in Sun et al., (2015)
	if (SolAltitude_LI_Uns[ts] == 0) {
		shadowLengthW = 0;
	} // I used the 5 just as an example! I need to make a solid argument about the threshold!
	else
	{
		double MaxSky = maxValue(VSAWest[NodeTemp], BSAWest[NodeTemp], TSAWest[NodeTemp]);
		if (VSAWest[NodeTemp] == MaxSky)
		{
			shadowLengthW = (BankH_W_LI[NodeTemp] + TreeH_W_LI[NodeTemp]) *
				fabs(sin((SolAzimuth_LI_Uns[ts]) - StrAzimuth_LI[NodeTemp]) / tan(SolAltitude_LI_Uns[ts]));
		}
		else if (BSAWest[NodeTemp] == MaxSky)
		{
			shadowLengthW = (BankH_W_LI[NodeTemp] + BuildH_W_LI[NodeTemp]) *
				fabs(sin((SolAzimuth_LI_Uns[ts]) - StrAzimuth_LI[NodeTemp]) / tan(SolAltitude_LI_Uns[ts]));
		}
		else
		{
			shadowLengthW = (BankH_W_LI[NodeTemp]) *
				fabs(sin((SolAzimuth_LI_Uns[ts]) - StrAzimuth_LI[NodeTemp]) / tan(SolAltitude_LI_Uns[ts]));
		}
	}

	/* Now I am going to calculate the delta1 and delta2 to calcualte the amount of effective shading
	Eq. #4 & 5 in Sun et al., 2015*/

	if (SolAltitude_LI_Uns[ts] == 0)
	{
		delta1 = -(BankH_W_LI[NodeTemp] + width_UnsTotal[Node]);
	} // I used the 5 just as an example! I need to make a solid argument about the threshold!
	else
	{
		double MaxSky = maxValue(VSAWest[NodeTemp], BSAWest[NodeTemp], TSAWest[NodeTemp]);
		if (VSAWest[NodeTemp] == MaxSky)
		{
			delta1 = ((BankH_W_LI[NodeTemp] + TreeH_W_LI[NodeTemp]) *
				fabs(sin((SolAzimuth_LI_Uns[ts]) - StrAzimuth_LI[NodeTemp]) / tan(SolAltitude_LI_Uns[ts]))) -
				(BankH_W_LI[NodeTemp] + width_UnsTotal[Node]);
		}
		else if (BSAWest[NodeTemp] == MaxSky)
		{
			delta1 = ((BankH_W_LI[NodeTemp] + BuildH_W_LI[NodeTemp]) *
				fabs(sin((SolAzimuth_LI_Uns[ts]) - StrAzimuth_LI[NodeTemp]) / tan(SolAltitude_LI_Uns[ts]))) -
				(BankH_W_LI[NodeTemp] + width_UnsTotal[Node]);
		}
		else
		{
			delta1 = (BankH_W_LI[NodeTemp] *
				fabs(sin((SolAzimuth_LI_Uns[ts]) - StrAzimuth_LI[NodeTemp]) / tan(SolAltitude_LI_Uns[ts]))) -
				(BankH_W_LI[NodeTemp] + width_UnsTotal[Node]);
		}
	}
	if (SolAltitude_LI_Uns[ts] == 0)
	{
		delta2 = -(width_UnsTotal[Node]);
	}
	else
	{
		double MaxSky = maxValue(VSAWest[NodeTemp], BSAWest[NodeTemp], TSAWest[NodeTemp]);
		if (VSAWest[NodeTemp] == MaxSky)
		{
			delta2 = ((BankH_W_LI[NodeTemp] + TreeH_W_LI[NodeTemp]) *
				fabs(sin((SolAzimuth_LI_Uns[ts]) - StrAzimuth_LI[NodeTemp]) / tan(SolAltitude_LI_Uns[ts]))) -
				(width_UnsTotal[Node]);
		}
		else if (BSAWest[NodeTemp] == MaxSky)
		{
			delta2 = ((BankH_W_LI[NodeTemp] + BuildH_W_LI[NodeTemp]) *
				fabs(sin((SolAzimuth_LI_Uns[ts]) - StrAzimuth_LI[NodeTemp]) / tan(SolAltitude_LI_Uns[ts]))) -
				(width_UnsTotal[Node]);
		}
		else
		{
			delta2 = (BankH_W_LI[NodeTemp] *
				fabs(sin((SolAzimuth_LI_Uns[ts]) - StrAzimuth_LI[NodeTemp]) / tan(SolAltitude_LI_Uns[ts]))) -
				(width_UnsTotal[Node]);
		}
	}

	solarPhi = (cos(SolAltitude_LI_Uns[ts]) * fabs(sin(SolAzimuth_LI_Uns[ts] - StrAzimuth_LI[NodeTemp])));

	/* calculating the radiation extinction coefficient which is estimated as a function of LAI.
	Reference: http://onlinelibrary.wiley.com/doi/10.1111/j.1752-1688.2010.00423.x/abstract;  DeWalle (2010) */

	//Eq. #1 in Sun et al., (2015) and Sridhar et al. (2004)

	// The next two variables for calculating the extinction coefficient should be shortwave instead longwave based on the following paper
	double abovVegRadiation = SolDirW[ts] * (1 - SWreflVec_Uns[ts]) * ((sin(slope) * cos(SolAltitude_LI_Uns[ts]) * cos(SolAzimuth_LI_Uns[ts] - aspect)) + (cos(slope) * sin(SolAltitude_LI_Uns[ts])));

	double vegRadiation = SolDirW[ts] * (1 - SWreflVec_Uns[ts]); // Direct shortwave radiation based on the Sridhar et al. 2004 ---> Eqn. 6 & 8

	// Link address to Sridhar et al. (2004):
	//http://onlinelibrary.wiley.com/doi/10.1111/j.1752-1688.2004.tb01019.x/abstract
	// Calculating the extinction coefficient based on (DeWalle, 2010 --> Eqn. 2)
	// DeWalle (2010): http://onlinelibrary.wiley.com/doi/10.1111/j.1752-1688.2010.00423.x/abstract
	if (vegRadiation <= 0 || abovVegRadiation <= 0)
		extinctCoeff = 0;
	else
		extinctCoeff = -(log(abovVegRadiation / vegRadiation) / CanopyLAI);

	// calculating the overhanging shade (like I3 in Ning Sun's work using following methodology:
	// http://ascelibrary.org/doi/abs/10.1061/%28ASCE%290733-9372%281998%29124%3A4%28304%29

	double overHangW_W = 0;
	double canDens = input->CoolRiverVariables["CR_canDensity"];
	if (((0.1 * TreeH_W_LI[NodeTemp]) - CanDist_W_LI[NodeTemp]) < width_UnsTotal[Node])
	{
		overHangW_W = ((0.1 * TreeH_W_LI[NodeTemp]) - CanDist_W_LI[NodeTemp]) * canDens;
	}
	else
	{
		overHangW_W = width_UnsTotal[Node] * canDens;
	}

	// calculating of the average path (Lavg) based on the table 1 of  Sun et al., (2015)
	// (1) No shade
	if (VSAWest[NodeTemp] > max(TSAWest[NodeTemp], BSAWest[NodeTemp]))
	{
		if ((delta1 <= 0.0) && (delta2 <= 0.0))
		{
			avgPath = 0;
		}
		// (2) Partial shade, sun above buffer canopy
		else if ((delta1 <= 0.0) && (delta2 <= Canbuffer))
		{
			avgPath = ((0.5 * delta2) / solarPhi);
		}
		// (3) Partial shade, sun below buffer canopy
		else if ((delta1 <= 0.0) && (delta2 > Canbuffer))
		{
			avgPath = ((0.5 * Canbuffer) / solarPhi);
		}
		// (4) Full shade, sun above buffer canopy
		else if ((delta1 > 0.0) && (delta2 <= Canbuffer))
		{
			avgPath = ((0.5 * (delta1 + delta2)) / solarPhi);
		}
		// (5) Full shade, sun partially below buffer canopy
		else if ((delta1 <= Canbuffer) && (delta2 > Canbuffer))
		{
			avgPath = ((0.5 * (delta1 + Canbuffer)) / solarPhi);
		}
		// (6) Full shade, sun entirely below buffer canopy
		else if ((delta1 > Canbuffer) && (delta2 > Canbuffer))
		{
			avgPath = (Canbuffer / solarPhi);
		}
		//Eq. #6 in Sun et al., (2015)
		// The shadow length as the initial value for shadow (Eq. #6 in Sun et al., 2015) for Eastern side
		if (shadowLengthW < CanDist_E_LI[NodeTemp])
		{
			effShadowLengthW = 0;
		}
		else
		{
			effShadowLengthW = ((shadowLengthW - CanDist_E_LI[NodeTemp] - overHangW_W) *
				(1 - exp(-(extinctCoeff * avgPath))));
		}
	}
	else
	{
		if (shadowLengthW < BuildDist_W_LI[NodeTemp])
		{
			effShadowLengthW = 0;
		}
		effShadowLengthW = shadowLengthW - BuildDist_W_LI[NodeTemp] - overHangW_W;
	}

	return effShadowLengthW;
}

void StreamTemperature::netSolarDiffRadE_Uns(const vector<double>& SolDiffSW, int timeStep, int Node)
{
	DiffSW_UnsE = 0;
	switch (SolvingMethod)
	{
	case 1:
		//DiffSW_UnsE in the calculations, Eq. #8 in Sun et al., 2015 for East side
		DiffSW_UnsE = SolDiffSW[timeStep] * SkyToView_UnsE[Node] * (1 - SWreflVec_Uns[timeStep]);
		break;

	case 2:
		// Using the fix coverage values
		if (calculation == 2)
		{
			DiffSW_UnsE = SolDiffSW[timeStep] * (1 - SF_LI_Uns[Node]) * (1 - SWreflVec_Uns[timeStep]);
		}
		if (calculation == 3)
		{
			DiffSW_UnsE = SolDiffSW[timeStep] * (1 - SF_LI_Uns[Node]) * (1 - SWreflVec[timeStep]);
		}
		break;

	default:
		cout << "Wrong shortwave radiation methodology. Stop model and select other option." << endl;
	}
}

void StreamTemperature::netSolarDiffRadW_Uns(const vector<double>& SolDiffSW, int timeStep, int Node)
{
	DiffSW_UnsW = 0;
	switch (SolvingMethod) {
		case 1: {
			//DiffSW_UnsW in the calculations, Eq. #8 in Sun et al., 2015 for East side
			DiffSW_UnsW = SolDiffSW[timeStep] * SkyToView_UnsW[Node] * (1 - SWreflVec_Uns[timeStep]);
			break;
		}
		case 2: {
			// Using the fix coverage values
			if (calculation == 2)
			{
				DiffSW_UnsW = SolDiffSW[timeStep] * (1 - SF_LI_Uns[Node]) * (1 - SWreflVec_Uns[timeStep]);
			}
			if (calculation == 3)
			{
				DiffSW_UnsW = SolDiffSW[timeStep] * (1 - SF_LI_Uns[Node]) * (1 - SWreflVec[timeStep]);
			}

			break;
		}
		default: {
			cout << "Wrong shortwave radiation methodology. Stop model and select other option." << endl;
		}
	}
}

void StreamTemperature::longWaveRadiation_Uns(const vector<double>& airTemperature,
	const vector<double>& relHumidity,
	const vector<double>& cloadinessCoeff, int timeStep, int Node)
{
	double SBConst = 0.000000056696; // Stefan-Boltzman constant, 5.6696*10-8 (kg�s-3�K-4)

	LW_Atm_Uns = 0;
	LW_LC_Uns = 0;
	LW_Back_Uns = 0;
	LW_Uns = 0;
	double StrTemp;
	int NodeTemp;
	if (Node == 0)
	{
		NodeTemp = 0;
	}
	else
	{
		NodeTemp = int((Node * dx_Interval_m) - 1);
	}

	if (calculation == 2)
	{
		StrTemp = Temp_unsteady[0][Node];
	}
	if (calculation == 3)
	{
		//StrTemp = HeatFluxADR_Temperature_C[Node][timeStep];
		if (Node == 0)
		{
			StrTemp = HeatFluxADR_Temperature_C[Node][timeStep];
		}
		else
		{
			StrTemp = HeatFluxADR_Temperature_C[Node - 1][timeStep];
		}
	}
	double VaporPressure_Saturated_kPa = 0;
	double VaporPressure_Actual_kPa = 0;
	double emis_Uns;
	switch (SolvingMethod) {
		case 1: {
			// solving based on the calculated sky view factor

			//VaporPressure_Saturated_kPa (kPa) as Tetens' formula in Eq 4.2.2 Shuttleworth (1993), e_kPa=0.6108*exp[(17.27*T_C)/(237.3+T_C)]
			VaporPressure_Saturated_kPa = 0.6108 * exp((17.27 * airTemperature[timeStep]) / (airTemperature[timeStep] + 237.3));
			VaporPressure_Actual_kPa = (relHumidity[timeStep] / 100.0) * VaporPressure_Saturated_kPa;
			emis_Uns = 1.72 * pow(((VaporPressure_Actual_kPa) / (airTemperature[timeStep] + 273.2)), (1.0 / 7.0)) *
				(1 + (0.22 * (pow(cloadinessCoeff[timeStep], 2.0))));
			if (emis_Uns > 0.96)
			{
				emis_Uns = 0.96;
			}
			LW_Atm_Uns = 0.96 * emis_Uns * SBConst * pow((airTemperature[timeStep] + 273.2), 4) * SkyToView_UnsE[Node];
			// Land cover longwave radiation
			LW_LC_Uns = 0.96 * (1 - SkyToView_UnsE[Node]) * 0.96 * SBConst * pow((airTemperature[timeStep] + 273.2), 4.0);
			LW_Back_Uns = -0.96 * SBConst * pow((StrTemp + 273.2), 4.0);
			break;
		}
		case 2: {

			VaporPressure_Saturated_kPa = 0.611 * exp((17.27 * airTemperature[timeStep]) / (airTemperature[timeStep] + 237.3));
			VaporPressure_Actual_kPa = (relHumidity[timeStep] / 100.0) * VaporPressure_Saturated_kPa;
			emis_Uns = 1.72 * pow(((VaporPressure_Actual_kPa) / (airTemperature[timeStep] + 273.2)), (1.0 / 7.0)) *
				(1 + (pow((0.22 * cloadinessCoeff[timeStep]), 2.0))); // Dingman p 282
			if (emis_Uns > 0.96)
			{
				emis_Uns = 0.96;
			}
			LW_Atm_Uns = 0.96 * emis_Uns * SBConst * pow((airTemperature[timeStep] + 273.2), 4) * SkyToView_UnsE[Node];
			// Land cover longwave radiation
			LW_LC_Uns = 0.96 * (1 - SkyToView_UnsE[Node]) * 0.96 * SBConst * pow((airTemperature[timeStep] + 273.2), 4.0);
			LW_Back_Uns = -0.96 * SBConst * pow((StrTemp + 273.2), 4.0);
			break;
		}
		default: {
			cout << "Check StreamTemperature.cpp line regarding case 1 or 2 for longwave radiation methodology" << endl;
		}
	}

	LW_Uns = LW_Atm_Uns + LW_LC_Uns + LW_Back_Uns;
}

void StreamTemperature::latentHeat_Uns(const vector<double>& airTemperature,
	const vector<double>& relHumidity,
	const vector<double>& windSp, int timeStep, int Node)
{

	double c_air = 1004; // heat capacity of air (J/kg deg C)
	double rho_air = 1.2041; // density of air at 20 deg C (kg/m^3)

	int NodeTemp;
	if (Node == 0) {
		NodeTemp = 0;
	}
	else {
		NodeTemp = int((Node * dx_Interval_m) - 1);
	}

	latent_Uns = 0;
	evap_Rate = 0;
	double StrTemp;
	if (calculation == 2) {
		StrTemp = Temp_unsteady[0][Node];
	}

	if (calculation == 3) {
		//StrTemp = HeatFluxADR_Temperature_C[Node][timeStep];
		if (Node == 0) {
			StrTemp = HeatFluxADR_Temperature_C[Node][timeStep];
		}
		else {
			StrTemp = HeatFluxADR_Temperature_C[Node - 1][timeStep];
		}
	}

	// <<<<<<<<<Evaporation section>>>>>>>>
	double L_e = 1000000 * (2.501 - (0.002361 * StrTemp)); // Calculate the latent heat of vaporization J/kg
	// Calculate the slope of the saturated vapor pressure curve at a given air temperature
	double VaporPressure_Saturated_kPa = 0.611 * exp((17.27 * airTemperature[timeStep]) / (airTemperature[timeStep] + 237.3));
	double VaporPressure_Actual_kPa = (relHumidity[timeStep] / 100.0) * VaporPressure_Saturated_kPa;
	double s = (4100.0 * VaporPressure_Saturated_kPa) / (pow((237.0 + airTemperature[timeStep]), 2.0)); //kPa / deg C
	// Calculate the aerodynamic resistance
	double r_a = 245.0 / ((0.54 * windSp[timeStep]) + 0.5); //[s / m]

	// Calculate air pressure
	// z = elevation of station where met data was obtained
	double Pa = 101.3 - (0.0105 * elev_LI[NodeTemp]);
	// Calculate psychrometric constant(kPa / deg C) (based on air pressure(Pa), (value should be adjusted for different site elevations),
	//ratio of water to dry air = .622, and the latent heat of water vaporization = 2.45E6[J / kg deg C])
	double psy = (c_air * Pa) / (0.622 * 2450000.0);
	// Calculate the Penman open water evaporation
	double E = ((s * (SW_Uns + LW_Uns)) / (1000.0 * L_e * (s + psy))) +
		((c_air * rho_air * psy * (VaporPressure_Saturated_kPa - VaporPressure_Actual_kPa)) / (1000.0 * L_e * r_a * (s + psy)));

	latent_Uns = (-rho_water * L_e * E);
	evap_Rate = E;
}

void StreamTemperature::sensibleHeat_Uns(const vector<double>& airTemperature,
	const vector<double>& windSp,
	const vector<double>& relHumidity, int timeStep, int Node)
{
	Sensible_Uns = 0;
	int NodeTemp;
	if (Node == 0)
	{
		NodeTemp = 0;
	}
	else
	{
		NodeTemp = int((Node * dx_Interval_m) - 1);
	}

	double StrTemp;
	if (calculation == 2)
	{
		StrTemp = Temp_unsteady[0][Node];
	}
	if (calculation == 3)
	{
		//StrTemp = HeatFluxADR_Temperature_C[Node][timeStep];
		// I don't know why I have this here!! Feb. 20
		if (Node == 0)
		{
			StrTemp = HeatFluxADR_Temperature_C[Node][timeStep];
		}
		else
		{
			StrTemp = HeatFluxADR_Temperature_C[Node - 1][timeStep];
		}
	}

	int method = int(input->CoolRiverVariables["CR_sensMethod"]);
	double c_air = 1004;	 // (J / kg deg C) value for the heat capacity of air
	double rho_air = 1.2041; // (kg / m ^ 3) value for the density of air at 20 deg C

	double vaporLatHeat = 2499500;		   // latent heat of vaporization (Joules�kg-1)
	double empiricalConst = 0.00000000159; // empirical constant, (s�m-1�mb-1)

	sensible.resize(TotalDist);
	double z_veg, zd, z0, DH_DM, k, KH;
	double ews, ewa, Pa1, Br;
	switch (method)
	{
	case 1:
		z_veg = 0.25;	  // (m)  height of vegetation around stream
		zd = 0.7 * z_veg; // zero - plane displacement, m
		z0 = 0.1 * z_veg; //roughness height, m
		DH_DM = 1;		  // ratio of diffusivity of sensible heat to diffusivity
		// of momentum, m2 / s(1 under stable conditions)
		k = 0.4;																					   //dimensionless constant
		KH = DH_DM * c_air * rho_air * ((pow(k, 2)) / (pow((log((elev_LI[NodeTemp] - zd) / z0)), 2))); // (J / C deg m3)
		Sensible_Uns = -KH * windSp[timeStep] * (StrTemp - airTemperature[timeStep]);				   // W / m2
		break;
	case 2:
		ews = 0.61275 * exp((17.27 * StrTemp) / (237.3 + StrTemp)); //kPa
		ewa = (relHumidity[timeStep] / 100.0) * ews;				//kPa
		Pa1 = 101.3 * pow(((293 - (0.0065 * elev_LI[NodeTemp])) / 293), 5.256);
		Br = 0.00061 * Pa1 * ((StrTemp - airTemperature[timeStep]) / (ews - ewa));
		if (Br > 1)
		{
			Br = 0.64;
		}
		Sensible_Uns = Br * latent_Uns;
		break;
	case 3:
		// Ning Sun's methodology
		ews = 0.61275 * exp((17.27 * StrTemp) / (237.3 + StrTemp)); //kPa
		ewa = (humidity / 100) * ews;								//kPa
		Pa1 = 101.3 * pow(((293 - (0.0065 * elev_LI[NodeTemp])) / 293), 5.256);
		Br = 0.00061 * Pa1 * ((StrTemp - airTemperature[timeStep]) / (ews - ewa));
		if (Br > 1)
		{
			Br = 0.64;
		}
		Sensible_Uns = Br * rho_water * vaporLatHeat * empiricalConst * windSp[timeStep] * (airTemperature[timeStep] - StrTemp);
		break;
	default:
		cout << "Check StreamTemperature.cpp line regarding case 1, 2, or 3 for sensible heat methodology." << endl;
	}
}

void StreamTemperature::bedSediment_Uns(const vector<double>& Ksed_index,
	const vector<double>& bedTemp,
	const vector<double>& depthMeas, int timeStep, int Node)
{

	// streamTemp and sedimentTemp should be based on Celsius
	bed_Uns = 0;
	int NodeTemp;
	double StrTemp;
	if (Node == 0)
	{
		NodeTemp = 0;
	}
	else
	{
		NodeTemp = int((Node * dx_Interval_m) - 1);
	}

	if (calculation == 2)
	{
		StrTemp = Temp_unsteady[0][Node];
	}
	if (calculation == 3)
	{
		if (Node == 0)
		{
			StrTemp = HeatFluxADR_Temperature_C[Node][timeStep];
		}
		else
		{
			StrTemp = HeatFluxADR_Temperature_C[Node - 1][timeStep];
		}
	}

	bed_Uns = 2.0 * (Ksed_index[NodeTemp] * ((bedTemp[timeStep] - StrTemp) / (depthMeas[Node] / 2.0)));
}
void StreamTemperature::ConductionFlux_HR(vector<vector<double>>& thePorosity,
	const vector<double>& bedTemp,
	int timeStep, int Node, int RotationHR)
{

	// ==========================================================
	// Variables used in bed conduction
	// Substrate Conduction Constants
	int Sed_Density = 1600;				   // kg/m3
	double Sed_ThermalDiffuse = 0.0000045; // m2/s
	int Sed_HeatCapacity = 2219;		   // J/(kg *C)
	// ======================================================
	// Variables used in bed conduction
	// Water Conduction Constants
	double H2O_ThermalDiffuse = 0.00000014331; // m2/s
	// ======================================================
	// Variables used in bed conduction
	// Calculate the sediment depth (conduction layer)
	double Sed_Depth;
	Sed_Depth = 10 * particleSize_Uns[Node] / 1000;
	if (Sed_Depth > 1)
	{
		Sed_Depth = 1;
	}
	if (Sed_Depth < 0.1)
		Sed_Depth = 0.1;

	double StrTemp;
	if (Node == 0)
	{
		StrTemp = HeatFluxADR_Temperature_C[Node][timeStep];
	}
	else
	{
		StrTemp = HeatFluxADR_Temperature_C[Node - 1][timeStep];
	}

	// ======================================================
	// Calculate Volumetric Ratio of Water and Substrate
	// Use this Ratio to Estimate Conduction Constants

	double Volume_Sediment = (1 - thePorosity[Node][timeStep]) * Pw_ALL_HR[Node][timeStep] * Sed_Depth * dx_Interval_m;
	double Volume_H2O = thePorosity[Node][timeStep] * Pw_ALL_HR[Node][timeStep] * Sed_Depth * dx_Interval_m;
	double Volume_Hyp = Pw_ALL_HR[Node][timeStep] * Sed_Depth * dx_Interval_m;
	double Ratio_Sediment = Volume_Sediment / Volume_Hyp;
	double Ratio_H2O = Volume_H2O / Volume_Hyp;
	double Density = (Sed_Density * Ratio_Sediment) + (rho_water * Ratio_H2O);
	double HeatCapacity = (Sed_HeatCapacity * Ratio_Sediment) + (c_water * Ratio_H2O);
	double ThermalDiffuse = (Sed_ThermalDiffuse * Ratio_Sediment) + (H2O_ThermalDiffuse * Ratio_H2O);

	// ======================================================
	// Calculate the conduction flux between water column & substrate

	if (Node == 0)
	{
		if (calculation == 2)
		{
			FluxConduction_HR[Node][timeStep] = ThermalDiffuse * Density * HeatCapacity * (bedTemp[timeStep] - Tobs_minBased[timeStep]) / (Sed_Depth / 2.0);
		}
		if (calculation == 3)
		{
			FluxConduction_HR[Node][timeStep] = ThermalDiffuse * Density * HeatCapacity * (bedTemp[timeStep] - obs_xo_LI[timeStep]) / (Sed_Depth / 2.0);
		}
	}
	else
	{
		FluxConduction_HR[Node][timeStep] = ThermalDiffuse * Density * HeatCapacity * (bedTemp[timeStep] - StrTemp) / (Sed_Depth / 2.0);
	}

	double Flux_Conduction_Alluvium = ThermalDiffuse * Density * HeatCapacity * (bedTemp[timeStep] - BedTn_LI_Uns[Node]) / (Sed_Depth / 2.0);
	

	// ======================================================
	// Calculate the amount of heat transfered to the sediments from stream water flowing into HR zone

	if (RotationHR > 0)
	{
		Flux_HEF = HyporheicExchange_HR[Node][timeStep] * rho_water * c_water * (HeatFluxADR_Temperature_C[Node - 1][timeStep] - bedTemp[timeStep]) / (Pw_ALL_HR[Node][timeStep] * dx_Interval_m);
	}
	else
	{
		Flux_HEF = HyporheicExchange_HR[Node][timeStep] * rho_water * c_water * (HeatFluxADR_Temperature_C[Node][timeStep] - bedTemp[timeStep]) / (Pw_ALL_HR[Node][timeStep] * dx_Interval_m);
	}
}

void StreamTemperature::bedSedimentHS(const vector<double>& bedTemp, int timeStep, int Node)
{

	bed_Uns = 0;
	// ==========================================================
	// Variables used in bed conduction
	// Substrate Conduction Constants
	int Sed_Density = 1600;				   // kg/m3
	double Sed_ThermalDiffuse = 0.0000045; // m2/s
	int Sed_HeatCapacity = 2219;		   // J/(kg *C)
	// ======================================================
	// Variables used in bed conduction
	// Water Conduction Constants
	double H2O_ThermalDiffuse = 0.00000014331; // m2/s
	// ======================================================

	// Variables used in bed conduction
	// Calculate the sediment depth (conduction layer)
	double Sed_Depth;
	Sed_Depth = 10 * particleSize_Uns[Node] / 1000;
	if (Sed_Depth > 1)
	{
		Sed_Depth = 1;
	}
	if (Sed_Depth < 0.1)
		Sed_Depth = 0.1;

	double StrTemp = Temp_unsteady[0][Node];

	// ======================================================
	// Ratio Size of dominant substrate
	double Dummy1 = particleSize_Uns[Node] * (1.0 - embeddedness_Uns[Node]);
	// Ratio Conductivity of sand - low range
	double Dummy2 = 0.062 * embeddedness_Uns[Node];
	// Estimated Porosity
	double Porosity = 0.3683 * pow((Dummy1 + Dummy2), (-0.0641));
	// ======================================================
	// Calculate Volumetric Ratio of Water and Substrate
	// Use this Ratio to Estimate Conduction Constants

	double Volume_Sediment = (1 - Porosity) * Pw_unsteady[Node] * Sed_Depth * dx_Interval_m;
	double Volume_H2O = Porosity * Pw_unsteady[Node] * Sed_Depth * dx_Interval_m;
	double Volume_Hyp = Pw_unsteady[Node] * Sed_Depth * dx_Interval_m;
	double Ratio_Sediment = Volume_Sediment / Volume_Hyp;
	double Ratio_H2O = Volume_H2O / Volume_Hyp;
	double Density = (Sed_Density * Ratio_Sediment) + (rho_water * Ratio_H2O);
	double HeatCapacity = (Sed_HeatCapacity * Ratio_Sediment) + (c_water * Ratio_H2O);
	double ThermalDiffuse = (Sed_ThermalDiffuse * Ratio_Sediment) + (H2O_ThermalDiffuse * Ratio_H2O);

	// ======================================================
	// Calculate the conduction flux between water column & substrate

	if (Node == 0)
	{
		bed_Uns = ThermalDiffuse * Density * HeatCapacity * (bedTemp[timeStep] - Tobs_minBased[timeStep]) / (Sed_Depth / 2.0);
	}
	else
	{
		bed_Uns = ThermalDiffuse * Density * HeatCapacity * (bedTemp[timeStep] - StrTemp) / (Sed_Depth / 2.0);
	}
}