int TimestepSchemeStrang::GetSubStepCount() const { HorizontalDynamics * pHorizontalDynamics = m_model.GetHorizontalDynamics(); if (pHorizontalDynamics == NULL) { _EXCEPTIONT("HorizontalDynamics has not been initialized"); } int nHorizontalDynamicsSubSteps = pHorizontalDynamics->GetSubStepAfterSubCycleCount(); return (m_nExplicitSubSteps + nHorizontalDynamicsSubSteps + 1); }
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"); }