// --------------------------------------------------------------- // advance solution by one timestep // return max safe timestep Real AMRNavierStokes::advance() { if (s_verbosity >= 2) { pout () << "AMRNavierStokes::advance " << m_level << ", starting time = " << setiosflags(ios::fixed) << setprecision(6) << setw(12) << m_time << ", dt = " << setiosflags(ios::fixed) << setprecision(6) << setw(12) << dt() << endl; } #ifdef DEBUG // if we're at the beginning of a composite timestep, // save current multilevel state if (m_level == 0) { AMRNavierStokes* levelPtr = this; // figure out finest level while (!levelPtr->finestLevel()) { levelPtr = levelPtr->finerNSPtr(); } int finest_level = levelPtr->m_level; levelPtr = this; for (int lev=0; lev<= finest_level; lev++) { levelPtr->m_saved_time = m_time; levelPtr->newVel().copyTo(levelPtr->newVel().interval(), *levelPtr->m_vel_save_ptr, levelPtr->m_vel_save_ptr->interval()); levelPtr->newLambda().copyTo(levelPtr->newLambda().interval(), *levelPtr->m_lambda_save_ptr, levelPtr->m_lambda_save_ptr->interval()); for (int comp=0; comp<s_num_scal_comps; comp++) { levelPtr->newScal(comp).copyTo(levelPtr->newScal(comp).interval(), *levelPtr->m_scal_save[comp], levelPtr->m_scal_save[comp]->interval()); } levelPtr = levelPtr->finerNSPtr(); } } #endif Real old_time = m_time; Real new_time = m_time + m_dt; m_dt_save = m_dt; swapOldAndNewStates(); const DisjointBoxLayout levelGrids = newVel().getBoxes(); // initialize flux registers if (!finestLevel()) { m_flux_register.setToZero(); for (int comp=0; comp<s_num_scal_comps; comp++) { m_scal_fluxreg_ptrs[comp]->setToZero(); } m_lambda_flux_reg.setToZero(); } // compute advection velocities -- if we're using the // patchGodunov approach, these will have ghost cells. IntVect advVelGhost(IntVect::Unit); LevelData<FluxBox> advectionVel(levelGrids, 1, advVelGhost); if (s_set_bogus_values) { setValLevel(advectionVel, s_bogus_value); } computeAdvectionVelocities(advectionVel); // now that advection velocities have been computed, // update advected scalars // do scalar boundary conditions on lambda // (also grow to appropriate size) LevelData<FArrayBox> lambdaTemp; fillLambda(lambdaTemp, old_time); LevelFluxRegister* crseLambdaFluxRegPtr = NULL; if (m_level > 0) { crseLambdaFluxRegPtr = &(crseNSPtr()->m_lambda_flux_reg); } advectScalar(newLambda(), lambdaTemp, advectionVel, crseLambdaFluxRegPtr, m_lambda_flux_reg, m_patchGodLambda, m_dt); // now do advected-diffused scalars if (s_num_scal_comps > 0) { // loop over scalar components for (int comp=0; comp<s_num_scal_comps; comp++) { BCHolder scalPhysBCs = m_physBCPtr->scalarTraceFuncBC(comp); LevelData<FArrayBox> scalarTemp; fillScalars(scalarTemp, old_time,comp); // now get coarse-level scalars for BC's if necessary LevelData<FArrayBox>* newCrseScalPtr = NULL; LevelData<FArrayBox>* oldCrseScalPtr = NULL; Real oldCrseTime = -s_bogus_value; Real newCrseTime = s_bogus_value; LevelFluxRegister* crseScalFluxRegPtr = NULL; if (m_level > 0) { newCrseScalPtr = &(crseNSPtr()->newScal(comp)); oldCrseScalPtr = &(crseNSPtr()->oldScal(comp)); newCrseTime = crseNSPtr()->time(); oldCrseTime = newCrseTime - crseNSPtr()->dt(); crseScalFluxRegPtr = (crseNSPtr()->m_scal_fluxreg_ptrs[comp]); } advectDiffuseScalar(newScal(comp), scalarTemp, advectionVel, s_scal_coeffs[comp], oldCrseScalPtr, newCrseScalPtr, oldCrseTime, newCrseTime, crseScalFluxRegPtr, *(m_scal_fluxreg_ptrs[comp]), *(m_patchGodScalars[comp]), scalPhysBCs, m_dt, comp); } // end loop over components } // end advected-diffused scalars // now predict velocities -- this returns the advection term // put this in "new_vel" LevelData<FArrayBox>& uStar = newVel(); predictVelocities(uStar, advectionVel); computeUStar(uStar); // if a coarser level exists, will need coarse-level data for proj LevelData<FArrayBox>* crseVelPtr = NULL; if (m_level > 0) { const DisjointBoxLayout& crseGrids = crseNSPtr()->newVel().getBoxes(); crseVelPtr = new LevelData<FArrayBox>(crseGrids, SpaceDim); // coarse velocity BC data is interpolated in time crseNSPtr()->fillVelocity(*crseVelPtr, new_time); } // need to do physical boundary conditions and exchanges bool isViscous = (s_nu > 0); VelBCHolder velBC(m_physBCPtr->uStarFuncBC(isViscous)); velBC.applyBCs(uStar, levelGrids, m_problem_domain, m_dx, false); // inhomogeneous // noel -- all time in level project m_projection.LevelProject(uStar, crseVelPtr, new_time, m_dt); // as things stand now, physical BC's are re-set in LevelProjection // compute maximum safe timestep for next iteration Real newDt = computeDt(); // clean up temp storage if (crseVelPtr != NULL) { delete crseVelPtr; crseVelPtr = NULL; } ++m_level_steps; if (s_verbosity >= 2) { pout () << "AMRNavierStokes::advance " << m_level << ", end time = " << setiosflags(ios::fixed) << setprecision(6) << setw(12) << m_time << ", dt = " << setiosflags(ios::fixed) << setprecision(6) << setw(12) << dt() << endl; } return newDt; }
void timeStepper::timeStep(int &numReads, int &numWrites) { af::timer timeStepTimer = af::timer::start(); PetscPrintf(PETSC_COMM_WORLD, " Time = %f, dt = %f\n\n", time, dt); int numReadsDt, numWritesDt; computeDt(numReadsDt, numWritesDt); /* First take a half step */ PetscPrintf(PETSC_COMM_WORLD, " ---Half step--- \n"); af::timer halfStepTimer = af::timer::start(); currentStep = timeStepperSwitches::HALF_STEP; /* Apply boundary conditions on primOld */ af::timer boundaryTimer = af::timer::start(); boundaries::applyBoundaryConditions(boundaryLeft, boundaryRight, boundaryTop, boundaryBottom, boundaryFront, boundaryBack, *primOld ); setProblemSpecificBCs(numReads,numWrites); double boundaryTime = af::timer::stop(boundaryTimer); int numReadsElemSet, numWritesElemSet; int numReadsComputeFluxes, numWritesComputeFluxes; af::timer elemOldTimer = af::timer::start(); elemOld->set(*primOld, *geomCenter, numReadsElemSet, numWritesElemSet ); double elemOldTime = af::timer::stop(elemOldTimer); af::timer consOldTimer = af::timer::start(); elemOld->computeFluxes(0, *consOld, numReadsComputeFluxes, numWritesComputeFluxes ); numReads = numReadsElemSet + numReadsComputeFluxes; numWrites = numWritesElemSet + numWritesComputeFluxes; double consOldTime = af::timer::stop(consOldTimer); int numReadsExplicitSouces, numWritesExplicitSouces; af::timer explicitSourcesTimer = af::timer::start(); double dX[3]; dX[0] = XCoords->dX1; dX[1] = XCoords->dX2; dX[2] = XCoords->dX3; elemOld->computeExplicitSources(dX, *sourcesExplicit, numReadsExplicitSouces, numWritesExplicitSouces ); numReads += numReadsExplicitSouces; numWrites += numWritesExplicitSouces; double explicitSourcesTime = af::timer::stop(explicitSourcesTimer); int numReadsImplicitSources, numWritesImplicitSources; elemOld->computeImplicitSources(*sourcesImplicitOld, elemOld->tau, numReadsImplicitSources, numWritesImplicitSources ); numReads += numReadsImplicitSources; numWrites += numWritesImplicitSources; af::timer divFluxTimer = af::timer::start(); int numReadsDivFluxes, numWritesDivFluxes; computeDivOfFluxes(*primOld, numReadsDivFluxes, numWritesDivFluxes); numReads += numReadsDivFluxes; numWrites += numWritesDivFluxes; double divFluxTime = af::timer::stop(divFluxTimer); /* Set a guess for prim */ for (int var=0; var < vars::numFluidVars; var++) { prim->vars[var] = primOld->vars[var]; numReads += 1; numWrites += 1; } af::timer inductionEqnTimer = af::timer::start(); cons->vars[vars::B1] = consOld->vars[vars::B1] - 0.5*dt*divFluxes->vars[vars::B1]; cons->vars[vars::B2] = consOld->vars[vars::B2] - 0.5*dt*divFluxes->vars[vars::B2]; cons->vars[vars::B3] = consOld->vars[vars::B3] - 0.5*dt*divFluxes->vars[vars::B3]; prim->vars[vars::B1] = cons->vars[vars::B1]/geomCenter->g; prim->vars[vars::B1].eval(); prim->vars[vars::B2] = cons->vars[vars::B2]/geomCenter->g; prim->vars[vars::B2].eval(); prim->vars[vars::B3] = cons->vars[vars::B3]/geomCenter->g; prim->vars[vars::B3].eval(); double inductionEqnTime = af::timer::stop(inductionEqnTimer); primGuessPlusEps->vars[vars::B1] = prim->vars[vars::B1]; primGuessPlusEps->vars[vars::B2] = prim->vars[vars::B2]; primGuessPlusEps->vars[vars::B3] = prim->vars[vars::B3]; primGuessLineSearchTrial->vars[vars::B1] = prim->vars[vars::B1]; primGuessLineSearchTrial->vars[vars::B2] = prim->vars[vars::B2]; primGuessLineSearchTrial->vars[vars::B3] = prim->vars[vars::B3]; /* Solve dU/dt + div.F - S = 0 to get prim at n+1/2 */ jacobianAssemblyTime = 0.; lineSearchTime = 0.; linearSolverTime = 0.; /* Use simple ideal solver if able and requested */ af::sync(); af::timer solverTimer; af::timer stepConsTimer; double solverTime, stepConsTime; if (params::conduction == 0 && params::viscosity == 0 && params::solver == solvers::IDEAL) { stepConsTimer = af::timer::start(); timeStepFluidCons(0.5*dt); af::sync(); stepConsTime = af::timer::stop(stepConsTimer); int numreads, numwrites; solverTimer = af::timer::start(); idealSolver(*prim, numreads, numwrites); af::sync(); solverTime = af::timer::stop(solverTimer); } else { solverTimer = af::timer::start(); solve(*prim); solverTime = af::timer::stop(solverTimer); } //double solverTime = af::timer::stop(solverTimer); /* Copy solution to primHalfStepGhosted. WARNING: Right now * primHalfStep->vars[var] points to prim->vars[var]. Might need to do a deep * copy. */ for (int var=0; var < prim->numVars; var++) { primHalfStep->vars[var] = prim->vars[var]; numReads += 1; numWrites += 1; } af::timer halfStepCommTimer = af::timer::start(); primHalfStep->communicate(); double halfStepCommTime = af::timer::stop(halfStepCommTimer); af::timer halfStepDiagTimer = af::timer::start(); halfStepDiagnostics(numReads,numWrites); double halfStepDiagTime = af::timer::stop(halfStepDiagTimer); /* Half step complete */ double halfStepTime = af::timer::stop(halfStepTimer); /*PetscPrintf(PETSC_COMM_WORLD, "\n"); PetscPrintf(PETSC_COMM_WORLD, " ---Performance report--- \n"); PetscPrintf(PETSC_COMM_WORLD, " Boundary Conditions : %g secs, %g %\n", boundaryTime, boundaryTime/halfStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Setting elemOld : %g secs, %g %\n", elemOldTime, elemOldTime/halfStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Conserved vars Old : %g secs, %g %\n", consOldTime, consOldTime/halfStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Explicit sources : %g secs, %g %\n", explicitSourcesTime, explicitSourcesTime/halfStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Divergence of fluxes: %g secs, %g %\n", divFluxTime, divFluxTime/halfStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Nonlinear solver : %g secs, %g %\n", solverTime, solverTime/halfStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " |- Jacobian assembly: %g secs, %g %\n", jacobianAssemblyTime, jacobianAssemblyTime/halfStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " |- Linear solver : %g secs, %g %\n", linearSolverTime, linearSolverTime/halfStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " |- Linesearch : %g secs, %g %\n", lineSearchTime, lineSearchTime/halfStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Fluid cons : %g secs, %g %\n", stepConsTime, stepConsTime/halfStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Induction equation : %g secs, %g %\n", inductionEqnTime, inductionEqnTime/halfStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Communication : %g secs, %g %\n", halfStepCommTime, halfStepCommTime/halfStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Diagnostics : %g secs, %g %\n", halfStepDiagTime, halfStepDiagTime/halfStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Half step time : %g secs\n\n", halfStepTime );*/ /* Now take the full step */ PetscPrintf(PETSC_COMM_WORLD, " ---Full step--- \n"); af::sync(); af::timer fullStepTimer = af::timer::start(); currentStep = timeStepperSwitches::FULL_STEP; /* apply boundary conditions on primHalfStep */ boundaryTimer = af::timer::start(); boundaries::applyBoundaryConditions(boundaryLeft, boundaryRight, boundaryTop, boundaryBottom, boundaryFront, boundaryBack, *primHalfStep ); setProblemSpecificBCs(numReads,numWrites); af::sync(); boundaryTime = af::timer::stop(boundaryTimer); af::timer elemHalfStepTimer = af::timer::start(); elemHalfStep->set(*primHalfStep, *geomCenter, numReadsElemSet, numWritesElemSet ); numReads += numReadsElemSet; numWrites += numWritesElemSet; af::sync(); double elemHalfStepTime = af::timer::stop(elemHalfStepTimer); explicitSourcesTimer = af::timer::start(); elemHalfStep->computeExplicitSources(dX, *sourcesExplicit, numReadsExplicitSouces, numWritesExplicitSouces ); numReads += numReadsExplicitSouces; numWrites += numWritesExplicitSouces; af::sync(); explicitSourcesTime = af::timer::stop(explicitSourcesTimer); af::timer implicitSourcesTimer = af::timer::start(); elemOld->computeImplicitSources(*sourcesImplicitOld, elemHalfStep->tau, numReadsImplicitSources, numWritesImplicitSources ); numReads += numReadsImplicitSources; numWrites += numWritesImplicitSources; af::sync(); double implicitSourcesTime = af::timer::stop(implicitSourcesTimer); divFluxTimer = af::timer::start(); computeDivOfFluxes(*primHalfStep, numReadsDivFluxes, numWritesDivFluxes); numReads += numReadsDivFluxes; numWrites += numWritesDivFluxes; af::sync(); divFluxTime = af::timer::stop(divFluxTimer); inductionEqnTimer = af::timer::start(); cons->vars[vars::B1] = consOld->vars[vars::B1] - dt*divFluxes->vars[vars::B1]; cons->vars[vars::B2] = consOld->vars[vars::B2] - dt*divFluxes->vars[vars::B2]; cons->vars[vars::B3] = consOld->vars[vars::B3] - dt*divFluxes->vars[vars::B3]; prim->vars[vars::B1] = cons->vars[vars::B1]/geomCenter->g; prim->vars[vars::B1].eval(); prim->vars[vars::B2] = cons->vars[vars::B2]/geomCenter->g; prim->vars[vars::B2].eval(); prim->vars[vars::B3] = cons->vars[vars::B3]/geomCenter->g; prim->vars[vars::B3].eval(); primGuessPlusEps->vars[vars::B1] = prim->vars[vars::B1]; primGuessPlusEps->vars[vars::B2] = prim->vars[vars::B2]; primGuessPlusEps->vars[vars::B3] = prim->vars[vars::B3]; primGuessLineSearchTrial->vars[vars::B1] = prim->vars[vars::B1]; primGuessLineSearchTrial->vars[vars::B2] = prim->vars[vars::B2]; primGuessLineSearchTrial->vars[vars::B3] = prim->vars[vars::B3]; af::sync(); inductionEqnTime = af::timer::stop(inductionEqnTimer); /* Solve dU/dt + div.F - S = 0 to get prim at n+1/2. NOTE: prim already has * primHalfStep as a guess */ /* Use simple ideal solver if able and requested */ if (params::conduction == 0 && params::viscosity == 0 && params::solver == solvers::IDEAL) { stepConsTimer = af::timer::start(); timeStepFluidCons(dt); af::sync(); stepConsTime = af::timer::stop(stepConsTimer); int numreads, numwrites; solverTimer = af::timer::start(); idealSolver(*prim, numreads, numwrites); af::sync(); solverTime = af::timer::stop(solverTimer); } else { jacobianAssemblyTime = 0.; lineSearchTime = 0.; linearSolverTime = 0.; solverTimer = af::timer::start(); solve(*prim); solverTime = af::timer::stop(solverTimer); } af::timer fullStepCommTimer = af::timer::start(); /* Copy solution to primOldGhosted */ for (int var=0; var < prim->numVars; var++) { primOld->vars[var] = prim->vars[var]; numReads += 1; numWrites += 1; } /* Compute diagnostics */ primOld->communicate(); af::sync(); double fullStepCommTime = af::timer::stop(fullStepCommTimer); time += dt; af::timer fullStepDiagTimer = af::timer::start(); fullStepDiagnostics(numReads,numWrites); af::sync(); double fullStepDiagTime = af::timer::stop(fullStepDiagTimer); /* done */ double fullStepTime = af::timer::stop(fullStepTimer); double timeStepTime = af::timer::stop(timeStepTimer); PetscPrintf(PETSC_COMM_WORLD, "\n"); PetscPrintf(PETSC_COMM_WORLD, " ---Performance report--- \n"); PetscPrintf(PETSC_COMM_WORLD, " Boundary Conditions : %g secs, %g %\n", boundaryTime, boundaryTime/fullStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Setting elemHalfStep: %g secs, %g %\n", elemHalfStepTime, elemHalfStepTime/fullStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Explicit sources : %g secs, %g %\n", explicitSourcesTime, explicitSourcesTime/fullStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Implciit sources : %g secs, %g %\n", implicitSourcesTime, implicitSourcesTime/fullStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Divergence of fluxes: %g secs, %g %\n", divFluxTime, divFluxTime/fullStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Nonlinear solver : %g secs, %g %\n", solverTime, solverTime/fullStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " |- Jacobian assembly: %g secs, %g %\n", jacobianAssemblyTime, jacobianAssemblyTime/fullStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " |- Linear solver : %g secs, %g %\n", linearSolverTime, linearSolverTime/fullStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " |- Linesearch : %g secs, %g %\n", lineSearchTime, lineSearchTime/fullStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Fluid cons : %g secs, %g %\n", stepConsTime, stepConsTime/fullStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Induction equation : %g secs, %g %\n", inductionEqnTime, inductionEqnTime/fullStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Communication : %g secs, %g %\n", fullStepCommTime, fullStepCommTime/fullStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Diagnostics : %g secs, %g %\n", fullStepDiagTime, fullStepDiagTime/fullStepTime * 100 ); PetscPrintf(PETSC_COMM_WORLD, " Full step time : %g secs\n\n", fullStepTime ); PetscPrintf(PETSC_COMM_WORLD, " ---Performance / proc : %g Zone cycles/sec/proc\n", prim->N1Local * prim->N2Local * prim->N3Local / timeStepTime ); PetscPrintf(PETSC_COMM_WORLD, " ---Total Performance : %g Zone cycles/sec\n", N1 * N2 * N3 / timeStepTime ); }