コード例 #1
0
int TimestepSchemeStrang::SubStep(
	bool fFirstStep,
	bool fLastStep,
	const Time & time,
	double dDeltaT,
	int iSubStep
) {
	Grid * pGrid = m_model.GetGrid();

	HorizontalDynamics * pHorizontalDynamics = m_model.GetHorizontalDynamics();

	VerticalDynamics * pVerticalDynamics = m_model.GetVerticalDynamics();

	if (pGrid == NULL) {
		_EXCEPTIONT("Model Grid has not been initialized");
	}
	if (pHorizontalDynamics == NULL) {
		_EXCEPTIONT("Model HorizontalDynamics has not been initialized");
	}
	if (pVerticalDynamics == NULL) {
		_EXCEPTIONT("Model VerticalDynamics has not been initialized");
	}

	// Half a time step
	double dHalfDeltaT = 0.5 * dDeltaT;

	// Number of HorizontalDynamics substeps
	int nHorizontalDynamicsSubSteps =
		pHorizontalDynamics->GetSubStepAfterSubCycleCount();

	// Vertical timestep
	if (iSubStep == 0) {

		// Vertical timestep
		if (fFirstStep) {
			pVerticalDynamics->StepImplicit(0, 0, time, dHalfDeltaT);

		} else {
			pGrid->LinearCombineData(m_dCarryoverCombination, 0, DataType_State);
			pGrid->LinearCombineData(m_dCarryoverCombination, 0, DataType_Tracers);

			pVerticalDynamics->FilterNegativeTracers(0);
		}
	}
	
	// Forward Euler
	if (m_eExplicitDiscretization == ForwardEuler) {
		if (iSubStep == 0) {
			pGrid->CopyData(0, 4, DataType_State);
			pGrid->CopyData(0, 4, DataType_Tracers);
			pHorizontalDynamics->StepExplicit(0, 4, time, dDeltaT);
			pVerticalDynamics->StepExplicit(0, 4, time, dDeltaT);

			return 4;
		}

	// Explicit fourth-order Runge-Kutta
	} else if (m_eExplicitDiscretization == RungeKutta4) {
		if (iSubStep == 0) {
			pGrid->CopyData(0, 1, DataType_State);
			pGrid->CopyData(0, 1, DataType_Tracers);
			pHorizontalDynamics->StepExplicit(0, 1, time, dHalfDeltaT);
			pVerticalDynamics->StepExplicit(0, 1, time, dHalfDeltaT);

			return 1;

		} else if (iSubStep == 1) {
			pGrid->CopyData(0, 2, DataType_State);
			pGrid->CopyData(0, 2, DataType_Tracers);
			pHorizontalDynamics->StepExplicit(1, 2, time, dHalfDeltaT);
			pVerticalDynamics->StepExplicit(1, 2, time, dHalfDeltaT);

			return 2;

		} else if (iSubStep == 2) {
			pGrid->CopyData(0, 3, DataType_State);
			pGrid->CopyData(0, 3, DataType_Tracers);
			pHorizontalDynamics->StepExplicit(2, 3, time, dDeltaT);
			pVerticalDynamics->StepExplicit(2, 3, time, dDeltaT);

			return 3;

		} else if (iSubStep == 3) {
			pGrid->LinearCombineData(m_dRK4Combination, 4, DataType_State);
			pGrid->LinearCombineData(m_dRK4Combination, 4, DataType_Tracers);

			pHorizontalDynamics->StepExplicit(3, 4, time, dDeltaT / 6.0);
			pVerticalDynamics->StepExplicit(3, 4, time, dDeltaT / 6.0);

			return 4;
		}

	// Explicit strong stability preserving third-order Runge-Kutta
	} else if (m_eExplicitDiscretization == RungeKuttaSSP3) {
		if (iSubStep == 0) {
			pGrid->CopyData(0, 1, DataType_State);
			pGrid->CopyData(0, 1, DataType_Tracers);
			pHorizontalDynamics->StepExplicit(0, 1, time, dDeltaT);
			pVerticalDynamics->StepExplicit(0, 1, time, dDeltaT);

			return 1;

		} else if (iSubStep == 1) {
			pGrid->LinearCombineData(m_dSSPRK3CombinationA, 2, DataType_State);
			pGrid->LinearCombineData(m_dSSPRK3CombinationA, 2, DataType_Tracers);
			pHorizontalDynamics->StepExplicit(1, 2, time, 0.25 * dDeltaT);
			pVerticalDynamics->StepExplicit(1, 2, time, 0.25 * dDeltaT);

			return 2;

		} else if (iSubStep == 2) {
			pGrid->LinearCombineData(m_dSSPRK3CombinationB, 4, DataType_State);
			pGrid->LinearCombineData(m_dSSPRK3CombinationB, 4, DataType_Tracers);
			pHorizontalDynamics->StepExplicit(2, 4, time, (2.0/3.0) * dDeltaT);
			pVerticalDynamics->StepExplicit(2, 4, time, (2.0/3.0) * dDeltaT);

			return 4;
		}

	// Explicit Kinnmark, Gray and Ullrich third-order five-stage Runge-Kutta
	} else if (m_eExplicitDiscretization == KinnmarkGrayUllrich35) {
		if (iSubStep == 0) {
			pGrid->CopyData(0, 1, DataType_State);
			pGrid->CopyData(0, 1, DataType_Tracers);
			pHorizontalDynamics->StepExplicit(0, 1, time, dDeltaT / 5.0);
			pVerticalDynamics->StepExplicit(0, 1, time, dDeltaT / 5.0);

			return 1;

		} else if (iSubStep == 1) {
			pGrid->CopyData(0, 2, DataType_State);
			pGrid->CopyData(0, 2, DataType_Tracers);
			pHorizontalDynamics->StepExplicit(1, 2, time, dDeltaT / 5.0);
			pVerticalDynamics->StepExplicit(1, 2, time, dDeltaT / 5.0);

			return 2;

		} else if (iSubStep == 2) {
			pGrid->CopyData(0, 3, DataType_State);
			pGrid->CopyData(0, 3, DataType_Tracers);
			pHorizontalDynamics->StepExplicit(2, 3, time, dDeltaT / 3.0);
			pVerticalDynamics->StepExplicit(2, 3, time, dDeltaT / 3.0);

			return 3;

		} else if (iSubStep == 3) {
			pGrid->CopyData(0, 2, DataType_State);
			pGrid->CopyData(0, 2, DataType_Tracers);
			pHorizontalDynamics->StepExplicit(3, 2, time, 2.0 * dDeltaT / 3.0);
			pVerticalDynamics->StepExplicit(3, 2, time, 2.0 * dDeltaT / 3.0);

			return 2;

		} else if (iSubStep == 4) {
			pGrid->LinearCombineData(
				m_dKinnmarkGrayUllrichCombination, 4, DataType_State);
			pGrid->LinearCombineData(
				m_dKinnmarkGrayUllrichCombination, 4, DataType_Tracers);
			pHorizontalDynamics->StepExplicit(2, 4, time, 3.0 * dDeltaT / 4.0);
			pVerticalDynamics->StepExplicit(2, 4, time, 3.0 * dDeltaT / 4.0);

			return 4;
		}

	// Explicit strong stability preserving five-stage third-order Runge-Kutta
	} else if (m_eExplicitDiscretization == RungeKuttaSSPRK53) {
		if (iSubStep == 0) {
			const double dStepOne = 0.377268915331368;

			pGrid->CopyData(0, 1, DataType_State);
			pGrid->CopyData(0, 1, DataType_Tracers);
			pHorizontalDynamics->StepExplicit(0, 1, time, dStepOne * dDeltaT);
			pVerticalDynamics->StepExplicit(0, 1, time, dStepOne * dDeltaT);

			return 1;

		} else if (iSubStep == 1) {
			const double dStepOne = 0.377268915331368;

			pGrid->CopyData(1, 2, DataType_State);
			pGrid->CopyData(1, 2, DataType_Tracers);
			pHorizontalDynamics->StepExplicit(1, 2, time, dStepOne * dDeltaT);
			pVerticalDynamics->StepExplicit(1, 2, time, dStepOne * dDeltaT);

			return 2;

		} else if (iSubStep == 2) {
			const double dStepThree = 0.242995220537396;

			pGrid->LinearCombineData(m_dSSPRK53CombinationA, 3, DataType_State);
			pGrid->LinearCombineData(m_dSSPRK53CombinationA, 3, DataType_Tracers);
			pHorizontalDynamics->StepExplicit(2, 3, time, dStepThree * dDeltaT);
			pVerticalDynamics->StepExplicit(2, 3, time, dStepThree * dDeltaT);

			return 3;

		} else if (iSubStep == 3) {
			const double dStepFour = 0.238458932846290;

			pGrid->LinearCombineData(m_dSSPRK53CombinationB, 0, DataType_State);
			pGrid->LinearCombineData(m_dSSPRK53CombinationB, 0, DataType_Tracers);
			pHorizontalDynamics->StepExplicit(3, 0, time, dStepFour * dDeltaT);
			pVerticalDynamics->StepExplicit(3, 0, time, dStepFour * dDeltaT);

			return 0;

		} else if (iSubStep == 4) {
			const double dStepFive = 0.287632146308408;

			pGrid->LinearCombineData(m_dSSPRK53CombinationC, 4, DataType_State);
			pGrid->LinearCombineData(m_dSSPRK53CombinationC, 4, DataType_Tracers);
			pHorizontalDynamics->StepExplicit(0, 4, time, dStepFive * dDeltaT);
			pVerticalDynamics->StepExplicit(0, 4, time, dStepFive * dDeltaT);

			return 4;
		}

	// Fixers, filters and diffusion
	} else if (
		(iSubStep >= m_nExplicitSubSteps) &&
	    (iSubStep <  m_nExplicitSubSteps + nHorizontalDynamicsSubSteps)
	) {
		return pHorizontalDynamics->SubStepAfterSubCycle(
			4, 1, 2, time, dDeltaT, iSubStep - m_nExplicitSubSteps);

	// Vertical timestep
	} else if (
		iSubStep == m_nExplicitSubSteps + nHorizontalDynamicsSubSteps
	) {
		pGrid->CopyData(1, 0, DataType_State);
		pGrid->CopyData(1, 0, DataType_Tracers);
		pVerticalDynamics->StepImplicit(0, 0, time, 0.5 * dDeltaT);

		if (!fLastStep) {
			pGrid->LinearCombineData(m_dCarryoverFinal, 1, DataType_State);
			pGrid->LinearCombineData(m_dCarryoverFinal, 1, DataType_Tracers);
		}

#pragma message "Merge this vertical timestep in above"
		return (-1);

	}
	
	// Invalid substep
	_EXCEPTIONT("Invalid iSubStep");
}
コード例 #2
0
void TimestepSchemeStrang::Step(
	bool fFirstStep,
	bool fLastStep,
	const Time & time,
	double dDeltaT
) {
	// Get a copy of the grid
	Grid * pGrid = m_model.GetGrid();

	// Get a copy of the HorizontalDynamics
	HorizontalDynamics * pHorizontalDynamics =
		m_model.GetHorizontalDynamics();

	// Get a copy of the VerticalDynamics
	VerticalDynamics * pVerticalDynamics =
		m_model.GetVerticalDynamics();

	// Half a time step
	double dHalfDeltaT = 0.5 * dDeltaT;

	// Vertical timestep
	if (fFirstStep) {
		pVerticalDynamics->StepImplicit(0, 0, time, dHalfDeltaT);

	} else {
		pGrid->LinearCombineData(m_dCarryoverCombination, 0, DataType_State);
	}

	// Forward Euler
	if (m_eExplicitDiscretization == ForwardEuler) {
		pGrid->CopyData(0, 4, DataType_State);
		pHorizontalDynamics->StepExplicit(0, 4, time, dDeltaT);
		pVerticalDynamics->StepExplicit(0, 4, time, dDeltaT);
		pGrid->PostProcessSubstage(4, DataType_State);
		pGrid->PostProcessSubstage(4, DataType_Tracers);

	// Explicit fourth-order Runge-Kutta
	} else if (m_eExplicitDiscretization == RungeKutta4) {
		pGrid->CopyData(0, 1, DataType_State);
		pHorizontalDynamics->StepExplicit(0, 1, time, dHalfDeltaT);
		pVerticalDynamics->StepExplicit(0, 1, time, dHalfDeltaT);
		pGrid->PostProcessSubstage(1, DataType_State);
		pGrid->PostProcessSubstage(1, DataType_Tracers);

		pGrid->CopyData(0, 2, DataType_State);
		pHorizontalDynamics->StepExplicit(1, 2, time, dHalfDeltaT);
		pVerticalDynamics->StepExplicit(1, 2, time, dHalfDeltaT);
		pGrid->PostProcessSubstage(2, DataType_State);
		pGrid->PostProcessSubstage(2, DataType_Tracers);

		pGrid->CopyData(0, 3, DataType_State);
		pHorizontalDynamics->StepExplicit(2, 3, time, dDeltaT);
		pVerticalDynamics->StepExplicit(2, 3, time, dDeltaT);
		pGrid->PostProcessSubstage(3, DataType_State);
		pGrid->PostProcessSubstage(3, DataType_Tracers);

		pGrid->LinearCombineData(m_dRK4Combination, 4, DataType_State);

		pHorizontalDynamics->StepExplicit(3, 4, time, dDeltaT / 6.0);
		pVerticalDynamics->StepExplicit(3, 4, time, dDeltaT / 6.0);
		pGrid->PostProcessSubstage(4, DataType_State);
		pGrid->PostProcessSubstage(4, DataType_Tracers);

	// Explicit strong stability preserving third-order Runge-Kutta
	} else if (m_eExplicitDiscretization == RungeKuttaSSP3) {

		pGrid->CopyData(0, 1, DataType_State);
		pHorizontalDynamics->StepExplicit(0, 1, time, dDeltaT);
		pVerticalDynamics->StepExplicit(0, 1, time, dDeltaT);
		pGrid->PostProcessSubstage(1, DataType_State);
		pGrid->PostProcessSubstage(1, DataType_Tracers);

		pGrid->LinearCombineData(m_dSSPRK3CombinationA, 2, DataType_State);
		pHorizontalDynamics->StepExplicit(1, 2, time, 0.25 * dDeltaT);
		pVerticalDynamics->StepExplicit(1, 2, time, 0.25 * dDeltaT);
		pGrid->PostProcessSubstage(2, DataType_State);
		pGrid->PostProcessSubstage(2, DataType_Tracers);

		pGrid->LinearCombineData(m_dSSPRK3CombinationB, 4, DataType_State);
		pHorizontalDynamics->StepExplicit(2, 4, time, (2.0/3.0) * dDeltaT);
		pVerticalDynamics->StepExplicit(2, 4, time, (2.0/3.0) * dDeltaT);
		pGrid->PostProcessSubstage(4, DataType_State);
		pGrid->PostProcessSubstage(4, DataType_Tracers);

	// Explicit Kinnmark, Gray and Ullrich third-order five-stage Runge-Kutta
	} else if (m_eExplicitDiscretization == KinnmarkGrayUllrich35) {

		pGrid->CopyData(0, 1, DataType_State);
		pHorizontalDynamics->StepExplicit(0, 1, time, dDeltaT / 5.0);
		pVerticalDynamics->StepExplicit(0, 1, time, dDeltaT / 5.0);
		pGrid->PostProcessSubstage(1, DataType_State);
		pGrid->PostProcessSubstage(1, DataType_Tracers);

		pGrid->CopyData(0, 2, DataType_State);
		pHorizontalDynamics->StepExplicit(1, 2, time, dDeltaT / 5.0);
		pVerticalDynamics->StepExplicit(1, 2, time, dDeltaT / 5.0);
		pGrid->PostProcessSubstage(2, DataType_State);
		pGrid->PostProcessSubstage(2, DataType_Tracers);

		pGrid->CopyData(0, 3, DataType_State);
		pHorizontalDynamics->StepExplicit(2, 3, time, dDeltaT / 3.0);
		pVerticalDynamics->StepExplicit(2, 3, time, dDeltaT / 3.0);
		pGrid->PostProcessSubstage(3, DataType_State);
		pGrid->PostProcessSubstage(3, DataType_Tracers);

		pGrid->CopyData(0, 2, DataType_State);
		pHorizontalDynamics->StepExplicit(3, 2, time, 2.0 * dDeltaT / 3.0);
		pVerticalDynamics->StepExplicit(3, 2, time, 2.0 * dDeltaT / 3.0);
		pGrid->PostProcessSubstage(2, DataType_State);
		pGrid->PostProcessSubstage(2, DataType_Tracers);

		pGrid->LinearCombineData(
			m_dKinnmarkGrayUllrichCombination, 4, DataType_State);
		pHorizontalDynamics->StepExplicit(2, 4, time, 3.0 * dDeltaT / 4.0);
		pVerticalDynamics->StepExplicit(2, 4, time, 3.0 * dDeltaT / 4.0);
		pGrid->PostProcessSubstage(4, DataType_State);
		pGrid->PostProcessSubstage(4, DataType_Tracers);

	// Explicit strong stability preserving five-stage third-order Runge-Kutta
	} else if (m_eExplicitDiscretization == RungeKuttaSSPRK53) {

		const double dStepOne = 0.377268915331368;

		pGrid->CopyData(0, 1, DataType_State);
		pHorizontalDynamics->StepExplicit(0, 1, time, dStepOne * dDeltaT);
		pVerticalDynamics->StepExplicit(0, 1, time, dStepOne * dDeltaT);
		pGrid->PostProcessSubstage(1, DataType_State);
		pGrid->PostProcessSubstage(1, DataType_Tracers);

		pGrid->CopyData(1, 2, DataType_State);
		pHorizontalDynamics->StepExplicit(1, 2, time, dStepOne * dDeltaT);
		pVerticalDynamics->StepExplicit(1, 2, time, dStepOne * dDeltaT);
		pGrid->PostProcessSubstage(2, DataType_State);
		pGrid->PostProcessSubstage(2, DataType_Tracers);

		const double dStepThree = 0.242995220537396;

		pGrid->LinearCombineData(m_dSSPRK53CombinationA, 3, DataType_State);
		pHorizontalDynamics->StepExplicit(2, 3, time, dStepThree * dDeltaT);
		pVerticalDynamics->StepExplicit(2, 3, time, dStepThree * dDeltaT);
		pGrid->PostProcessSubstage(3, DataType_State);
		pGrid->PostProcessSubstage(3, DataType_Tracers);

		const double dStepFour = 0.238458932846290;

		pGrid->LinearCombineData(m_dSSPRK53CombinationB, 0, DataType_State);
		pHorizontalDynamics->StepExplicit(3, 0, time, dStepFour * dDeltaT);
		pVerticalDynamics->StepExplicit(3, 0, time, dStepFour * dDeltaT);
		pGrid->PostProcessSubstage(0, DataType_State);
		pGrid->PostProcessSubstage(0, DataType_Tracers);

		const double dStepFive = 0.287632146308408;

		pGrid->LinearCombineData(m_dSSPRK53CombinationC, 4, DataType_State);
		pHorizontalDynamics->StepExplicit(0, 4, time, dStepFive * dDeltaT);
		pVerticalDynamics->StepExplicit(0, 4, time, dStepFive * dDeltaT);
		pGrid->PostProcessSubstage(4, DataType_State);
		pGrid->PostProcessSubstage(4, DataType_Tracers);

	// Invalid explicit discretization
	} else {
		_EXCEPTIONT("Invalid explicit discretization");
	}

	// Apply hyperdiffusion
	pGrid->CopyData(4, 1, DataType_State);
	pHorizontalDynamics->StepAfterSubCycle(4, 1, 2, time, dDeltaT);

	// Vertical timestep
	double dOffCenterDeltaT = 0.5 * (1.0 + m_dOffCentering) * dDeltaT;

	pGrid->CopyData(1, 0, DataType_State);
	pVerticalDynamics->StepImplicit(0, 0, time, dOffCenterDeltaT);

	pGrid->LinearCombineData(m_dOffCenteringCombination, 0, DataType_State);

	if (!fLastStep) {
		pGrid->LinearCombineData(m_dCarryoverFinal, 1, DataType_State);
	}

	//pGrid->CopyData(0, 1, DataType_State);
	//pVerticalDynamics->StepExplicit(0, 1, time, dDeltaT);
	//pVerticalDynamics->StepImplicit(0, 0, time, dDeltaT);
/*
	if (0) {
	//if (fLastStep) {
		DataVector<double> dDifference;
		dDifference.Initialize(2);
		dDifference[0] = -1.0;
		dDifference[1] = 1.0;
		pGrid->LinearCombineData(dDifference, 0, DataType_State);
	} else {
		pGrid->CopyData(4, 0, DataType_State);
	}
*/
}
コード例 #3
0
void TimestepSchemeARS443::Step(
	bool fFirstStep,
	bool fLastStep,
	const Time & time,
	double dDeltaT
) {
	// Get a copy of the grid
	Grid * pGrid = m_model.GetGrid();

	// Get a copy of the HorizontalDynamics
	HorizontalDynamics * pHorizontalDynamics = m_model.GetHorizontalDynamics();

	// Get a copy of the VerticalDynamics
	VerticalDynamics * pVerticalDynamics = m_model.GetVerticalDynamics();

	// u2 explicit evaluation combination
	m_du2fCombo[0] = 1.0 - m_dExpCf[1][0] / m_dExpCf[0][0];
	m_du2fCombo[1] = m_dExpCf[1][0] / m_dExpCf[0][0] - 
					 m_dImpCf[1][0] / m_dImpCf[0][0];
	m_du2fCombo[2] = m_dImpCf[1][0] / m_dImpCf[0][0];
	m_du2fCombo[3] = 0.0;
	m_du2fCombo[4] = 0.0;
	m_du2fCombo[5] = 0.0;
	m_du2fCombo[6] = 0.0;
	m_du2fCombo[7] = 0.0;

	// u3 explicit evaluation combination
	m_du3fCombo[0] = 1.0 - m_dExpCf[2][0] / m_dExpCf[0][0];
	m_du3fCombo[1] = m_dExpCf[2][0] / m_dExpCf[0][0] - 
					 m_dImpCf[2][0] / m_dImpCf[0][0];
	m_du3fCombo[2] = m_dImpCf[2][0] / m_dImpCf[0][0];
	m_du3fCombo[3] = m_dExpCf[2][1] / m_dExpCf[1][1] - 
					 m_dImpCf[2][1] / m_dImpCf[1][1];
	m_du3fCombo[4] = m_dImpCf[2][1] / m_dImpCf[1][1];
	m_du3fCombo[5] = 0.0;
	m_du3fCombo[6] = 0.0;
	m_du3fCombo[7] = -m_dExpCf[2][1] / m_dExpCf[1][1];
	m_du3fCombo[8] = 0.0;
	
        // u4 explicit evaluation combination
	m_du4fCombo[0] = 1.0 - m_dExpCf[3][0] / m_dExpCf[0][0];
	m_du4fCombo[1] = m_dExpCf[3][0] / m_dExpCf[0][0] - 
	m_dImpCf[3][0] / m_dImpCf[0][0];
	m_du4fCombo[2] = m_dImpCf[3][0] / m_dImpCf[0][0];
	m_du4fCombo[3] = m_dExpCf[3][1] / m_dExpCf[1][1] - 
	m_dImpCf[3][1] / m_dImpCf[1][1];
	m_du4fCombo[4] = m_dImpCf[3][1] / m_dImpCf[1][1];
	m_du4fCombo[5] = m_dExpCf[3][2] / m_dExpCf[2][2] - 
	m_dImpCf[3][2] / m_dImpCf[2][2];
	m_du4fCombo[6] = m_dImpCf[3][2] / m_dImpCf[2][2];
	m_du4fCombo[7] = -m_dExpCf[3][1] / m_dExpCf[1][1];
	m_du4fCombo[8] = -m_dExpCf[3][2] / m_dExpCf[2][2];
	m_du4fCombo[9] = 0.0;

	// STAGE 1
	// Compute uf1 into index 1
	pGrid->CopyData(0, 1, DataType_State);
	pGrid->CopyData(0, 1, DataType_Tracers);
	pHorizontalDynamics->StepExplicit(
		0, 1, time, m_dExpCf[0][0] * dDeltaT);
	pVerticalDynamics->StepExplicit(
		0, 1, time, m_dExpCf[0][0] * dDeltaT);
	pGrid->PostProcessSubstage(1, DataType_State);
	pGrid->PostProcessSubstage(1, DataType_Tracers);

	// Compute u1 into index 2
	pGrid->CopyData(1, 2, DataType_State);
	pGrid->CopyData(1, 2, DataType_State);
	pVerticalDynamics->StepImplicit(
		2, 2, time, m_dImpCf[0][0] * dDeltaT);
	pGrid->PostProcessSubstage(2, DataType_State);
	pGrid->PostProcessSubstage(2, DataType_Tracers);

	// STAGE 2
	// Compute uf2 from u1 (index 2) into index 7
	pGrid->LinearCombineData(m_du2fCombo, 7, DataType_State);
	pGrid->LinearCombineData(m_du2fCombo, 7, DataType_Tracers);
	pGrid->CopyData(7, 3, DataType_State);
	pGrid->CopyData(7, 3, DataType_Tracers);
	pHorizontalDynamics->StepExplicit(
		2, 3, time, m_dExpCf[1][1] * dDeltaT);
	pVerticalDynamics->StepExplicit(
		2, 3, time, m_dExpCf[1][1] * dDeltaT);
	pGrid->PostProcessSubstage(3, DataType_State);
	pGrid->PostProcessSubstage(3, DataType_Tracers);

	// Compute u2 from uf2 (index 3) into index 4
	pGrid->CopyData(3, 4, DataType_State);
	pGrid->CopyData(3, 4, DataType_State);
	pVerticalDynamics->StepImplicit(
		4, 4, time, m_dImpCf[1][1] * dDeltaT);
	pGrid->PostProcessSubstage(4, DataType_State);
	pGrid->PostProcessSubstage(4, DataType_Tracers);

	// STAGE 3
	// Compute uf3 from u2 (index 4) into index 8
	pGrid->LinearCombineData(m_du3fCombo, 8, DataType_State);
	pGrid->LinearCombineData(m_du3fCombo, 8, DataType_Tracers);
	pGrid->CopyData(8, 5, DataType_State);
	pGrid->CopyData(8, 5, DataType_Tracers);
	pHorizontalDynamics->StepExplicit(
		4, 5, time, m_dExpCf[2][2] * dDeltaT);
	pVerticalDynamics->StepExplicit(
		4, 5, time, m_dExpCf[2][2] * dDeltaT);
	pGrid->PostProcessSubstage(5, DataType_State);
	pGrid->PostProcessSubstage(5, DataType_Tracers);

	// Compute u3 from uf3 (index 3) into index 6
	pGrid->CopyData(5, 6, DataType_State);
	pGrid->CopyData(5, 6, DataType_State);
	pVerticalDynamics->StepImplicit(
		6, 6, time, m_dImpCf[2][2] * dDeltaT);
	pGrid->PostProcessSubstage(6, DataType_State);
	pGrid->PostProcessSubstage(6, DataType_Tracers);

	// STAGE 4
	// Compute uf4 from u3 (index 6) into index 9
	pGrid->LinearCombineData(m_du4fCombo, 9, DataType_State);
	pGrid->LinearCombineData(m_du4fCombo, 9, DataType_Tracers);
	pHorizontalDynamics->StepExplicit(
		6, 9, time, m_dExpCf[3][3] * dDeltaT);
	pVerticalDynamics->StepExplicit(
		6, 9, time, m_dExpCf[3][3] * dDeltaT);
	pGrid->PostProcessSubstage(9, DataType_State);
	pGrid->PostProcessSubstage(9, DataType_Tracers);

	// Compute u2 from uf2 (index 7) into index 2
	pVerticalDynamics->StepImplicit(
		9, 9, time, m_dImpCf[3][3] * dDeltaT);
	pGrid->PostProcessSubstage(9, DataType_State);
	pGrid->PostProcessSubstage(9, DataType_Tracers);

	// Apply hyperdiffusion at the end of the explicit substep (ask Paul)
	pGrid->CopyData(9, 2, DataType_State);
	pGrid->CopyData(9, 2, DataType_Tracers);
	pHorizontalDynamics->StepAfterSubCycle(2, 1, 9, time, dDeltaT);
	pGrid->CopyData(1, 0, DataType_State);
	pGrid->CopyData(1, 0, DataType_Tracers);
}