Ejemplo n.º 1
0
void
BJacobiPreconditioner::initializeSolverState(
    const SAMRAIVectorReal<NDIM,double>& x,
    const SAMRAIVectorReal<NDIM,double>& b)
{
    Pointer<PatchHierarchy<NDIM> > hierarchy = x.getPatchHierarchy();
    const int coarsest_ln = x.getCoarsestLevelNumber();
    const int finest_ln = x.getFinestLevelNumber();
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(hierarchy == b.getPatchHierarchy());
    TBOX_ASSERT(coarsest_ln == b.getCoarsestLevelNumber());
    TBOX_ASSERT(finest_ln == b.getFinestLevelNumber());
    TBOX_ASSERT(x.getNumberOfComponents() == b.getNumberOfComponents());
#endif
    // Initialize the component preconditioners.
    const std::string& x_name = x.getName();
    const std::string& b_name = b.getName();
    for (std::map<unsigned int,Pointer<LinearSolver> >::iterator it = d_pc_map.begin(); it != d_pc_map.end(); ++it)
    {
        const int comp = it->first;
        SAMRAIVectorReal<NDIM,double> x_comp(x_name+"_component", hierarchy, coarsest_ln, finest_ln);
        x_comp.addComponent(x.getComponentVariable(comp), x.getComponentDescriptorIndex(comp), x.getControlVolumeIndex(comp));
        SAMRAIVectorReal<NDIM,double> b_comp(b_name+"_component", hierarchy, coarsest_ln, finest_ln);
        b_comp.addComponent(b.getComponentVariable(comp), b.getComponentDescriptorIndex(comp), b.getControlVolumeIndex(comp));
        d_pc_map[comp]->initializeSolverState(x_comp, b_comp);
    }

    // Indicate that the preconditioner is initialized.
    d_is_initialized = true;
    return;
}// initializeSolverState
Ejemplo n.º 2
0
bool
BJacobiPreconditioner::solveSystem(
    SAMRAIVectorReal<NDIM,double>& x,
    SAMRAIVectorReal<NDIM,double>& b)
{
    // Initialize the preconditioner, when necessary.
    const bool deallocate_after_solve = !d_is_initialized;
    if (deallocate_after_solve) initializeSolverState(x,b);

    Pointer<PatchHierarchy<NDIM> > hierarchy = x.getPatchHierarchy();
    const int coarsest_ln = x.getCoarsestLevelNumber();
    const int   finest_ln = x.getFinestLevelNumber()  ;
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(x.getNumberOfComponents() == b.getNumberOfComponents());
    TBOX_ASSERT(hierarchy == b.getPatchHierarchy());
    TBOX_ASSERT(coarsest_ln == b.getCoarsestLevelNumber());
    TBOX_ASSERT(  finest_ln == b.getFinestLevelNumber()  );
#endif
    const std::string& x_name = x.getName();
    const std::string& b_name = b.getName();
    bool ret_val = true;

    // Zero out the initial guess.
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(d_initial_guess_nonzero == false);
#endif
    x.setToScalar(0.0, /*interior_only*/ false);

    for (int comp = 0; comp < x.getNumberOfComponents(); ++comp)
    {
        // Setup a SAMRAIVectorReal to correspond to the individual vector
        // component.
        std::ostringstream str;
        str << comp;

        SAMRAIVectorReal<NDIM,double> x_comp(x_name+"_component_"+str.str(), hierarchy, coarsest_ln, finest_ln);
        x_comp.addComponent(x.getComponentVariable(comp), x.getComponentDescriptorIndex(comp), x.getControlVolumeIndex(comp));

        SAMRAIVectorReal<NDIM,double> b_comp(b_name+"_component_"+str.str(), hierarchy, coarsest_ln, finest_ln);
        b_comp.addComponent(b.getComponentVariable(comp), b.getComponentDescriptorIndex(comp), b.getControlVolumeIndex(comp));

        // Configure the component preconditioner.
        Pointer<LinearSolver> pc_comp = d_pc_map[comp];
        pc_comp->setInitialGuessNonzero(d_initial_guess_nonzero);
        pc_comp->setMaxIterations(d_max_iterations);
        pc_comp->setAbsoluteTolerance(d_abs_residual_tol);
        pc_comp->setRelativeTolerance(d_rel_residual_tol);

        // Apply the component preconditioner.
        const bool ret_val_comp = pc_comp->solveSystem(x_comp, b_comp);
        ret_val = ret_val && ret_val_comp;
    }

    // Deallocate the preconditioner, when necessary.
    if (deallocate_after_solve) deallocateSolverState();
    return ret_val;
}// solveSystem
Ejemplo n.º 3
0
Pointer<SAMRAIVectorReal<NDIM,double> >
FACPreconditionerStrategy::getLevelSAMRAIVectorReal(
    const SAMRAIVectorReal<NDIM,double>& vec,
    int level_num) const
{
    std::ostringstream name_str;
    name_str << vec.getName() << "::level_" << level_num;
    Pointer<SAMRAIVectorReal<NDIM,double> > level_vec = new SAMRAIVectorReal<NDIM,double>(name_str.str(), vec.getPatchHierarchy(), level_num, level_num);
    for (int comp = 0; comp < vec.getNumberOfComponents(); ++comp)
    {
        level_vec->addComponent(vec.getComponentVariable(comp), vec.getComponentDescriptorIndex(comp), vec.getControlVolumeIndex(comp));
    }
    return level_vec;
}// getLevelSAMRAIVectorReal
Ejemplo n.º 4
0
bool
FACPreconditioner::checkVectorStateCompatibility(
   const SAMRAIVectorReal<double>& solution,
   const SAMRAIVectorReal<double>& rhs) const
{
   /*
    * It is an error when the state is not initialized.
    */
   if (!d_patch_hierarchy) {
      TBOX_ERROR(
         d_object_name << ": cannot check vector-state\n"
                       << "compatibility when the state is uninitialized.\n");
   }
   bool rvalue = true;
   const SAMRAIVectorReal<double>& error = *d_error_vector;
   if (solution.getPatchHierarchy() != d_patch_hierarchy
       || rhs.getPatchHierarchy() != d_patch_hierarchy) {
      rvalue = false;
   }
   if (rvalue == true) {
      if (solution.getCoarsestLevelNumber() != d_coarsest_ln
          || rhs.getCoarsestLevelNumber() != d_coarsest_ln
          || solution.getFinestLevelNumber() != d_finest_ln
          || rhs.getFinestLevelNumber() != d_finest_ln) {
         rvalue = false;
      }
   }
   if (rvalue == true) {
      const int ncomp = error.getNumberOfComponents();
      if (solution.getNumberOfComponents() != ncomp
          || rhs.getNumberOfComponents() != ncomp) {
         rvalue = false;
      }
   }
   return rvalue;
}
void BGaussSeidelPreconditioner::initializeSolverState(const SAMRAIVectorReal<NDIM, double>& x,
                                                       const SAMRAIVectorReal<NDIM, double>& b)
{
#if !defined(NDEBUG)
    Pointer<PatchHierarchy<NDIM> > hierarchy = x.getPatchHierarchy();
    const int coarsest_ln = x.getCoarsestLevelNumber();
    const int finest_ln = x.getFinestLevelNumber();
    TBOX_ASSERT(hierarchy == b.getPatchHierarchy());
    TBOX_ASSERT(coarsest_ln == b.getCoarsestLevelNumber());
    TBOX_ASSERT(finest_ln == b.getFinestLevelNumber());
    TBOX_ASSERT(x.getNumberOfComponents() == b.getNumberOfComponents());
#endif
    // Setup SAMRAIVectorReal objects to correspond to the individual vector
    // components.
    std::vector<Pointer<SAMRAIVectorReal<NDIM, double> > > x_comps =
        getComponentVectors(ConstPointer<SAMRAIVectorReal<NDIM, double> >(&x, false));
    std::vector<Pointer<SAMRAIVectorReal<NDIM, double> > > b_comps =
        getComponentVectors(ConstPointer<SAMRAIVectorReal<NDIM, double> >(&b, false));

    // Initialize the component operators and preconditioners.
    const int ncomps = x.getNumberOfComponents();
    for (int comp = 0; comp < ncomps; ++comp)
    {
        for (int c = 0; c < ncomps; ++c)
        {
            // Skip the diagonal operators.
            if (c == comp) continue;
            d_linear_ops_map[comp][c]->initializeOperatorState(*x_comps[comp], *b_comps[comp]);
        }
        d_pc_map[comp]->initializeSolverState(*x_comps[comp], *b_comps[comp]);
    }

    // Indicate that the preconditioner is initialized.
    d_is_initialized = true;
    return;
} // initializeSolverState
void
IBImplicitModHelmholtzPETScLevelSolver::initializeSolverState(
    const SAMRAIVectorReal<NDIM,double>& x,
    const SAMRAIVectorReal<NDIM,double>& b)
{
    IBAMR_TIMER_START(t_initialize_solver_state);

    // Rudimentary error checking.
#ifdef DEBUG_CHECK_ASSERTIONS
    if (x.getNumberOfComponents() != b.getNumberOfComponents())
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                   << "  vectors must have the same number of components" << std::endl);
    }

    const Pointer<PatchHierarchy<NDIM> >& patch_hierarchy = x.getPatchHierarchy();
    if (patch_hierarchy != b.getPatchHierarchy())
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                   << "  vectors must have the same hierarchy" << std::endl);
    }

    const int coarsest_ln = x.getCoarsestLevelNumber();
    if (coarsest_ln < 0)
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                   << "  coarsest level number must not be negative" << std::endl);
    }
    if (coarsest_ln != b.getCoarsestLevelNumber())
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                   << "  vectors must have same coarsest level number" << std::endl);
    }

    const int finest_ln = x.getFinestLevelNumber();
    if (finest_ln < coarsest_ln)
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                   << "  finest level number must be >= coarsest level number" << std::endl);
    }
    if (finest_ln != b.getFinestLevelNumber())
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                   << "  vectors must have same finest level number" << std::endl);
    }

    for (int ln = coarsest_ln; ln <= finest_ln; ++ln)
    {
        if (patch_hierarchy->getPatchLevel(ln).isNull())
        {
            TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                       << "  hierarchy level " << ln << " does not exist" << std::endl);
        }
    }

    if (coarsest_ln != finest_ln)
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                   << "  coarsest_ln != finest_ln in IBImplicitModHelmholtzPETScLevelSolver" << std::endl);
    }
