/** This is called by cc projection to enforceVelocityBCs on face velocities averaged from centers before calculating divergence in mac projection. */ void InflowOutflowPoissonDomainBC:: getFaceVel(Real& a_faceFlux, const FaceIndex& a_face, const EBFluxFAB& a_vel, const RealVect& a_probLo, const RealVect& a_dx, const int& a_idir, const int& a_icomp, const Real& a_time, const Side::LoHiSide& a_side, const bool& a_doDivFreeOutflow) { int velcomp = DirichletPoissonEBBC::s_velComp; CH_assert(a_vel.nComp() == 1); bool isInflow = (a_side==Side::Lo) && (a_idir==m_flowDir); bool isOutflow= (a_side==Side::Hi) && (a_idir==m_flowDir); RealVect point = EBArith::getFaceLocation(a_face, a_dx, a_probLo); RealVect normal = EBArith::getDomainNormal(a_idir, a_side); const EBISBox& ebisBox= a_vel[0].getEBISBox(); if (isOutflow) { //quadratic extrapolation with homogeneous Neumann for outflow bc a_faceFlux = EBArith::extrapFaceVelToOutflow(a_face,a_side,a_idir,ebisBox.getEBGraph(),a_vel[a_idir],0);//be careful of this 0, it is the component } else if (isInflow && (velcomp==m_flowDir)) { //input component is always zero. //value of face direction corresponds to velocity direction here if (!m_doPoiseInflow && !m_doWomersleyInflow) { a_faceFlux = m_inflowVel; } else if (m_doPoiseInflow) { RealVect prob_lo = RealVect::Zero; const RealVect loc = EBArith::getFaceLocation(a_face, a_dx, prob_lo); Real radius = m_poiseInflowFunc->getRadius(loc); a_faceFlux = m_poiseInflowFunc->getVel(radius)[m_flowDir]; } else if (m_doWomersleyInflow) { double PI = 3.1416; int freq[10] = { 1,2,3,4,5,6,7,8 }; double Vp[10] = { 0.33,0.24,0.24,0.12,0.11,0.13,0.06,0.04 }; double Theta[10] = { 74,79,121,146,147,179,233,218 }; double AmpXsi[10] = { 1.7639,1.4363,1.2517,1.1856,1.1603,1.1484,1.1417,1.1214 }; double AngXsi[10] = { -0.2602,-0.3271,-0.2799,-0.2244,-0.1843,-0.1576,-0.1439,-0.1195 }; Real VelMult = 2; int Maxp = 8; for (int p=0;p<Maxp;p++) VelMult += Vp[p] * AmpXsi[p] * cos (2 * PI * freq[p] * g_simulationTime - Theta[p]*PI/180 + AngXsi[p]); a_faceFlux = m_inflowVel*VelMult/2; } } else { //must be a solid wall or tangential velocity at inflow a_faceFlux = 0; } }
/** This is called by cc projection to enforceVelocityBCs on face velocities averaged from centers before calculating divergence in mac projection. */ void InflowOutflowPoissonDomainBC:: getFaceVel(Real& a_faceFlux, const FaceIndex& a_face, const EBFluxFAB& a_vel, const RealVect& a_probLo, const RealVect& a_dx, const int& a_idir, const int& a_icomp, const Real& a_time, const Side::LoHiSide& a_side, const bool& a_doDivFreeOutflow) { int velcomp = DirichletPoissonEBBC::s_velComp; CH_assert(a_vel.nComp() == 1); bool isInflow = (a_side==Side::Lo) && (a_idir==m_flowDir); bool isOutflow= (a_side==Side::Hi) && (a_idir==m_flowDir); RealVect point = EBArith::getFaceLocation(a_face, a_dx, a_probLo); RealVect normal = EBArith::getDomainNormal(a_idir, a_side); const EBISBox& ebisBox= a_vel[0].getEBISBox(); if (isOutflow) { if (!(m_doJet2)) { //quadratic extrapolation with homogeneous Neumann for outflow bc a_faceFlux = EBArith::extrapFaceVelToOutflow(a_face,a_side,a_idir,ebisBox.getEBGraph(),a_vel[a_idir],0);//be careful of this 0, it is the component } else if (m_doJet2) { const RealVect tubeCenter = m_jet2PoiseInflowFunc->getTubeCenter(); Real tubeRadius = m_jet2PoiseInflowFunc->getTubeRadius(); CH_assert(point[m_flowDir] == tubeCenter[m_flowDir]); Real radius = m_jet2PoiseInflowFunc->getRadius(point); bool isInsideTube = false; // 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 if (radius <= tubeRadius) { isInsideTube = true; } if (isInsideTube && (velcomp == m_flowDir)) { if (m_doJet2PoiseInflow) { a_faceFlux = m_jet2PoiseInflowFunc->getVel(radius)[m_flowDir]; } else if (!(m_doJet2PoiseInflow)) { a_faceFlux = m_jet2inflowVel; } } else if (isInsideTube && (velcomp != m_flowDir)) { a_faceFlux = 0; // set tangential components to 0 } else if (!(isInsideTube)) { //quadratic extrapolation with homogeneous Neumann for outflow bc a_faceFlux = EBArith::extrapFaceVelToOutflow(a_face,a_side,a_idir,ebisBox.getEBGraph(),a_vel[a_idir],0);//be careful of this 0, it is the component } } } else if (isInflow && (velcomp==m_flowDir)) { //input component is always zero. //value of face direction corresponds to velocity direction here if (!m_doJet1PoiseInflow) { a_faceFlux = m_jet1inflowVel; } else if (m_doJet1PoiseInflow) { RealVect prob_lo = RealVect::Zero; const RealVect loc = EBArith::getFaceLocation(a_face, a_dx, prob_lo); Real radius = m_jet1PoiseInflowFunc->getRadius(loc); a_faceFlux = m_jet1PoiseInflowFunc->getVel(radius)[m_flowDir]; } } else { //must be a solid wall or tangential velocity at inflow a_faceFlux = 0; } }
void EBCompositeMACProjector:: correctVelocityComponent(BaseIVFAB<Real> & a_coveredVel, const Vector<VolIndex>& a_coveredFace, const IntVectSet & a_coveredSets, const EBFluxFAB & a_macGradient, const EBISBox & a_ebisBox, int a_coveredFaceDir, Side::LoHiSide a_sd, int a_faceGradComp) { CH_TIME("EBCompositeMACProjector::correctVelocityComponent"); //if a_coveredFaceDir == faceGradComp, just linearly extrapolate gradient and subtract. //if a_coveredFaceDir != faceGradComp, need to average to cell centers then extrapolate and subtract CH_assert(a_coveredVel.nComp() == 1); CH_assert(a_macGradient.nComp() == 1); const EBFaceFAB& macGradFAB = a_macGradient[a_faceGradComp]; for (int ivof = 0; ivof < a_coveredFace.size(); ivof++) { const VolIndex& vof = a_coveredFace[ivof]; Vector<FaceIndex> nearFaces, farFaces; bool hasNearFaces = false; bool hasFarFaces = false; VolIndex nearVoF, farVoF; FaceIndex nearFace, farFace; nearFaces = a_ebisBox.getFaces(vof, a_coveredFaceDir, flip(a_sd)); hasNearFaces = (nearFaces.size()==1) && (!nearFaces[0].isBoundary()); if (hasNearFaces) { nearFace = nearFaces[0]; nearVoF = nearFace.getVoF(flip(a_sd)); farFaces = a_ebisBox.getFaces(nearVoF, a_coveredFaceDir, flip(a_sd)); hasFarFaces = (farFaces.size()==1) && (!farFaces[0].isBoundary()); if (hasFarFaces) { farFace = farFaces[0]; farVoF = farFace.getVoF(flip(a_sd)); } } Real extrapGrad; if (a_coveredFaceDir == a_faceGradComp) { //if a_coveredFaceDir == faceGradComp, just linearly extrapolate gradient and subtract. if (hasNearFaces && hasFarFaces) { Real nearGrad = macGradFAB(nearFace, 0); Real farGrad = macGradFAB(farFace, 0); extrapGrad = 2.0*nearGrad - farGrad; } else if (hasNearFaces) { extrapGrad = macGradFAB(nearFace, 0); } else { extrapGrad = 0.0; } } else { //if a_coveredFaceDir != faceGradComp, need to average to cell centers then extrapolate and subtract Real nearGrad = getAverageFaceGrad(vof, macGradFAB, a_ebisBox, a_faceGradComp); if (hasNearFaces) { Real farGrad = getAverageFaceGrad(nearVoF, macGradFAB, a_ebisBox, a_faceGradComp); extrapGrad = 1.5*nearGrad - 0.5*farGrad; } else { extrapGrad = nearGrad; } } a_coveredVel(vof, 0) -= extrapGrad; } }
Real EBGradDivFilter:: getDomainDivergence(const EBCellFAB& a_gradVel, const EBCellFAB& a_vel, const EBFluxFAB& a_fluxVel, const Box& a_grid, const EBISBox& a_ebisBox, const int& a_faceDir, const FaceIndex& a_face, const Side::LoHiSide& a_side) { CH_TIME("EBGradDivFilter::getDomainDivergence"); Real divVel; CH_assert(a_fluxVel.nComp() == 1); Real velB = a_fluxVel[a_faceDir](a_face, 0); //compute normal derivative. //need second-order derivative at the boundary so //given u_b, u_i, u_i+1, //ux_b = (9u_i - u_i+1 - 8u_b)/(6 dx) VolIndex vofNear, vofStart; Real valNear=0; Real valStart =0; bool hasVoFNear; vofStart = a_face.getVoF(flip(a_side)); valStart = a_vel(vofStart, a_faceDir); int iflipsign = sign(flip(a_side)); Real rsign = Real(iflipsign); Vector<FaceIndex> facesNear = a_ebisBox.getFaces(vofStart, a_faceDir, flip(a_side)); hasVoFNear = (facesNear.size() == 1); if (hasVoFNear) { vofNear = facesNear[0].getVoF(flip(a_side)); valNear = a_vel(vofNear, a_faceDir); } Real hsign = rsign*m_dxFine[a_faceDir]; if (hasVoFNear) { divVel = (2.25*(valStart-velB) - 0.25*(valNear-velB))/(0.75*hsign); } else { //if there is no farther away value, drop order of derivative divVel = (valStart - velB)/(0.5*hsign); } //now add in tangential derivatives of tangential velocities //using extrapolated gradients for (int tanDir = 0; tanDir< SpaceDim; tanDir++) { if (tanDir != a_faceDir) { Real gradVel = 0.0; int gradcomp = getGradComp(tanDir, tanDir); if (hasVoFNear) { Real gradNear = a_gradVel(vofNear, gradcomp); Real gradStart = a_gradVel(vofStart, gradcomp); gradVel = 1.5*gradStart - 0.5*gradNear; } else { Real gradStart = a_gradVel(vofStart, gradcomp); gradVel = gradStart; } divVel += gradVel; } } return divVel; }