void BaseFab<Real>::performCopy (const BaseFab<Real>& src, const Box& srcbox, int srccomp, const Box& destbox, int destcomp, int numcomp) { BL_ASSERT(destbox.ok()); BL_ASSERT(src.box().contains(srcbox)); BL_ASSERT(box().contains(destbox)); BL_ASSERT(destbox.sameSize(srcbox)); BL_ASSERT(srccomp >= 0 && srccomp+numcomp <= src.nComp()); BL_ASSERT(destcomp >= 0 && destcomp+numcomp <= nComp()); if (destbox == domain && srcbox == src.box()) { Real* data_dst = dataPtr(destcomp); const Real* data_src = src.dataPtr(srccomp); for (long i = 0, N = numcomp*numpts; i < N; i++) { *data_dst++ = *data_src++; } } else { const int* destboxlo = destbox.loVect(); const int* destboxhi = destbox.hiVect(); const int* _th_plo = loVect(); const int* _th_phi = hiVect(); const int* _x_lo = srcbox.loVect(); const int* _x_plo = src.loVect(); const int* _x_phi = src.hiVect(); Real* _th_p = dataPtr(destcomp); const Real* _x_p = src.dataPtr(srccomp); FORT_FASTCOPY(_th_p, ARLIM(_th_plo), ARLIM(_th_phi), D_DECL(destboxlo[0],destboxlo[1],destboxlo[2]), D_DECL(destboxhi[0],destboxhi[1],destboxhi[2]), _x_p, ARLIM(_x_plo), ARLIM(_x_phi), D_DECL(_x_lo[0],_x_lo[1],_x_lo[2]), &numcomp); } }
/** This is called by EBAMRPoissonOp::applyDomainFlux in EBAMRPoissonOp::applyOp for reg cells. For boundary conditions on velocity in viscous operator. */ void InflowOutflowHelmholtzDomainBC::getFaceFlux(BaseFab<Real>& a_faceFlux, const BaseFab<Real>& a_phi, const RealVect& a_probLo, const RealVect& a_dx, const int& a_idir, const Side::LoHiSide& a_side, const DataIndex& a_dit, const Real& a_time, const bool& a_useHomogeneous) { //vel: outflow is neumann. all others dirichlet. inflow uses inflow vel as the value int velcomp = DirichletPoissonEBBC::s_velComp; bool isOutflow = ((a_side==Side::Hi) && (a_idir==m_flowDir)); bool isInflow = ((a_side==Side::Lo) && (a_idir==m_flowDir)); bool isSlipWall = ((a_idir!=m_flowDir) && (a_idir != velcomp) && ((m_doSlipWallsHi[a_idir]==1 && a_side == Side::Hi)||(m_doSlipWallsLo[a_idir]==1 && a_side == Side::Lo))); // bool isVelNeum = (isOutflow || isSlipWall); if (isSlipWall) { NeumannPoissonDomainBC neumannBC; neumannBC.setValue(0.); neumannBC.getFaceFlux(a_faceFlux, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time, a_useHomogeneous); } else if (isInflow) { DirichletPoissonDomainBC diriBC; if (velcomp==m_flowDir) { if (!m_doJet1PoiseInflow) { diriBC.setValue(m_jet1inflowVel); } else if (m_doJet1PoiseInflow) { diriBC.setFunction(m_jet1PoiseInflowFunc); } } else { diriBC.setValue(0.0); } //basefab flux--EBAMRPoissonOp::applyDomainFlux calls this directly for viscous operator if (s_higherOrderHelmBC) { diriBC.getHigherOrderFaceFlux(a_faceFlux, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time, a_useHomogeneous); } else { diriBC.getFaceFlux(a_faceFlux, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time, a_useHomogeneous); } } else if (isOutflow) { if (!m_doJet2) { NeumannPoissonDomainBC neumannBC; neumannBC.setValue(0.); neumannBC.getFaceFlux(a_faceFlux, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time, a_useHomogeneous); } else if (m_doJet2) { const RealVect tubeCenter = m_jet2PoiseInflowFunc->getTubeCenter(); Real tubeRadius = m_jet2PoiseInflowFunc->getTubeRadius(); CH_assert(a_phi.nComp() == 1); // start hardwire Real wallThickness = 0.075; Real bcFactor = 0.5; // % of outflow face to be set to inflow condition ParmParse pp; pp.get("wall_thickness",wallThickness); tubeRadius += wallThickness * bcFactor /2.0; // end hardwire for (int comp=0; comp<a_phi.nComp(); comp++) { const Box& box = a_faceFlux.box(); int iside = -1; //a_side == Side::Hi BoxIterator bit(box); for (bit.begin(); bit.ok(); ++bit) { const IntVect& iv = bit(); RealVect loc = EBArith::getIVLocation(iv,a_dx,a_probLo); loc[a_idir] -= iside * 0.5 * a_dx[a_idir];//point is now at the face center CH_assert(loc[m_flowDir] == tubeCenter[m_flowDir]); bool isInsideTube = false; Real radius = m_jet2PoiseInflowFunc->getRadius(loc); if (radius <= tubeRadius) { isInsideTube = true; } if (isInsideTube) // Dirichlet { Real value = 0.0; // takes care of tangential comps if (velcomp == m_flowDir) { if (m_doJet2PoiseInflow) { value = m_jet2PoiseInflowFunc->getVel(radius)[m_flowDir]; } else if (!(m_doJet2PoiseInflow)) { value = m_jet2inflowVel; } } if (s_higherOrderHelmBC) { IntVect iv1 = bit(); Real phi0 = a_phi(iv1,comp); iv1[a_idir] += iside; Real phi1 = a_phi(iv1,comp); iv1[a_idir] -= iside; a_faceFlux(iv,comp) = -iside*(8.0*value + phi1 - 9.0*phi0)/(3.0*a_dx[a_idir]); } else if (!s_higherOrderHelmBC) { Real ihdx = 2.0 / a_dx[a_idir]; Real phiVal = a_phi(iv,comp); a_faceFlux(iv,comp) = iside * ihdx * (phiVal - value); } } else if (!isInsideTube) // Neumann { Real value = 0.0; a_faceFlux(iv,comp) = iside * value; } } } } } else { //wall bc no slip DirichletPoissonDomainBC diriBC; diriBC.setValue(0.0); if (s_higherOrderHelmBC) { diriBC.getHigherOrderFaceFlux(a_faceFlux, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time, a_useHomogeneous); } else { diriBC.getFaceFlux(a_faceFlux, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time, a_useHomogeneous); } } }
//////called by MAC projection solver for domain bc on phi void InflowOutflowPoissonDomainBC::getFaceFlux(BaseFab<Real>& a_faceFlux, const BaseFab<Real>& a_phi, const RealVect& a_probLo, const RealVect& a_dx, const int& a_idir, const Side::LoHiSide& a_side, const DataIndex& a_dit, const Real& a_time, const bool& a_useHomogeneous) { //for phi: outflow dirichlet. inflow neumann bool isOutflow= (a_side==Side::Hi) && (a_idir==m_flowDir); if (!isOutflow) { NeumannPoissonDomainBC neumannBC; neumannBC.setValue(0.0); neumannBC.getFaceFlux(a_faceFlux, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time, a_useHomogeneous); } else { if (!(m_doJet2)) { DirichletPoissonDomainBC diriBC; diriBC.setValue(0.0); diriBC.getFaceFlux(a_faceFlux, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time, a_useHomogeneous); // diriBC.getHigherOrderFaceFlux(a_faceFlux, a_phi, a_probLo, a_dx, a_idir, a_side, a_dit, a_time, a_useHomogeneous); } else if (m_doJet2) { const RealVect tubeCenter = m_jet2PoiseInflowFunc->getTubeCenter(); Real tubeRadius = m_jet2PoiseInflowFunc->getTubeRadius(); // start hardwire Real wallThickness = 0.075; Real bcFactor = 0.5; // % of outflow face to be set to inflow condition ParmParse pp; pp.get("wall_thickness",wallThickness); tubeRadius += wallThickness * bcFactor /2.0; // end hardwire CH_assert(a_phi.nComp() == 1); for (int comp=0; comp<a_phi.nComp(); comp++) { const Box& box = a_faceFlux.box(); int iside = -1; // a_side == Side::Hi in this loop Real value = 0.0; BoxIterator bit(box); for (bit.begin(); bit.ok(); ++bit) { const IntVect& iv = bit(); RealVect loc = EBArith::getIVLocation(iv,a_dx,a_probLo); loc[a_idir] -= iside * 0.5 * a_dx[a_idir]; //loc is now at the face center CH_assert(loc[m_flowDir] == tubeCenter[m_flowDir]); bool isInsideTube = false; Real radius = m_jet2PoiseInflowFunc->getRadius(loc); if (radius <= tubeRadius) { isInsideTube = true; } if (isInsideTube) { a_faceFlux(iv,comp) = iside * value; //Neumann } else if (!(isInsideTube)) { Real ihdx = 2.0 / a_dx[a_idir]; Real phiVal = a_phi(iv,comp); a_faceFlux(iv,comp) = iside * ihdx * (phiVal - value); //Dirichlet } } } } } }
void NeumannConductivityDomainBC:: getFaceFlux(BaseFab<Real>& a_faceFlux, const BaseFab<Real>& a_phi, const RealVect& a_probLo, const RealVect& a_dx, const int& a_idir, const Side::LoHiSide& a_side, const DataIndex& a_dit, const Real& a_time, const bool& a_useHomogeneous) { CH_TIME("NeumannPoissonDomainBC::getFaceFlux"); CH_assert(a_phi.nComp() == 1); for (int comp=0; comp<a_phi.nComp(); comp++) { const Box& box = a_faceFlux.box(); int iside; if (a_side == Side::Lo) { iside = 1; } else { iside = -1; } if (a_useHomogeneous) { Real value = 0.0; a_faceFlux.setVal(iside * value); } else { if (m_isFunction) { BoxIterator bit(box); for (bit.begin(); bit.ok(); ++bit) { const IntVect& iv = bit(); RealVect point = EBArith::getIVLocation(iv,a_dx,a_probLo); point[a_idir] -= iside * 0.5 * a_dx[a_idir];//point is now at the face center RealVect normal = RealVect::Zero; normal[a_idir] = iside; a_faceFlux(iv,comp) = iside * m_flux->value(iv,a_dit,point,normal,a_time,comp); } } else { if (m_onlyHomogeneous) { MayDay::Error("NeumannPoissonDomainBC::getFaceFlux called with undefined inhomogeneous BC"); } Real value = m_value; a_faceFlux.setVal(iside * value); } } } //again, following the odd convention of EBAMRPoissonOp //(because I am reusing its BC classes), //the input flux here is CELL centered and the input box //is the box adjacent to the domain boundary on the valid side. //because I am not insane (yet) I will just shift the flux's box //over and multiply by the appropriate coefficient a_faceFlux.shiftHalf(a_idir, -sign(a_side)); const Box& faceBox = a_faceFlux.box(); const BaseFab<Real>& regCoef = (*m_bcoef)[a_dit][a_idir].getSingleValuedFAB(); int isrc = 0; int idst = 0; int inum = 1; FORT_MULTIPLYTWOFAB(CHF_FRA(a_faceFlux), CHF_CONST_FRA(regCoef), CHF_BOX(faceBox), CHF_INT(isrc),CHF_INT(idst),CHF_INT(inum)); //shift flux back to cell centered land a_faceFlux.shiftHalf(a_idir, sign(a_side)); }