#endif
    // Deallocate the solver state if the solver is already initialized.
    if (d_is_initialized) deallocateSolverState();

    // Get the hierarchy information.
    d_hierarchy = x.getPatchHierarchy();
    d_level_num = x.getCoarsestLevelNumber();
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(d_level_num == x.getFinestLevelNumber());
#endif

    const int x_idx = x.getComponentDescriptorIndex(0);
    Pointer<SideVariable<NDIM,double> > x_var = x.getComponentVariable(0);
    const int b_idx = b.getComponentDescriptorIndex(0);
    Pointer<SideVariable<NDIM,double> > b_var = b.getComponentVariable(0);

    // Allocate DOF index data.
    VariableDatabase<NDIM>* var_db = VariableDatabase<NDIM>::getDatabase();
    Pointer<SideDataFactory<NDIM,double> > x_fac =
        var_db->getPatchDescriptor()->getPatchDataFactory(x_idx);
    const int depth = x_fac->getDefaultDepth();
    Pointer<SideDataFactory<NDIM,int> > dof_index_fac =
        var_db->getPatchDescriptor()->getPatchDataFactory(d_dof_index_idx);
    dof_index_fac->setDefaultDepth(depth);
    Pointer<PatchLevel<NDIM> > level = d_hierarchy->getPatchLevel(d_level_num);
    if (!level->checkAllocated(d_dof_index_idx)) level->allocatePatchData(d_dof_index_idx);

    // Setup PETSc objects.
    int ierr;
    PETScVecUtilities::constructPatchLevelVec(d_petsc_x, x_idx, x_var, level);
    PETScVecUtilities::constructPatchLevelVec(d_petsc_b, b_idx, b_var, level);
    PETScVecUtilities::constructPatchLevelDOFIndices(d_dof_index_idx, d_dof_index_var, x_idx, x_var, level);
    const double C = d_poisson_spec.cIsZero() ? 0.0 : d_poisson_spec.getCConstant();
    const double D = d_poisson_spec.getDConstant();
    PETScMatUtilities::constructPatchLevelLaplaceOp(d_petsc_mat, C, D, x_idx, x_var, d_dof_index_idx, d_dof_index_var, level, d_dof_index_fill);
    if (d_SJR_mat != PETSC_NULL)
    {
        ierr = PETScMatOps::MatAXPY(d_petsc_mat, 1.0, d_SJR_mat); IBTK_CHKERRQ(ierr);
    }
    ierr = MatSetBlockSize(d_petsc_mat, NDIM); IBTK_CHKERRQ(ierr);

    ierr = KSPCreate(PETSC_COMM_WORLD, &d_petsc_ksp); IBTK_CHKERRQ(ierr);
    ierr = KSPSetOperators(d_petsc_ksp, d_petsc_mat, d_petsc_mat, SAME_PRECONDITIONER); IBTK_CHKERRQ(ierr);
    if (!d_options_prefix.empty())
    {
        ierr = KSPSetOptionsPrefix(d_petsc_ksp, d_options_prefix.c_str()); IBTK_CHKERRQ(ierr);
    }
    ierr = KSPSetFromOptions(d_petsc_ksp); IBTK_CHKERRQ(ierr);

    // Indicate that the solver is initialized.
    d_is_initialized = true;

    IBAMR_TIMER_STOP(t_initialize_solver_state);
    return;
}// initializeSolverState
Ejemplo n.º 7
0
void
FACPreconditioner::facCycle_McCormick(
   SAMRAIVectorReal<double>& e,
   SAMRAIVectorReal<double>& r,
   SAMRAIVectorReal<double>& u,
   int lmax,
   int lmin,
   int ln)
{

   /*
    * The steps 1-4 in this function correspond to McCormick's steps
    * those in his description.
    *
    * 1. If on the coarsest level, solve it.
    * 2. Presmoothing.
    * 3. Recurse to next lower level.
    * 4. Postsmoothing.
    */

   /*
    * Step 1.
    */
   if (ln == lmin) {
      /*
       * Solve coarsest level.
       */
      d_fac_operator->solveCoarsestLevel(e,
         r,
         ln);
   } else {

      int i, num_components = e.getNumberOfComponents();

      /*
       * Step 2a.
       */
      d_fac_operator->computeCompositeResidualOnLevel(*d_tmp_residual,
         e,
         r,
         ln,
         true);
      for (i = 0; i < num_components; ++i) {
         int tmp_id = d_tmp_error->getComponentDescriptorIndex(i);
         d_controlled_level_ops[i]->resetLevels(ln,
            ln);
         d_controlled_level_ops[i]->setToScalar(tmp_id,
            0.0);
      }
      /*
       * Step 2b.
       */
      d_fac_operator->smoothError(*d_tmp_error,
         *d_tmp_residual,
         ln,
         d_presmoothing_sweeps);
      /*
       * Step 2c.
       */
      for (i = 0; i < num_components; ++i) {
         int tmp_id = d_tmp_error->getComponentDescriptorIndex(i);
         int id = e.getComponentDescriptorIndex(i);
         d_controlled_level_ops[i]->resetLevels(ln,
            ln);
         d_controlled_level_ops[i]->add(id,
            id,
            tmp_id);
      }
      /*
       * Step 3a.
       */
      d_fac_operator->computeCompositeResidualOnLevel(*d_tmp_residual,
         e,
         r,
         ln,
         true);
      d_fac_operator->restrictResidual(*d_tmp_residual,
         *d_tmp_residual,
         ln - 1);
      /*
       * Step 3b.
       */
      for (i = 0; i < num_components; ++i) {
         int tmp_id = e.getComponentDescriptorIndex(i);
         d_controlled_level_ops[i]->resetLevels(ln - 1,
            ln - 1);
         d_controlled_level_ops[i]->setToScalar(tmp_id,
            0.0);
      }
      /*
       * Step 3c.
       */
      facCycle_McCormick(e,
         r,
         u,
         lmax,
         lmin,
         ln - 1);
      /*
       * Step 3d.
       */
      d_fac_operator->prolongErrorAndCorrect(e,
         e,
         ln);
      /*
       * Step 4a.
       */
      d_fac_operator->computeCompositeResidualOnLevel(*d_tmp_residual,
         e,
         r,
         ln,
         true);
      for (i = 0; i < num_components; ++i) {
         int tmp_id = d_tmp_error->getComponentDescriptorIndex(i);
         d_controlled_level_ops[i]->resetLevels(ln,
            ln);
         d_controlled_level_ops[i]->setToScalar(tmp_id,
            0.0);
      }
      /*
       * Step 4b.
       */
      d_fac_operator->smoothError(*d_tmp_error,
         *d_tmp_residual,
         ln,
         d_postsmoothing_sweeps);
      /*
       * Step 4c.
       */
      for (i = 0; i < num_components; ++i) {
         int tmp_id = d_tmp_error->getComponentDescriptorIndex(i);
         int id = e.getComponentDescriptorIndex(i);
         d_controlled_level_ops[i]->resetLevels(ln,
            ln);
         d_controlled_level_ops[i]->add(id,
            id,
            tmp_id);
      }

   }
}
Ejemplo n.º 8
0
void
FACPreconditioner::initializeSolverState(
   const SAMRAIVectorReal<double>& solution,
   const SAMRAIVectorReal<double>& rhs)
{
   /*
    * First get rid of current data.
    */
   deallocateSolverState();
   /*
    * Set hierarchy and levels to solve.
    */
   d_patch_hierarchy = solution.getPatchHierarchy();
   d_coarsest_ln = solution.getCoarsestLevelNumber();
   d_finest_ln = solution.getFinestLevelNumber();
   /*
    * Set the solution-vector-dependent scratch space.
    */
   d_error_vector = solution.cloneVector(d_object_name + "::error");
   d_error_vector->allocateVectorData();
   if (d_algorithm_choice == "mccormick-s4.3") {
      d_tmp_error = solution.cloneVector(d_object_name + "::temporary_error");
      d_tmp_error->allocateVectorData();
   }
   d_residual_vector = rhs.cloneVector(d_object_name + "::residual");
   d_residual_vector->allocateVectorData();
   d_tmp_residual = rhs.cloneVector(d_object_name + "::FAC coarser residual");
   d_tmp_residual->allocateVectorData();
   /*
    * Set the controlled level operators, which depend on the number
    * of components in the solution vector.
    */
   math::HierarchyDataOpsManager* ops_manager =
      math::HierarchyDataOpsManager::getManager();
   int num_components = solution.getNumberOfComponents();
   d_controlled_level_ops.resize(num_components);
   for (int i = 0; i < num_components; ++i) {
      d_controlled_level_ops[i] =
         ops_manager->getOperationsDouble(
            solution.getComponentVariable(i),
            d_patch_hierarchy,
            true);
      /*
       * Note: the variable used above is only for the purpose of determining
       * the variable alignment on the grid.  It is not specific to any
       * instance.
       */
   }
   /*
    * Error checking.
    */
#ifdef DEBUG_CHECK_ASSERTIONS
   if (d_patch_hierarchy != rhs.getPatchHierarchy()) {
      TBOX_ERROR(d_object_name << ": vectors must have the same hierarchy.\n");
   }
   if (d_coarsest_ln < 0) {
      TBOX_ERROR(d_object_name << ": coarsest level must not be negative.\n");
   }
   if (d_coarsest_ln > d_finest_ln) {
      TBOX_ERROR(d_object_name << ": coarsest level must be <= finest"
                               << "level.\n");
   }
#endif
   for (int ln = d_coarsest_ln; ln <= d_finest_ln; ++ln) {
      if (!d_patch_hierarchy->getPatchLevel(ln)) {
         TBOX_ERROR("FACPreconditioner::initializeSolverState error ..."
            << "\n   object name = " << d_object_name
            << "\n   hierarchy level " << ln
            << " does not exist" << std::endl);
      }
   }
   d_fac_operator->initializeOperatorState(solution, rhs);
}
Ejemplo n.º 9
0
void PETScNewtonKrylovSolver::initializeSolverState(const SAMRAIVectorReal<NDIM, double>& x,
                                                    const SAMRAIVectorReal<NDIM, double>& b)
{
    IBTK_TIMER_START(t_initialize_solver_state);

    int ierr;

// Rudimentary error checking.
#if !defined(NDEBUG)
    if (x.getNumberOfComponents() != b.getNumberOfComponents())
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                                 << "  vectors must have the same number of components"
                                 << std::endl);
    }

    const Pointer<PatchHierarchy<NDIM> >& patch_hierarchy = x.getPatchHierarchy();
    if (patch_hierarchy != b.getPatchHierarchy())
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                                 << "  vectors must have the same hierarchy" << std::endl);
    }

    const int coarsest_ln = x.getCoarsestLevelNumber();
    if (coarsest_ln < 0)
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                                 << "  coarsest level number must not be negative"
                                 << std::endl);
    }
    if (coarsest_ln != b.getCoarsestLevelNumber())
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                                 << "  vectors must have same coarsest level number"
                                 << std::endl);
    }

    const int finest_ln = x.getFinestLevelNumber();
    if (finest_ln < coarsest_ln)
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                                 << "  finest level number must be >= coarsest level number"
                                 << std::endl);
    }
    if (finest_ln != b.getFinestLevelNumber())
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                                 << "  vectors must have same finest level number"
                                 << std::endl);
    }

    for (int ln = coarsest_ln; ln <= finest_ln; ++ln)
    {
        if (!patch_hierarchy->getPatchLevel(ln))
        {
            TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                                     << "  hierarchy level " << ln << " does not exist"
                                     << std::endl);
        }
    }
