Skip to content

Commit 9afd7e6

Browse files
authored
Merge pull request #3383 from reverendbedford/reuse_preconditioner_edge_cases
Fix edge cases in preconditioner reuse
2 parents 10bd1bc + 58a8b18 commit 9afd7e6

File tree

5 files changed

+40
-21
lines changed

5 files changed

+40
-21
lines changed

include/solvers/nonlinear_solver.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -365,14 +365,19 @@ class NonlinearSolver : public ReferenceCountedObject<NonlinearSolver<T>>,
365365
virtual void set_reuse_preconditioner(bool reuse);
366366

367367
/**
368-
* Get the reuse_preconditioner_max_its parameter
368+
* Get the reuse_preconditioner_max_linear_its parameter
369369
*/
370-
virtual unsigned int reuse_preconditioner_max_its() const;
370+
virtual unsigned int reuse_preconditioner_max_linear_its() const;
371371

372372
/**
373-
* Set the reuse_preconditioner_max_its parameter
373+
* Set the reuse_preconditioner_max_linear_its parameter
374374
*/
375-
virtual void set_reuse_preconditioner_max_its(unsigned int i);
375+
virtual void set_reuse_preconditioner_max_linear_its(unsigned int i);
376+
377+
/**
378+
* Immediately force a new preconditioner
379+
*/
380+
virtual void force_new_preconditioner() {};
376381

377382

378383
protected:
@@ -384,7 +389,7 @@ class NonlinearSolver : public ReferenceCountedObject<NonlinearSolver<T>>,
384389
/**
385390
* Number of linear iterations to retain the preconditioner
386391
*/
387-
unsigned int _reuse_preconditioner_max_its;
392+
unsigned int _reuse_preconditioner_max_linear_its;
388393

389394
/**
390395
* A reference to the system we are solving.
@@ -447,7 +452,7 @@ NonlinearSolver<T>::NonlinearSolver (sys_type & s) :
447452
minimum_linear_tolerance(0),
448453
converged(false),
449454
_reuse_preconditioner(false),
450-
_reuse_preconditioner_max_its(0),
455+
_reuse_preconditioner_max_linear_its(0),
451456
_system(s),
452457
_is_initialized (false),
453458
_preconditioner (nullptr),

include/solvers/petsc_nonlinear_solver.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,12 @@ class PetscNonlinearSolver : public NonlinearSolver<T>
215215
/**
216216
* Getter for the maximum iterations flag for preconditioner reuse
217217
*/
218-
virtual unsigned int reuse_preconditioner_max_its() const override;
218+
virtual unsigned int reuse_preconditioner_max_linear_its() const override;
219+
220+
/**
221+
* Immediately force a new preconditioner, even if reuse is set
222+
*/
223+
virtual void force_new_preconditioner() override;
219224

220225
protected:
221226

src/solvers/nonlinear_solver.C

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,15 @@ void NonlinearSolver<T>::set_reuse_preconditioner(bool reuse)
9797
}
9898

9999
template <typename T>
100-
unsigned int NonlinearSolver<T>::reuse_preconditioner_max_its() const
100+
unsigned int NonlinearSolver<T>::reuse_preconditioner_max_linear_its() const
101101
{
102102
libmesh_not_implemented();
103103
}
104104

105105
template <typename T>
106-
void NonlinearSolver<T>::set_reuse_preconditioner_max_its(unsigned int i)
106+
void NonlinearSolver<T>::set_reuse_preconditioner_max_linear_its(unsigned int i)
107107
{
108-
_reuse_preconditioner_max_its = i;
108+
_reuse_preconditioner_max_linear_its = i;
109109
}
110110

111111
//------------------------------------------------------------------

src/solvers/petsc_nonlinear_solver.C

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ extern "C"
126126
ierr = KSPGetIterationNumber(ksp, &niter);
127127
LIBMESH_CHKERR2(solver->comm(),ierr);
128128

129-
if (niter > cast_int<PetscInt>(solver->reuse_preconditioner_max_its()))
129+
if (niter > cast_int<PetscInt>(solver->reuse_preconditioner_max_linear_its()))
130130
{
131131
// -2 is a magic number for "recalculate next time you need it
132132
// and then not again"
@@ -682,8 +682,6 @@ void PetscNonlinearSolver<T>::clear ()
682682
}
683683
}
684684

