int fluxRegTest() { #ifdef CH_USE_HDF5 writeLevel(NULL); #endif int retflag = 0; int nref; Vector<Box> fineboxes; Vector<Box> coarboxes; Box domf, domc; //set coarse and fine grid boxes setDefaults(nref, coarboxes, fineboxes, domc, domf); { // first do nonperiodic test Interval interv(0,0); //set up coarse and fine grids DisjointBoxLayout dblFineCell,dblCoarCell; Vector<int> procAssignCoar(coarboxes.size(), 0); Vector<int> procAssignFine(fineboxes.size(), 0); LoadBalance(procAssignCoar, coarboxes); LoadBalance(procAssignFine, fineboxes); dblCoarCell.define(coarboxes, procAssignCoar); dblFineCell.define(fineboxes, procAssignFine); dblCoarCell.close(); dblFineCell.close(); LevelData<FArrayBox> coarData(dblCoarCell, 1); LevelData<FArrayBox> fineData(dblFineCell, 1); DataIterator coarIt = coarData.dataIterator(); DataIterator fineIt = fineData.dataIterator(); LevelFluxRegister fluxReg(dblFineCell, dblCoarCell, domf, nref, 1); //set data and flux registers to zero for (coarIt.reset(); coarIt.ok(); ++coarIt) coarData[coarIt()].setVal(0.); fluxReg.setToZero(); //increment and decrement //flux registers with equal size fluxes Real scale = 1.0; Real fluxVal = 4.77; for (coarIt.reset(); coarIt.ok(); ++coarIt) { const Box& cellBoxCoar = dblCoarCell.get(coarIt()); for (int idir = 0; idir < SpaceDim; idir++) { Box edgeBoxCoar = surroundingNodes(cellBoxCoar, idir); FArrayBox edgeFlux(edgeBoxCoar,1); edgeFlux.setVal(fluxVal); DataIndex dataIndGlo = coarIt(); fluxReg.incrementCoarse(edgeFlux, scale, dataIndGlo, interv, interv, idir); } } for (fineIt.reset(); fineIt.ok(); ++fineIt) { const Box& cellBoxFine = dblFineCell.get(fineIt()); for (int idir = 0; idir < SpaceDim; idir++) { Box edgeBoxFine = surroundingNodes(cellBoxFine, idir); FArrayBox edgeFlux(edgeBoxFine,1); edgeFlux.setVal(fluxVal); SideIterator sit; DataIndex dataIndGlo = fineIt(); for (sit.reset(); sit.ok(); ++sit) { fluxReg.incrementFine(edgeFlux, scale, dataIndGlo, interv, interv, idir, sit()); } } } //reflux what ought to be zero into zero and the result should be zero fluxReg.reflux(coarData, scale); DataIterator datIt = coarData.dataIterator(); for (datIt.reset(); datIt.ok(); ++datIt) { const FArrayBox& data = coarData[datIt()]; Real rmax = Abs(data.max()); Real rmin = Abs(data.min()); if ((rmax > 1.0e-10)||(rmin > 1.0e-10)) { pout() << indent << pgmname << ": fluxRegister failed the nonperiodic conservation test = " << endl; retflag = 1; } } } // end non-periodic test // now do the same thing all over again, this time with a periodic domain { ProblemDomain coarseDomain(domc); ProblemDomain fineDomain(domf); for (int dir=0; dir<SpaceDim; dir++) { coarseDomain.setPeriodic(dir, true); fineDomain.setPeriodic(dir, true); } Interval interv(0,0); //set up coarse and fine grids DisjointBoxLayout dblFineCell,dblCoarCell; Vector<int> procAssignCoar(coarboxes.size(), 0); Vector<int> procAssignFine(fineboxes.size(), 0); LoadBalance(procAssignCoar, coarboxes); LoadBalance(procAssignFine, fineboxes); dblCoarCell.define(coarboxes, procAssignCoar, coarseDomain); dblFineCell.define(fineboxes, procAssignFine, fineDomain); dblCoarCell.close(); dblFineCell.close(); LevelData<FArrayBox> coarData(dblCoarCell, 1); LevelData<FArrayBox> fineData(dblFineCell, 1); DataIterator coarIt = coarData.dataIterator(); DataIterator fineIt = fineData.dataIterator(); LevelFluxRegister fluxReg(dblFineCell, dblCoarCell, fineDomain, nref, 1); //set data and flux registers to zero for (coarIt.reset(); coarIt.ok(); ++coarIt) coarData[coarIt()].setVal(0.); fluxReg.setToZero(); //increment and decrement //flux registers with equal size fluxes Real scale = 1.0; Real fluxVal = 4.77; for (coarIt.reset(); coarIt.ok(); ++coarIt) { const Box& cellBoxCoar = dblCoarCell.get(coarIt()); for (int idir = 0; idir < SpaceDim; idir++) { Box edgeBoxCoar = surroundingNodes(cellBoxCoar, idir); FArrayBox edgeFlux(edgeBoxCoar,1); edgeFlux.setVal(fluxVal); DataIndex dataIndGlo = coarIt(); fluxReg.incrementCoarse(edgeFlux, scale, dataIndGlo, interv, interv, idir); } } for (fineIt.reset(); fineIt.ok(); ++fineIt) { const Box& cellBoxFine = dblFineCell.get(fineIt()); for (int idir = 0; idir < SpaceDim; idir++) { Box edgeBoxFine = surroundingNodes(cellBoxFine, idir); FArrayBox edgeFlux(edgeBoxFine,1); edgeFlux.setVal(fluxVal); SideIterator sit; DataIndex dataIndGlo = fineIt(); for (sit.reset(); sit.ok(); ++sit) { fluxReg.incrementFine(edgeFlux, scale, dataIndGlo, interv, interv, idir, sit()); } } } //reflux what ought to be zero into zero and the result should be zero fluxReg.reflux(coarData, scale); DataIterator datIt = coarData.dataIterator(); for (datIt.reset(); datIt.ok(); ++datIt) { const FArrayBox& data = coarData[datIt()]; Real rmax = Abs(data.max()); Real rmin = Abs(data.min()); if ((rmax > 1.0e-10)||(rmin > 1.0e-10)) { pout() << indent << pgmname << ": fluxRegister failed the periodic conservation test " << endl; retflag += 2; } } } // end periodic test return retflag; }
void MultiGridManagement2D::coarsen(plint fineLevel, Box2D coarseDomain){ // The coarsest multi-block, at level 0, cannot be further coarsened. PLB_PRECONDITION( fineLevel>=1 && fineLevel<(plint)bulks.size() ); plint coarseLevel = fineLevel-1; // First, trim the domain coarseDomain in case it exceeds the extent of the // multi-block, and determine whether coarseDomain touches one of the boundaries // of the multi-block. This information is needed, because the coarse domain // fully replaces the fine domain on boundaries of the multi-block, and there // is therefore no need to create a coarse-fine coupling. bool touchLeft=false, touchRight=false, touchBottom=false, touchTop=false; trimDomain(coarseLevel, coarseDomain, touchLeft, touchRight, touchBottom, touchTop); // Convert the coarse domain to fine units. Box2D fineDomain(coarseDomain.multiply(2)); // The reduced fine domain is the one which is going to be excluded from // the original fine lattice. Box2D intermediateFineDomain(fineDomain.enlarge(-1)); // The extended coarse domain it the one which is going to be added // to the original coarse lattice. Box2D extendedCoarseDomain(coarseDomain.enlarge(1)); // If the domain in question touches a boundary of the multi-block, // both the reduced fine domain and the extended coarse domain are // identified with the boundary location. if (touchLeft) { intermediateFineDomain.x0 -= 1; extendedCoarseDomain.x0 += 1; } if (touchRight) { intermediateFineDomain.x1 += 1; extendedCoarseDomain.x1 -= 1; } if (touchBottom) { intermediateFineDomain.y0 -= 1; extendedCoarseDomain.y0 += 1; } if (touchTop) { intermediateFineDomain.y1 += 1; extendedCoarseDomain.y1 -= 1; } // Extract reduced fine domain from the original fine multi-block. std::vector<Box2D> exceptedBlocks; for (pluint iBlock=0; iBlock<bulks[fineLevel].size(); ++iBlock) { except(bulks[fineLevel][iBlock], intermediateFineDomain, exceptedBlocks); } exceptedBlocks.swap(bulks[fineLevel]); // Add extended coarse domain to the original coarse multi-block. bulks[coarseLevel].push_back(extendedCoarseDomain); // Define coupling interfaces for all four sides of the refined domain, unless they // touch a boundary of the multi-block. if (!touchLeft) { coarseGridInterfaces[coarseLevel].push_back( Box2D( extendedCoarseDomain.x0, extendedCoarseDomain.x0, extendedCoarseDomain.y0, extendedCoarseDomain.y1 ) ); fineGridInterfaces[fineLevel].push_back( Box2D( coarseDomain.x0, coarseDomain.x0, coarseDomain.y0, coarseDomain.y1 ) ); // it is a left border in the coarse case coarseInterfaceOrientations[coarseLevel].push_back(Array<plint,2>(0,-1)); // it is an right border in the fine case fineInterfaceOrientations[fineLevel].push_back(Array<plint,2>(0,1)); } if (!touchRight) { coarseGridInterfaces[coarseLevel].push_back( Box2D( extendedCoarseDomain.x1, extendedCoarseDomain.x1, extendedCoarseDomain.y0, extendedCoarseDomain.y1 ) ); fineGridInterfaces[fineLevel].push_back( Box2D( coarseDomain.x1, coarseDomain.x1, coarseDomain.y0, coarseDomain.y1 ) ); // it is a right border in the coarse case coarseInterfaceOrientations[coarseLevel].push_back(Array<plint,2>(0,1)); // it is a left border in the fine case fineInterfaceOrientations[fineLevel].push_back(Array<plint,2>(0,-1)); } if (!touchBottom) { coarseGridInterfaces[coarseLevel].push_back( Box2D( extendedCoarseDomain.x0, extendedCoarseDomain.x1, extendedCoarseDomain.y0, extendedCoarseDomain.y0 ) ); fineGridInterfaces[fineLevel].push_back( Box2D( coarseDomain.x0, coarseDomain.x1, coarseDomain.y0, coarseDomain.y0 ) ); // it is a bottom border in the coarse case coarseInterfaceOrientations[coarseLevel].push_back(Array<plint,2>(1,-1)); //TODO check this!!! // it is a top border in the fine case fineInterfaceOrientations[fineLevel].push_back(Array<plint,2>(1,1)); } if (!touchTop) { coarseGridInterfaces[coarseLevel].push_back( Box2D( extendedCoarseDomain.x0, extendedCoarseDomain.x1, extendedCoarseDomain.y1, extendedCoarseDomain.y1 ) ); fineGridInterfaces[fineLevel].push_back( Box2D( coarseDomain.x0, coarseDomain.x1, coarseDomain.y1, coarseDomain.y1 ) ); // it is a top border in the coarse case coarseInterfaceOrientations[coarseLevel].push_back(Array<plint,2>(1,1)); // it is an bottom border in the fine case fineInterfaceOrientations[fineLevel].push_back(Array<plint,2>(1,-1)); } }