#endif
    // Deallocate the solver state if the solver is already initialized.
    if (d_is_initialized)
    {
        d_reinitializing_solver = true;
        deallocateSolverState();
    }

    // Create the SNES solver.
    if (d_managing_petsc_snes)
    {
        ierr = SNESCreate(d_petsc_comm, &d_petsc_snes);
        IBTK_CHKERRQ(ierr);
        resetSNESOptions();
    }
    else if (!d_petsc_snes)
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                                 << "  cannot initialize solver state for wrapped PETSc SNES "
                                    "object if the wrapped object is NULL" << std::endl);
    }

    // Setup solution and rhs vectors.
    d_x = x.cloneVector(x.getName());
    d_petsc_x = PETScSAMRAIVectorReal::createPETScVector(d_x, d_petsc_comm);

    d_b = b.cloneVector(b.getName());
    d_petsc_b = PETScSAMRAIVectorReal::createPETScVector(d_b, d_petsc_comm);

    d_r = b.cloneVector(b.getName());
    d_petsc_r = PETScSAMRAIVectorReal::createPETScVector(d_r, d_petsc_comm);

    // Setup the nonlinear operator.
    if (d_F) d_F->initializeOperatorState(*d_x, *d_b);
    if (d_managing_petsc_snes || d_user_provided_function) resetSNESFunction();

    // Setup the Jacobian.
    if (d_J) d_J->initializeOperatorState(*d_x, *d_b);
    if (d_managing_petsc_snes || d_user_provided_jacobian) resetSNESJacobian();

    // Set the SNES options from the PETSc options database.
    if (d_options_prefix != "")
    {
        ierr = SNESSetOptionsPrefix(d_petsc_snes, d_options_prefix.c_str());
        IBTK_CHKERRQ(ierr);
    }
    ierr = SNESSetFromOptions(d_petsc_snes);
    IBTK_CHKERRQ(ierr);

    // Reset the member state variables to correspond to the values used by the
    // SNES object.  (Command-line options always take precedence.)
    ierr = SNESGetTolerances(d_petsc_snes,
                             &d_abs_residual_tol,
                             &d_rel_residual_tol,
                             &d_solution_tol,
                             &d_max_iterations,
                             &d_max_evaluations);
    IBTK_CHKERRQ(ierr);

    // Setup the KrylovLinearSolver wrapper to correspond to the KSP employed by
    // the SNES solver.
    KSP petsc_ksp;
    ierr = SNESGetKSP(d_petsc_snes, &petsc_ksp);
    IBTK_CHKERRQ(ierr);
    Pointer<PETScKrylovLinearSolver> p_krylov_solver = d_krylov_solver;
    if (p_krylov_solver) p_krylov_solver->resetWrappedKSP(petsc_ksp);

    // Setup the Krylov solver.
    if (d_krylov_solver) d_krylov_solver->initializeSolverState(*d_x, *d_b);

    // Indicate that the solver is initialized.
    d_reinitializing_solver = false;
    d_is_initialized = true;

    IBTK_TIMER_STOP(t_initialize_solver_state);
    return;
} // initializeSolverState
Ejemplo n.º 10
0
void
CCDivGradHypreLevelSolver::initializeSolverState(
    const SAMRAIVectorReal<NDIM,double>& x,
    const SAMRAIVectorReal<NDIM,double>& b)
{
    IBTK_TIMER_START(t_initialize_solver_state);

    // Rudimentary error checking.
#ifdef DEBUG_CHECK_ASSERTIONS
    if (x.getNumberOfComponents() != b.getNumberOfComponents())
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                   << "  vectors must have the same number of components" << std::endl);
    }

    const Pointer<PatchHierarchy<NDIM> >& patch_hierarchy = x.getPatchHierarchy();
    if (patch_hierarchy != b.getPatchHierarchy())
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                   << "  vectors must have the same hierarchy" << std::endl);
    }

    const int coarsest_ln = x.getCoarsestLevelNumber();
    if (coarsest_ln < 0)
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                   << "  coarsest level number must not be negative" << std::endl);
    }
    if (coarsest_ln != b.getCoarsestLevelNumber())
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                   << "  vectors must have same coarsest level number" << std::endl);
    }

    const int finest_ln = x.getFinestLevelNumber();
    if (finest_ln < coarsest_ln)
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                   << "  finest level number must be >= coarsest level number" << std::endl);
    }
    if (finest_ln != b.getFinestLevelNumber())
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                   << "  vectors must have same finest level number" << std::endl);
    }

    for (int ln = coarsest_ln; ln <= finest_ln; ++ln)
    {
        if (patch_hierarchy->getPatchLevel(ln).isNull())
        {
            TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                       << "  hierarchy level " << ln << " does not exist" << std::endl);
        }
    }

    if (coarsest_ln != finest_ln)
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                   << "  coarsest_ln != finest_ln in CCDivGradHypreLevelSolver" << std::endl);
    }
