void VCAMRPoissonOp2::residualI(LevelData<FArrayBox>& a_lhs, const LevelData<FArrayBox>& a_phi, const LevelData<FArrayBox>& a_rhs, bool a_homogeneous) { CH_TIME("VCAMRPoissonOp2::residualI"); LevelData<FArrayBox>& phi = (LevelData<FArrayBox>&)a_phi; Real dx = m_dx; const DisjointBoxLayout& dbl = a_lhs.disjointBoxLayout(); DataIterator dit = phi.dataIterator(); { CH_TIME("VCAMRPoissonOp2::residualIBC"); for (dit.begin(); dit.ok(); ++dit) { m_bc(phi[dit], dbl[dit()],m_domain, dx, a_homogeneous); } } phi.exchange(phi.interval(), m_exchangeCopier); for (dit.begin(); dit.ok(); ++dit) { const Box& region = dbl[dit()]; const FluxBox& thisBCoef = (*m_bCoef)[dit]; #if CH_SPACEDIM == 1 FORT_VCCOMPUTERES1D #elif CH_SPACEDIM == 2 FORT_VCCOMPUTERES2D #elif CH_SPACEDIM == 3 FORT_VCCOMPUTERES3D #else This_will_not_compile! #endif (CHF_FRA(a_lhs[dit]), CHF_CONST_FRA(phi[dit]), CHF_CONST_FRA(a_rhs[dit]), CHF_CONST_REAL(m_alpha), CHF_CONST_FRA((*m_aCoef)[dit]), CHF_CONST_REAL(m_beta), #if CH_SPACEDIM >= 1 CHF_CONST_FRA(thisBCoef[0]), #endif #if CH_SPACEDIM >= 2 CHF_CONST_FRA(thisBCoef[1]), #endif #if CH_SPACEDIM >= 3 CHF_CONST_FRA(thisBCoef[2]), #endif #if CH_SPACEDIM >= 4 This_will_not_compile! #endif CHF_BOX(region), CHF_CONST_REAL(m_dx)); } // end loop over boxes }
int scopingTest() { Vector<Box> boxes; int retflag = 0; setGrids(boxes); LevelData<FArrayBox> levelFab; makeLevelData(boxes, levelFab); const DisjointBoxLayout& dbl = levelFab.getBoxes(); DataIterator dit = dbl.dataIterator(); int ivec = 0; for (dit.begin(); dit.ok(); ++dit) { if (!dbl.check(dit())) { if (verbose) pout() << indent2 << pgmname << ": failed at box " << ivec << endl; retflag = 1; } else { levelFab[dit].setVal(0.); } if (retflag > 0) break; ivec++; } return retflag; }
void initData(LevelData<FArrayBox>& a_data, const Real a_dx) { DataIterator dit = a_data.dataIterator(); const DisjointBoxLayout& interiorBoxes = a_data.getBoxes(); for (dit.begin(); dit.ok(); ++dit) { // first set to a bogus value which will persist in ghost cells // after initialization a_data[dit()].setVal(1.0e9); // this will be slow, but who cares? FArrayBox& localData = a_data[dit()]; BoxIterator boxIt(interiorBoxes[dit()]); Real localVal; for (boxIt.begin(); boxIt.ok(); ++boxIt) { const IntVect& loc = boxIt(); for (int comp=0; comp<localData.nComp(); comp++) { localVal = dataVal(loc, comp); localData(loc, comp) = localVal; } } } }
// ----------------------------------------------------------------------------- // Interpolate ghosts at CF interface using zeros on coarser grids. // ----------------------------------------------------------------------------- void homogeneousCFInterp (LevelData<FArrayBox>& a_phif, const RealVect& a_fineDx, const RealVect& a_crseDx, const CFRegion& a_cfRegion, const IntVect& a_applyDirs) { CH_TIME("homogeneousCFInterp (full level)"); // Loop over grids, directions, and sides and call the worker function. DataIterator dit = a_phif.dataIterator(); for (dit.begin(); dit.ok(); ++dit) { if (a_phif[dit].box().isEmpty()) continue; for (int dir = 0; dir < SpaceDim; ++dir) { if (a_applyDirs[dir] == 0) continue; SideIterator sit; for (sit.begin(); sit.ok(); sit.next()) { homogeneousCFInterp(a_phif, dit(), dir, sit(), a_fineDx[dir], a_crseDx[dir], a_cfRegion); } } } }
// this preconditioner first initializes phihat to (IA)phihat = rhshat // (diagonization of L -- A is the matrix version of L) // then smooths with a couple of passes of levelGSRB void VCAMRPoissonOp2::preCond(LevelData<FArrayBox>& a_phi, const LevelData<FArrayBox>& a_rhs) { CH_TIME("VCAMRPoissonOp2::preCond"); // diagonal term of this operator in: // // alpha * a(i) // + beta * sum_over_dir (b(i-1/2*e_dir) + b(i+1/2*e_dir)) / (dx*dx) // // The inverse of this is our initial multiplier. int ncomp = a_phi.nComp(); CH_assert(m_lambda.isDefined()); CH_assert(a_rhs.nComp() == ncomp); CH_assert(m_bCoef->nComp() == ncomp); // Recompute the relaxation coefficient if needed. resetLambda(); // don't need to use a Copier -- plain copy will do DataIterator dit = a_phi.dataIterator(); for (dit.begin(); dit.ok(); ++dit) { // also need to average and sum face-centered bCoefs to cell-centers Box gridBox = a_rhs[dit].box(); // approximate inverse a_phi[dit].copy(a_rhs[dit]); a_phi[dit].mult(m_lambda[dit], gridBox, 0, 0, ncomp); } relax(a_phi, a_rhs, 2); }
void TimeInterpolatorRK4::saveRHS(const LevelData<FArrayBox>& a_rhs) { CH_assert(m_defined); CH_assert(m_gotDt); CH_assert(m_gotInitialSoln); CH_assert(!m_gotFullTaylorPoly); CH_assert(m_countRHS >= 0); CH_assert(m_countRHS < 4); CH_assert(a_rhs.nComp() == m_numStates); // a_rhs is on the coarse layout; // m_rhsCopy is on the coarsened fine layout. a_rhs.copyTo(m_rhsCopy, m_copier); DataIterator dit = m_rhsCopy.dataIterator(); for (dit.begin(); dit.ok(); ++dit) { const FArrayBox& rhsCopyFab = m_rhsCopy[dit]; FArrayBox& taylorFab = m_taylorCoeffs[dit]; for (int ind = 0; ind < m_numCoeffs; ind++) { Real multFactor = m_coeffs[ind][m_countRHS]; if (multFactor != 0.) { taylorFab.plus(rhsCopyFab, multFactor, // multiply rhsCopyFab by this 0, // start rhsCopyFab component ind * m_numStates, // start taylorFab component m_numStates); // number of components } } // These are for getting to RK4 intermediates: // diff12 = m_dt * (rhs[2] - rhs[1]) if (m_countRHS == 1) { FArrayBox& diff12Fab = m_diff12[dit]; diff12Fab.copy(rhsCopyFab); } if (m_countRHS == 2) { FArrayBox& diff12Fab = m_diff12[dit]; diff12Fab -= rhsCopyFab; diff12Fab *= -m_dt; } } m_countRHS++; if (m_countRHS == 4) { m_taylorCoeffs.exchange(); m_gotFullTaylorPoly = true; } }
// // Generate field data. We're not solving any real problem here; // the only purpose of this is to come up with some numbers that couldn't // happen by accident, so we can check if the hdf5 I/O is working. // // New data is a function of prev_checksum (a vector -- one element per // level). // Updates curr_checksum. // void EBRestart::fillData( Vector<LevelData<EBCellFAB>* >& a_ebvector, int a_nlevs, int a_ncomps, const EBRestart::CheckSumVect& a_prev_checksums ) { static int g_i; g_i = 0; for (int lev=0; lev<a_nlevs; ++lev) { LevelData<EBCellFAB>& ld( *a_ebvector[lev] ); DataIterator dit = ld.dataIterator(); for ( dit.begin(); dit.ok(); ++dit ) { EBCellFAB& ebcf( ld[dit] ); // // Single-valued cells // BaseFab<Real>& singFab(ebcf.getSingleValuedFAB()); for ( int i=0; i<singFab.box().numPts()*a_ncomps; ++i ) { long x = (i+a_prev_checksums[lev].sum) % (a_prev_checksums[lev].len_irreg+100); singFab.dataPtr()[i] = x; // singFab.dataPtr()[i] = g_i++; } // // Multivalued cells // Box box( ld.disjointBoxLayout().get(dit) ); box.grow( ld.ghostVect() ); const IntVectSet& irregIVS( ebcf.getEBISBox().boundaryIVS(box) ); const EBGraph& graph( ebcf.getEBISBox().getEBGraph() ); Vector<Real> multidat( a_ncomps ); const IntVectSet& multiIVS( ebcf.getMultiValuedFAB().getIVS() ); for ( VoFIterator it(irregIVS,graph); it.ok(); ++it ) { if ( multiIVS.contains( it().gridIndex() ) ) { for ( int c=0;c<a_ncomps;++c ) { // multidat[c] = 111000 + g_i++; multidat[c] = 111000 + g_i++ + 10*c + a_prev_checksums[lev].sum%71; } ebcf.assign( &multidat[0], it(), Interval(0,a_ncomps-1) ); } } } } }
void initData(LevelData<FArrayBox>& a_data, Real a_dx) { // for now, set phi to 1 everywhere Real phiVal = 1.0; DataIterator dit = a_data.dataIterator(); for (dit.begin(); dit.ok(); ++dit) { a_data[dit].setVal(phiVal); } }
// --------------------------------------------------------- void AMRNavierStokes::computeKineticEnergy(LevelData<FArrayBox>& a_energy) const { // this is simple since no BC's need to be set. const LevelData<FArrayBox>& levelVel = *m_vel_new_ptr; const DisjointBoxLayout& levelGrids = levelVel.getBoxes(); DataIterator dit = a_energy.dataIterator(); for (dit.begin(); dit.ok(); ++dit) { FORT_KINETICENERGY(CHF_FRA1(a_energy[dit],0), CHF_CONST_FRA(levelVel[dit]), CHF_BOX(levelGrids[dit])); } }
void VCAMRPoissonOp2::applyOpNoBoundary(LevelData<FArrayBox>& a_lhs, const LevelData<FArrayBox>& a_phi) { CH_TIME("VCAMRPoissonOp2::applyOpNoBoundary"); LevelData<FArrayBox>& phi = (LevelData<FArrayBox>&)a_phi; const DisjointBoxLayout& dbl = a_lhs.disjointBoxLayout(); DataIterator dit = phi.dataIterator(); phi.exchange(phi.interval(), m_exchangeCopier); for (dit.begin(); dit.ok(); ++dit) { const Box& region = dbl[dit()]; const FluxBox& thisBCoef = (*m_bCoef)[dit]; #if CH_SPACEDIM == 1 FORT_VCCOMPUTEOP1D #elif CH_SPACEDIM == 2 FORT_VCCOMPUTEOP2D #elif CH_SPACEDIM == 3 FORT_VCCOMPUTEOP3D #else This_will_not_compile! #endif (CHF_FRA(a_lhs[dit]), CHF_CONST_FRA(phi[dit]), CHF_CONST_REAL(m_alpha), CHF_CONST_FRA((*m_aCoef)[dit]), CHF_CONST_REAL(m_beta), #if CH_SPACEDIM >= 1 CHF_CONST_FRA(thisBCoef[0]), #endif #if CH_SPACEDIM >= 2 CHF_CONST_FRA(thisBCoef[1]), #endif #if CH_SPACEDIM >= 3 CHF_CONST_FRA(thisBCoef[2]), #endif #if CH_SPACEDIM >= 4 This_will_not_compile! #endif CHF_BOX(region), CHF_CONST_REAL(m_dx)); } // end loop over boxes }
void VCAMRPoissonOp2::applyOpI(LevelData<FArrayBox>& a_lhs, const LevelData<FArrayBox>& a_phi, bool a_homogeneous ) { CH_TIME("VCAMRPoissonOp2::applyOpI"); LevelData<FArrayBox>& phi = (LevelData<FArrayBox>&)a_phi; Real dx = m_dx; const DisjointBoxLayout& dbl = a_lhs.disjointBoxLayout(); DataIterator dit = phi.dataIterator(); for (dit.begin(); dit.ok(); ++dit) { m_bc(phi[dit], dbl[dit()],m_domain, dx, a_homogeneous); } applyOpNoBoundary(a_lhs, a_phi); }
// Find the maximum wave speed on the current level Real OldLevelGodunov::getMaxWaveSpeed(const LevelData<FArrayBox>& a_U) { const DisjointBoxLayout& disjointBoxLayout = a_U.disjointBoxLayout(); DataIterator dit = disjointBoxLayout.dataIterator(); // Initial maximum wave speed Real speed = 0.0; // This computation doesn't need involve a time but the time being set // is checked by OldPatchGodunov::getMaxWaveSpeed so we have to set it // to something... m_patchGodunov->setCurrentTime(0.0); // Loop over all grids to get the maximum wave speed for (dit.begin(); dit.ok(); ++dit) { const Box& currentBox = disjointBoxLayout.get(dit()); // Set the current box and get the maximum wave speed on the current grid m_patchGodunov->setCurrentBox(currentBox); Real speedOverBox = m_patchGodunov->getMaxWaveSpeed(a_U[dit()], currentBox); // Compute a running maximum speed = Max(speed,speedOverBox); } // Gather maximum wave speeds and broadcast the maximum over these Vector<Real> allSpeeds; gather(allSpeeds,speed,uniqueProc(SerialTask::compute)); if (procID() == uniqueProc(SerialTask::compute)) { speed = allSpeeds[0]; for (int i = 1; i < allSpeeds.size (); ++i) { speed = Max(speed,allSpeeds[i]); } } broadcast(speed,uniqueProc(SerialTask::compute)); // Return the maximum wave speed return speed; }
void setValue(LevelData<EBCellFAB>& phase, const BaseBCValue& value, const Box& domain, const RealVect& dx, const RealVect& origin, bool useKappa) { RealVect loc; IntVect originIV = domain.smallEnd(); DataIterator dit = phase.dataIterator(); for (dit.begin(); dit.ok(); ++dit) { EBCellFAB& efab = phase[dit]; FArrayBox& fab = efab.getFArrayBox(); ForAllX(Real, fab) { D_EXPR(loc[0]=iR+nR-nR+originIV[0], loc[1]=jR+originIV[1], loc[2]=kR+originIV[2]); loc+=0.5; loc*=dx; loc+=origin; fabR = value.value(loc, RealVect::Zero, 1.e99,0); } EndFor ; if (useKappa) { const EBISBox& ebox = efab.getEBISBox(); IntVectSet ivs = ebox.getIrregIVS(efab.getRegion()); IVSIterator it(ivs); for (; it.ok(); ++it) { const IntVect iv = it(); VolIndex vi(iv,0); if (ebox.bndryArea(vi) != 0) { loc = iv; loc+=0.5; loc+= ebox.centroid(vi); loc*=dx; loc+=origin; efab(vi, 0) = value.value(loc, RealVect::Zero, 1.e99,0)*ebox.volFrac(vi); } } } }
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; }
// Set up initial conditions void ExplosionIBC::initialize(LevelData<FArrayBox>& a_U) { CH_assert(m_isFortranCommonSet == true); CH_assert(m_isDefined == true); DataIterator dit = a_U.boxLayout().dataIterator(); // Iterator of all grids in this level for (dit.begin(); dit.ok(); ++dit) { // Storage for current grid FArrayBox& U = a_U[dit()]; // Box of current grid Box uBox = U.box(); uBox &= m_domain; // Set up initial condition in this grid FORT_EXPLOSIONINITF(CHF_FRA(U), CHF_CONST_REAL(m_dx), CHF_BOX(uBox)); } }
void TimeInterpolatorRK4::saveInitialSoln(const LevelData<FArrayBox>& a_soln) { CH_assert(m_defined); CH_assert(m_gotDt); CH_assert(!m_gotInitialSoln); CH_assert(a_soln.nComp() == m_numStates); // First zero out taylorFab. DataIterator dit = m_taylorCoeffs.dataIterator(); for (dit.begin(); dit.ok(); ++dit) { FArrayBox& taylorFab = m_taylorCoeffs[dit]; taylorFab.setVal(0.); } // a_soln is on the coarse layout; // m_taylorCoeffs is on the coarsened fine layout. // Copy from a_soln to first m_numStates components of m_taylorCoeffs. const Interval& srcInt = a_soln.interval(); a_soln.copyTo(srcInt, m_taylorCoeffs, srcInt, m_copier); m_gotInitialSoln = true; }
void initData(LevelData<FArrayBox>& a_data, const Real a_dx) { DataIterator dit = a_data.dataIterator(); const DisjointBoxLayout& interiorBoxes = a_data.getBoxes(); for (dit.begin(); dit.ok(); ++dit) { // first set to a bogus value which will persist in ghost cells // after initialization a_data[dit()].setVal(1.0e9); // this will be slow, but who cares? FArrayBox& localData = a_data[dit()]; BoxIterator boxIt(interiorBoxes[dit()]); Real localVal; for (boxIt.begin(); boxIt.ok(); ++boxIt) { const IntVect& loc = boxIt(); // linear profile //localVal = a_dx*(D_TERM(loc[0]+0.5, // + loc[1]+0.5, // + loc[2]+0.5)); // quadratic profile localVal = a_dx*a_dx*(D_TERM6((loc[0]+0.5)*(loc[0]+0.5), + (loc[1]+0.5)*(loc[1]+0.5), + (loc[2]+0.5)*(loc[2]+0.5), + (loc[3]+0.5)*(loc[3]+0.5), + (loc[4]+0.5)*(loc[4]+0.5), + (loc[5]+0.5)*(loc[5]+0.5))); localData(loc) = localVal; } } }
void VCAMRPoissonOp2::levelJacobi(LevelData<FArrayBox>& a_phi, const LevelData<FArrayBox>& a_rhs) { CH_TIME("VCAMRPoissonOp2::levelJacobi"); // Recompute the relaxation coefficient if needed. resetLambda(); LevelData<FArrayBox> resid; create(resid, a_rhs); // Get the residual residual(resid,a_phi,a_rhs,true); // Multiply by the weights DataIterator dit = m_lambda.dataIterator(); for (dit.begin(); dit.ok(); ++dit) { resid[dit].mult(m_lambda[dit]); } // Do the Jacobi relaxation incr(a_phi, resid, 0.5); }
// this function averages down the fine solution to the valid // regions of the computed solution, then subtracts ir from // the computed solution. (error is exact-computed) void computeAMRError(Vector<LevelData<FArrayBox>* >& a_error, const Vector<string>& a_errorVars, const Vector<LevelData<FArrayBox>* >& a_computedSoln, const Vector<string>& a_computedVars, const Vector<DisjointBoxLayout>& a_computedGrids, const Real a_computedDx, const Vector<int>& a_computedRefRatio, const Vector<LevelData<FArrayBox>* >& a_exactSoln, const Vector<string>& a_exactVars, const Real a_exactDx, Real a_bogus_value, bool a_HOaverage, bool a_computeRelativeError) { int numLevels = a_computedSoln.size(); CH_assert(a_exactSoln.size() == 1); CH_assert(a_error.size() == numLevels); CH_assert(a_exactDx <= a_computedDx); CH_assert(a_computedRefRatio.size() >= numLevels - 1); if (a_exactDx == a_computedDx) { cerr << "Exact dx and computed dx are equal." << endl; } // check whether input file selects "sum all variables" bool sumAll = false; ParmParse pp; pp.query("sumAll",sumAll); // const DisjointBoxLayout& exactGrids = a_exactSoln[0]->getBoxes(); Real dxLevel = a_computedDx; // do a bit of sleight-of-hand in the case where there are no // ghost cells in the exact solution -- allocate a temporary which // _has_ ghost cells, and do a copyTo LevelData<FArrayBox>* exactSolnPtr = NULL; bool allocatedMemory = false; if (a_exactSoln[0]->ghostVect() == IntVect::Zero) { exactSolnPtr = new LevelData<FArrayBox>(a_exactSoln[0]->getBoxes(), a_exactSoln[0]->nComp(), IntVect::Unit); a_exactSoln[0]->copyTo(*exactSolnPtr); allocatedMemory = true; } else { // if there are ghost cells, we can use the exactSoln as-is exactSolnPtr = a_exactSoln[0]; } LevelData<FArrayBox>& exactSolnRef = *exactSolnPtr; // first need to set boundary conditions on exactsoln // this is for the Laplacian which is needed in AverageHO DataIterator ditFine = exactSolnRef.dataIterator(); DomainGhostBC exactBC; Interval exactComps(0, a_exactVars.size() - 1); for (int dir = 0; dir < SpaceDim; dir++) { SideIterator sit; for (sit.reset(); sit.ok(); ++sit) { // use HO extrapolation at physical boundaries HOExtrapBC thisBC(dir, sit(), exactComps); exactBC.setBoxGhostBC(thisBC); } } for (ditFine.begin(); ditFine.ok(); ++ditFine) { FArrayBox& thisFineSoln = exactSolnRef[ditFine()]; const Box& fineBox = exactSolnRef.getBoxes()[ditFine()]; exactBC.applyInhomogeneousBCs(thisFineSoln, fineBox, a_exactDx); } exactSolnRef.exchange(exactComps); // outer loop is over levels for (int level = 0; level < numLevels; level++) { LevelData<FArrayBox>& thisLevelError = *a_error[level]; LevelData<FArrayBox>& thisLevelComputed = *a_computedSoln[level]; // compute refinement ratio between solution at this level // and exact solution Real nRefTemp = (dxLevel / a_exactDx); int nRefExact = (int) nRefTemp; // this is to do rounding properly if necessary if (nRefTemp - nRefExact > 0.5) nRefExact += 1; // make sure it's not zero if (nRefExact == 0) nRefExact =1; const DisjointBoxLayout levelGrids = a_error[level]->getBoxes(); const DisjointBoxLayout fineGrids = a_exactSoln[0]->getBoxes(); DisjointBoxLayout coarsenedFineGrids; // petermc, 14 Jan 2014: Replace this because fineGrids might // not be coarsenable by nRefExact. // coarsen(coarsenedFineGrids, fineGrids, nRefExact); int nCoarsenExact = nRefExact; while ( !fineGrids.coarsenable(nCoarsenExact) && (nCoarsenExact > 0) ) { // Divide nCoarsenExact by 2 until fineGrids is coarsenable by it. nCoarsenExact /= 2; } if (nCoarsenExact == 0) { nCoarsenExact = 1; } coarsen(coarsenedFineGrids, fineGrids, nCoarsenExact); int numExact = a_exactVars.size(); LevelData<FArrayBox> averagedExact(coarsenedFineGrids, numExact); Box fineRefBox(IntVect::Zero, (nCoarsenExact-1)*IntVect::Unit); // average fine solution down to coarsened-fine level // loop over grids and do HO averaging down //DataIterator crseExactDit = coarsenedFineGrids.dataIterator(); for (ditFine.reset(); ditFine.ok(); ++ditFine) { const Box fineBox = exactSolnRef.getBoxes()[ditFine()]; FArrayBox fineTemp(fineBox, 1); Box coarsenedFineBox(fineBox); coarsenedFineBox.coarsen(nCoarsenExact); if (a_exactDx < a_computedDx) { // loop over components for (int comp = 0; comp < numExact; comp++) { Box coarseBox(coarsenedFineGrids.get(ditFine())); coarseBox &= coarsenedFineBox; if (!coarseBox.isEmpty()) { // for now, this is a quick and dirty way to avoid // stepping out of bounds if there are no ghost cells. // LapBox will be the box over which we are // able to compute the Laplacian. Box LapBox = exactSolnRef[ditFine()].box(); LapBox.grow(-1); LapBox &= fineBox; fineTemp.setVal(0.0); int doHO = 0; if (a_HOaverage) { doHO = 1; } // average by default int doAverage = 1; if (sumAll || sumVar(a_exactVars[comp])) { doAverage = 0; } // average or sum, based on booleans FORT_AVERAGEHO(CHF_FRA1(averagedExact[ditFine], comp), CHF_CONST_FRA1(exactSolnRef[ditFine], comp), CHF_FRA1(fineTemp, 0), CHF_BOX(coarseBox), CHF_BOX(LapBox), CHF_CONST_INT(nCoarsenExact), CHF_BOX(fineRefBox), CHF_INT(doHO), CHF_INT(doAverage)); } // end if crseBox not empty } // end loop over comps } else { // if cell sizes are the same, then copy averagedExact[ditFine].copy(exactSolnRef[ditFine]); } } // end loop over exact solution boxes int nRefineComputed = nRefExact / nCoarsenExact; LevelData<FArrayBox>* thisLevelComputedRefinedPtr = &thisLevelComputed; LevelData<FArrayBox>* thisLevelErrorRefinedPtr = &thisLevelError; if (nRefineComputed > 1) { // Do piecewise constant interpolation (replication) by nRefineComputed // on thisLevelComputed. DisjointBoxLayout levelRefinedGrids; refine(levelRefinedGrids, levelGrids, nRefineComputed); int nCompComputed = thisLevelComputed.nComp(); IntVect ghostVectComputed = nRefineComputed * thisLevelComputed.ghostVect(); thisLevelComputedRefinedPtr = new LevelData<FArrayBox>(levelRefinedGrids, nCompComputed, ghostVectComputed); ProblemDomain levelDomain = levelRefinedGrids.physDomain(); FineInterp interpolator(levelRefinedGrids, nCompComputed, nRefineComputed, levelDomain); interpolator.pwcinterpToFine(*thisLevelComputedRefinedPtr, thisLevelComputed); int nCompErr = thisLevelError.nComp(); IntVect ghostVectErr = nRefineComputed * thisLevelError.ghostVect(); thisLevelErrorRefinedPtr = new LevelData<FArrayBox>(levelRefinedGrids, nCompErr, ghostVectErr); } // initialize error to 0 // also initialize error to a bogus value DataIterator levelDit = thisLevelError.dataIterator(); for (levelDit.begin(); levelDit.ok(); ++levelDit) { (*thisLevelErrorRefinedPtr)[levelDit].setVal(a_bogus_value); } Box refComputedBox(IntVect::Zero, (nRefineComputed-1)*IntVect::Unit); // loop over variables for (int nErr = 0; nErr < a_errorVars.size(); nErr++) { string thisErrVar = a_errorVars[nErr]; bool done = false; // first loop over exact variables for (int exactComp = 0; exactComp < a_exactVars.size(); exactComp++) { string thisExactVar = a_exactVars[exactComp]; // check if this exact variable is "the one" if ((thisExactVar == thisErrVar) || nonAverageVar(thisErrVar)) { int computedComp = 0; // now loop over computed variables while (!done && (computedComp < a_computedVars.size())) { if (a_computedVars[computedComp] == thisErrVar) { if (!nonAverageVar(thisErrVar)) { // copy averaged exact solution -> error // and then subtract computed solution Interval exactInterval(exactComp, exactComp); Interval errorInterval(nErr, nErr); averagedExact.copyTo(exactInterval, *thisLevelErrorRefinedPtr, errorInterval); } DataIterator levelDit = thisLevelError.dataIterator(); for (levelDit.reset(); levelDit.ok(); ++levelDit) { FArrayBox& thisComputedRefined = (*thisLevelComputedRefinedPtr)[levelDit]; FArrayBox& thisErrorRefined = (*thisLevelErrorRefinedPtr)[levelDit]; if (a_computeRelativeError) { // do this a little strangely -- relative // error is one - computed/exact. thisErrorRefined.divide(thisComputedRefined, computedComp, nErr, 1); thisErrorRefined.invert(-1.0, nErr, 1); thisErrorRefined.plus(1.0, nErr, 1); } else { thisErrorRefined.minus(thisComputedRefined, computedComp, nErr, 1); } if (nRefineComputed > 1) { FArrayBox& thisError = thisLevelError[levelDit]; Box coarseBox = thisError.box(); // Average thisErrorRefined to thisError. int doHO = 0; if (a_HOaverage) { doHO = 1; } CH_assert(doHO == 0); // for now, this is a quick and dirty way to avoid // stepping out of bounds if there are no ghost cells. // LapBox will be the box over which we are // able to compute the Laplacian. Box LapBox = thisErrorRefined.box(); LapBox.grow(-1); // LapBox &= fineBox; FArrayBox fineTemp(thisErrorRefined.box(), 1); fineTemp.setVal(0.0); // average by default int doAverage = 1; // average or sum, based on booleans FORT_AVERAGEHO(CHF_FRA1(thisError, nErr), CHF_CONST_FRA1(thisErrorRefined, nErr), CHF_FRA1(fineTemp, 0), CHF_BOX(coarseBox), CHF_BOX(LapBox), CHF_CONST_INT(nRefineComputed), CHF_BOX(refComputedBox), CHF_INT(doHO), CHF_INT(doAverage)); } } // end loop over coarse grids done = true; } // if computedVar is a_errorVar computedComp += 1; } // end loop over a_computedVars if (!done) { pout() << "Variable " << thisErrVar << " not found!!!" << endl; MayDay::Error(); } } // end if this exactVar is correct } // end loop over exact variables } // end loop over errors if (nRefineComputed > 1) { delete thisLevelComputedRefinedPtr; delete thisLevelErrorRefinedPtr; } // now need to set covered regions to 0 if (level < numLevels - 1) { // will need to loop over all boxes in finer level, not just // those on this processor... const BoxLayout& finerGrids = a_computedSoln[level + 1]->boxLayout(); LayoutIterator fineLit = finerGrids.layoutIterator(); // outer loop over this level's grids, since there are fewer of them DataIterator levelDit = thisLevelError.dataIterator(); for (levelDit.reset(); levelDit.ok(); ++levelDit) { const Box& coarseBox = levelGrids[levelDit()]; FArrayBox& thisError = thisLevelError[levelDit()]; int numError = thisError.nComp(); for (fineLit.reset(); fineLit.ok(); ++fineLit) { Box fineBox(finerGrids[fineLit()]); // now coarsen box down to this level fineBox.coarsen(a_computedRefRatio[level]); // if coarsened fine box intersects error's box, set // overlap to 0 fineBox &= coarseBox; if (!fineBox.isEmpty()) { thisError.setVal(0.0, fineBox, 0, numError); } } // end loop over finer-level grids } // end loop over this-level grids // this is a good place to update dx as well dxLevel = dxLevel / a_computedRefRatio[level]; } // end if there is a finer level thisLevelError.exchange(); } // end loop over levels // clean up if we need to if (allocatedMemory) { delete exactSolnPtr; exactSolnPtr = NULL; } }
// --------------------------------------------------------------- void AMRNavierStokes::computeAdvectionVelocities(LevelData<FluxBox>& a_advVel) { if (s_verbosity >= 3) { pout() << "AMRNavierStokes::computeAdvectionVelocities: " << m_level << endl; } bool isViscous = (s_nu > 0.0); const DisjointBoxLayout& levelGrids = newVel().getBoxes(); /// need to build grown grids to get be able to do all of /// tracing properly IntVect advect_grow(D_DECL(ADVECT_GROW, ADVECT_GROW, ADVECT_GROW)); LevelData<FArrayBox> old_vel(levelGrids, SpaceDim, advect_grow); LevelData<FArrayBox> viscousSource(levelGrids, SpaceDim, advect_grow); LevelData<FArrayBox>* crseVelPtr = NULL; if (s_set_bogus_values) { setValLevel(old_vel, s_bogus_value); setValLevel(viscousSource, s_bogus_value); } // m_time contains the time at which the new state is centered Real old_time = m_time - m_dt; fillVelocity(old_vel, old_time); // set physical boundary conditions here // set physical boundary conditions on velocity if (isViscous) { LevelData<FArrayBox> viscousVel(levelGrids, SpaceDim, advect_grow); DataIterator dit = viscousVel.dataIterator(); // rather than resetting BC's on old_vel, and then setting them // back, just copy old_vel to a temporary holder, and set // BCs on that one. for (dit.begin(); dit.ok(); ++dit) { viscousVel[dit].copy(old_vel[dit]); } VelBCHolder velBC(m_physBCPtr->viscousVelFuncBC()); velBC.applyBCs(viscousVel, levelGrids, m_problem_domain, m_dx, false); // inhomogeneous // if crse level exists, fill coarse velocity BC if (m_level > 0) { const DisjointBoxLayout& crseGrids = crseNSPtr()->newVel().getBoxes(); crseVelPtr = new LevelData<FArrayBox>(crseGrids, SpaceDim); crseNSPtr()->fillVelocity(*crseVelPtr, old_time); } computeLapVel(viscousSource, viscousVel, crseVelPtr); for (dit.reset(); dit.ok(); ++dit) { viscousSource[dit].mult(s_nu); } } else { setValLevel(viscousSource, 0.0); } // tracing will use inviscid BC's { VelBCHolder velBC(m_physBCPtr->tracingVelFuncBC()); velBC.applyBCs(old_vel, levelGrids, m_problem_domain, m_dx, false); // inhomogeneous } // call utility function to do tracing traceAdvectionVel(a_advVel, old_vel, viscousSource, m_patchGodVelocity, old_time, m_dt); EdgeVelBCHolder edgeVelBC(m_physBCPtr->advectionVelFuncBC(isViscous)); edgeVelBC.applyBCs(a_advVel, levelGrids, m_problem_domain, m_dx, false); // inhomogeneous // noel levelMacProject is big guy // now MAC project m_projection.levelMacProject(a_advVel, old_time, m_dt); // finally, add volume discrepancy correction if (m_projection.etaLambda() > 0 && s_applyFreestreamCorrection) { LevelData<FluxBox>& grad_e_Lambda = m_projection.grad_eLambda(); DataIterator dit = levelGrids.dataIterator(); for (dit.reset(); dit.ok(); ++dit) { FluxBox& thisGrad_eLambda = grad_e_Lambda[dit]; FluxBox& thisAdvVel = a_advVel[dit]; for (int dir=0; dir<SpaceDim; dir++) { thisAdvVel[dir] += thisGrad_eLambda[dir]; } } } edgeVelBC.applyBCs(a_advVel, levelGrids, m_problem_domain, m_dx, false); // inhomogeneous // clean up storage if (crseVelPtr != NULL) { delete crseVelPtr; crseVelPtr = NULL; } }
int main(int argc ,char *argv[] ) { #ifdef CH_MPI MPI_Init(&argc, &argv); #endif int status = 0; // Make this test pass automatically if DIM > 3, to avoid FAIL message. if (SpaceDim <= 3) { parseTestOptions(argc, argv); // establish periodic domain -- first multiply periodic in all directions int baseDomainSize = 8; int numGhost = 2; IntVect ghostVect(numGhost*IntVect::Unit); Box baseDomBox(IntVect::Zero, (baseDomainSize-1)*IntVect::Unit); ProblemDomain baseDomain(baseDomBox); // set periodic in all directions for (int dir=0; dir<SpaceDim; dir++) { baseDomain.setPeriodic(dir, true); } { // QuadCFInterp test int nRef = 2; ProblemDomain fineDomain(baseDomain); fineDomain.refine(nRef); const Box domainBox = baseDomain.domainBox(); Vector<Box> crseBoxes(1, domainBox); Vector<int> crseProcAssign(1,0); DisjointBoxLayout crseGrids(crseBoxes, crseProcAssign, baseDomain); // note the lack of ghost cells on the base level LevelData<FArrayBox> crseData(crseGrids, 1, IntVect::Zero); Real dxCrse = 1.0/(baseDomainSize); Real dxFine = dxCrse/nRef; initData(crseData, dxCrse); #if (CH_SPACEDIM == 1) Vector<Box> fineBoxes(2); Vector<int> fineProcAssign(2); fineBoxes[0] = Box(IntVect::Zero, 5*IntVect::Unit); fineBoxes[1] = Box(IntVect(D_DECL6(6,10,10,6,10,0)), IntVect(D_DECL6(11,15,15,11,15,15))); #else // try multiple boxes for fine level Vector<Box> fineBoxes(4); Vector<int> fineProcAssign(4); fineBoxes[0] = Box(IntVect::Zero, 9*IntVect::Unit); fineBoxes[1] = Box(IntVect(D_DECL6(6,10,10,6,10,0)), IntVect(D_DECL6(11,15,15,11,15,15))); // this box should fail the disjointness test //fineBoxes[1] = Box(IntVect(D_DECL(7,10,10)), 17*IntVect::Unit); fineBoxes[2] = Box(IntVect(D_DECL6(12,2,0,12,2,0)), IntVect(D_DECL6(15,7,7,15,7,7))); fineBoxes[3] = Box(IntVect(D_DECL6(12,12,0,12,12,0)), 15*IntVect::Unit); #endif int loadbalancestatus = LoadBalance(fineProcAssign, fineBoxes); CH_assert (loadbalancestatus == 0); DisjointBoxLayout fineGrids; fineGrids.define(fineBoxes, fineProcAssign, fineDomain); LevelData<FArrayBox> fineData(fineGrids, 1, ghostVect); // set these to a bogus value to start with DataIterator fineDit = fineData.dataIterator(); for (fineDit.begin(); fineDit.ok(); ++fineDit) { fineData[fineDit()].setVal(1.0e9); } FineInterp interpolator(fineGrids, 1, nRef, fineDomain); // turn on fine-data averaging even though it's unnecessary // since this is a test (so we'd like to know if it's broken) bool averageFineData = true; interpolator.interpToFine(fineData, crseData, averageFineData); // now fill in ghost cells QuadCFInterp filler(fineGrids, &crseGrids, dxFine, nRef, 1, fineDomain); filler.coarseFineInterp(fineData, crseData); } { // fineInterp near boundary test int numLev = 3; Vector<int> nRefVect(numLev); nRefVect[0] = 4; nRefVect[1] = 2; nRefVect[2] = -1; Vector<Real> dxVect(numLev); Vector<ProblemDomain> levelDomains(numLev); levelDomains[0] = Box(IntVect::Zero, 15*IntVect::Unit); dxVect[0] = 1.0/(levelDomains[0].domainBox().size(0)); for (int lev=1; lev<numLev; lev++) { levelDomains[lev] = levelDomains[lev-1]; levelDomains[lev].refine(nRefVect[lev-1]); dxVect[lev] = dxVect[lev-1]/nRefVect[lev-1]; } Vector<DisjointBoxLayout> levelGrids(numLev); Vector<LevelData<FArrayBox>* > levelData(numLev, NULL); const Box domainBox = levelDomains[0].domainBox(); Vector<Box> crseBoxes(1, domainBox); Vector<int> crseProcAssign(1,0); DisjointBoxLayout level0Grids(crseBoxes, crseProcAssign, levelDomains[0]); levelGrids[0] = level0Grids; // note the lack of ghost cells on the base level levelData[0] = new LevelData<FArrayBox>(level0Grids, 1, IntVect::Zero); initData(*levelData[0], dxVect[0]); Vector<Box> level1Boxes(1, levelDomains[1].domainBox()); int loadbalancestatus = LoadBalance(crseProcAssign, level1Boxes); CH_assert (loadbalancestatus == 0); IntVect newGhostVect(4*IntVect::Unit); DisjointBoxLayout fineGrids; fineGrids.define(level1Boxes, crseProcAssign, levelDomains[1]); levelGrids[1] = fineGrids; levelData[1] = new LevelData<FArrayBox>(fineGrids, 1, newGhostVect); Vector<Box> level2Boxes(1); //level2Boxes[0] = Box(20*IntVect::Unit, 119*IntVect::Unit); level2Boxes[0] = Box(100*IntVect::Unit, 127*IntVect::Unit); DisjointBoxLayout finestGrids(level2Boxes, crseProcAssign, levelDomains[2]); levelGrids[2] = finestGrids; levelData[2] = new LevelData<FArrayBox>(finestGrids, 1, newGhostVect); for (int lev=1; lev<numLev; lev++) { LevelData<FArrayBox>& fineData = *levelData[lev]; LevelData<FArrayBox>& crseData = *levelData[lev-1]; // set these to a bogus value to start with DataIterator fineDit = fineData.dataIterator(); for (fineDit.begin(); fineDit.ok(); ++fineDit) { fineData[fineDit()].setVal(1.0e9); } FineInterp interpolator(levelGrids[lev], 1, nRefVect[lev-1], levelDomains[lev]); // turn on fine-data averaging even though it's unnecessary // since this is a test (so we'd like to know if it's broken) bool averageFineData = true; interpolator.interpToFine(fineData, crseData, averageFineData); pout() << "grids at level = " << lev << endl; dumpDBL(&levelGrids[lev]); pout() << "grids at level = " << lev-1 << endl; dumpDBL(&levelGrids[lev-1]); // now fill in ghost cells QuadCFInterp filler(levelGrids[lev], &levelGrids[lev-1], dxVect[lev], nRefVect[lev-1], 1, levelDomains[lev]); filler.coarseFineInterp(fineData, crseData); } #ifdef CH_USE_HDF5 // dump data if (writePlots) { string fname = "interp.hdf5"; Vector<string> varNames(1,"phi"); Real dt = 0.0; Real time= 0.0; WriteAMRHierarchyHDF5(fname, levelGrids, levelData, varNames, levelDomains[0].domainBox(), dxVect[0], dt, time, nRefVect, numLev); } #endif // clean up memory for (int lev=0; lev<levelData.size(); lev++) { if (levelData[lev] != NULL) { delete levelData[lev]; levelData[lev] = NULL; } } } // now test partially periodic case (also coarsen back to original domain // no such thing as "partially periodic" for 1D; for 1D, test moving // fine-grid boxes from low-end of domain to high-end of domain { baseDomain.setPeriodic(0,false); // try similar tests to the previous case int nRef = 2; ProblemDomain fineDomain(baseDomain); fineDomain.refine(nRef); const Box domainBox = baseDomain.domainBox(); Vector<Box> crseBoxes(1, domainBox); Vector<int> crseProcAssign(1,0); DisjointBoxLayout crseGrids(crseBoxes, crseProcAssign, baseDomain); // note the lack of ghost cells on the base level LevelData<FArrayBox> crseData(crseGrids, 1, IntVect::Zero); Real dxCrse = 1.0/(baseDomainSize); Real dxFine = dxCrse/nRef; initData(crseData, dxCrse); #if (CH_SPACEDIM == 1) Vector<Box> fineBoxes(2); Vector<int> fineProcAssign(2); fineBoxes[0] = Box(12*IntVect::Unit, 15*IntVect::Unit); fineBoxes[1] = Box(IntVect(D_DECL6(6,10,10,6,10,10)), IntVect(D_DECL6(11,15,15,11,15,15))); #else // try multiple boxes for fine level // note grids are different in this case to allow for all periodic checking Vector<Box> fineBoxes(3); Vector<int> fineProcAssign(3); fineBoxes[0] = Box(IntVect::Zero, 9*IntVect::Unit); fineBoxes[1] = Box(IntVect(D_DECL6(6,10,10,6,10,10)), IntVect(D_DECL6(11,15,15,11,15,15))); // this box should fail the disjointness test //fineBoxes[1] = Box(IntVect(D_DECL(7,10,10)), 17*IntVect::Unit); fineBoxes[2] = Box(IntVect(D_DECL6(12,2,0,12,2,0)), IntVect(D_DECL6(15,7,7,15,7,7))); //fineBoxes[3] = Box(IntVect(D_DECL(12,12,0)), 15*IntVect::Unit); #endif int loadbalancestatus = LoadBalance(fineProcAssign, fineBoxes); CH_assert (loadbalancestatus == 0); DisjointBoxLayout fineGrids; fineGrids.define(fineBoxes, fineProcAssign, fineDomain); LevelData<FArrayBox> fineData(fineGrids, 1, ghostVect); // set these to a bogus value to start with DataIterator fineDit = fineData.dataIterator(); for (fineDit.begin(); fineDit.ok(); ++fineDit) { fineData[fineDit()].setVal(1.0e9); } FineInterp interpolator(fineGrids, 1, nRef, fineDomain); // turn on fine-data averaging even though it's unnecessary // since this is a test (so we'd like to know if it's broken) bool averageFineData = true; interpolator.interpToFine(fineData, crseData, averageFineData); // now fill in first layer of ghost cells QuadCFInterp filler(fineGrids, &crseGrids, dxFine, nRef, 1, fineDomain); filler.coarseFineInterp(fineData, crseData); // now fill in remaining ghost cell with extrapolation Interval extrapInterval(1,1); ExtrapFillPatch extrapFiller(fineGrids, fineDomain, extrapInterval); for (int dir=0; dir<SpaceDim; dir++) { extrapFiller.fillExtrap(fineData,dir,0,1); } fineData.exchange(fineData.interval()); } } // if (SpaceDim <= 3) pout() << indent << pgmname << ": " << ( (status == 0) ? "passed all tests" : "failed at least one test,") << endl; #ifdef CH_MPI MPI_Finalize(); #endif return status ; }
void MappedLevelFluxRegister::define(const DisjointBoxLayout& a_dbl, const DisjointBoxLayout& a_dblCoarse, const ProblemDomain& a_dProblem, const IntVect& a_nRefine, int a_nComp, bool a_scaleFineFluxes) { CH_TIME("MappedLevelFluxRegister::define"); m_isDefined = FluxRegDefined; // Basically, define was called m_nRefine = a_nRefine; m_scaleFineFluxes = a_scaleFineFluxes; DisjointBoxLayout coarsenedFine; coarsen(coarsenedFine, a_dbl, a_nRefine); #ifndef DISABLE_TEMPORARY_FLUX_REGISTER_OPTIMIZATION // This doesn't work for multi-block calculations, which are // not properly nested. -JNJ //begin temporary optimization. bvs int numPts = 0; for (LayoutIterator lit = a_dblCoarse.layoutIterator(); lit.ok(); ++lit) { numPts += a_dblCoarse[lit].numPts(); } for (LayoutIterator lit = coarsenedFine.layoutIterator(); lit.ok(); ++lit) { numPts -= coarsenedFine[lit].numPts(); } if (numPts == 0) { m_coarFlux.clear(); // OK, fine region completely covers coarse region. no registers. return; } #endif //end temporary optimization. bvs m_coarFlux.define( a_dblCoarse, a_nComp); m_isDefined |= FluxRegCoarseDefined; m_domain = a_dProblem; ProblemDomain coarsenedDomain; coarsen(coarsenedDomain, a_dProblem, a_nRefine); m_fineFlux.define( coarsenedFine, a_nComp, IntVect::Unit); m_isDefined |= FluxRegFineDefined; m_reverseCopier.ghostDefine(coarsenedFine, a_dblCoarse, coarsenedDomain, IntVect::Unit); for (int i = 0; i < CH_SPACEDIM; i++) { m_coarseLocations[i].define(a_dblCoarse); m_coarseLocations[i + CH_SPACEDIM].define(a_dblCoarse); } DataIterator dC = a_dblCoarse.dataIterator(); LayoutIterator dF = coarsenedFine.layoutIterator(); for (dC.begin(); dC.ok(); ++dC) { const Box& cBox = a_dblCoarse.get(dC); for (dF.begin(); dF.ok(); ++dF) { const Box& fBox = coarsenedFine.get(dF); if (fBox.bigEnd(0) + 1 < cBox.smallEnd(0)) { //can skip this box since they cannot intersect, due to sorting } else if (fBox.smallEnd(0) - 1 > cBox.bigEnd(0)) { //skip to end, since all the rest of boxes will not intersect either dF.end(); } else { for (int i = 0; i < CH_SPACEDIM; i++) { Vector<Box>& lo = m_coarseLocations[i][dC]; Vector<Box>& hi = m_coarseLocations[i + CH_SPACEDIM][dC]; Box loBox = adjCellLo(fBox, i, 1); Box hiBox = adjCellHi(fBox, i, 1); if (cBox.intersectsNotEmpty(loBox)) lo.push_back(loBox & cBox); if (cBox.intersectsNotEmpty(hiBox)) hi.push_back(hiBox & cBox); } } } } Box domainBox = coarsenedDomain.domainBox(); if (a_dProblem.isPeriodic()) { Vector<Box> periodicBoxes[2 * CH_SPACEDIM]; for (dF.begin(); dF.ok(); ++dF) { const Box& fBox = coarsenedFine.get(dF); for (int i = 0; i < CH_SPACEDIM; i++) { if (a_dProblem.isPeriodic(i)) { if (fBox.smallEnd(i) == domainBox.smallEnd(i)) periodicBoxes[i].push_back(adjCellLo(fBox, i, 1)); if (fBox.bigEnd(i) == domainBox.bigEnd(i)) periodicBoxes[i + CH_SPACEDIM].push_back(adjCellHi(fBox, i, 1)); } } } for (int i = 0; i < CH_SPACEDIM; i++) { Vector<Box>& loV = periodicBoxes[i]; Vector<Box>& hiV = periodicBoxes[i + CH_SPACEDIM]; int size = domainBox.size(i); for (int j = 0; j < loV.size(); j++) loV[j].shift(i, size); for (int j = 0; j < hiV.size(); j++) hiV[j].shift(i, -size); } for (dC.begin(); dC.ok(); ++dC) { const Box& cBox = a_dblCoarse.get(dC); for (int i = 0; i < CH_SPACEDIM; i++) if (a_dProblem.isPeriodic(i)) { Vector<Box>& loV = periodicBoxes[i]; Vector<Box>& hiV = periodicBoxes[i + CH_SPACEDIM]; if (cBox.smallEnd(i) == domainBox.smallEnd(i) ) { Vector<Box>& hi = m_coarseLocations[i + CH_SPACEDIM][dC]; for (int j = 0; j < hiV.size(); j++) { if (cBox.intersectsNotEmpty(hiV[j])) hi.push_back(cBox & hiV[j]); } } if (cBox.bigEnd(i) == domainBox.bigEnd(i) ) { Vector<Box>& lo = m_coarseLocations[i][dC]; for (int j = 0; j < loV.size(); j++) { if (cBox.intersectsNotEmpty(loV[j])) lo.push_back(cBox & loV[j]); } } } } } }
void LevelFluxRegisterEdge::refluxCurl(LevelData<FluxBox>& a_uCoarse, Real a_scale) { CH_assert(isDefined()); CH_assert(a_uCoarse.nComp() == m_nComp); SideIterator side; // idir is the normal direction to the coarse-fine interface for (int idir=0 ; idir<SpaceDim; ++idir) { for (side.begin(); side.ok(); ++side) { LevelData<FluxBox>& fineReg = m_fabFine[index(idir, side())]; // first, create temp LevelData<FluxBox> to hold "coarse flux" const DisjointBoxLayout coarseBoxes = m_regCoarse.getBoxes(); // this fills the place of what used to be m_fabCoarse in the old // implementation LevelData<FluxBox> coarReg(coarseBoxes, m_nComp, IntVect::Unit); // now fill the coarReg with the curl of the stored coarse-level // edge-centered flux DataIterator crseDit = coarseBoxes.dataIterator(); for (crseDit.begin(); crseDit.ok(); ++crseDit) { FluxBox& thisCoarReg = coarReg[crseDit]; thisCoarReg.setVal(0.0); EdgeDataBox& thisEdgeData = m_regCoarse[crseDit]; for (int edgeDir=0; edgeDir<SpaceDim; edgeDir++) { if (idir != edgeDir) { FArrayBox& crseEdgeDataDir = thisEdgeData[edgeDir]; for (int faceDir = 0; faceDir<SpaceDim; faceDir++) { if (faceDir != edgeDir) { FArrayBox& faceData = thisCoarReg[faceDir]; int shiftDir = -1; for (int i=0; i<SpaceDim; i++) { if ((i != faceDir) && (i != edgeDir) ) { shiftDir = i; } } CH_assert(shiftDir >= 0); crseEdgeDataDir.shiftHalf(shiftDir, sign(side())); // scaling already taken care of in incrementCrse Real scale = 1.0; faceData.plus(crseEdgeDataDir, scale, 0, 0, faceData.nComp()); crseEdgeDataDir.shiftHalf(shiftDir, -sign(side())); } // end if not normal direction } // end loop over face directions } // end if edgeDir != idir } // end loop over edge directions } // end loop over crse boxes // first, we need to create a temp LevelData<FluxBox> // to make a local copy in the coarse layout space of // the fine register increments LevelData<FluxBox> fineRegLocal(coarReg.getBoxes(), m_nComp, IntVect::Unit); fineReg.copyTo(fineReg.interval(), fineRegLocal, fineRegLocal.interval(), m_crseCopiers[index(idir,side())]); for (DataIterator it = a_uCoarse.dataIterator(); it.ok(); ++it) { // loop over flux components here for (int fluxComp=0; fluxComp < SpaceDim; fluxComp++) { // we don't do anything in the normal direction if (fluxComp != idir) { // fluxDir is the direction of the face-centered flux FArrayBox& U = a_uCoarse[it()][fluxComp]; // set up IntVectSet to avoid double counting of updates Box coarseGridBox = U.box(); // transfer to Cell-centered, then create IVS coarseGridBox.shiftHalf(fluxComp,1); IntVectSet nonUpdatedEdges(coarseGridBox); // remember, we want to take the curl here // also recall that fluxComp is the component // of the face-centered curl (not the edge-centered // vector field that we're refluxing, which is why // the sign may seem like it's the opposite of what // you might expect! Real local_scale = -sign(side())*a_scale; //int testDir = (fluxComp+1)%(SpaceDim); if (((fluxComp+1)%(SpaceDim)) == idir) local_scale *= -1; Vector<IntVectSet>& ivsV = m_refluxLocations[index(idir, side())][it()][fluxComp]; Vector<DataIndex>& indexV = m_coarToCoarMap[index(idir, side())][it()]; IVSIterator iv; for (int i=0; i<ivsV.size(); ++i) { iv.define(ivsV[i]); const FArrayBox& coar = coarReg[indexV[i]][fluxComp]; const FArrayBox& fine = fineRegLocal[indexV[i]][fluxComp]; for (iv.begin(); iv.ok(); ++iv) { IntVect thisIV = iv(); if (nonUpdatedEdges.contains(thisIV)) { for (int comp=0; comp <m_nComp; ++comp) { //Real coarVal = coar(thisIV, comp); //Real fineVal = fine(thisIV, comp); U(thisIV, comp) -= local_scale*(coar(thisIV, comp) +fine(thisIV, comp)); } nonUpdatedEdges -= thisIV; } } } } // end if not normal face } // end loop over fluxbox directions } // end loop over coarse boxes } // end loop over sides } // end loop over directions }
// new define void LevelFluxRegisterEdge::define( const DisjointBoxLayout& a_dbl, const DisjointBoxLayout& a_dblCoarse, const ProblemDomain& a_dProblem, int a_nRefine, int a_nComp) { m_isDefined = true; CH_assert(a_nRefine > 0); CH_assert(a_nComp > 0); CH_assert(!a_dProblem.isEmpty()); m_nComp = a_nComp; m_nRefine = a_nRefine; m_domainCoarse = coarsen(a_dProblem, a_nRefine); CH_assert (a_dblCoarse.checkPeriodic(m_domainCoarse)); // allocate copiers m_crseCopiers.resize(SpaceDim*2); SideIterator side; // create a Vector<Box> of the fine boxes which also includes periodic images, // since we don't really care about the processor layouts, etc Vector<Box> periodicFineBoxes; CFStencil::buildPeriodicVector(periodicFineBoxes, a_dProblem, a_dbl); // now coarsen these boxes... for (int i=0; i<periodicFineBoxes.size(); i++) { periodicFineBoxes[i].coarsen(m_nRefine); } for (int idir=0 ; idir<SpaceDim; ++idir) { for (side.begin(); side.ok(); ++side) { // step one, build fineBoxes, flux register boxes // indexed by the fine level but in the coarse index // space DisjointBoxLayout fineBoxes,tmp; // first create coarsened dbl, then compute flux register boxes // adjacent to coarsened fine boxes coarsen(tmp, a_dbl, m_nRefine); if (side() == Side::Lo) { adjCellLo(fineBoxes, tmp, idir,1); } else { adjCellHi(fineBoxes, tmp, idir,1); } // now define the FluxBoxes of fabFine on this DisjointBoxLayout m_fabFine[index(idir, side())].define(fineBoxes, a_nComp); LayoutData<Vector<Vector<IntVectSet> > >& ivsetsVect = m_refluxLocations[index(idir, side())]; ivsetsVect.define(a_dblCoarse); LayoutData<Vector<DataIndex> >& mapsV = m_coarToCoarMap[index(idir, side())]; mapsV.define(a_dblCoarse); DisjointBoxLayout coarseBoxes = a_dblCoarse; DataIterator dit = a_dblCoarse.dataIterator(); for (dit.begin(); dit.ok(); ++dit) { unsigned int thisproc = a_dblCoarse.procID(dit()); if (thisproc == procID()) { ivsetsVect[DataIndex(dit())].resize(SpaceDim); } const Box& coarseBox = a_dblCoarse[dit()]; int count = 0; for (int i=0; i<periodicFineBoxes.size(); i++) { Box regBox; if (side() == Side::Lo) { regBox = adjCellLo(periodicFineBoxes[i], idir, 1); } else { regBox = adjCellHi(periodicFineBoxes[i], idir, 1); } // do this little dance in order to ensure that // we catch corner cells which might be in different // boxes. Box testBox(regBox); testBox.grow(1); testBox.grow(idir,-1); if (testBox.intersectsNotEmpty(coarseBox)) { testBox &= coarseBox; ++count; unsigned int proc = a_dblCoarse.procID(dit()); const DataIndex index = DataIndex(dit()); if (proc == procID()) { mapsV[DataIndex(dit())].push_back(index); // loop over face directions here for (int faceDir=0; faceDir<SpaceDim; faceDir++) { // do nothing in normal direction if (faceDir != idir) { // this should give us the face indices for the // faceDir-centered faces adjacent to the coarse-fine // interface which are contained in the current // coarse box Box intersectBox(regBox); Box coarseEdgeBox(coarseBox); coarseEdgeBox.surroundingNodes(faceDir); intersectBox.surroundingNodes(faceDir); intersectBox &= coarseEdgeBox; intersectBox.shiftHalf(faceDir,1); IntVectSet localIV(intersectBox); ivsetsVect[DataIndex(dit())][faceDir].push_back(localIV); } } } } } // end loop over boxes on coarse level } m_regCoarse.define(coarseBoxes, a_nComp, IntVect::Unit); // last thing to do is to define copiers m_crseCopiers[index(idir, side())].define(fineBoxes, coarseBoxes, IntVect::Unit); } } }
// this function works on two solutions on equivalent grids. // It subtracts the computed solution from the exact solution // if a_doGhostCells == true, then does box-by-box comparison, // including ghost cells (boxes must be the same for each). // Otherwise, only does this for valid cells, but boxes don't // need to be the same. void computeSameSizeError(Vector<LevelData<FArrayBox>* >& a_error, const Vector<string>& a_errorVars, const Vector<LevelData<FArrayBox>* >& a_computedSoln, const Vector<string>& a_computedVars, const Vector<DisjointBoxLayout>& a_computedGrids, const Real a_dx, const Vector<int>& a_refRatio, const Vector<LevelData<FArrayBox>* >& a_exactSoln, const Vector<string>& a_exactVars, Real a_bogus_value, bool a_computeRelativeError, bool a_doGhostCells) { int numLevels = a_computedSoln.size(); CH_assert(a_exactSoln.size() == numLevels); CH_assert(a_error.size() == numLevels); CH_assert(a_refRatio.size() >= numLevels - 1); Real dxLevel = a_dx; // outer loop is over levels for (int level = 0; level < numLevels; level++) { LevelData<FArrayBox>& thisLevelError = *a_error[level]; LevelData<FArrayBox>& thisLevelComputed = *a_computedSoln[level]; LevelData<FArrayBox>& thisLevelExact = *a_exactSoln[level]; const DisjointBoxLayout levelGrids = thisLevelComputed.getBoxes(); const DisjointBoxLayout exactGrids = thisLevelExact.getBoxes(); DataIterator levelDit = levelGrids.dataIterator(); for (levelDit.begin(); levelDit.ok(); ++levelDit) { // initialize error to a bogus value thisLevelError[levelDit()].setVal(a_bogus_value); } // loop over variables for (int nErr = 0; nErr < a_errorVars.size(); nErr++) { string thisErrVar = a_errorVars[nErr]; bool done = false; // this is where things differ between the ghost-cell // and non-ghost-cell approach. if (a_doGhostCells) { // this is the older approach to things -- // do everything grid-by-grid // first loop over exact variables for (int exactComp = 0; exactComp < a_exactVars.size(); exactComp++) { string thisExactVar = a_exactVars[exactComp]; // check if this exact variable is "the one" if (thisExactVar == thisErrVar) { int computedComp = 0; // now loop over computed variables while (!done && (computedComp < a_computedVars.size())) { if (a_computedVars[computedComp] == thisErrVar) { // copy exact solution -> error // and then subtract computed solution DataIterator exactDit = thisLevelExact.dataIterator(); for (levelDit.reset(); levelDit.ok(); ++levelDit) { FArrayBox& thisComputed = thisLevelComputed[levelDit()]; FArrayBox& thisError = thisLevelError[levelDit()]; const Box& thisBox = levelGrids[levelDit()]; for (exactDit.begin(); exactDit.ok(); ++exactDit) { if (thisBox.contains(exactGrids[exactDit()])) { thisError.copy(thisLevelExact[exactDit()], exactComp, nErr, 1); } // end if exact and computed boxes match } // end loop over exact grids if (a_computeRelativeError) { // do this a little strangely -- relative // error is one - computed/exact. thisError.divide(thisComputed, computedComp, nErr, 1); thisError.invert(-1.0, nErr, 1); thisError.plus(1.0, nErr, 1); } else { thisError.minus(thisComputed, computedComp, nErr, 1); } } // end loop over grids done = true; } // if a_computedVar is a_errorVar computedComp += 1; } // end loop over a_computedVars if (!done) { pout() << "Variable " << thisErrVar << " not found!!!" << endl; MayDay::Error(); } } // end if this exactVar is correct } // end loop over exact variables } else // non-ghost cell case; this is simpler: { // first loop over exact variables and copy into error for (int exactComp=0; exactComp<a_exactVars.size(); ++exactComp) { string thisExactVar = a_exactVars[exactComp]; // check if this exact variable is "the one" if (thisExactVar == thisErrVar) { // copy exact solution -> error Interval exactInterval(exactComp, exactComp); Interval errInterval(nErr, nErr); thisLevelExact.copyTo(exactInterval, thisLevelError, errInterval); done = true; } // end if this exact var is the error var } // end loop over exact comps if (!done) { pout() << "Variable " << thisErrVar << " not found in exact solution!!!" << endl; MayDay::Error(); } done = false; int computedComp = 0; // now loop over computed variables and subtract computed solution while (!done && (computedComp < a_computedVars.size())) { if (a_computedVars[computedComp] == thisErrVar) { for (levelDit.reset(); levelDit.ok(); ++levelDit) { FArrayBox& thisComputed = thisLevelComputed[levelDit()]; FArrayBox& thisError = thisLevelError[levelDit()]; thisError.minus(thisComputed, computedComp, nErr, 1); } // end loop over computed/error grids done = true; } // if a_computedVar is a_errorVar computedComp += 1; } // end loop over a_computedVars if (!done) { pout() << "Variable " << thisErrVar << " not found!!!" << endl; MayDay::Error(); } } // end non-ghost-cell case } // end loop over errors // now need to set covered regions to 0 if (level < numLevels - 1) { // will need to loop over all boxes in finer level, not just // those on this processor... const BoxLayout& finerGrids = a_computedSoln[level + 1]->boxLayout(); LayoutIterator fineLit = finerGrids.layoutIterator(); // outer loop over this level's grids, since there are fewer of them DataIterator levelDit = thisLevelError.dataIterator(); for (levelDit.reset(); levelDit.ok(); ++levelDit) { const Box& coarseBox = levelGrids[levelDit()]; FArrayBox& thisError = thisLevelError[levelDit()]; int numError = thisError.nComp(); for (fineLit.reset(); fineLit.ok(); ++fineLit) { Box fineBox(finerGrids[fineLit()]); // now coarsen box down to this level fineBox.coarsen(a_refRatio[level]); // if coarsened fine box intersects error's box, set // overlap to 0 fineBox &= coarseBox; if (!fineBox.isEmpty()) { thisError.setVal(0.0, fineBox, 0, numError); } } // end loop over finer-level grids } // end loop over this-level grids // this is a good place to update dx as well dxLevel = dxLevel / a_refRatio[level]; } // end if there is a finer level // finally, if we're not doing ghost cells, do an exchange just // to "prettify" the output if (!a_doGhostCells) { thisLevelError.exchange(thisLevelError.interval()); } } // end loop over levels }
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; }
// Create tags for regridding void AMRLevelPluto::tagCells(IntVectSet& a_tags) { CH_assert(allDefined()); if (s_verbosity >= 3) { pout() << "AMRLevelPluto::tagCells " << m_level << endl; } // Create tags based on undivided gradient of density const DisjointBoxLayout& levelDomain = m_UNew.disjointBoxLayout(); IntVectSet localTags; // If there is a coarser level interpolate undefined ghost cells if (m_hasCoarser) { const AMRLevelPluto* amrGodCoarserPtr = getCoarserLevel(); PiecewiseLinearFillPluto pwl; pwl.define(levelDomain, amrGodCoarserPtr->m_UNew.disjointBoxLayout(), m_numStates, amrGodCoarserPtr->m_problem_domain, amrGodCoarserPtr->m_ref_ratio, m_dx, 1); pwl.fillInterp(m_UNew, amrGodCoarserPtr->m_UNew, amrGodCoarserPtr->m_UNew, 1.0, 0, 0, m_numStates); } m_UNew.exchange(Interval(0,m_numStates-1)); #if GEOMETRY != CARTESIAN const LevelData<FArrayBox>& dV = m_levelPluto.getdV(); #endif // Compute relative gradient DataIterator dit = levelDomain.dataIterator(); for (dit.begin(); dit.ok(); ++dit){ const Box& b = levelDomain[dit()]; FArrayBox gradFab(b,1); FArrayBox& UFab = m_UNew[dit()]; #if GEOMETRY != CARTESIAN const FArrayBox& curdV = dV[dit()]; #else const FArrayBox curdV; #endif m_patchPluto->computeRefGradient(gradFab, UFab, curdV, b); // Tag where gradient exceeds threshold BoxIterator bit(b); for (bit.begin(); bit.ok(); ++bit){ const IntVect& iv = bit(); if (gradFab(iv) >= m_refineThresh) { localTags |= iv; } } } localTags.grow(m_tagBufferSize); // Need to do this in two steps unless a IntVectSet::operator &= // (ProblemDomain) operator is defined Box localTagsBox = localTags.minBox(); localTagsBox &= m_problem_domain; localTags &= localTagsBox; a_tags = localTags; }
int main(int argc, char** argv) { //This test is an attempt to test linearization //of eb data holders directly int eekflag=0; #ifdef CH_MPI MPI_Init(&argc, &argv); #endif //begin forever present scoping trick { //registerDebugger(); // Set up some geometry. Box domain; Real dx; do_geo( domain, dx ); Vector<Box> boxes(1, domain); Vector<int> procs(1, 0); // Make a layout for the space. DisjointBoxLayout dbl(boxes, procs); // Fill in the layout with the geometrical info. EBISLayout ebisl; EBIndexSpace *ebisPtr = Chombo_EBIS::instance(); ebisPtr->fillEBISLayout(ebisl, dbl, domain, 1 ); // Define the leveldata for my one and only level. DataIterator dit = dbl.dataIterator(); for ( dit.begin(); dit.ok(); ++dit ) { eekflag = testIVFAB(ebisl[dit()], dbl.get(dit())); if (eekflag != 0) { pout() << "IVFAB linearization test failed " << endl; return eekflag; } eekflag = testIFFAB(ebisl[dit()], dbl.get(dit())); if (eekflag != 0) { pout() << "IFFAB linearization test failed " << endl; return eekflag; } eekflag = testEBCellFAB(ebisl[dit()], dbl.get(dit())); if (eekflag != 0) { pout() << "EBCellFAB linearization test failed " << endl; return eekflag; } eekflag = testEBFaceFAB(ebisl[dit()], dbl.get(dit())); if (eekflag != 0) { pout() << "EBFaceFAB linearization test failed " << endl; return eekflag; } eekflag = testEBFluxFAB(ebisl[dit()], dbl.get(dit())); if (eekflag != 0) { pout() << "EBFluxFAB linearization test failed " << endl; return eekflag; } } ebisPtr->clear(); }//end scoping trick pout() << "linearization tests passed "<< endl; #ifdef CH_MPI MPI_Finalize(); #endif return eekflag; }
int main(int argc ,char *argv[] ) { #ifdef CH_MPI MPI_Init(&argc, &argv); #endif parseTestOptions(argc, argv); // establish periodic domain -- first multiply periodic in all directions int status = 0; int baseDomainSize = 8; int numGhost = 2; IntVect ghostVect(numGhost*IntVect::Unit); Box baseDomBox(IntVect::Zero, (baseDomainSize-1)*IntVect::Unit); ProblemDomain baseDomain(baseDomBox); // set periodic in all directions for (int dir=0; dir<SpaceDim; dir++) { baseDomain.setPeriodic(dir, true); } // quick check // should be (3^SpaceDim) -1 vectors int numVect =0; if (verbose) pout() << "ShiftIterator shift vectors:" << endl; ShiftIterator sit1 = baseDomain.shiftIterator(); for (sit1.begin(); sit1.ok(); ++sit1) { numVect++; if (verbose) pout() << " " << sit1() << endl; } Real exact = pow(3.0,SpaceDim) -1; Real eps = 0.0001; if ((exact - numVect) > eps) { //fail if (verbose) { pout() << "failed ShiftIterator count test " << endl; } status += 1; } ShiftIterator sit2 = baseDomain.shiftIterator(); { // first try a single box on this level if (verbose) pout() << "Single box test -- " << endl; Vector<Box> levelBoxes(1, baseDomBox); Vector<int> procAssign(1, 0); DisjointBoxLayout levelGrids(levelBoxes,procAssign, baseDomain); LevelData<FArrayBox> tester(levelGrids, 1, ghostVect); Real dx = 1.0/baseDomainSize; initData(tester, dx); // test exchange in this case -- should fill ghost cells with // periodically copied data if (verbose) pout() << " begin exchange..." << endl; Interval comps = tester.interval(); tester.exchange(comps); if (verbose) pout() << " done exchange..." << endl; DataIterator dit = tester.dataIterator(); for (dit.begin(); dit.ok(); ++dit) { FArrayBox& testFab = tester[dit()]; // now check to be sure that this passed for (int dir=0; dir<SpaceDim; dir++) { if (verbose) pout() << "check lo cells in dir " << dir << endl; Box loGhostBox = adjCellLo(baseDomBox, dir, numGhost); BoxIterator loBit(loGhostBox); for (loBit.begin(); loBit.ok(); ++loBit) { const IntVect iv = loBit(); IntVect validLoc = iv; validLoc.shift(dir, baseDomBox.size(dir)); for (int comp=0; comp<tester.nComp(); comp++) { Real validVal = dataVal(validLoc, comp); if (testFab(iv, comp) != validVal) { if (verbose) { pout() << "failed single-box exchange test at " << iv << endl; } status += 10; } } } // end loop over lo ghost cells if (verbose) pout() << "check hi cells in dir " << dir << endl; Box hiGhostBox = adjCellHi(baseDomBox, dir, numGhost); BoxIterator hiBit(hiGhostBox); for (hiBit.begin(); hiBit.ok(); ++hiBit) { const IntVect iv = hiBit(); IntVect validLoc = iv; validLoc.shift(dir, -baseDomBox.size(dir)); for (int comp=0; comp<tester.nComp(); comp++) { Real validVal = dataVal(validLoc, comp); if (testFab(iv, comp) != validVal) { if (verbose) { pout() << "failed single-box exchange test at " << iv << endl; } status += 100; } } } // end loop over hi ghost cells } // end loop over directions } // end loop over boxes if (verbose) pout() << "done single-box test" << endl; } // end single-box test // now try refining things, this time look at 2 boxes baseDomain.refine(2); { if (verbose) pout() << "2-box test..." << endl; const Box domainBox = baseDomain.domainBox(); Vector<Box> levelBoxes1(1, domainBox); Vector<int> procAssign1(1,0); DisjointBoxLayout levelGrids1(levelBoxes1, procAssign1, baseDomain); LevelData<FArrayBox> tester0(levelGrids1, 1, IntVect::Zero); LevelData<FArrayBox> tester1(levelGrids1, 1, ghostVect); Real dx = 1.0/(2.0*baseDomainSize); initData(tester1, dx); initData(tester0, dx); // first test exchange for single box Interval comps = tester1.interval(); Copier ex; ex.exchangeDefine(levelGrids1, ghostVect); pout() << "copier = " << ex << endl; tester1.exchange(comps, ex); // now try multiple boxes Vector<Box> levelBoxes2(3); Vector<int> procAssign2(3); if (SpaceDim == 1) { // do this a little differently in 1d levelBoxes2[0] = Box(IntVect::Zero, 9*IntVect::Unit); levelBoxes2[1] = Box(10*IntVect::Unit, 11*IntVect::Unit); levelBoxes2[2] = Box(14*IntVect::Unit, 15*IntVect::Unit); } else { levelBoxes2[0] = Box(IntVect::Zero, 9*IntVect::Unit); levelBoxes2[1] = Box(IntVect(D_DECL6(7,10,10,10,10,10)), 15*IntVect::Unit); // this box should fail the disjointness test //levelBoxes2[1] = Box(IntVect(D_DECL6(7,10,10,10,10,10)),17*IntVect::Unit); levelBoxes2[2] = Box(IntVect(D_DECL6(11,0,0,0,0,0)), IntVect(D_DECL6(15,7,7,7,7,7))); } int loadbalancestatus = LoadBalance(procAssign2, levelBoxes2); CH_assert (loadbalancestatus == 0); DisjointBoxLayout levelGrids2; levelGrids2.define(levelBoxes2, procAssign2, baseDomain); LevelData<FArrayBox> tester2(levelGrids2, 1, ghostVect); if (verbose) pout() << " begin copyTo test" << endl; tester0.copyTo(comps, tester2, comps); if (verbose) pout() << " done copyTo, now test values" << endl; // check that periodic copies worked OK: DataIterator dit2 = tester2.dataIterator(); for (dit2.begin(); dit2.ok(); ++dit2) { const Box& thisBox = tester2[dit2()].box(); if (!domainBox.contains(thisBox)) { FArrayBox& destFab = tester2[dit2]; for (int dir=0; dir<SpaceDim; dir++) { if (verbose) { pout() << " check lo cells in dir " << dir << endl; } Box loGhost = adjCellLo(domainBox, dir, numGhost); loGhost &= thisBox; if (!loGhost.isEmpty()) { BoxIterator loBit(loGhost); for (loBit.begin(); loBit.ok(); ++loBit) { IntVect iv = loBit(); IntVect srcIV = iv; srcIV.shift(dir, domainBox.size(dir)); for (int comp=0; comp<destFab.nComp(); comp++) { Real validVal = dataVal(srcIV, comp); if (validVal != destFab(iv, comp)) { if (verbose) { pout() << "failed multi-box copy test at " << iv << endl; } status += 1000; } // end if we fail test } // end loop over components } // end loop over ghost cells outside domain } // end if there are lo-end ghost cells if (verbose) { pout() << " check hi cells in dir " << dir << endl; } Box hiGhost = adjCellHi(domainBox, dir, numGhost); hiGhost &= thisBox; if (!hiGhost.isEmpty()) { BoxIterator hiBit(hiGhost); for (hiBit.begin(); hiBit.ok(); ++hiBit) { IntVect iv = hiBit(); IntVect srcIV = iv; srcIV.shift(dir, -domainBox.size(dir)); for (int comp=0; comp<destFab.nComp(); comp++) { Real validVal = dataVal(srcIV, comp); if (validVal != destFab(iv, comp)) { if (verbose) { pout() << "failed multi-box copy test at " << iv << endl; } status += 10000; } // end if we fail test } // end loop over components } // end loop over high-end ghost cells } // end if there are hi-end ghost cells } // end loop over directions } // end if there are ghost cells } // end loop over grids in destination if (verbose) pout() << "done 2-box test" << endl; } // this last test makes no sense in 1D if (SpaceDim > 1) { if (verbose) pout() << "partially-periodic case" << endl; // now test partially periodic case (also coarsen back to original domain) baseDomain.coarsen(2); baseDomain.setPeriodic(0,false); // try similar tests to the second case, only coarsened const Box domainBox = baseDomain.domainBox(); Vector<Box> levelBoxes1(1, domainBox); Vector<int> procAssign1(1,0); DisjointBoxLayout levelGrids1(levelBoxes1, procAssign1, baseDomain); LevelData<FArrayBox> tester0(levelGrids1, 1, IntVect::Zero); LevelData<FArrayBox> tester1(levelGrids1, 1, ghostVect); Real dx = 1.0/(baseDomainSize); initData(tester1, dx); initData(tester0, dx); if (verbose) pout() << " partially-periodic exchange..." << endl; // first test exchange for single box Interval comps = tester1.interval(); tester1.exchange(comps); if (verbose) pout() << " .... done" << endl; if (verbose) pout() << " multi-box partially periodic case" << endl; // now try multiple boxes Vector<Box> levelBoxes2(3); Vector<int> procAssign2(3); levelBoxes2[0] = Box(IntVect::Zero, 4*IntVect::Unit); levelBoxes2[1] = Box(IntVect(D_DECL6(3,5,5,5,5,5)), 7*IntVect::Unit); // this box should fail the disjointness test //levelBoxes2[1] = Box(IntVect(D_DECL6(3,5,5)), 10*IntVect::Unit); levelBoxes2[2] = Box(IntVect(D_DECL6(6,0,0,0,0,0)), IntVect(D_DECL6(7,1,1,1,1,1))); int loadbalancestatus = LoadBalance(procAssign2, levelBoxes2); CH_assert (loadbalancestatus == 0); DisjointBoxLayout levelGrids2(levelBoxes2, procAssign2, baseDomain); LevelData<FArrayBox> tester2(levelGrids2, 1, ghostVect); tester0.copyTo(comps, tester2, comps); if (verbose) pout() << "done partially-periodic case" << endl; // We don't care about the results of these -- just want to see if they compile: if ( argc == 12345 ) { tester0.apply( leveldataApplyFunc ); tester0.apply( LevelDataApplyFunctor(3.14159) ); } } // I'm thinking all pout()'s should be before MPI_Finalize... (ndk) pout() << indent << pgmname << ": " << ( (status == 0) ? "passed all tests" : "failed at least one test,") << endl; #ifdef CH_MPI MPI_Finalize(); #endif return status ; }
void VCAMRPoissonOp2::looseGSRB(LevelData<FArrayBox>& a_phi, const LevelData<FArrayBox>& a_rhs) { CH_TIME("VCAMRPoissonOp2::looseGSRB"); #if 1 MayDay::Abort("VCAMRPoissonOp2::looseGSRB - Not implemented"); #else // This implementation converges at half the rate of "levelGSRB" in // multigrid solves CH_assert(a_phi.isDefined()); CH_assert(a_rhs.isDefined()); CH_assert(a_phi.ghostVect() >= IntVect::Unit); CH_assert(a_phi.nComp() == a_rhs.nComp()); // Recompute the relaxation coefficient if needed. resetLambda(); const DisjointBoxLayout& dbl = a_phi.disjointBoxLayout(); DataIterator dit = a_phi.dataIterator(); // fill in intersection of ghostcells and a_phi's boxes { CH_TIME("VCAMRPoissonOp2::looseGSRB::homogeneousCFInterp"); homogeneousCFInterp(a_phi); } { CH_TIME("VCAMRPoissonOp2::looseGSRB::exchange"); a_phi.exchange(a_phi.interval(), m_exchangeCopier); } // now step through grids... for (dit.begin(); dit.ok(); ++dit) { // invoke physical BC's where necessary { CH_TIME("VCAMRPoissonOp2::looseGSRB::BCs"); m_bc(a_phi[dit], dbl[dit()], m_domain, m_dx, true); } const Box& region = dbl.get(dit()); const FluxBox& thisBCoef = (*m_bCoef)[dit]; int whichPass = 0; #if CH_SPACEDIM == 1 FORT_GSRBHELMHOLTZVC1D #elif CH_SPACEDIM == 2 FORT_GSRBHELMHOLTZVC2D #elif CH_SPACEDIM == 3 FORT_GSRBHELMHOLTZVC3D #else This_will_not_compile! #endif (CHF_FRA(a_phi[dit]), CHF_CONST_FRA(a_rhs[dit]), CHF_BOX(region), CHF_CONST_REAL(m_dx), CHF_CONST_REAL(m_alpha), CHF_CONST_FRA((*m_aCoef)[dit]), CHF_CONST_REAL(m_beta), #if CH_SPACEDIM >= 1 CHF_CONST_FRA(thisBCoef[0]), #endif #if CH_SPACEDIM >= 2 CHF_CONST_FRA(thisBCoef[1]), #endif #if CH_SPACEDIM >= 3 CHF_CONST_FRA(thisBCoef[2]), #endif #if CH_SPACEDIM >= 4 This_will_not_compile! #endif CHF_CONST_FRA(m_lambda[dit]), CHF_CONST_INT(whichPass)); whichPass = 1; #if CH_SPACEDIM == 1 FORT_GSRBHELMHOLTZVC1D #elif CH_SPACEDIM == 2 FORT_GSRBHELMHOLTZVC2D #elif CH_SPACEDIM == 3 FORT_GSRBHELMHOLTZVC3D #else This_will_not_compile! #endif (CHF_FRA(a_phi[dit]), CHF_CONST_FRA(a_rhs[dit]), CHF_BOX(region), CHF_CONST_REAL(m_dx), CHF_CONST_REAL(m_alpha), CHF_CONST_FRA((*m_aCoef)[dit]), CHF_CONST_REAL(m_beta), #if CH_SPACEDIM >= 1 CHF_CONST_FRA(thisBCoef[0]), #endif #if CH_SPACEDIM >= 2 CHF_CONST_FRA(thisBCoef[1]), #endif #if CH_SPACEDIM >= 3 CHF_CONST_FRA(thisBCoef[2]), #endif #if CH_SPACEDIM >= 4 This_will_not_compile! #endif CHF_CONST_FRA(m_lambda[dit]), CHF_CONST_INT(whichPass)); } // end loop through grids #endif }