/*
 *************************************************************************
 *
 * Compute BoxOverlap that specifies data to be filled by refinement
 * operator.
 *
 *************************************************************************
 */
std::shared_ptr<hier::BoxOverlap>
FirstLayerCellVariableFillPattern::computeFillBoxesOverlap(
   const hier::BoxContainer& fill_boxes,
   const hier::BoxContainer& node_fill_boxes,
   const hier::Box& patch_box,
   const hier::Box& data_box,
   const hier::PatchDataFactory& pdf) const
{
   NULL_USE(pdf);
   NULL_USE(node_fill_boxes);

   hier::BoxContainer stencil_boxes;
   computeStencilBoxes(stencil_boxes, patch_box);

   hier::BoxContainer overlap_boxes(fill_boxes);
   overlap_boxes.intersectBoxes(data_box);
   overlap_boxes.intersectBoxes(stencil_boxes);

   return std::make_shared<CellOverlap>(
             overlap_boxes,
             hier::Transformation(hier::IntVector::getZero(patch_box.getDim())));
}
Pointer<BoxOverlap<NDIM> > SideNoCornersFillPattern::calculateOverlap(const BoxGeometry<NDIM>& dst_geometry,
                                                                      const BoxGeometry<NDIM>& src_geometry,
                                                                      const Box<NDIM>& /*dst_patch_box*/,
                                                                      const Box<NDIM>& src_mask,
                                                                      const bool overwrite_interior,
                                                                      const IntVector<NDIM>& src_offset) const
{
    Pointer<SideOverlap<NDIM> > box_geom_overlap =
        dst_geometry.calculateOverlap(src_geometry, src_mask, overwrite_interior, src_offset);
#if !defined(NDEBUG)
    TBOX_ASSERT(box_geom_overlap);
#endif
    const SideGeometry<NDIM>* const t_dst_geometry = dynamic_cast<const SideGeometry<NDIM>*>(&dst_geometry);
#if !defined(NDEBUG)
    TBOX_ASSERT(t_dst_geometry);
#endif
    boost::array<BoxList<NDIM>, NDIM> dst_boxes;
    if (!box_geom_overlap->isOverlapEmpty())
    {
        const Box<NDIM>& dst_box = t_dst_geometry->getBox();
        for (unsigned int axis = 0; axis < NDIM; ++axis)
        {
            const BoxList<NDIM>& box_geom_overlap_boxes = box_geom_overlap->getDestinationBoxList(axis);

            // Determine the stencil boxes with the specified ghost cell width.
            BoxList<NDIM> stencil_boxes;
            if (NDIM == 2 || (!d_include_edges_on_src_level && !d_include_edges_on_dst_level))
            {
                for (unsigned int i = 0; i < NDIM; ++i)
                {
                    Box<NDIM> box = dst_box;
                    box.lower()(i) -= d_stencil_width(i);
                    box.upper()(i) += d_stencil_width(i);
                    stencil_boxes.appendItem(SideGeometry<NDIM>::toSideBox(box, axis));
                }
            }
            else
            {
                for (unsigned int j = 0; j < NDIM; ++j)
                {
                    for (unsigned int i = 0; i < NDIM; ++i)
                    {
                        if (i == j) continue;
                        Box<NDIM> box = dst_box;
                        box.lower()(i) -= d_stencil_width(i);
                        box.upper()(i) += d_stencil_width(i);
                        box.lower()(j) -= d_stencil_width(j);
                        box.upper()(j) += d_stencil_width(j);
                        stencil_boxes.appendItem(SideGeometry<NDIM>::toSideBox(box, axis));
                    }
                }
            }

            // Intersect the overlap boxes with the stencil boxes.
            for (BoxList<NDIM>::Iterator it1(box_geom_overlap_boxes); it1; it1++)
            {
                BoxList<NDIM> overlap_boxes(stencil_boxes);
                overlap_boxes.intersectBoxes(it1());
                for (BoxList<NDIM>::Iterator it2(overlap_boxes); it2; it2++)
                {
                    const Box<NDIM>& overlap_box = it2();
                    if (!overlap_box.empty()) dst_boxes[axis].appendItem(overlap_box);
                }
            }
        }
    }
    return new SideOverlap<NDIM>(dst_boxes.data(), src_offset);
} // calculateOverlap