#else
    NULL_USE(b);
#endif
    // Deallocate the solver state if the solver is already initialized.
    if (d_is_initialized) deallocateSolverState();

    // Get the hierarchy information.
    d_hierarchy = x.getPatchHierarchy();
    d_level_num = x.getCoarsestLevelNumber();

    // Allocate and initialize the hypre data structures.
    allocateHypreData();
    setMatrixCoefficients();
    setupHypreSolver();

    // Indicate that the solver is initialized.
    d_is_initialized = true;

    IBTK_TIMER_STOP(t_initialize_solver_state);
    return;
}// initializeSolverState
Ejemplo n.º 11
0
void PETScKrylovLinearSolver::initializeSolverState(const SAMRAIVectorReal<NDIM, double>& x,
                                                    const SAMRAIVectorReal<NDIM, double>& b)
{
    IBTK_TIMER_START(t_initialize_solver_state);

    int ierr;

// Rudimentary error checking.
#if !defined(NDEBUG)
    if (x.getNumberOfComponents() != b.getNumberOfComponents())
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                                 << "  vectors must have the same number of components"
                                 << std::endl);
    }

    const Pointer<PatchHierarchy<NDIM> >& patch_hierarchy = x.getPatchHierarchy();
    if (patch_hierarchy != b.getPatchHierarchy())
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                                 << "  vectors must have the same hierarchy" << std::endl);
    }

    const int coarsest_ln = x.getCoarsestLevelNumber();
    if (coarsest_ln < 0)
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                                 << "  coarsest level number must not be negative"
                                 << std::endl);
    }
    if (coarsest_ln != b.getCoarsestLevelNumber())
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                                 << "  vectors must have same coarsest level number"
                                 << std::endl);
    }

    const int finest_ln = x.getFinestLevelNumber();
    if (finest_ln < coarsest_ln)
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                                 << "  finest level number must be >= coarsest level number"
                                 << std::endl);
    }
    if (finest_ln != b.getFinestLevelNumber())
    {
        TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                                 << "  vectors must have same finest level number"
                                 << std::endl);
    }

    for (int ln = coarsest_ln; ln <= finest_ln; ++ln)
    {
        if (!patch_hierarchy->getPatchLevel(ln))
        {
            TBOX_ERROR(d_object_name << "::initializeSolverState()\n"
                                     << "  hierarchy level " << ln << " does not exist"
                                     << std::endl);
        }
    }
