void NewPoissonOp:: createCoarsened(FArrayBox& a_lhs, const FArrayBox& a_rhs, const int & a_refRat) { int ncomp = a_rhs.nComp(); //fill ebislayout Box coarsenedBox = coarsen(a_rhs.box(), a_refRat); a_lhs.define(coarsenedBox, ncomp); }
void getUnitSquareGrid(const int a_n_radial, const int a_n_poloidal, FArrayBox& a_xi) { Box box(IntVect::Zero, IntVect(a_n_radial,a_n_poloidal)); RealVect dx(1./a_n_radial,1./a_n_poloidal); a_xi.define(box,2); for (BoxIterator bit(box);bit.ok();++bit) { IntVect iv = bit(); for (int dir=0; dir<SpaceDim; ++dir) { a_xi(iv,dir) = iv[dir]*dx[dir]; } } }
void NewPoissonOp::createCoarser(FArrayBox& a_coarse, const FArrayBox& a_fine, bool ghosted) { Box c = a_fine.box(); if (ghosted) { c.grow(-1); } c.coarsen(2); c.refine(2); if (ghosted) c.grow(1); CH_assert(c == a_fine.box()); if (ghosted) c.grow(-1); c.coarsen(2); if (ghosted) { c.grow(1); } a_coarse.define(c, a_fine.nComp()); }
void NewPoissonOp::create( FArrayBox& a_lhs, const FArrayBox& a_rhs) { a_lhs.define(a_rhs.box(), a_rhs.nComp()); }
// Compute the time-centered values of the primitive variable on the // interior cell faces of the cell-centered box a_box. void PatchGodunov::computeWHalf(FluxBox& a_WHalf, const FArrayBox& a_U, const FArrayBox& a_S, const Real& a_dt, const Box& a_box) { CH_assert(isDefined()); CH_assert(a_box == m_currentBox); // Get the number of various variables int numPrim = m_gdnvPhysics->numPrimitives(); // The current box of valid cells Box curBox = m_currentBox; // Boxes for face-centered state - used for the riemann() and // artificialViscosity() calls Box faceBox[SpaceDim]; // Boxes for face-centered fluxes Box fluxBox[SpaceDim]; // Boxes for cell-centered state - used for the updatePrim() calls Box ccBox[SpaceDim]; for (int dir1 = 0; dir1 < SpaceDim; ++dir1) { // faceBox[dir1] is face-centered in direction "dir1", // is valid "curBox" grown by 1 in all directions except "dir1", // and stays one cell away, in "dir1", from the domain boundary. faceBox[dir1] = curBox; // valid cell-centered box faceBox[dir1].grow(1); faceBox[dir1] &= m_domain; faceBox[dir1].grow(dir1, -1); faceBox[dir1].surroundingNodes(dir1); // ccBox[dir1] is cell-centered, // is valid "curBox" grown by 1 in all directions except "dir1", // but only within the domain, "m_domain". ccBox[dir1] = curBox; ccBox[dir1].grow(1); ccBox[dir1].grow(dir1, -1); ccBox[dir1] &= m_domain; // fluxBox[dir1] is face-centered in direction "dir1", // consisting of all those faces of cells of "ccBox[dir1]". fluxBox[dir1] = ccBox[dir1]; fluxBox[dir1].surroundingNodes(dir1); // The difference between faceBox[dir1] and fluxBox[dir1] is: // if curBox abuts the boundary of the domain in direction "dir1", // then fluxBox[dir1] contains faces along that boundary, // but faceBox[dir1] does not. } // cell-centered box: but restrict it to within domain Box WBox = a_U.box(); WBox &= m_domain; // Primitive variables FArrayBox W(WBox,numPrim); // Calculate the primitive variables W from the conserved variables a_U, // on cell-centered WBox. m_gdnvPhysics->consToPrim(W, a_U, WBox); // slopeBox is the cell-centered box where slopes will be needed: // it is one larger than the final update box "curBox" of valid cells, // but within domain. // On slopeBox we define the FABs flattening, WMinus, and WPlus. Box slopeBox = curBox; slopeBox.grow(1); slopeBox &= m_domain; // Compute flattening once for all slopes if needed FArrayBox flattening(slopeBox, 1); // cell-centered if (m_useFlattening) { Interval velInt = m_gdnvPhysics->velocityInterval(); int pressureIndex = m_gdnvPhysics->pressureIndex(); Real smallPressure = m_gdnvPhysics->smallPressure(); int bulkIndex = m_gdnvPhysics->bulkModulusIndex(); m_util.computeFlattening(flattening, W, velInt, pressureIndex, smallPressure, bulkIndex, slopeBox); } // Intermediate, extrapolated primitive variables FArrayBox WMinus[SpaceDim]; FArrayBox WPlus [SpaceDim]; // Initial fluxes FArrayBox WHalf1[SpaceDim]; // Source term computed from current state FArrayBox localSource; // If the source term is valid, make a local copy, increment it, and scale // it by 1/2 the timestep if (!a_S.box().isEmpty()) { localSource.define(a_S.box(), a_S.nComp()); localSource.copy(a_S); m_gdnvPhysics->incrementSource(localSource,W,slopeBox); localSource *= 0.5 * a_dt; } // Compute initial fluxes for (int dir1 = 0; dir1 < SpaceDim; dir1++) { // Size the intermediate, extrapolated primitive variables WMinus[dir1].resize(slopeBox,numPrim); // cell-centered WPlus [dir1].resize(slopeBox,numPrim); // cell-centered // Compute predictor step to obtain extrapolated primitive variables if (m_normalPredOrder == 0) { CTUNormalPred(WMinus[dir1],WPlus[dir1],a_dt,m_dx,W, flattening,dir1,slopeBox); } else if (m_normalPredOrder == 1) { PLMNormalPred(WMinus[dir1],WPlus[dir1],a_dt,m_dx,W, flattening,dir1,slopeBox); } else if (m_normalPredOrder == 2) { PPMNormalPred(WMinus[dir1],WPlus[dir1],a_dt,m_dx,W, flattening,dir1,slopeBox); } else { MayDay::Error("PatchGodunov::computeWHalf: Normal predictor order must be 1 (PLM) or 2 (PPM)"); } // If the source term is valid add it to the primitive quantities if (!localSource.box().isEmpty()) { WMinus[dir1] += localSource; WPlus [dir1] += localSource; } // Solve the Riemann problem WHalf1[dir1].resize(fluxBox[dir1],numPrim); // face-centered m_gdnvPhysics->riemann(WHalf1[dir1],WPlus[dir1],WMinus[dir1],W, m_currentTime,dir1,faceBox[dir1]); } #if (CH_SPACEDIM == 3) // In 3D, compute some additional intermediate fluxes // // NOTE: The diagonal entries of this array of fluxes are not // used and will not be defined. FArrayBox WHalf2[SpaceDim][SpaceDim]; // Compute the intermediate, corrected fluxes in each direction for (int dir1 = 0; dir1 < SpaceDim; dir1++) { // Correct fluxes using fluxes from a different direction for (int dir2 = 0; dir2 < SpaceDim; dir2++) { // A different direction has been found if (dir2 != dir1) { // Temporary primitive variables FArrayBox WTempMinus(WMinus[dir1].box(),numPrim); FArrayBox WTempPlus (WPlus [dir1].box(),numPrim); FArrayBox AdWdx(WPlus[dir1].box(),numPrim); // preventing uninitialized memory reads which cause // FPE's on some machines // AdWdx.setVal(666.666); // Copy data for in place modification WTempMinus.copy(WMinus[dir1]); WTempPlus .copy(WPlus [dir1]); // Update the current, extrapolated primitive variable using a flux // in a different direction m_gdnvPhysics->quasilinearUpdate(AdWdx, WHalf1[dir2], WTempMinus, -(1.0/3.0) * a_dt / m_dx, dir2, ccBox[dir2]); WTempMinus += AdWdx; m_gdnvPhysics->quasilinearUpdate(AdWdx, WHalf1[dir2], WTempPlus, -(1.0/3.0) * a_dt / m_dx, dir2, ccBox[dir2]); WTempPlus += AdWdx; // Solve the Riemann problem. WHalf2[dir1][dir2].resize(fluxBox[dir1],numPrim); m_gdnvPhysics->riemann(WHalf2[dir1][dir2], WTempPlus, WTempMinus, W, m_currentTime, dir1, faceBox[dir1]); } } } #endif // faceBox and fluxBox are now a bit smaller for the final corrections for (int dir1 = 0; dir1 < SpaceDim; ++dir1) { faceBox[dir1] = curBox; faceBox[dir1].grow(dir1,1); faceBox[dir1] &= m_domain; faceBox[dir1].grow(dir1,-1); faceBox[dir1].surroundingNodes(dir1); fluxBox[dir1] = curBox; fluxBox[dir1].surroundingNodes(dir1); } // Do the final corrections to the fluxes for (int dir1 = 0; dir1 < SpaceDim; dir1++) { // Correct the flux using fluxes in the remaining direction(s) for (int dir2 = 0; dir2 < SpaceDim; dir2++) { // A different direction has been found if (dir2 != dir1) { #if (CH_SPACEDIM == 2) // In 2D, the current primitive state is updated by a flux in // the other direction FArrayBox AdWdx(WPlus[dir1].box(),numPrim); m_gdnvPhysics->quasilinearUpdate(AdWdx, WHalf1[dir2], WMinus[dir1], -(1.0/2.0) * a_dt / m_dx, dir2, ccBox[dir2]); WMinus[dir1] += AdWdx; m_gdnvPhysics->quasilinearUpdate(AdWdx, WHalf1[dir2], WPlus [dir1], -(1.0/2.0) * a_dt / m_dx, dir2, ccBox[dir2]); WPlus[dir1] += AdWdx; #elif (CH_SPACEDIM == 3) // In 3D, find a direction different from the two above int dir3 = 3 - dir1 - dir2; // Update the conservative state using both corrected fluxes in // the other two directions FArrayBox AdWdx(WPlus[dir1].box(),numPrim); m_gdnvPhysics->quasilinearUpdate(AdWdx, WHalf2[dir2][dir3], WMinus[dir1], -(1.0/2.0) * a_dt / m_dx, dir2, ccBox[dir2]); WMinus[dir1].plus(AdWdx,0,0,numPrim); m_gdnvPhysics->quasilinearUpdate(AdWdx, WHalf2[dir2][dir3], WPlus [dir1], -(1.0/2.0) * a_dt / m_dx, dir2, ccBox[dir2]); WPlus [dir1].plus(AdWdx,0,0,numPrim); #else // Only 2D and 3D should be possible MayDay::Error("PatchGodunov::computeWHalf: CH_SPACEDIM not 2 or 3!"); #endif } } // Solve the Riemann problem to obtain time-centered face values. // be returned FArrayBox& WHalf = a_WHalf[dir1]; m_gdnvPhysics->riemann(WHalf, WPlus[dir1], WMinus[dir1], W, m_currentTime, dir1, faceBox[dir1]); } }