void
INSCollocatedPPMConvectiveOperator::applyConvectiveOperator(
    const int U_idx,
    const int N_idx)
{
    IBAMR_TIMER_START(t_apply_convective_operator);
#ifdef DEBUG_CHECK_ASSERTIONS
    if (!d_is_initialized)
    {
        TBOX_ERROR("INSCollocatedPPMConvectiveOperator::applyConvectiveOperator():\n"
                   << "  operator must be initialized prior to call to applyConvectiveOperator\n");
    }
#endif

    // Setup communications algorithm.
    Pointer<CartesianGridGeometry<NDIM> > grid_geom = d_hierarchy->getGridGeometry();
    Pointer<RefineAlgorithm<NDIM> > refine_alg = new RefineAlgorithm<NDIM>();
    Pointer<RefineOperator<NDIM> > refine_op = grid_geom->lookupRefineOperator(d_U_var, "CONSERVATIVE_LINEAR_REFINE");
    refine_alg->registerRefine(d_U_scratch_idx, U_idx, d_U_scratch_idx, refine_op);

    // Extrapolate from cell centers to cell faces.
    for (int ln = d_coarsest_ln; ln <= d_finest_ln; ++ln)
    {
        refine_alg->resetSchedule(d_ghostfill_scheds[ln]);
        d_ghostfill_scheds[ln]->fillData(d_solution_time);
        d_ghostfill_alg->resetSchedule(d_ghostfill_scheds[ln]);
        Pointer<PatchLevel<NDIM> > level = d_hierarchy->getPatchLevel(ln);
        for (PatchLevel<NDIM>::Iterator p(level); p; p++)
        {
            Pointer<Patch<NDIM> > patch = level->getPatch(p());

            const Box<NDIM>& patch_box = patch->getBox();
            const IntVector<NDIM>& patch_lower = patch_box.lower();
            const IntVector<NDIM>& patch_upper = patch_box.upper();

            Pointer<CellData<NDIM,double> > U_data = patch->getPatchData(d_U_scratch_idx);
            const IntVector<NDIM>& U_data_gcw = U_data->getGhostCellWidth();
#ifdef DEBUG_CHECK_ASSERTIONS
            TBOX_ASSERT(U_data_gcw.min() == U_data_gcw.max());
#endif
            Pointer<FaceData<NDIM,double> > u_ADV_data = patch->getPatchData(d_u_idx);
            const IntVector<NDIM>& u_ADV_data_gcw = u_ADV_data->getGhostCellWidth();
#ifdef DEBUG_CHECK_ASSERTIONS
            TBOX_ASSERT(u_ADV_data_gcw.min() == u_ADV_data_gcw.max());
#endif
            Pointer<FaceData<NDIM,double> > u_extrap_data = patch->getPatchData(d_u_extrap_idx);
            const IntVector<NDIM>& u_extrap_data_gcw = u_extrap_data->getGhostCellWidth();
#ifdef DEBUG_CHECK_ASSERTIONS
            TBOX_ASSERT(u_extrap_data_gcw.min() == u_extrap_data_gcw.max());
#endif
            CellData<NDIM,double>& U0_data = *U_data;
            CellData<NDIM,double>  U1_data(patch_box, 1, U_data_gcw);
#if (NDIM == 3)
            CellData<NDIM,double>  U2_data(patch_box, 1, U_data_gcw);
#endif
            CellData<NDIM,double>  dU_data(patch_box, 1, U_data_gcw);
            CellData<NDIM,double> U_L_data(patch_box, 1, U_data_gcw);
            CellData<NDIM,double> U_R_data(patch_box, 1, U_data_gcw);

            // Extrapolate from cell centers to cell faces.
            for (unsigned int axis = 0; axis < NDIM; ++axis)
            {
                GODUNOV_EXTRAPOLATE_FC(
#if (NDIM == 2)
                    patch_lower(0), patch_upper(0),
                    patch_lower(1), patch_upper(1),
                    U_data_gcw(0), U_data_gcw(1),
                    U0_data.getPointer(axis), U1_data.getPointer(),
                    dU_data.getPointer(), U_L_data.getPointer(), U_R_data.getPointer(),
                    u_ADV_data_gcw   (0), u_ADV_data_gcw   (1),
                    u_extrap_data_gcw(0), u_extrap_data_gcw(1),
                    u_ADV_data   ->getPointer(0),      u_ADV_data   ->getPointer(1),
                    u_extrap_data->getPointer(0,axis), u_extrap_data->getPointer(1,axis)
#endif
#if (NDIM == 3)
                    patch_lower(0), patch_upper(0),
                    patch_lower(1), patch_upper(1),
                    patch_lower(2), patch_upper(2),
                    U_data_gcw(0), U_data_gcw(1), U_data_gcw(2),
                    U0_data.getPointer(axis), U1_data.getPointer(), U2_data.getPointer(),
                    dU_data.getPointer(), U_L_data.getPointer(), U_R_data.getPointer(),
                    u_ADV_data_gcw   (0), u_ADV_data_gcw   (1), u_ADV_data_gcw   (2),
                    u_extrap_data_gcw(0), u_extrap_data_gcw(1), u_extrap_data_gcw(2),
                    u_ADV_data   ->getPointer(0),      u_ADV_data   ->getPointer(1),      u_ADV_data   ->getPointer(2),
                    u_extrap_data->getPointer(0,axis), u_extrap_data->getPointer(1,axis), u_extrap_data->getPointer(2,axis)
#endif
                                       );
            }

            // If we are using conservative or skew-symmetric differencing,
            // compute the advective fluxes.  These need to be synchronized on
            // the patch hierarchy.
            if (d_difference_form == CONSERVATIVE || d_difference_form == SKEW_SYMMETRIC)
            {
                Pointer<FaceData<NDIM,double> > u_ADV_data = patch->getPatchData(d_u_idx);
                const IntVector<NDIM>& u_ADV_data_gcw = u_ADV_data->getGhostCellWidth();
                Pointer<FaceData<NDIM,double> > u_flux_data = patch->getPatchData(d_u_flux_idx);
                const IntVector<NDIM>& u_flux_data_gcw = u_flux_data->getGhostCellWidth();
                for (unsigned int axis = 0; axis < NDIM; ++axis)
                {
                    static const double dt = 1.0;
                    ADVECT_FLUX_FC(
                        dt,
#if (NDIM == 2)
                        patch_lower(0), patch_upper(0),
                        patch_lower(1), patch_upper(1),
//                      u_extrap_data_gcw(0), u_extrap_data_gcw(1),
                        u_ADV_data_gcw   (0), u_ADV_data_gcw   (1),
                        u_extrap_data_gcw(0), u_extrap_data_gcw(1),
                        u_flux_data_gcw  (0), u_flux_data_gcw  (1),
//                      u_extrap_data->getPointer(0,0),    u_extrap_data->getPointer(1,1),
                        u_ADV_data   ->getPointer(0),      u_ADV_data   ->getPointer(1),
                        u_extrap_data->getPointer(0,axis), u_extrap_data->getPointer(1,axis),
                        u_flux_data  ->getPointer(0,axis), u_flux_data  ->getPointer(1,axis)
#endif
#if (NDIM == 3)
                        patch_lower(0), patch_upper(0),
                        patch_lower(1), patch_upper(1),
                        patch_lower(2), patch_upper(2),
//                      u_extrap_data_gcw(0), u_extrap_data_gcw(1), u_extrap_data_gcw(2),
                        u_ADV_data_gcw   (0), u_ADV_data_gcw   (1), u_ADV_data_gcw   (2),
                        u_extrap_data_gcw(0), u_extrap_data_gcw(1), u_extrap_data_gcw(2),
                        u_flux_data_gcw  (0), u_flux_data_gcw  (1), u_flux_data_gcw  (2),
//                      u_extrap_data->getPointer(0,0),    u_extrap_data->getPointer(1,1),    u_extrap_data->getPointer(2,2),
                        u_ADV_data   ->getPointer(0),      u_ADV_data   ->getPointer(1),      u_ADV_data   ->getPointer(2),
                        u_extrap_data->getPointer(0,axis), u_extrap_data->getPointer(1,axis), u_extrap_data->getPointer(2,axis),
                        u_flux_data  ->getPointer(0,axis), u_flux_data  ->getPointer(1,axis), u_flux_data  ->getPointer(2,axis)
#endif
                                   );
                }
            }
        }
    }

    // Synchronize data on the patch hierarchy.
    for (int ln = d_finest_ln; ln > d_coarsest_ln; --ln)
    {
        d_coarsen_scheds[ln]->coarsenData();
    }

    // Difference values on the patches.
    for (int ln = d_coarsest_ln; ln <= d_finest_ln; ++ln)
    {
        Pointer<PatchLevel<NDIM> > level = d_hierarchy->getPatchLevel(ln);
        for (PatchLevel<NDIM>::Iterator p(level); p; p++)
        {
            Pointer<Patch<NDIM> > patch = level->getPatch(p());

            const Box<NDIM>& patch_box = patch->getBox();
            const IntVector<NDIM>& patch_lower = patch_box.lower();
            const IntVector<NDIM>& patch_upper = patch_box.upper();

            const Pointer<CartesianPatchGeometry<NDIM> > patch_geom = patch->getPatchGeometry();
            const double* const dx = patch_geom->getDx();

            Pointer<CellData<NDIM,double> > N_data = patch->getPatchData(N_idx);
            const IntVector<NDIM>& N_data_gcw = N_data->getGhostCellWidth();

            if (d_difference_form == ADVECTIVE || d_difference_form == SKEW_SYMMETRIC)
            {
                Pointer<FaceData<NDIM,double> > u_ADV_data = patch->getPatchData(d_u_idx);
                const IntVector<NDIM>& u_ADV_data_gcw = u_ADV_data->getGhostCellWidth();
                Pointer<FaceData<NDIM,double> > u_extrap_data = patch->getPatchData(d_u_extrap_idx);
                const IntVector<NDIM>& u_extrap_data_gcw = u_extrap_data->getGhostCellWidth();
                for (unsigned int axis = 0; axis < NDIM; ++axis)
                {
                    ADVECT_DERIVATIVE_FC(
                        dx,
#if (NDIM == 2)
                        patch_lower(0), patch_upper(0),
                        patch_lower(1), patch_upper(1),
//                      u_extrap_data_gcw(0), u_extrap_data_gcw(1),
                        u_ADV_data_gcw   (0), u_ADV_data_gcw   (1),
                        u_extrap_data_gcw(0), u_extrap_data_gcw(1),
//                      u_extrap_data->getPointer(0,0),    u_extrap_data->getPointer(1,1),
                        u_ADV_data   ->getPointer(0),      u_ADV_data   ->getPointer(1),
                        u_extrap_data->getPointer(0,axis), u_extrap_data->getPointer(1,axis),
                        N_data_gcw(0), N_data_gcw(1),
#endif
#if (NDIM == 3)
                        patch_lower(0), patch_upper(0),
                        patch_lower(1), patch_upper(1),
                        patch_lower(2), patch_upper(2),
//                      u_extrap_data_gcw(0), u_extrap_data_gcw(1), u_extrap_data_gcw(2),
                        u_ADV_data_gcw   (0), u_ADV_data_gcw   (1), u_ADV_data_gcw   (2),
                        u_extrap_data_gcw(0), u_extrap_data_gcw(1), u_extrap_data_gcw(2),
//                      u_extrap_data->getPointer(0,0),    u_extrap_data->getPointer(1,1),    u_extrap_data->getPointer(2,2),
                        u_ADV_data   ->getPointer(0),      u_ADV_data   ->getPointer(1),      u_ADV_data   ->getPointer(2),
                        u_extrap_data->getPointer(0,axis), u_extrap_data->getPointer(1,axis), u_extrap_data->getPointer(2,axis),
                        N_data_gcw(0), N_data_gcw(1), N_data_gcw(2),
#endif
                        N_data->getPointer(axis));
                }
            }

            if (d_difference_form == CONSERVATIVE)
            {
                Pointer<FaceData<NDIM,double> > u_flux_data = patch->getPatchData(d_u_flux_idx);
                const IntVector<NDIM>& u_flux_data_gcw = u_flux_data->getGhostCellWidth();
                for (unsigned int axis = 0; axis < NDIM; ++axis)
                {
                    static const double alpha = 1.0;
                    F_TO_C_DIV_FC(
                        N_data->getPointer(axis), N_data_gcw.min(),
                        alpha,
#if (NDIM == 2)
                        u_flux_data->getPointer(0,axis), u_flux_data->getPointer(1,axis), u_flux_data_gcw.min(),
                        patch_lower(0), patch_upper(0),
                        patch_lower(1), patch_upper(1),
#endif
#if (NDIM == 3)
                        u_flux_data->getPointer(0,axis), u_flux_data->getPointer(1,axis), u_flux_data->getPointer(2,axis), u_flux_data_gcw.min(),
                        patch_lower(0), patch_upper(0),
                        patch_lower(1), patch_upper(1),
                        patch_lower(2), patch_upper(2),
#endif
                        dx);
                }
            }

            if (d_difference_form == SKEW_SYMMETRIC)
            {
                Pointer<FaceData<NDIM,double> > u_flux_data = patch->getPatchData(d_u_flux_idx);
                const IntVector<NDIM>& u_flux_data_gcw = u_flux_data->getGhostCellWidth();
                for (unsigned int axis = 0; axis < NDIM; ++axis)
                {
                    static const double alpha = 0.5;
                    static const double beta  = 0.5;
                    F_TO_C_DIV_ADD_FC(
                        N_data->getPointer(axis), N_data_gcw.min(),
                        alpha,
#if (NDIM == 2)
                        u_flux_data->getPointer(0,axis), u_flux_data->getPointer(1,axis), u_flux_data_gcw.min(),
                        beta,
                        N_data->getPointer(axis), N_data_gcw.min(),
                        patch_lower(0), patch_upper(0),
                        patch_lower(1), patch_upper(1),
#endif
#if (NDIM == 3)
                        u_flux_data->getPointer(0,axis), u_flux_data->getPointer(1,axis), u_flux_data->getPointer(2,axis), u_flux_data_gcw.min(),
                        beta,
                        N_data->getPointer(axis), N_data_gcw.min(),
                        patch_lower(0), patch_upper(0),
                        patch_lower(1), patch_upper(1),
                        patch_lower(2), patch_upper(2),
#endif
                        dx);
                }
            }
        }
    }
    IBAMR_TIMER_STOP(t_apply_convective_operator);
    return;
}// applyConvectiveOperator
Пример #2
0
void
QInit::setDataOnPatch(const int data_idx,
                      Pointer<Variable<NDIM> > /*var*/,
                      Pointer<Patch<NDIM> > patch,
                      const double data_time,
                      const bool /*initial_time*/,
                      Pointer<PatchLevel<NDIM> > /*level*/)
{
    Pointer<CellData<NDIM, double> > Q_data = patch->getPatchData(data_idx);
#if !defined(NDEBUG)
    TBOX_ASSERT(Q_data);
#endif
    const Box<NDIM>& patch_box = patch->getBox();
    const Index<NDIM>& patch_lower = patch_box.lower();
    Pointer<CartesianPatchGeometry<NDIM> > pgeom = patch->getPatchGeometry();

    const double* const x_lower = pgeom->getXLower();
    const double* const dx = pgeom->getDx();

    double r_squared;
    VectorNd X;
    const double t = data_time;

    Q_data->fillAll(0.0);

    if (d_init_type == "GAUSSIAN")
    {
        for (CellIterator<NDIM> ic(patch_box); ic; ic++)
        {
            const Index<NDIM>& i = ic();
            // NOTE: This assumes the lattice of Gaussians are being advected
            // and diffused in the unit square.
            boost::array<int, NDIM> offset;
            for (offset[0] = -2; offset[0] <= 2; ++(offset[0]))
            {
                for (offset[1] = -2; offset[1] <= 2; ++(offset[1]))
                {
#if (NDIM > 2)
                    for (offset[2] = -2; offset[2] <= 2; ++(offset[2]))
                    {
#endif
                        r_squared = 0.0;
                        for (unsigned int d = 0; d < NDIM; ++d)
                        {
                            X[d] = x_lower[d] + dx[d] * (static_cast<double>(i(d) - patch_lower(d)) + 0.5);
                            r_squared += pow(X[d] - (d_X[d] + static_cast<double>(offset[d])), 2.0);
                        }
                        (*Q_data)(i) += exp(-r_squared / (4.0 * d_gaussian_kappa)) /
                                        pow(4.0 * M_PI * d_gaussian_kappa * (1.0 + t), 0.5 * static_cast<double>(NDIM));
#if (NDIM > 2)
                    }
#endif
                }
            }
        }
    }
    else if (d_init_type == "ZALESAK")
    {
        for (CellIterator<NDIM> ic(patch_box); ic; ic++)
        {
            const Index<NDIM>& i = ic();
            r_squared = 0.0;
            for (unsigned int d = 0; d < NDIM; ++d)
            {
                X[d] = x_lower[d] + dx[d] * (static_cast<double>(i(d) - patch_lower(d)) + 0.5);
                r_squared += pow((X[d] - d_X[d]), 2.0);
            }
            if ((sqrt(r_squared) > d_zalesak_r) ||
                ((abs(X[0] - d_X[0]) < d_zalesak_slot_w) && (X[1] - d_X[1]) < d_zalesak_slot_l))
            {
                (*Q_data)(i) = 0.0;
            }
            else
            {
                (*Q_data)(i) = 1.0;
            }
        }
    }
    else
    {
        TBOX_ERROR(d_object_name << "::initializeDataOnPatch()\n"
                                 << "  invalid initialization type "
                                 << d_init_type
                                 << "\n");
    }
    return;
} // setDataOnPatch
void INSStaggeredCenteredConvectiveOperator::applyConvectiveOperator(const int U_idx,
                                                                     const int N_idx)
{
    IBAMR_TIMER_START(t_apply_convective_operator);
#if !defined(NDEBUG)
    if (!d_is_initialized)
    {
        TBOX_ERROR(
            "INSStaggeredCenteredConvectiveOperator::applyConvectiveOperator():\n"
            << "  operator must be initialized prior to call to applyConvectiveOperator\n");
    }
    TBOX_ASSERT(U_idx == d_u_idx);
#endif

    // Fill ghost cell values for all components.
    static const bool homogeneous_bc = false;
    typedef HierarchyGhostCellInterpolation::InterpolationTransactionComponent
    InterpolationTransactionComponent;
    std::vector<InterpolationTransactionComponent> transaction_comps(1);
    transaction_comps[0] = InterpolationTransactionComponent(d_U_scratch_idx,
                                                             U_idx,
                                                             "CONSERVATIVE_LINEAR_REFINE",
                                                             false,
                                                             "CONSERVATIVE_COARSEN",
                                                             d_bdry_extrap_type,
                                                             false,
                                                             d_bc_coefs);
    d_hier_bdry_fill->resetTransactionComponents(transaction_comps);
    d_hier_bdry_fill->setHomogeneousBc(homogeneous_bc);
    StaggeredStokesPhysicalBoundaryHelper::setupBcCoefObjects(
        d_bc_coefs, NULL, d_U_scratch_idx, -1, homogeneous_bc);
    d_hier_bdry_fill->fillData(d_solution_time);
    StaggeredStokesPhysicalBoundaryHelper::resetBcCoefObjects(d_bc_coefs, NULL);
    //  d_bc_helper->enforceDivergenceFreeConditionAtBoundary(d_U_scratch_idx);
    d_hier_bdry_fill->resetTransactionComponents(d_transaction_comps);

    // Compute the convective derivative.
    for (int ln = d_coarsest_ln; ln <= d_finest_ln; ++ln)
    {
        Pointer<PatchLevel<NDIM> > level = d_hierarchy->getPatchLevel(ln);
        for (PatchLevel<NDIM>::Iterator p(level); p; p++)
        {
            Pointer<Patch<NDIM> > patch = level->getPatch(p());

            const Pointer<CartesianPatchGeometry<NDIM> > patch_geom =
                patch->getPatchGeometry();
            const double* const dx = patch_geom->getDx();

            const Box<NDIM>& patch_box = patch->getBox();
            const IntVector<NDIM>& patch_lower = patch_box.lower();
            const IntVector<NDIM>& patch_upper = patch_box.upper();

            Pointer<SideData<NDIM, double> > N_data = patch->getPatchData(N_idx);
            Pointer<SideData<NDIM, double> > U_data = patch->getPatchData(d_U_scratch_idx);

            const IntVector<NDIM>& N_data_gcw = N_data->getGhostCellWidth();
            const IntVector<NDIM>& U_data_gcw = U_data->getGhostCellWidth();

            switch (d_difference_form)
            {
            case CONSERVATIVE:
                NAVIER_STOKES_STAGGERED_DIV_DERIVATIVE_FC(dx,
#if (NDIM == 2)
                                                          patch_lower(0),
                                                          patch_upper(0),
                                                          patch_lower(1),
                                                          patch_upper(1),
                                                          U_data_gcw(0),
                                                          U_data_gcw(1),
                                                          U_data->getPointer(0),
                                                          U_data->getPointer(1),
                                                          N_data_gcw(0),
                                                          N_data_gcw(1),
                                                          N_data->getPointer(0),
                                                          N_data->getPointer(1)
#endif
#if (NDIM == 3)
                                                          patch_lower(0),
                                                          patch_upper(0),
                                                          patch_lower(1),
                                                          patch_upper(1),
                                                          patch_lower(2),
                                                          patch_upper(2),
                                                          U_data_gcw(0),
                                                          U_data_gcw(1),
                                                          U_data_gcw(2),
                                                          U_data->getPointer(0),
                                                          U_data->getPointer(1),
                                                          U_data->getPointer(2),
                                                          N_data_gcw(0),
                                                          N_data_gcw(1),
                                                          N_data_gcw(2),
                                                          N_data->getPointer(0),
                                                          N_data->getPointer(1),
                                                          N_data->getPointer(2)
#endif
                                                          );
                break;
            case ADVECTIVE:
                NAVIER_STOKES_STAGGERED_ADV_DERIVATIVE_FC(dx,
#if (NDIM == 2)
                                                          patch_lower(0),
                                                          patch_upper(0),
                                                          patch_lower(1),
                                                          patch_upper(1),
                                                          U_data_gcw(0),
                                                          U_data_gcw(1),
                                                          U_data->getPointer(0),
                                                          U_data->getPointer(1),
                                                          N_data_gcw(0),
                                                          N_data_gcw(1),
                                                          N_data->getPointer(0),
                                                          N_data->getPointer(1)
#endif
#if (NDIM == 3)
                                                          patch_lower(0),
                                                          patch_upper(0),
                                                          patch_lower(1),
                                                          patch_upper(1),
                                                          patch_lower(2),
                                                          patch_upper(2),
                                                          U_data_gcw(0),
                                                          U_data_gcw(1),
                                                          U_data_gcw(2),
                                                          U_data->getPointer(0),
                                                          U_data->getPointer(1),
                                                          U_data->getPointer(2),
                                                          N_data_gcw(0),
                                                          N_data_gcw(1),
                                                          N_data_gcw(2),
                                                          N_data->getPointer(0),
                                                          N_data->getPointer(1),
                                                          N_data->getPointer(2)
#endif
                                                          );
                break;
            case SKEW_SYMMETRIC:
                NAVIER_STOKES_STAGGERED_SKEW_SYM_DERIVATIVE_FC(dx,
#if (NDIM == 2)
                                                               patch_lower(0),
                                                               patch_upper(0),
                                                               patch_lower(1),
                                                               patch_upper(1),
                                                               U_data_gcw(0),
                                                               U_data_gcw(1),
                                                               U_data->getPointer(0),
                                                               U_data->getPointer(1),
                                                               N_data_gcw(0),
                                                               N_data_gcw(1),
                                                               N_data->getPointer(0),
                                                               N_data->getPointer(1)
#endif
#if (NDIM == 3)
                                                               patch_lower(0),
                                                               patch_upper(0),
                                                               patch_lower(1),
                                                               patch_upper(1),
                                                               patch_lower(2),
                                                               patch_upper(2),
                                                               U_data_gcw(0),
                                                               U_data_gcw(1),
                                                               U_data_gcw(2),
                                                               U_data->getPointer(0),
                                                               U_data->getPointer(1),
                                                               U_data->getPointer(2),
                                                               N_data_gcw(0),
                                                               N_data_gcw(1),
                                                               N_data_gcw(2),
                                                               N_data->getPointer(0),
                                                               N_data->getPointer(1),
                                                               N_data->getPointer(2)
#endif
                                                               );
                break;
            default:
                TBOX_ERROR(
                    "INSStaggeredCenteredConvectiveOperator::applyConvectiveOperator():\n"
                    << "  unsupported differencing form: "
                    << enum_to_string<ConvectiveDifferencingType>(d_difference_form) << " \n"
                    << "  valid choices are: ADVECTIVE, CONSERVATIVE, SKEW_SYMMETRIC\n");
            }
        }
    }

    IBAMR_TIMER_STOP(t_apply_convective_operator);
    return;
} // applyConvectiveOperator
void
AdvDiffCenteredConvectiveOperator::applyConvectiveOperator(const int Q_idx, const int N_idx)
{
    IBAMR_TIMER_START(t_apply_convective_operator);
#if !defined(NDEBUG)
    if (!d_is_initialized)
    {
        TBOX_ERROR("AdvDiffCenteredConvectiveOperator::applyConvectiveOperator():\n"
                   << "  operator must be initialized prior to call to applyConvectiveOperator\n");
    }
#endif

    // Allocate scratch data.
    for (int ln = d_coarsest_ln; ln <= d_finest_ln; ++ln)
    {
        Pointer<PatchLevel<NDIM> > level = d_hierarchy->getPatchLevel(ln);
        level->allocatePatchData(d_Q_scratch_idx);
        level->allocatePatchData(d_q_extrap_idx);
        if (d_difference_form == CONSERVATIVE || d_difference_form == SKEW_SYMMETRIC)
            level->allocatePatchData(d_q_flux_idx);
    }

    // Setup communications algorithm.
    Pointer<CartesianGridGeometry<NDIM> > grid_geom = d_hierarchy->getGridGeometry();
    Pointer<RefineAlgorithm<NDIM> > refine_alg = new RefineAlgorithm<NDIM>();
    Pointer<RefineOperator<NDIM> > refine_op = grid_geom->lookupRefineOperator(d_Q_var, "CONSERVATIVE_LINEAR_REFINE");
    refine_alg->registerRefine(d_Q_scratch_idx, Q_idx, d_Q_scratch_idx, refine_op);

    // Extrapolate from cell centers to cell faces.
    for (int ln = d_coarsest_ln; ln <= d_finest_ln; ++ln)
    {
        refine_alg->resetSchedule(d_ghostfill_scheds[ln]);
        d_ghostfill_scheds[ln]->fillData(d_solution_time);
        d_ghostfill_alg->resetSchedule(d_ghostfill_scheds[ln]);
        Pointer<PatchLevel<NDIM> > level = d_hierarchy->getPatchLevel(ln);
        for (PatchLevel<NDIM>::Iterator p(level); p; p++)
        {
            Pointer<Patch<NDIM> > patch = level->getPatch(p());

            const Box<NDIM>& patch_box = patch->getBox();
            const IntVector<NDIM>& patch_lower = patch_box.lower();
            const IntVector<NDIM>& patch_upper = patch_box.upper();

            Pointer<CellData<NDIM, double> > Q_data = patch->getPatchData(d_Q_scratch_idx);
            const IntVector<NDIM>& Q_data_gcw = Q_data->getGhostCellWidth();
#if !defined(NDEBUG)
            TBOX_ASSERT(Q_data_gcw.min() == Q_data_gcw.max());
#endif
            Pointer<FaceData<NDIM, double> > u_ADV_data = patch->getPatchData(d_u_idx);
            const IntVector<NDIM>& u_ADV_data_gcw = u_ADV_data->getGhostCellWidth();
#if !defined(NDEBUG)
            TBOX_ASSERT(u_ADV_data_gcw.min() == u_ADV_data_gcw.max());
#endif
            Pointer<FaceData<NDIM, double> > q_extrap_data = patch->getPatchData(d_q_extrap_idx);
            const IntVector<NDIM>& q_extrap_data_gcw = q_extrap_data->getGhostCellWidth();
#if !defined(NDEBUG)
            TBOX_ASSERT(q_extrap_data_gcw.min() == q_extrap_data_gcw.max());
#endif
            // Enforce physical boundary conditions at inflow boundaries.
            AdvDiffPhysicalBoundaryUtilities::setPhysicalBoundaryConditions(
                Q_data,
                u_ADV_data,
                patch,
                d_bc_coefs,
                d_solution_time,
                /*inflow_boundary_only*/ d_outflow_bdry_extrap_type != "NONE",
                d_homogeneous_bc);

            // Interpolate from cell centers to cell faces.
            for (unsigned int d = 0; d < d_Q_data_depth; ++d)
            {
                C_TO_F_CWISE_INTERP_2ND_FC(
#if (NDIM == 2)
                    q_extrap_data->getPointer(0, d),
                    q_extrap_data->getPointer(1, d),
                    q_extrap_data_gcw.min(),
                    Q_data->getPointer(d),
                    Q_data_gcw.min(),
                    patch_lower(0),
                    patch_upper(0),
                    patch_lower(1),
                    patch_upper(1)
#endif
#if (NDIM == 3)
                        q_extrap_data->getPointer(0, d),
                    q_extrap_data->getPointer(1, d),
                    q_extrap_data->getPointer(2, d),
                    q_extrap_data_gcw.min(),
                    Q_data->getPointer(d),
                    Q_data_gcw.min(),
                    patch_lower(0),
                    patch_upper(0),
                    patch_lower(1),
                    patch_upper(1),
                    patch_lower(2),
                    patch_upper(2)
#endif
                        );
            }

            // If we are using conservative or skew-symmetric differencing,
            // compute the advective fluxes.  These need to be synchronized on
            // the patch hierarchy.
            if (d_difference_form == CONSERVATIVE || d_difference_form == SKEW_SYMMETRIC)
            {
                Pointer<FaceData<NDIM, double> > q_flux_data = patch->getPatchData(d_q_flux_idx);
                const IntVector<NDIM>& q_flux_data_gcw = q_flux_data->getGhostCellWidth();
                for (unsigned int d = 0; d < d_Q_data_depth; ++d)
                {
                    static const double dt = 1.0;
                    ADVECT_FLUX_FC(dt,
#if (NDIM == 2)
                                   patch_lower(0),
                                   patch_upper(0),
                                   patch_lower(1),
                                   patch_upper(1),
                                   u_ADV_data_gcw(0),
                                   u_ADV_data_gcw(1),
                                   q_extrap_data_gcw(0),
                                   q_extrap_data_gcw(1),
                                   q_flux_data_gcw(0),
                                   q_flux_data_gcw(1),
                                   u_ADV_data->getPointer(0),
                                   u_ADV_data->getPointer(1),
                                   q_extrap_data->getPointer(0, d),
                                   q_extrap_data->getPointer(1, d),
                                   q_flux_data->getPointer(0, d),
                                   q_flux_data->getPointer(1, d)
#endif
#if (NDIM == 3)
                                       patch_lower(0),
                                   patch_upper(0),
                                   patch_lower(1),
                                   patch_upper(1),
                                   patch_lower(2),
                                   patch_upper(2),
                                   u_ADV_data_gcw(0),
                                   u_ADV_data_gcw(1),
                                   u_ADV_data_gcw(2),
                                   q_extrap_data_gcw(0),
                                   q_extrap_data_gcw(1),
                                   q_extrap_data_gcw(2),
                                   q_flux_data_gcw(0),
                                   q_flux_data_gcw(1),
                                   q_flux_data_gcw(2),
                                   u_ADV_data->getPointer(0),
                                   u_ADV_data->getPointer(1),
                                   u_ADV_data->getPointer(2),
                                   q_extrap_data->getPointer(0, d),
                                   q_extrap_data->getPointer(1, d),
                                   q_extrap_data->getPointer(2, d),
                                   q_flux_data->getPointer(0, d),
                                   q_flux_data->getPointer(1, d),
                                   q_flux_data->getPointer(2, d)
#endif
                                       );
                }
            }
        }
    }

    // Synchronize data on the patch hierarchy.
    for (int ln = d_finest_ln; ln > d_coarsest_ln; --ln)
    {
        d_coarsen_scheds[ln]->coarsenData();
    }

    // Difference values on the patches.
    for (int ln = d_coarsest_ln; ln <= d_finest_ln; ++ln)
    {
        Pointer<PatchLevel<NDIM> > level = d_hierarchy->getPatchLevel(ln);
        for (PatchLevel<NDIM>::Iterator p(level); p; p++)
        {
            Pointer<Patch<NDIM> > patch = level->getPatch(p());

            const Box<NDIM>& patch_box = patch->getBox();
            const IntVector<NDIM>& patch_lower = patch_box.lower();
            const IntVector<NDIM>& patch_upper = patch_box.upper();

            const Pointer<CartesianPatchGeometry<NDIM> > patch_geom = patch->getPatchGeometry();
            const double* const dx = patch_geom->getDx();

            Pointer<CellData<NDIM, double> > N_data = patch->getPatchData(N_idx);
            const IntVector<NDIM>& N_data_gcw = N_data->getGhostCellWidth();

            if (d_difference_form == ADVECTIVE || d_difference_form == SKEW_SYMMETRIC)
            {
                Pointer<FaceData<NDIM, double> > u_ADV_data = patch->getPatchData(d_u_idx);
                const IntVector<NDIM>& u_ADV_data_gcw = u_ADV_data->getGhostCellWidth();
                Pointer<FaceData<NDIM, double> > q_extrap_data = patch->getPatchData(d_q_extrap_idx);
                const IntVector<NDIM>& q_extrap_data_gcw = q_extrap_data->getGhostCellWidth();
                for (unsigned int d = 0; d < d_Q_data_depth; ++d)
                {
                    ADVECT_DERIVATIVE_FC(dx,
#if (NDIM == 2)
                                         patch_lower(0),
                                         patch_upper(0),
                                         patch_lower(1),
                                         patch_upper(1),
                                         u_ADV_data_gcw(0),
                                         u_ADV_data_gcw(1),
                                         q_extrap_data_gcw(0),
                                         q_extrap_data_gcw(1),
                                         u_ADV_data->getPointer(0),
                                         u_ADV_data->getPointer(1),
                                         q_extrap_data->getPointer(0, d),
                                         q_extrap_data->getPointer(1, d),
                                         N_data_gcw(0),
                                         N_data_gcw(1),
#endif
#if (NDIM == 3)
                                         patch_lower(0),
                                         patch_upper(0),
                                         patch_lower(1),
                                         patch_upper(1),
                                         patch_lower(2),
                                         patch_upper(2),
                                         u_ADV_data_gcw(0),
                                         u_ADV_data_gcw(1),
                                         u_ADV_data_gcw(2),
                                         q_extrap_data_gcw(0),
                                         q_extrap_data_gcw(1),
                                         q_extrap_data_gcw(2),
                                         u_ADV_data->getPointer(0),
                                         u_ADV_data->getPointer(1),
                                         u_ADV_data->getPointer(2),
                                         q_extrap_data->getPointer(0, d),
                                         q_extrap_data->getPointer(1, d),
                                         q_extrap_data->getPointer(2, d),
                                         N_data_gcw(0),
                                         N_data_gcw(1),
                                         N_data_gcw(2),
#endif
                                         N_data->getPointer(d));
                }
            }

            if (d_difference_form == CONSERVATIVE)
            {
                Pointer<FaceData<NDIM, double> > q_flux_data = patch->getPatchData(d_q_flux_idx);
                const IntVector<NDIM>& q_flux_data_gcw = q_flux_data->getGhostCellWidth();
                for (unsigned int d = 0; d < d_Q_data_depth; ++d)
                {
                    static const double alpha = 1.0;
                    F_TO_C_DIV_FC(N_data->getPointer(d),
                                  N_data_gcw.min(),
                                  alpha,
#if (NDIM == 2)
                                  q_flux_data->getPointer(0, d),
                                  q_flux_data->getPointer(1, d),
                                  q_flux_data_gcw.min(),
                                  patch_lower(0),
                                  patch_upper(0),
                                  patch_lower(1),
                                  patch_upper(1),
#endif
#if (NDIM == 3)
                                  q_flux_data->getPointer(0, d),
                                  q_flux_data->getPointer(1, d),
                                  q_flux_data->getPointer(2, d),
                                  q_flux_data_gcw.min(),
                                  patch_lower(0),
                                  patch_upper(0),
                                  patch_lower(1),
                                  patch_upper(1),
                                  patch_lower(2),
                                  patch_upper(2),
#endif
                                  dx);
                }
            }

            if (d_difference_form == SKEW_SYMMETRIC)
            {
                Pointer<FaceData<NDIM, double> > q_flux_data = patch->getPatchData(d_q_flux_idx);
                const IntVector<NDIM>& q_flux_data_gcw = q_flux_data->getGhostCellWidth();
                for (unsigned int d = 0; d < d_Q_data_depth; ++d)
                {
                    static const double alpha = 0.5;
                    static const double beta = 0.5;
                    F_TO_C_DIV_ADD_FC(N_data->getPointer(d),
                                      N_data_gcw.min(),
                                      alpha,
#if (NDIM == 2)
                                      q_flux_data->getPointer(0, d),
                                      q_flux_data->getPointer(1, d),
                                      q_flux_data_gcw.min(),
                                      beta,
                                      N_data->getPointer(d),
                                      N_data_gcw.min(),
                                      patch_lower(0),
                                      patch_upper(0),
                                      patch_lower(1),
                                      patch_upper(1),
#endif
#if (NDIM == 3)
                                      q_flux_data->getPointer(0, d),
                                      q_flux_data->getPointer(1, d),
                                      q_flux_data->getPointer(2, d),
                                      q_flux_data_gcw.min(),
                                      beta,
                                      N_data->getPointer(d),
                                      N_data_gcw.min(),
                                      patch_lower(0),
                                      patch_upper(0),
                                      patch_lower(1),
                                      patch_upper(1),
                                      patch_lower(2),
                                      patch_upper(2),
#endif
                                      dx);
                }
            }
        }
    }

    // Deallocate scratch data.
    for (int ln = d_coarsest_ln; ln <= d_finest_ln; ++ln)
    {
        Pointer<PatchLevel<NDIM> > level = d_hierarchy->getPatchLevel(ln);
        level->deallocatePatchData(d_Q_scratch_idx);
        level->deallocatePatchData(d_q_extrap_idx);
        if (d_difference_form == CONSERVATIVE || d_difference_form == SKEW_SYMMETRIC)
            level->deallocatePatchData(d_q_flux_idx);
    }

    IBAMR_TIMER_STOP(t_apply_convective_operator);
    return;
} // applyConvectiveOperator
Пример #5
0
void muParserRobinBcCoefs::setBcCoefs(Pointer<ArrayData<NDIM, double> >& acoef_data,
                                      Pointer<ArrayData<NDIM, double> >& bcoef_data,
                                      Pointer<ArrayData<NDIM, double> >& gcoef_data,
                                      const Pointer<Variable<NDIM> >& /*variable*/,
                                      const Patch<NDIM>& patch,
                                      const BoundaryBox<NDIM>& bdry_box,
                                      double fill_time) const
{
    const Box<NDIM>& patch_box = patch.getBox();
    const Index<NDIM>& patch_lower = patch_box.lower();
    Pointer<CartesianPatchGeometry<NDIM> > pgeom = patch.getPatchGeometry();

    const double* const x_lower = pgeom->getXLower();
    const double* const dx = pgeom->getDx();

    // Loop over the boundary box and set the coefficients.
    const unsigned int location_index = bdry_box.getLocationIndex();
    const unsigned int bdry_normal_axis = location_index / 2;
    const Box<NDIM>& bc_coef_box =
        (acoef_data ? acoef_data->getBox() : bcoef_data ? bcoef_data->getBox() : gcoef_data ? gcoef_data->getBox() :
                                                                                              Box<NDIM>());
#if !defined(NDEBUG)
    TBOX_ASSERT(!acoef_data || bc_coef_box == acoef_data->getBox());
    TBOX_ASSERT(!bcoef_data || bc_coef_box == bcoef_data->getBox());
    TBOX_ASSERT(!gcoef_data || bc_coef_box == gcoef_data->getBox());
#endif

    const mu::Parser& acoef_parser = d_acoef_parsers[location_index];
    const mu::Parser& bcoef_parser = d_bcoef_parsers[location_index];
    const mu::Parser& gcoef_parser = d_gcoef_parsers[location_index];
    *d_parser_time = fill_time;
    for (Box<NDIM>::Iterator b(bc_coef_box); b; b++)
    {
        const Index<NDIM>& i = b();
        for (unsigned int d = 0; d < NDIM; ++d)
        {
            if (d != bdry_normal_axis)
            {
                (*d_parser_posn)[d] = x_lower[d] + dx[d] * (static_cast<double>(i(d) - patch_lower(d)) + 0.5);
            }
            else
            {
                (*d_parser_posn)[d] = x_lower[d] + dx[d] * (static_cast<double>(i(d) - patch_lower(d)));
            }
        }
        try
        {
            if (acoef_data) (*acoef_data)(i, 0) = acoef_parser.Eval();
            if (bcoef_data) (*bcoef_data)(i, 0) = bcoef_parser.Eval();
            if (gcoef_data) (*gcoef_data)(i, 0) = gcoef_parser.Eval();
        }
        catch (mu::ParserError& e)
        {
            TBOX_ERROR("muParserRobinBcCoefs::setDataOnPatch():\n"
                       << "  error: " << e.GetMsg() << "\n"
                       << "  in:    " << e.GetExpr() << "\n");
        }
        catch (...)
        {
            TBOX_ERROR("muParserRobinBcCoefs::setDataOnPatch():\n"
                       << "  unrecognized exception generated by muParser library.\n");
        }
    }
    return;
} // setBcCoefs
Пример #6
0
/*******************************************************************************
 * For each run, the input filename must be given on the command line.  In all *
 * cases, the command line is:                                                 *
 *                                                                             *
 *    executable <input file name>                                             *
 *                                                                             *
 *******************************************************************************/