685-
686-
687685
template <typename T>
688686
void PetscNonlinearSolver<T>::init (const char * name)
689687
{
@@ -855,7 +853,6 @@ PetscNonlinearSolver<T>::solve (SparseMatrix<T> & pre_in, // System Preconditi
855853
LOG_SCOPE("solve()", "PetscNonlinearSolver");
856854
this->init ();
857855

858-
859856
// Make sure the data passed in are really of Petsc types
860857
PetscMatrix<T> * pre = cast_ptr<PetscMatrix<T> *>(&pre_in);
861858
PetscVector<T> * x = cast_ptr<PetscVector<T> *>(&x_in);
@@ -878,7 +875,7 @@ PetscNonlinearSolver<T>::solve (SparseMatrix<T> & pre_in, // System Preconditi
878875
ierr = SNESSetLagPreconditioner(_snes, -2);
879876
LIBMESH_CHKERR(ierr);
880877
// Add in our callback which will trigger recalculating
881-
// the preconditioner when we hit reuse_preconditioner_max_its
878+
// the preconditioner when we hit reuse_preconditioner_max_linear_its
882879
ierr = SNESMonitorSet(_snes, &libmesh_petsc_recalculate_monitor,
883880
this,
884881
NULL);
@@ -1129,11 +1126,19 @@ bool PetscNonlinearSolver<T>::reuse_preconditioner() const
11291126
}
11301127

11311128
template <typename T>
1132-
unsigned int PetscNonlinearSolver<T>::reuse_preconditioner_max_its() const
1129+
unsigned int PetscNonlinearSolver<T>::reuse_preconditioner_max_linear_its() const
11331130
{
1134-
return this->_reuse_preconditioner_max_its;
1131+
return this->_reuse_preconditioner_max_linear_its;
11351132
}
11361133

1134+
template <typename T>
1135+
void PetscNonlinearSolver<T>::force_new_preconditioner()
1136+
{
1137+
// Easiest way is just to clear everything out
1138+
this->_is_initialized = false;
1139+
_snes.destroy();
1140+
_setup_reuse = false;
1141+
}
11371142

11381143
//------------------------------------------------------------------
11391144
// Explicit instantiations

src/systems/nonlinear_implicit_system.C

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ NonlinearImplicitSystem::NonlinearImplicitSystem (EquationSystems & es,
5454
es.parameters.set<Real>("nonlinear solver relative step tolerance") = 1e-8;
5555

5656
es.parameters.set<bool>("reuse preconditioner") = false;
57-
es.parameters.set<unsigned int>("reuse preconditioner maximum iterations") = 1;
57+
es.parameters.set<unsigned int>("reuse preconditioner maximum linear iterations") = 1;
5858
}
5959

6060

@@ -82,6 +82,10 @@ void NonlinearImplicitSystem::reinit ()
8282
// re-initialize the nonlinear solver interface
8383
nonlinear_solver->clear();
8484

85+
// force the solver to get a new preconditioner, in
86+
// case reuse was set
87+
nonlinear_solver->force_new_preconditioner();
88+
8589
// FIXME - this is necessary for petsc_auto_fieldsplit
8690
// nonlinear_solver->init_names(*this);
8791

@@ -134,8 +138,8 @@ void NonlinearImplicitSystem::set_solver_parameters ()
134138

135139
const bool reuse_preconditioner =
136140
es.parameters.get<bool>("reuse preconditioner");
137-
const unsigned int reuse_preconditioner_max_its =
138-
es.parameters.get<unsigned int>("reuse preconditioner maximum iterations");
141+
const unsigned int reuse_preconditioner_max_linear_its =
142+
es.parameters.get<unsigned int>("reuse preconditioner maximum linear iterations");
139143

140144
// Set all the parameters on the NonlinearSolver
141145
nonlinear_solver->max_nonlinear_iterations = maxits;
@@ -149,7 +153,7 @@ void NonlinearImplicitSystem::set_solver_parameters ()
149153
nonlinear_solver->initial_linear_tolerance = linear_tol;
150154
nonlinear_solver->minimum_linear_tolerance = linear_min_tol;
151155
nonlinear_solver->set_reuse_preconditioner(reuse_preconditioner);
152-
nonlinear_solver->set_reuse_preconditioner_max_its(reuse_preconditioner_max_its);
156+
nonlinear_solver->set_reuse_preconditioner_max_linear_its(reuse_preconditioner_max_linear_its);
153157

154158
if (diff_solver.get())
155159
{

0 commit comments

Comments
 (0)