432 const double rel_tol,
433 const double abs_tol,
434 const unsigned int m_its,
435 ksp_solve_func_type solve_func)
438 PetscVector<T> * solution = cast_ptr<PetscVector<T> *>(&solution_in);
445 PetscInt its=0, max_its =
static_cast<PetscInt
>(m_its);
446 PetscReal final_resid=0.;
448 std::unique_ptr<PetscMatrixBase<Number>> subprecond_matrix;
458 if (_restrict_solve_to_is)
460 PetscInt is_local_size = this->restrict_solve_to_is_local_size();
462 LibmeshPetscCall(VecCreate(this->comm().get(), subrhs.
get()));
463 LibmeshPetscCall(VecSetSizes(subrhs, is_local_size, PETSC_DECIDE));
464 LibmeshPetscCall(VecSetFromOptions(subrhs));
466 LibmeshPetscCall(VecCreate(this->comm().get(), subsolution.
get()));
467 LibmeshPetscCall(VecSetSizes(subsolution, is_local_size, PETSC_DECIDE));
468 LibmeshPetscCall(VecSetFromOptions(subsolution));
470 LibmeshPetscCall(VecScatterCreate(rhs->vec(), _restrict_solve_to_is, subrhs,
nullptr, scatter.
get()));
472 VecScatterBeginEnd(this->comm(), scatter, rhs->vec(), subrhs, INSERT_VALUES, SCATTER_FORWARD);
473 VecScatterBeginEnd(this->comm(), scatter, solution->
vec(), subsolution, INSERT_VALUES, SCATTER_FORWARD);
475 LibmeshPetscCall(LibMeshCreateSubMatrix(mat,
476 _restrict_solve_to_is,
477 _restrict_solve_to_is,
482 LibmeshPetscCall(LibMeshCreateSubMatrix(
const_cast<PetscMatrixBase<T> *
>(precond)->mat(),
483 _restrict_solve_to_is,
484 _restrict_solve_to_is,
494 this->create_complement_is(rhs_in);
495 PetscInt is_complement_local_size =
496 cast_int<PetscInt>(rhs_in.
local_size()-is_local_size);
499 LibmeshPetscCall(VecCreate(this->comm().get(), subvec1.
get()));
500 LibmeshPetscCall(VecSetSizes(subvec1, is_complement_local_size, PETSC_DECIDE));
501 LibmeshPetscCall(VecSetFromOptions(subvec1));
504 LibmeshPetscCall(VecScatterCreate(rhs->vec(), _restrict_solve_to_is_complement, subvec1,
nullptr, scatter1.
get()));
506 VecScatterBeginEnd(this->comm(), scatter1, _subset_solve_mode==
SUBSET_COPY_RHS ? rhs->vec() : solution->
vec(), subvec1, INSERT_VALUES, SCATTER_FORWARD);
508 LibmeshPetscCall(VecScale(subvec1, -1.0));
511 LibmeshPetscCall(LibMeshCreateSubMatrix(mat,
512 _restrict_solve_to_is,
513 _restrict_solve_to_is_complement,
517 LibmeshPetscCall(MatMultAdd(submat1, subvec1, subrhs, subrhs));
521 LibmeshPetscCall(KSPSetOperators(_ksp, submat, subprecond));
523 LibmeshPetscCall(KSPSetOperators(_ksp, submat, submat));
525 PetscBool ksp_reuse_preconditioner = this->same_preconditioner ? PETSC_TRUE : PETSC_FALSE;
526 LibmeshPetscCall(KSPSetReusePreconditioner(_ksp, ksp_reuse_preconditioner));
528 if (precond && this->_preconditioner)
530 subprecond_matrix = std::make_unique<PetscMatrix<Number>>(subprecond, this->comm());
531 this->_preconditioner->set_matrix(*subprecond_matrix);
532 this->_preconditioner->init();
537 PetscBool ksp_reuse_preconditioner = this->same_preconditioner ? PETSC_TRUE : PETSC_FALSE;
538 LibmeshPetscCall(KSPSetReusePreconditioner(_ksp, ksp_reuse_preconditioner));
541 LibmeshPetscCall(KSPSetOperators(_ksp, mat,
const_cast<PetscMatrixBase<T> *
>(precond)->mat()));
543 LibmeshPetscCall(KSPSetOperators(_ksp, mat, mat));
545 if (this->_preconditioner)
548 this->_preconditioner->set_matrix(*matrix);
552 this->_preconditioner->init();
558 LibmeshPetscCall(KSPSetTolerances(_ksp, rel_tol, abs_tol,
559 PETSC_DEFAULT, max_its));
562 LibmeshPetscCall(KSPSetFromOptions(_ksp));
564#if defined(LIBMESH_HAVE_PETSC_HYPRE) && PETSC_VERSION_LESS_THAN(3, 23, 0) && \
565 !PETSC_VERSION_LESS_THAN(3, 12, 0) && defined(PETSC_HAVE_HYPRE_DEVICE)
568 LibmeshPetscCallExternal(HYPRE_Initialize);
569 PetscScalar * dummyarray;
571 LibmeshPetscCall(VecGetArrayAndMemType(solution->
vec(), &dummyarray, &mtype));
572 LibmeshPetscCall(VecRestoreArrayAndMemType(solution->
vec(), &dummyarray));
573 if (PetscMemTypeHost(mtype))
574 LibmeshPetscCallExternal(HYPRE_SetMemoryLocation, HYPRE_MEMORY_HOST);
580 if (this->_solver_configuration)
582 this->_solver_configuration->configure_solver();
586 if (_restrict_solve_to_is)
587 LibmeshPetscCall(solve_func (_ksp, subrhs, subsolution));
589 LibmeshPetscCall(solve_func (_ksp, rhs->vec(), solution->
vec()));
592 LibmeshPetscCall(KSPGetIterationNumber (_ksp, &its));
595 LibmeshPetscCall(KSPGetResidualNorm (_ksp, &final_resid));
597 if (_restrict_solve_to_is)
599 switch(_subset_solve_mode)
602 LibmeshPetscCall(VecZeroEntries(solution->
vec()));
606 LibmeshPetscCall(VecCopy(rhs->vec(),solution->
vec()));
614 libmesh_error_msg(
"Invalid subset solve mode = " << _subset_solve_mode);
617 VecScatterBeginEnd(this->comm(), scatter, subsolution, solution->
vec(), INSERT_VALUES, SCATTER_REVERSE);
619 if (precond && this->_preconditioner)
624 this->_preconditioner->set_matrix(*matrix);
626 this->_preconditioner->set_matrix(*precond);
628 this->_preconditioner->init();
633 return std::make_pair(its, final_resid);