#endif
    // Deallocate the solver state if the solver is already initialized.
    if (d_is_initialized)
    {
        d_reinitializing_solver = true;
        deallocateSolverState();
    }

    // Create the KSP solver.
    if (d_managing_petsc_ksp)
    {
        ierr = KSPCreate(d_petsc_comm, &d_petsc_ksp);
        IBTK_CHKERRQ(ierr);
        resetKSPOptions();
    }
    else if (!d_petsc_ksp)
    {
        TBOX_ERROR(d_object_name
                   << "::initializeSolverState()\n"
                   << "  cannot initialize solver state for wrapped PETSc KSP object "
                      "if the wrapped object is NULL" << std::endl);
    }

    // Setup solution and rhs vectors.
    d_x = x.cloneVector(x.getName());
    d_petsc_x = PETScSAMRAIVectorReal::createPETScVector(d_x, d_petsc_comm);

    d_b = b.cloneVector(b.getName());
    d_petsc_b = PETScSAMRAIVectorReal::createPETScVector(d_b, d_petsc_comm);

    // Initialize the linear operator and preconditioner objects.
    if (d_A) d_A->initializeOperatorState(*d_x, *d_b);
    if (d_managing_petsc_ksp || d_user_provided_mat) resetKSPOperators();

    if (d_pc_solver) d_pc_solver->initializeSolverState(*d_x, *d_b);
    if (d_managing_petsc_ksp || d_user_provided_pc) resetKSPPC();

    // Set the KSP options from the PETSc options database.
    if (d_options_prefix != "")
    {
        ierr = KSPSetOptionsPrefix(d_petsc_ksp, d_options_prefix.c_str());
        IBTK_CHKERRQ(ierr);
    }
    ierr = KSPSetFromOptions(d_petsc_ksp);
    IBTK_CHKERRQ(ierr);

    // Reset the member state variables to correspond to the values used by the
    // KSP object.  (Command-line options always take precedence.)
    const char* ksp_type;
    ierr = KSPGetType(d_petsc_ksp, &ksp_type);
    IBTK_CHKERRQ(ierr);
    d_ksp_type = ksp_type;
    PetscBool initial_guess_nonzero;
    ierr = KSPGetInitialGuessNonzero(d_petsc_ksp, &initial_guess_nonzero);
    IBTK_CHKERRQ(ierr);
    d_initial_guess_nonzero = (initial_guess_nonzero == PETSC_TRUE);
    ierr = KSPGetTolerances(
        d_petsc_ksp, &d_rel_residual_tol, &d_abs_residual_tol, NULL, &d_max_iterations);
    IBTK_CHKERRQ(ierr);

    // Configure the nullspace object.
    resetKSPNullspace();

    // Indicate that the solver is initialized.
    d_reinitializing_solver = false;
    d_is_initialized = true;

    IBTK_TIMER_STOP(t_initialize_solver_state);
    return;
} // initializeSolverState
bool BGaussSeidelPreconditioner::solveSystem(SAMRAIVectorReal<NDIM, double>& x, SAMRAIVectorReal<NDIM, double>& b)
{
    // Initialize the preconditioner, when necessary.
    const bool deallocate_after_solve = !d_is_initialized;
    if (deallocate_after_solve) initializeSolverState(x, b);

#if !defined(NDEBUG)
    Pointer<PatchHierarchy<NDIM> > hierarchy = x.getPatchHierarchy();
    const int coarsest_ln = x.getCoarsestLevelNumber();
    const int finest_ln = x.getFinestLevelNumber();
    TBOX_ASSERT(x.getNumberOfComponents() == b.getNumberOfComponents());
    TBOX_ASSERT(hierarchy == b.getPatchHierarchy());
    TBOX_ASSERT(coarsest_ln == b.getCoarsestLevelNumber());
    TBOX_ASSERT(finest_ln == b.getFinestLevelNumber());
#endif
    bool ret_val = true;

// Zero out the initial guess.
#if !defined(NDEBUG)
    TBOX_ASSERT(d_initial_guess_nonzero == false);
#endif
    x.setToScalar(0.0, /*interior_only*/ false);

    // Setup SAMRAIVectorReal objects to correspond to the individual vector
    // components.
    std::vector<Pointer<SAMRAIVectorReal<NDIM, double> > > x_comps =
        getComponentVectors(Pointer<SAMRAIVectorReal<NDIM, double> >(&x, false));
    std::vector<Pointer<SAMRAIVectorReal<NDIM, double> > > b_comps =
        getComponentVectors(Pointer<SAMRAIVectorReal<NDIM, double> >(&b, false));

    // Clone the right-hand-side vector to avoid modifying it during the
    // preconditioning operation.
    Pointer<SAMRAIVectorReal<NDIM, double> > f = b.cloneVector(b.getName());
    f->allocateVectorData();
    f->copyVector(Pointer<SAMRAIVectorReal<NDIM, double> >(&b, false), false);
    std::vector<Pointer<SAMRAIVectorReal<NDIM, double> > > f_comps = getComponentVectors(f);

    // Setup the order in which the component preconditioner are to be applied.
    const int ncomps = x.getNumberOfComponents();
    std::vector<int> comps;
    comps.reserve(2 * ncomps - 1);
    if (!d_reverse_order)
    {
        // Standard order: Run from comp = 0 to comp = ncomp-1.
        for (int comp = 0; comp < ncomps; ++comp)
        {
            comps.push_back(comp);
        }
        if (d_symmetric_preconditioner)
        {
            for (int comp = ncomps - 2; comp >= 0; --comp)
            {
                comps.push_back(comp);
            }
        }
    }
    else
    {
        // Reversed order: Run from comp = ncomp-1 to comp = 0.
        for (int comp = ncomps - 1; comp >= 0; --comp)
        {
            comps.push_back(comp);
        }
        if (d_symmetric_preconditioner)
        {
            for (int comp = 1; comp < ncomps; ++comp)
            {
                comps.push_back(comp);
            }
        }
    }

    // Apply the component preconditioners.
    int count = 0;
    for (std::vector<int>::const_iterator it = comps.begin(); it != comps.end(); ++it, ++count)
    {
        const int comp = (*it);

        Pointer<SAMRAIVectorReal<NDIM, double> > x_comp = x_comps[comp];
        Pointer<SAMRAIVectorReal<NDIM, double> > b_comp = b_comps[comp];
        Pointer<SAMRAIVectorReal<NDIM, double> > f_comp = f_comps[comp];

        // Update the right-hand-side vector.
        f_comp->setToScalar(0.0);
        for (int c = 0; c < ncomps; ++c)
        {
            if (c == comp) continue;
            d_linear_ops_map[comp][c]->applyAdd(*x_comps[c], *f_comp, *f_comp);
        }
        f_comp->subtract(b_comp, f_comp);

        // Configure the component preconditioner.
        Pointer<LinearSolver> pc_comp = d_pc_map[comp];
        pc_comp->setInitialGuessNonzero(count >= ncomps);
        pc_comp->setMaxIterations(d_max_iterations);
        pc_comp->setAbsoluteTolerance(d_abs_residual_tol);
        pc_comp->setRelativeTolerance(d_rel_residual_tol);

        // Apply the component preconditioner.
        const bool ret_val_comp = pc_comp->solveSystem(*x_comp, *f_comp);
        ret_val = ret_val && ret_val_comp;
    }

    // Free the copied right-hand-side vector data.
    f->deallocateVectorData();
    f->freeVectorComponents();

    // Deallocate the preconditioner, when necessary.
    if (deallocate_after_solve) deallocateSolverState();
    return ret_val;
} // solveSystem