inline double compute_linear_extrap( D& patch_data, const I& i, const I& i_intr, const IntVector<NDIM>& i_shft, const int depth) { double ret_val = patch_data(i_intr,depth); for (unsigned int d = 0; d < NDIM; ++d) { if (i_shft(d) != 0) { const I& i_intr0 = i_intr; I i_intr1 = i_intr; i_intr1(d) += i_shft(d); const double& f0 = patch_data(i_intr0,depth); const double& f1 = patch_data(i_intr1,depth); const double du = f0-f1; const double delta = std::abs(i(d)-i_intr(d)); ret_val += du*delta; } } return ret_val; }// compute_linear_extrap
inline double compute_quadratic_extrap(D& patch_data, const I& i, const I& i_intr, const IntVector<NDIM>& i_shft, const int depth, const int codim) { if (codim == 1) { for (unsigned int d = 0; d < NDIM; ++d) { if (i_shft(d) != 0) { const I& i_intr0 = i_intr; I i_intr1 = i_intr; i_intr1(d) += i_shft(d); I i_intr2 = i_intr1; i_intr2(d) += i_shft(d); const double& f0 = patch_data(i_intr0, depth); const double& f1 = patch_data(i_intr1, depth); const double& f2 = patch_data(i_intr2, depth); const double x = std::abs(i(d) - i_intr(d)); return (1.0 / 2.0 * f2 - f1 + 1.0 / 2.0 * f0) * x * x + (-1.0 / 2.0 * f2 + 2.0 * f1 - 3.0 / 2.0 * f0) * x + f0; } } } else { return compute_linear_extrap(patch_data, i, i_intr, i_shft, depth); } return 0.0; // this statement should not be reached } // compute_quadratic_extrap
inline double compute_quadratic_extrap( D& patch_data, const I& i, const I& i_intr, const IntVector<NDIM>& i_shft, const int depth, const int codim) { if (codim == 1) { for (unsigned int d = 0; d < NDIM; ++d) { if (i_shft(d) != 0) { #if 1 const I& i_intr0 = i_intr; I i_intr1 = i_intr; i_intr1(d) += i_shft(d); I i_intr2 = i_intr1; i_intr2(d) += i_shft(d); const double& f0 = patch_data(i_intr0,depth); const double& f1 = patch_data(i_intr1,depth); const double& f2 = patch_data(i_intr2,depth); const double x = std::abs(i(d)-i_intr(d)); return (1.0/2.0*f2-f1+1.0/2.0*f0)*x*x+(-1.0/2.0*f2+2.0*f1-3.0/2.0*f0)*x+f0; #endif #if 0 // NOTE: The following only works in general for the case that // the ghost cell width is >= 3. const I& i_intr0 = i_intr; I i_intr2 = i_intr; i_intr2(d) += 2*i_shft(d); I i_intr3 = i_intr2; i_intr3(d) += i_shft(d); const double& f0 = patch_data(i_intr0,depth); const double& f2 = patch_data(i_intr2,depth); const double& f3 = patch_data(i_intr3,depth); const double x = std::abs(i(d)-i_intr(d)); return (1.0/3.0*f3-1.0/2.0*f2+1.0/6.0*f0)*x*x+(-2.0/3.0*f3+3.0/2.0*f2-5.0/6.0*f0)*x+f0; #endif } } } else { return compute_linear_extrap(patch_data, i, i_intr, i_shft, depth); } return 0.0; // this statement should not be reached }// compute_quadratic_extrap
void AdvDiffPhysicalBoundaryUtilities::setPhysicalBoundaryConditions( Pointer<CellData<NDIM,double> > Q_data, Pointer<FaceData<NDIM,double> > u_ADV_data, Pointer<Patch<NDIM> > patch, const std::vector<RobinBcCoefStrategy<NDIM>*>& bc_coefs, const double fill_time, const bool inflow_boundaries_only, const bool homogeneous_bc) { Pointer<CartesianPatchGeometry<NDIM> > pgeom = patch->getPatchGeometry(); if (!pgeom->getTouchesRegularBoundary()) return; const Array<BoundaryBox<NDIM> > physical_codim1_boxes = PhysicalBoundaryUtilities::getPhysicalBoundaryCodim1Boxes(*patch); if (physical_codim1_boxes.size() == 0) return; // Loop over the boundary fill boxes and set boundary conditions. const Box<NDIM>& patch_box = patch->getBox(); const double* const dx = pgeom->getDx(); // Setup any extended Robin BC coef objects. for (int depth = 0; depth < Q_data->getDepth(); ++depth) { ExtendedRobinBcCoefStrategy* extended_bc_coef = dynamic_cast<ExtendedRobinBcCoefStrategy*>(bc_coefs[depth]); if (extended_bc_coef) { extended_bc_coef->clearTargetPatchDataIndex(); extended_bc_coef->setHomogeneousBc(homogeneous_bc); } } // Set the boundary conditions. const IntVector<NDIM>& gcw = Q_data->getGhostCellWidth(); for (int n = 0; n < physical_codim1_boxes.size(); ++n) { const BoundaryBox<NDIM>& bdry_box = physical_codim1_boxes[n]; const unsigned int location_index = bdry_box.getLocationIndex(); const unsigned int bdry_normal_axis = location_index/2; const bool is_lower = location_index%2 == 0; static const IntVector<NDIM> gcw_to_fill = 1; const Box<NDIM> bc_fill_box = pgeom->getBoundaryFillBox(bdry_box, patch_box, gcw_to_fill); const BoundaryBox<NDIM> trimmed_bdry_box(bdry_box.getBox() * bc_fill_box, bdry_box.getBoundaryType(), bdry_box.getLocationIndex()); Box<NDIM> bc_coef_box = PhysicalBoundaryUtilities::makeSideBoundaryCodim1Box(trimmed_bdry_box); for (unsigned int d = 0; d < NDIM; ++d) { if (d != bdry_normal_axis) { bc_coef_box.lower(d) = std::max(bc_coef_box.lower(d), patch_box.lower(d)); bc_coef_box.upper(d) = std::min(bc_coef_box.upper(d), patch_box.upper(d)); } } Pointer<ArrayData<NDIM,double> > acoef_data = new ArrayData<NDIM,double>(bc_coef_box, 1); Pointer<ArrayData<NDIM,double> > bcoef_data = new ArrayData<NDIM,double>(bc_coef_box, 1); Pointer<ArrayData<NDIM,double> > gcoef_data = new ArrayData<NDIM,double>(bc_coef_box, 1); for (int depth = 0; depth < Q_data->getDepth(); ++depth) { bc_coefs[depth]->setBcCoefs(acoef_data, bcoef_data, gcoef_data, NULL, *patch, trimmed_bdry_box, fill_time); ExtendedRobinBcCoefStrategy* extended_bc_coef = dynamic_cast<ExtendedRobinBcCoefStrategy*>(bc_coefs[depth]); if (homogeneous_bc && !extended_bc_coef) gcoef_data->fillAll(0.0); for (Box<NDIM>::Iterator bc(bc_coef_box); bc; bc++) { const Index<NDIM>& i = bc(); const FaceIndex<NDIM> i_f(i, bdry_normal_axis, FaceIndex<NDIM>::Lower); bool is_inflow_bdry = (is_lower && (*u_ADV_data)(i_f) > 0.0) || (!is_lower && (*u_ADV_data)(i_f) < 0.0); if (!inflow_boundaries_only || is_inflow_bdry) { const double& a = (*acoef_data)(i,0); const double& b = (*bcoef_data)(i,0); const double& g = (*gcoef_data)(i,0); const double& h = dx[bdry_normal_axis]; int sgn; Index<NDIM> i_intr(i); if (is_lower) { sgn = -1; } else { sgn = +1; i_intr(bdry_normal_axis) -= 1; } Index<NDIM> i_true(i_intr), i_ghost(i_intr); for (int k = 1; k <= gcw(bdry_normal_axis); ++k) { i_ghost(bdry_normal_axis) = i_intr(bdry_normal_axis) + sgn*k; i_true (bdry_normal_axis) = i_intr(bdry_normal_axis) - sgn*(k-1); const double Q_i = (*Q_data)(i_true,depth); (*Q_data)(i_ghost,depth) = -(-4.0*g*h*k-2.0*g*h+2.0*a*Q_i*h*k+a*Q_i*h-2.0*b*Q_i)/(2.0*a*h*k+a*h+2.0*b); } } } } } return; }// setPhysicalBoundaryConditions