void TimeInterpolatorRK4::interpolate(/// interpolated solution on this level coarsened LevelData<FArrayBox>& a_U, /// time interpolation coefficient in range [0:1] const Real& a_timeInterpCoeff, /// interval of a_U to fill in const Interval& a_intvl) { CH_assert(m_defined); CH_assert(m_gotFullTaylorPoly); CH_assert(a_U.nComp() == m_numStates); LevelData<FArrayBox> UComp; aliasLevelData(UComp, &a_U, a_intvl); // For i in 0:m_numCoeffs-1, // coeffFirst[i] is index of first component of m_taylorCoeffs // that corresponds to a coefficient of t^i. Vector<int> coeffFirst(m_numCoeffs); int intervalLength = a_intvl.size(); for (int i = 0; i < m_numCoeffs; i++) { coeffFirst[i] = a_intvl.begin() + i * m_numStates; } DataIterator dit = UComp.dataIterator(); for (dit.begin(); dit.ok(); ++dit) { FArrayBox& UFab = UComp[dit]; const FArrayBox& taylorFab = m_taylorCoeffs[dit]; // Evaluate a0 + a1*t + a2*t^2 + a3*t^3 // as a0 + t * (a1 + t * (a2 + t * a3)). UFab.copy(taylorFab, coeffFirst[m_numCoeffs-1], 0, intervalLength); for (int ind = m_numCoeffs - 2; ind >=0; ind--) { UFab *= a_timeInterpCoeff; UFab.plus(taylorFab, coeffFirst[ind], 0, intervalLength); } } // dummy statement in order to get around gdb bug int dummy_unused = 0; dummy_unused = 0; }
// ----------------------------------------------------------------------------- // This does the actual computation to update the state variables. // I've included this function since the initializeGlobalPressure() and advance() // functions are, for the most part, the same piece of code. // ----------------------------------------------------------------------------- void AMRNavierStokes::PPMIGTimeStep (const Real a_oldTime, const Real a_dt, const bool a_updatePassiveScalars, const bool a_doLevelProj) { CH_TIME("AMRNavierStokes::PPMIGTimeStep"); pout() << setiosflags(ios::scientific) << setprecision(8) << flush; // Set up some basic values const RealVect& dx = m_levGeoPtr->getDx(); const DisjointBoxLayout& grids = newVel().getBoxes(); DataIterator dit = grids.dataIterator(); const Box domainBox = m_problem_domain.domainBox(); const bool isViscous = (s_nu > 0.0); // Initialize all flux registers if (!finestLevel()) { m_vel_flux_reg.setToZero(); for (int comp = 0; comp < s_num_scal_comps; ++comp) { m_scal_fluxreg_ptrs[comp]->setToZero(); } m_lambda_flux_reg.setToZero(); } // Sanity checks CH_assert(m_levGeoPtr->getBoxes() == grids); CH_assert(m_levGeoPtr->getDomain() == m_problem_domain); CH_assert(Abs(a_oldTime - (m_time - a_dt)) < TIME_EPS); CH_assert(s_num_scal_comps <= 1); CH_assert(s_num_scal_comps > 0 || s_gravityMethod == ProblemContext::GravityMethod::NONE); // Reference new holders LevelData<FArrayBox>& new_vel = newVel(); LevelData<FArrayBox>& new_lambda = newLambda(); LevelData<FArrayBox> new_b; if (s_num_scal_comps > 0) { aliasLevelData(new_b, &(newScal(0)), Interval(0,0)); } // Compute advecting velocities LevelData<FArrayBox> old_vel(grids, SpaceDim, m_tracingGhosts); fillVelocity(old_vel, a_oldTime); old_vel.exchange(m_tracingExCopier); LevelData<FluxBox> adv_vel(grids, 1, IntVect::Unit); // Changed from m_tracingGhosts to 1 computeAdvectingVelocities(adv_vel, old_vel, a_oldTime, a_dt); if (a_updatePassiveScalars) { // Lambda update LevelData<FArrayBox> old_lambda; fillLambda(old_lambda, a_oldTime); old_lambda.exchange(m_tracingExCopier); LevelData<FArrayBox> dLdt(grids, 1); getNewLambda(dLdt, new_lambda, old_lambda, old_vel, adv_vel, a_oldTime, a_dt, a_dt); } LevelData<FArrayBox> old_b; if (s_num_scal_comps > 0) { // Scalar update fillScalars(old_b, a_oldTime, 0); old_b.exchange(m_tracingExCopier); LevelData<FArrayBox> dSdt(grids, 1); getNewScalar(dSdt, new_b, old_b, old_vel, adv_vel, a_oldTime, a_dt, a_dt, 0); } for (int comp = 1; comp < s_num_scal_comps; ++comp) { // Scalar update LevelData<FArrayBox> old_scal; fillScalars(old_scal, a_oldTime, comp); old_scal.exchange(m_tracingExCopier); LevelData<FArrayBox> dSdt(grids, 1); getNewScalar(dSdt, newScal(comp), old_scal, old_vel, adv_vel, a_oldTime, a_dt, a_dt, comp); } { // Update CC velocities LevelData<FArrayBox> dUdt(grids, SpaceDim); getNewVelocity(dUdt, new_vel, old_vel, adv_vel, a_oldTime, a_dt, a_dt); } if (s_num_scal_comps > 0) { // Do implicit gravity update and CC projection. doCCIGProjection(new_vel, new_b, old_vel, old_b, adv_vel, a_oldTime, a_dt, a_doLevelProj); } else { // Do a standard CC projection. doCCProjection(new_vel, a_oldTime + a_dt, a_dt, a_doLevelProj); } }
void TimeInterpolatorRK4::intermediate(/// intermediate RK4 solution on this level coarsened LevelData<FArrayBox>& a_U, /// time interpolation coefficient in range [0:1] const Real& a_timeInterpCoeff, /// which RK4 stage: 0, 1, 2, 3 const int& a_stage, /// interval of a_U to fill in const Interval& a_intvl) const { CH_assert(m_defined); CH_assert(m_gotFullTaylorPoly); CH_assert(a_U.nComp() == m_numStates); CH_assert(a_stage >= 0); CH_assert(a_stage < 4); Real rinv = 1. / Real(m_refineCoarse); Vector<Real> intermCoeffs(4); // 0 is coefficient of m_taylorCoeffs[0] = Ucoarse(0) // 1 is coefficient of m_taylorCoeffs[1] = K1 // 2 is coefficient of m_taylorCoeffs[2] = 1/2 * (-3*K1 + 2*K2 + 2*K3 - K4) // 3 is coefficient of m_taylorCoeffs[3] = 2/3 * ( K1 - K2 - K3 + K4) Real diff12Coeffs; // coefficient of m_diff12 = - K2 + K3 switch (a_stage) { case 0: intermCoeffs[0] = 1.; intermCoeffs[1] = a_timeInterpCoeff; intermCoeffs[2] = a_timeInterpCoeff * a_timeInterpCoeff; intermCoeffs[3] = a_timeInterpCoeff * a_timeInterpCoeff * a_timeInterpCoeff; diff12Coeffs = 0.; break; case 1: intermCoeffs[0] = 1.; intermCoeffs[1] = 0.5*rinv + a_timeInterpCoeff; intermCoeffs[2] = a_timeInterpCoeff * (rinv + a_timeInterpCoeff); intermCoeffs[3] = a_timeInterpCoeff * a_timeInterpCoeff * (1.5*rinv + a_timeInterpCoeff); diff12Coeffs = 0.; break; case 2: intermCoeffs[0] = 1.; intermCoeffs[1] = 0.5*rinv + a_timeInterpCoeff; intermCoeffs[2] = 0.5*rinv*rinv + a_timeInterpCoeff * (rinv + a_timeInterpCoeff); intermCoeffs[3] = 0.375*rinv*rinv*rinv + a_timeInterpCoeff * (1.5*rinv*rinv + a_timeInterpCoeff * (1.5*rinv + a_timeInterpCoeff)); diff12Coeffs = -0.25 * rinv * rinv; break; case 3: intermCoeffs[0] = 1.; intermCoeffs[1] = rinv + a_timeInterpCoeff; intermCoeffs[2] = rinv*rinv + a_timeInterpCoeff * (2.*rinv + a_timeInterpCoeff); intermCoeffs[3] = 0.75*rinv*rinv*rinv + a_timeInterpCoeff * (3.*rinv*rinv + a_timeInterpCoeff * (3.*rinv + a_timeInterpCoeff)); diff12Coeffs = 0.5 * rinv * rinv; break; default: MayDay::Error("TimeInterpolatorRK4::intermediate must have a_stage in range 0:3"); } LevelData<FArrayBox> UComp; aliasLevelData(UComp, &a_U, a_intvl); // For i in 0:m_numCoeffs-1, // coeffFirst[i] is index of first component of m_taylorCoeffs // that corresponds to a coefficient of t^i. Vector<int> coeffFirst(m_numCoeffs); int intervalLength = a_intvl.size(); for (int i = 0; i < m_numCoeffs; i++) { coeffFirst[i] = a_intvl.begin() + i * m_numStates; } DataIterator dit = UComp.dataIterator(); for (dit.begin(); dit.ok(); ++dit) { FArrayBox& UFab = UComp[dit]; const FArrayBox& taylorFab = m_taylorCoeffs[dit]; // WAS: Evaluate a0 + a1*t + a2*t^2 + a3*t^3 // as a0 + t * (a1 + t * (a2 + t * a3)): // that is, set UFab to // a3, t*a3 + a2, t*(t*a3 + a2) + a1, t*(t*(t*a3 + a2) + a1) * a0. // NEW: Evaluate a0*c0 + a1*c1 + a2*c2 + a3*c3, // where c0, c1, c2, c3 are scalars, // and c0 = intermCoeffs[0] = 1. UFab.copy(taylorFab, coeffFirst[0], 0, intervalLength); for (int ind = 1; ind < 4; ind++) { UFab.plus(taylorFab, intermCoeffs[ind], coeffFirst[ind], 0, intervalLength); } const FArrayBox& diff12Fab = m_diff12[dit]; UFab.plus(diff12Fab, diff12Coeffs, 0, 0, intervalLength); } // dummy statement in order to get around gdb bug int dummy_unused = 0; dummy_unused = 0; }