bool
run_example(int argc, char* argv[])
{
    // Initialize PETSc, MPI, and SAMRAI.
    PetscInitialize(&argc, &argv, NULL, NULL);
    SAMRAI_MPI::setCommunicator(PETSC_COMM_WORLD);
    SAMRAI_MPI::setCallAbortInSerialInsteadOfExit();
    SAMRAIManager::startup();

    { // cleanup dynamically allocated objects prior to shutdown

        // Parse command line options, set some standard options from the input
        // file, and enable file logging.
        Pointer<AppInitializer> app_initializer = new AppInitializer(argc, argv, "cc_poisson.log");
        Pointer<Database> input_db = app_initializer->getInputDatabase();

        // Create major algorithm and data objects that comprise the
        // application.  These objects are configured from the input database.
        Pointer<CartesianGridGeometry<NDIM> > grid_geometry = new CartesianGridGeometry<NDIM>(
            "CartesianGeometry", app_initializer->getComponentDatabase("CartesianGeometry"));
        Pointer<PatchHierarchy<NDIM> > patch_hierarchy = new PatchHierarchy<NDIM>("PatchHierarchy", grid_geometry);
        Pointer<StandardTagAndInitialize<NDIM> > error_detector = new StandardTagAndInitialize<NDIM>(
            "StandardTagAndInitialize", NULL, app_initializer->getComponentDatabase("StandardTagAndInitialize"));
        Pointer<BergerRigoutsos<NDIM> > box_generator = new BergerRigoutsos<NDIM>();
        Pointer<LoadBalancer<NDIM> > load_balancer =
            new LoadBalancer<NDIM>("LoadBalancer", app_initializer->getComponentDatabase("LoadBalancer"));
        Pointer<GriddingAlgorithm<NDIM> > gridding_algorithm =
            new GriddingAlgorithm<NDIM>("GriddingAlgorithm",
                                        app_initializer->getComponentDatabase("GriddingAlgorithm"),
                                        error_detector,
                                        box_generator,
                                        load_balancer);

        // Initialize the AMR patch hierarchy.
        gridding_algorithm->makeCoarsestLevel(patch_hierarchy, 0.0);
        int tag_buffer = 1;
        int level_number = 0;
        bool done = false;
        while (!done && (gridding_algorithm->levelCanBeRefined(level_number)))
        {
            gridding_algorithm->makeFinerLevel(patch_hierarchy, 0.0, 0.0, tag_buffer);
            done = !patch_hierarchy->finerLevelExists(level_number);
            ++level_number;
        }

        // Create cell-centered data and extrapolate that data at physical
        // boundaries to obtain ghost cell values.
        VariableDatabase<NDIM>* var_db = VariableDatabase<NDIM>::getDatabase();
        Pointer<VariableContext> context = var_db->getContext("CONTEXT");
        Pointer<CellVariable<NDIM, double> > var = new CellVariable<NDIM, double>("v");
        const int gcw = 4;
        const int idx = var_db->registerVariableAndContext(var, context, gcw);
        for (int ln = 0; ln <= patch_hierarchy->getFinestLevelNumber(); ++ln)
        {
            Pointer<PatchLevel<NDIM> > level = patch_hierarchy->getPatchLevel(ln);
            level->allocatePatchData(idx);
            for (PatchLevel<NDIM>::Iterator p(level); p; p++)
            {
                Pointer<Patch<NDIM> > patch = level->getPatch(p());
                const Box<NDIM>& patch_box = patch->getBox();
                const Index<NDIM>& patch_lower = patch_box.lower();
                Pointer<CellData<NDIM, double> > data = patch->getPatchData(idx);
                for (Box<NDIM>::Iterator b(patch_box); b; b++)
                {
                    const Index<NDIM>& i = b();
                    (*data)(i) = 0;
                    for (unsigned int d = 0; d < NDIM; ++d)
                    {
                        (*data)(i) += 4 * (d + 1) * (d + 1) * i(d);
                    }
                }

                pout << "level number = " << ln << "\n";
                pout << "patch_box = " << patch_box << "\n";
                pout << "\n";

                plog << "interior data:\n";
                data->print(data->getBox());
                plog << "\n";

                CartExtrapPhysBdryOp constant_fill_op(idx, "CONSTANT");
                constant_fill_op.setPhysicalBoundaryConditions(*patch, 0.0, data->getGhostCellWidth());
                plog << "constant extrapolated ghost data:\n";
                data->print(data->getGhostBox());
                plog << "\n";

                CartExtrapPhysBdryOp linear_fill_op(idx, "LINEAR");
                linear_fill_op.setPhysicalBoundaryConditions(*patch, 0.0, data->getGhostCellWidth());
                plog << "linear extrapolated ghost data:\n";
                data->print(data->getGhostBox());
                plog << "\n";

                bool warning = false;
                for (Box<NDIM>::Iterator b(data->getGhostBox()); b; b++)
                {
                    const Index<NDIM>& i = b();
                    double val = 0;
                    for (int d = 0; d < NDIM; ++d)
                    {
                        val += 4 * (d + 1) * (d + 1) * i(d);
                    }

                    if (!MathUtilities<double>::equalEps(val, (*data)(i)))
                    {
                        warning = true;
                        pout << "warning: value at location " << i << " is not correct\n";
                        pout << "  expected value = " << val << "   computed value = " << (*data)(i) << "\n";
                    }
                }

                if (!warning)
                {
                    pout << "linearly extrapolated boundary data appears to be correct.\n";
                }
                else
                {
                    pout << "possible errors encountered in linearly extrapolated boundary data.\n";
                }

                pout << "checking robin bc handling . . .\n";

                Pointer<CartesianPatchGeometry<NDIM> > pgeom = patch->getPatchGeometry();
                const double* const x_lower = pgeom->getXLower();
                const double* const x_upper = grid_geometry->getXUpper();
                const double* const dx = pgeom->getDx();
                const double shift = 3.14159;
                for (Box<NDIM>::Iterator b(patch_box); b; b++)
                {
                    const Index<NDIM>& i = b();
                    double X[NDIM];
                    for (unsigned int d = 0; d < NDIM; ++d)
                    {
                        X[d] = x_lower[d] + dx[d] * (static_cast<double>(i(d) - patch_lower(d)) + 0.5);
                    }
                    (*data)(i) = 2.0 * X[NDIM - 1] + shift;
                }

                plog << "interior data:\n";
                data->print(data->getBox());
                plog << "\n";

                LocationIndexRobinBcCoefs<NDIM> dirichlet_bc_coef("dirichlet_bc_coef", NULL);
                for (unsigned int d = 0; d < NDIM - 1; ++d)
                {
                    dirichlet_bc_coef.setBoundarySlope(2 * d, 0.0);
                    dirichlet_bc_coef.setBoundarySlope(2 * d + 1, 0.0);
                }
                dirichlet_bc_coef.setBoundaryValue(2 * (NDIM - 1), shift);
                dirichlet_bc_coef.setBoundaryValue(2 * (NDIM - 1) + 1, 2.0 * x_upper[NDIM - 1] + shift);

                CartCellRobinPhysBdryOp dirichlet_bc_fill_op(idx, &dirichlet_bc_coef);
                dirichlet_bc_fill_op.setPhysicalBoundaryConditions(*patch, 0.0, data->getGhostCellWidth());
                plog << "extrapolated ghost data:\n";
                data->print(data->getGhostBox());
                plog << "\n";

                warning = false;
                for (Box<NDIM>::Iterator b(data->getGhostBox()); b; b++)
                {
                    const Index<NDIM>& i = b();
                    double X[NDIM];
                    for (unsigned int d = 0; d < NDIM; ++d)
                    {
                        X[d] = x_lower[d] + dx[d] * (static_cast<double>(i(d) - patch_lower(d)) + 0.5);
                    }
                    double val = 2.0 * X[NDIM - 1] + shift;

                    if (!MathUtilities<double>::equalEps(val, (*data)(i)))
                    {
                        warning = true;
                        pout << "warning: value at location " << i << " is not correct\n";
                        pout << "  expected value = " << val << "   computed value = " << (*data)(i) << "\n";
                    }
                }

                if (!warning)
                {
                    pout << "dirichlet boundary data appears to be correct.\n";
                }
                else
                {
                    pout << "possible errors encountered in extrapolated dirichlet boundary data.\n";
                }

                LocationIndexRobinBcCoefs<NDIM> neumann_bc_coef("neumann_bc_coef", NULL);
                for (unsigned int d = 0; d < NDIM - 1; ++d)
                {
                    neumann_bc_coef.setBoundarySlope(2 * d, 0.0);
                    neumann_bc_coef.setBoundarySlope(2 * d + 1, 0.0);
                }
                neumann_bc_coef.setBoundarySlope(2 * (NDIM - 1), -2.0);
                neumann_bc_coef.setBoundarySlope(2 * (NDIM - 1) + 1, +2.0);

                CartCellRobinPhysBdryOp neumann_bc_fill_op(idx, &neumann_bc_coef);
                neumann_bc_fill_op.setPhysicalBoundaryConditions(*patch, 0.0, data->getGhostCellWidth());
                plog << "extrapolated ghost data:\n";
                data->print(data->getGhostBox());
                plog << "\n";

                warning = false;
                for (Box<NDIM>::Iterator b(data->getGhostBox()); b; b++)
                {
                    const Index<NDIM>& i = b();
                    double X[NDIM];
                    for (unsigned int d = 0; d < NDIM; ++d)
                    {
                        X[d] = x_lower[d] + dx[d] * (static_cast<double>(i(d) - patch_lower(d)) + 0.5);
                    }
                    double val = 2.0 * X[NDIM - 1] + shift;

                    if (!MathUtilities<double>::equalEps(val, (*data)(i)))
                    {
                        warning = true;
                        pout << "warning: value at location " << i << " is not correct\n";
                        pout << "  expected value = " << val << "   computed value = " << (*data)(i) << "\n";
                    }
                }

                if (!warning)
                {
                    pout << "neumann boundary data appears to be correct.\n";
                }
                else
                {
                    pout << "possible errors encountered in extrapolated neumann boundary data.\n";
                }
            }
        }

    } // cleanup dynamically allocated objects prior to shutdown

    SAMRAIManager::shutdown();
    PetscFinalize();
    return true;
} // main
void
INSStaggeredUpwindConvectiveOperator::applyConvectiveOperator(const int U_idx, const int N_idx)
{
    IBAMR_TIMER_START(t_apply_convective_operator);
#if !defined(NDEBUG)
    if (!d_is_initialized)
    {
        TBOX_ERROR("INSStaggeredUpwindConvectiveOperator::applyConvectiveOperator():\n"
                   << "  operator must be initialized prior to call to applyConvectiveOperator\n");
    }
    TBOX_ASSERT(U_idx == d_u_idx);
#endif

    // Allocate scratch data.
    for (int ln = d_coarsest_ln; ln <= d_finest_ln; ++ln)
    {
        Pointer<PatchLevel<NDIM> > level = d_hierarchy->getPatchLevel(ln);
        level->allocatePatchData(d_U_scratch_idx);
    }

    // Fill ghost cell values for all components.
    static const bool homogeneous_bc = false;
    typedef HierarchyGhostCellInterpolation::InterpolationTransactionComponent InterpolationTransactionComponent;
    std::vector<InterpolationTransactionComponent> transaction_comps(1);
    transaction_comps[0] = InterpolationTransactionComponent(d_U_scratch_idx,
                                                             U_idx,
                                                             "CONSTANT_REFINE",
                                                             false,
                                                             "CONSERVATIVE_COARSEN",
                                                             d_bdry_extrap_type,
                                                             false,
                                                             d_bc_coefs);
    d_hier_bdry_fill->resetTransactionComponents(transaction_comps);
    d_hier_bdry_fill->setHomogeneousBc(homogeneous_bc);
    StaggeredStokesPhysicalBoundaryHelper::setupBcCoefObjects(d_bc_coefs, NULL, d_U_scratch_idx, -1, homogeneous_bc);
    d_hier_bdry_fill->fillData(d_solution_time);
    StaggeredStokesPhysicalBoundaryHelper::resetBcCoefObjects(d_bc_coefs, NULL);
    d_hier_bdry_fill->resetTransactionComponents(d_transaction_comps);

    // Compute the convective derivative.
    for (int ln = d_coarsest_ln; ln <= d_finest_ln; ++ln)
    {
        Pointer<PatchLevel<NDIM> > level = d_hierarchy->getPatchLevel(ln);
        for (PatchLevel<NDIM>::Iterator p(level); p; p++)
        {
            Pointer<Patch<NDIM> > patch = level->getPatch(p());

            const Pointer<CartesianPatchGeometry<NDIM> > patch_geom = patch->getPatchGeometry();
            const double* const dx = patch_geom->getDx();

            const Box<NDIM>& patch_box = patch->getBox();
            const IntVector<NDIM>& patch_lower = patch_box.lower();
            const IntVector<NDIM>& patch_upper = patch_box.upper();

            Pointer<SideData<NDIM, double> > N_data = patch->getPatchData(N_idx);
            Pointer<SideData<NDIM, double> > U_data = patch->getPatchData(d_U_scratch_idx);

            const IntVector<NDIM> ghosts = IntVector<NDIM>(1);
            boost::array<Box<NDIM>, NDIM> side_boxes;
            boost::array<Pointer<FaceData<NDIM, double> >, NDIM> U_adv_data;
            boost::array<Pointer<FaceData<NDIM, double> >, NDIM> U_half_data;
            for (unsigned int axis = 0; axis < NDIM; ++axis)
            {
                side_boxes[axis] = SideGeometry<NDIM>::toSideBox(patch_box, axis);
                U_adv_data[axis] = new FaceData<NDIM, double>(side_boxes[axis], 1, ghosts);
                U_half_data[axis] = new FaceData<NDIM, double>(side_boxes[axis], 1, ghosts);
            }
#if (NDIM == 2)
            NAVIER_STOKES_INTERP_COMPS_FC(patch_lower(0),
                                          patch_upper(0),
                                          patch_lower(1),
                                          patch_upper(1),
                                          U_data->getGhostCellWidth()(0),
                                          U_data->getGhostCellWidth()(1),
                                          U_data->getPointer(0),
                                          U_data->getPointer(1),
                                          side_boxes[0].lower(0),
                                          side_boxes[0].upper(0),
                                          side_boxes[0].lower(1),
                                          side_boxes[0].upper(1),
                                          U_adv_data[0]->getGhostCellWidth()(0),
                                          U_adv_data[0]->getGhostCellWidth()(1),
                                          U_adv_data[0]->getPointer(0),
                                          U_adv_data[0]->getPointer(1),
                                          side_boxes[1].lower(0),
                                          side_boxes[1].upper(0),
                                          side_boxes[1].lower(1),
                                          side_boxes[1].upper(1),
                                          U_adv_data[1]->getGhostCellWidth()(0),
                                          U_adv_data[1]->getGhostCellWidth()(1),
                                          U_adv_data[1]->getPointer(0),
                                          U_adv_data[1]->getPointer(1));
#endif
#if (NDIM == 3)
            NAVIER_STOKES_INTERP_COMPS_FC(patch_lower(0),
                                          patch_upper(0),
                                          patch_lower(1),
                                          patch_upper(1),
                                          patch_lower(2),
                                          patch_upper(2),
                                          U_data->getGhostCellWidth()(0),
                                          U_data->getGhostCellWidth()(1),
                                          U_data->getGhostCellWidth()(2),
                                          U_data->getPointer(0),
                                          U_data->getPointer(1),
                                          U_data->getPointer(2),
                                          side_boxes[0].lower(0),
                                          side_boxes[0].upper(0),
                                          side_boxes[0].lower(1),
                                          side_boxes[0].upper(1),
                                          side_boxes[0].lower(2),
                                          side_boxes[0].upper(2),
                                          U_adv_data[0]->getGhostCellWidth()(0),
                                          U_adv_data[0]->getGhostCellWidth()(1),
                                          U_adv_data[0]->getGhostCellWidth()(2),
                                          U_adv_data[0]->getPointer(0),
                                          U_adv_data[0]->getPointer(1),
                                          U_adv_data[0]->getPointer(2),
                                          side_boxes[1].lower(0),
                                          side_boxes[1].upper(0),
                                          side_boxes[1].lower(1),
                                          side_boxes[1].upper(1),
                                          side_boxes[1].lower(2),
                                          side_boxes[1].upper(2),
                                          U_adv_data[1]->getGhostCellWidth()(0),
                                          U_adv_data[1]->getGhostCellWidth()(1),
                                          U_adv_data[1]->getGhostCellWidth()(2),
                                          U_adv_data[1]->getPointer(0),
                                          U_adv_data[1]->getPointer(1),
                                          U_adv_data[1]->getPointer(2),
                                          side_boxes[2].lower(0),
                                          side_boxes[2].upper(0),
                                          side_boxes[2].lower(1),
                                          side_boxes[2].upper(1),
                                          side_boxes[2].lower(2),
                                          side_boxes[2].upper(2),
                                          U_adv_data[2]->getGhostCellWidth()(0),
                                          U_adv_data[2]->getGhostCellWidth()(1),
                                          U_adv_data[2]->getGhostCellWidth()(2),
                                          U_adv_data[2]->getPointer(0),
                                          U_adv_data[2]->getPointer(1),
                                          U_adv_data[2]->getPointer(2));
#endif
            for (unsigned int axis = 0; axis < NDIM; ++axis)
            {
                const ArrayData<NDIM, double>& U_array_data = U_data->getArrayData(axis);
                for (unsigned int d = 0; d < NDIM; ++d)
                {
                    for (FaceIterator<NDIM> ic(side_boxes[axis], d); ic; ic++)
                    {
                        const FaceIndex<NDIM>& i = ic();
                        const double u_ADV = (*U_adv_data[axis])(i);
                        const double U_lower = U_array_data(i.toCell(0), 0);
                        const double U_upper = U_array_data(i.toCell(1), 0);
                        (*U_half_data[axis])(i) =
                            (u_ADV > 1.0e-8) ? U_lower : (u_ADV < 1.0e-8) ? U_upper : 0.5 * (U_lower + U_upper);
                    }
                }
            }
            for (unsigned int axis = 0; axis < NDIM; ++axis)
            {
                switch (d_difference_form)
                {
                case CONSERVATIVE:
#if (NDIM == 2)
                    CONVECT_DERIVATIVE_FC(dx,
                                          side_boxes[axis].lower(0),
                                          side_boxes[axis].upper(0),
                                          side_boxes[axis].lower(1),
                                          side_boxes[axis].upper(1),
                                          U_adv_data[axis]->getGhostCellWidth()(0),
                                          U_adv_data[axis]->getGhostCellWidth()(1),
                                          U_half_data[axis]->getGhostCellWidth()(0),
                                          U_half_data[axis]->getGhostCellWidth()(1),
                                          U_adv_data[axis]->getPointer(0),
                                          U_adv_data[axis]->getPointer(1),
                                          U_half_data[axis]->getPointer(0),
                                          U_half_data[axis]->getPointer(1),
                                          N_data->getGhostCellWidth()(0),
                                          N_data->getGhostCellWidth()(1),
                                          N_data->getPointer(axis));
#endif
#if (NDIM == 3)
                    CONVECT_DERIVATIVE_FC(dx,
                                          side_boxes[axis].lower(0),
                                          side_boxes[axis].upper(0),
                                          side_boxes[axis].lower(1),
                                          side_boxes[axis].upper(1),
                                          side_boxes[axis].lower(2),
                                          side_boxes[axis].upper(2),
                                          U_adv_data[axis]->getGhostCellWidth()(0),
                                          U_adv_data[axis]->getGhostCellWidth()(1),
                                          U_adv_data[axis]->getGhostCellWidth()(2),
                                          U_half_data[axis]->getGhostCellWidth()(0),
                                          U_half_data[axis]->getGhostCellWidth()(1),
                                          U_half_data[axis]->getGhostCellWidth()(2),
                                          U_adv_data[axis]->getPointer(0),
                                          U_adv_data[axis]->getPointer(1),
                                          U_adv_data[axis]->getPointer(2),
                                          U_half_data[axis]->getPointer(0),
                                          U_half_data[axis]->getPointer(1),
                                          U_half_data[axis]->getPointer(2),
                                          N_data->getGhostCellWidth()(0),
                                          N_data->getGhostCellWidth()(1),
                                          N_data->getGhostCellWidth()(2),
                                          N_data->getPointer(axis));
#endif
                    break;
                case ADVECTIVE:
#if (NDIM == 2)
                    ADVECT_DERIVATIVE_FC(dx,
                                         side_boxes[axis].lower(0),
                                         side_boxes[axis].upper(0),
                                         side_boxes[axis].lower(1),
                                         side_boxes[axis].upper(1),
                                         U_adv_data[axis]->getGhostCellWidth()(0),
                                         U_adv_data[axis]->getGhostCellWidth()(1),
                                         U_half_data[axis]->getGhostCellWidth()(0),
                                         U_half_data[axis]->getGhostCellWidth()(1),
                                         U_adv_data[axis]->getPointer(0),
                                         U_adv_data[axis]->getPointer(1),
                                         U_half_data[axis]->getPointer(0),
                                         U_half_data[axis]->getPointer(1),
                                         N_data->getGhostCellWidth()(0),
                                         N_data->getGhostCellWidth()(1),
                                         N_data->getPointer(axis));
#endif
#if (NDIM == 3)
                    ADVECT_DERIVATIVE_FC(dx,
                                         side_boxes[axis].lower(0),
                                         side_boxes[axis].upper(0),
                                         side_boxes[axis].lower(1),
                                         side_boxes[axis].upper(1),
                                         side_boxes[axis].lower(2),
                                         side_boxes[axis].upper(2),
                                         U_adv_data[axis]->getGhostCellWidth()(0),
                                         U_adv_data[axis]->getGhostCellWidth()(1),
                                         U_adv_data[axis]->getGhostCellWidth()(2),
                                         U_half_data[axis]->getGhostCellWidth()(0),
                                         U_half_data[axis]->getGhostCellWidth()(1),
                                         U_half_data[axis]->getGhostCellWidth()(2),
                                         U_adv_data[axis]->getPointer(0),
                                         U_adv_data[axis]->getPointer(1),
                                         U_adv_data[axis]->getPointer(2),
                                         U_half_data[axis]->getPointer(0),
                                         U_half_data[axis]->getPointer(1),
                                         U_half_data[axis]->getPointer(2),
                                         N_data->getGhostCellWidth()(0),
                                         N_data->getGhostCellWidth()(1),
                                         N_data->getGhostCellWidth()(2),
                                         N_data->getPointer(axis));
#endif
                    break;
                case SKEW_SYMMETRIC:
#if (NDIM == 2)
                    SKEW_SYM_DERIVATIVE_FC(dx,
                                           side_boxes[axis].lower(0),
                                           side_boxes[axis].upper(0),
                                           side_boxes[axis].lower(1),
                                           side_boxes[axis].upper(1),
                                           U_adv_data[axis]->getGhostCellWidth()(0),
                                           U_adv_data[axis]->getGhostCellWidth()(1),
                                           U_half_data[axis]->getGhostCellWidth()(0),
                                           U_half_data[axis]->getGhostCellWidth()(1),
                                           U_adv_data[axis]->getPointer(0),
                                           U_adv_data[axis]->getPointer(1),
                                           U_half_data[axis]->getPointer(0),
                                           U_half_data[axis]->getPointer(1),
                                           N_data->getGhostCellWidth()(0),
                                           N_data->getGhostCellWidth()(1),
                                           N_data->getPointer(axis));
#endif
#if (NDIM == 3)
                    SKEW_SYM_DERIVATIVE_FC(dx,
                                           side_boxes[axis].lower(0),
                                           side_boxes[axis].upper(0),
                                           side_boxes[axis].lower(1),
                                           side_boxes[axis].upper(1),
                                           side_boxes[axis].lower(2),
                                           side_boxes[axis].upper(2),
                                           U_adv_data[axis]->getGhostCellWidth()(0),
                                           U_adv_data[axis]->getGhostCellWidth()(1),
                                           U_adv_data[axis]->getGhostCellWidth()(2),
                                           U_half_data[axis]->getGhostCellWidth()(0),
                                           U_half_data[axis]->getGhostCellWidth()(1),
                                           U_half_data[axis]->getGhostCellWidth()(2),
                                           U_adv_data[axis]->getPointer(0),
                                           U_adv_data[axis]->getPointer(1),
                                           U_adv_data[axis]->getPointer(2),
                                           U_half_data[axis]->getPointer(0),
                                           U_half_data[axis]->getPointer(1),
                                           U_half_data[axis]->getPointer(2),
                                           N_data->getGhostCellWidth()(0),
                                           N_data->getGhostCellWidth()(1),
                                           N_data->getGhostCellWidth()(2),
                                           N_data->getPointer(axis));
#endif
                    break;
                default:
                    TBOX_ERROR("INSStaggeredUpwindConvectiveOperator::applyConvectiveOperator():\n"
                               << "  unsupported differencing form: "
                               << enum_to_string<ConvectiveDifferencingType>(d_difference_form)
                               << " \n"
                               << "  valid choices are: ADVECTIVE, CONSERVATIVE, SKEW_SYMMETRIC\n");
                }
            }
        }
    }

    // Deallocate scratch data.
    for (int ln = d_coarsest_ln; ln <= d_finest_ln; ++ln)
    {
        Pointer<PatchLevel<NDIM> > level = d_hierarchy->getPatchLevel(ln);
        level->deallocatePatchData(d_U_scratch_idx);
    }

    IBAMR_TIMER_STOP(t_apply_convective_operator);
    return;
} // applyConvectiveOperator