libMesh
petsc_nonlinear_solver.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 #include "libmesh/libmesh_common.h"
21 
22 #ifdef LIBMESH_HAVE_PETSC
23 
24 // Local Includes
25 #include "libmesh/libmesh_logging.h"
26 #include "libmesh/nonlinear_implicit_system.h"
27 #include "libmesh/petsc_nonlinear_solver.h"
28 #include "libmesh/petsc_linear_solver.h"
29 #include "libmesh/petsc_vector.h"
30 #include "libmesh/petsc_mffd_matrix.h"
31 #include "libmesh/dof_map.h"
32 #include "libmesh/preconditioner.h"
33 #include "libmesh/solver_configuration.h"
34 #include "libmesh/petscdmlibmesh.h"
35 #include "libmesh/petsc_preconditioner.h"
36 
37 #if defined(LIBMESH_HAVE_PETSC_HYPRE) && PETSC_VERSION_LESS_THAN(3, 23, 0) && \
38  !PETSC_VERSION_LESS_THAN(3, 12, 0) && defined(PETSC_HAVE_HYPRE_DEVICE)
39 #include <HYPRE_utilities.h>
40 #endif
41 
42 namespace libMesh
43 {
45 {
46 public:
48  solver(solver_in),
49  sys(sys_in)
50  {}
51 
54 };
55 
57 libmesh_petsc_snes_residual_helper (SNES snes, Vec x, void * ctx)
58 {
59  LOG_SCOPE("residual()", "PetscNonlinearSolver");
60 
61  libmesh_assert(x);
63 
64  // No way to safety-check this cast, since we got a void *...
66  static_cast<PetscNonlinearSolver<Number> *> (ctx);
67 
68  libmesh_parallel_only(solver->comm());
69 
70  // Get the current iteration number from the snes object,
71  // store it in the PetscNonlinearSolver object for possible use
72  // by the user's residual function.
73  {
74  PetscInt n_iterations = 0;
75  LibmeshPetscCall2(solver->comm(), SNESGetIterationNumber(snes, &n_iterations));
76  solver->_current_nonlinear_iteration_number = cast_int<unsigned>(n_iterations);
77  }
78 
79  NonlinearImplicitSystem & sys = solver->system();
80 
81  PetscVector<Number> & X_sys = *cast_ptr<PetscVector<Number> *>(sys.solution.get());
82 
83  PetscVector<Number> X_global(x, sys.comm());
84 
85  // Use the system's update() to get a good local version of the
86  // parallel solution. This operation does not modify the incoming
87  // "x" vector, it only localizes information from "x" into
88  // sys.current_local_solution.
89  X_global.swap(X_sys);
90  sys.update();
91  X_global.swap(X_sys);
92 
93  // Enforce constraints (if any) exactly on the
94  // current_local_solution. This is the solution vector that is
95  // actually used in the computation of the residual below, and is
96  // not locked by debug-enabled PETSc the way that "x" is.
99 
100  return ResidualContext(solver, sys);
101 }
102 
103 //--------------------------------------------------------------------
104 // Functions with C linkage to pass to PETSc. PETSc will call these
105 // methods as needed.
106 //
107 // Since they must have C linkage they have no knowledge of a namespace.
108 // Give them an obscure name to avoid namespace pollution.
109 extern "C"
110 {
111  // -----------------------------------------------------------------
112  // this function monitors the nonlinear solve and checks to see
113  // if we want to recalculate the preconditioner. It only gets
114  // added to the SNES instance if we're reusing the preconditioner
115  PetscErrorCode
116  libmesh_petsc_recalculate_monitor(SNES snes, PetscInt, PetscReal, void* ctx)
117  {
118  PetscFunctionBegin;
119 
120  // No way to safety-check this cast, since we got a void *...
122  static_cast<PetscNonlinearSolver<Number> *> (ctx);
123 
124  KSP ksp;
125  LibmeshPetscCall2(solver->comm(), SNESGetKSP(snes, &ksp));
126 
127  PetscInt niter;
128  LibmeshPetscCall2(solver->comm(), KSPGetIterationNumber(ksp, &niter));
129 
130  if (niter > cast_int<PetscInt>(solver->reuse_preconditioner_max_linear_its()))
131  {
132  // -2 is a magic number for "recalculate next time you need it
133  // and then not again"
134  LibmeshPetscCall2(solver->comm(), SNESSetLagPreconditioner(snes, -2));
135  }
136  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
137  }
138 
139  //-------------------------------------------------------------------
140  // this function is called by PETSc at the end of each nonlinear step
141  PetscErrorCode
142  libmesh_petsc_snes_monitor (SNES, PetscInt its, PetscReal fnorm, void *)
143  {
144  PetscFunctionBegin;
145  libMesh::out << " NL step "
146  << std::setw(2) << its
147  << std::scientific
148  << ", |residual|_2 = " << fnorm
149  << std::endl;
150  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
151  }
152 
153  //---------------------------------------------------------------
154  // this function is called by PETSc to evaluate the residual at X
155  PetscErrorCode
156  libmesh_petsc_snes_residual (SNES snes, Vec x, Vec r, void * ctx)
157  {
158  PetscFunctionBegin;
159 
161 
162  libmesh_parallel_only(rc.sys.comm());
163 
164  libmesh_assert(r);
165  PetscVector<Number> R(r, rc.sys.comm());
166 
167  if (rc.solver->_zero_out_residual)
168  R.zero();
169 
170  //-----------------------------------------------------------------------------
171  // if the user has provided both function pointers and objects only the pointer
172  // will be used, so catch that as an error
173  libmesh_error_msg_if(rc.solver->residual && rc.solver->residual_object,
174  "ERROR: cannot specify both a function and object to compute the Residual!");
175 
176  libmesh_error_msg_if(rc.solver->matvec && rc.solver->residual_and_jacobian_object,
177  "ERROR: cannot specify both a function and object to compute the combined Residual & Jacobian!");
178 
179  if (rc.solver->residual != nullptr)
180  rc.solver->residual(*rc.sys.current_local_solution.get(), R, rc.sys);
181 
182  else if (rc.solver->residual_object != nullptr)
184 
185  else if (rc.solver->matvec != nullptr)
186  rc.solver->matvec (*rc.sys.current_local_solution.get(), &R, nullptr, rc.sys);
187 
188  else if (rc.solver->residual_and_jacobian_object != nullptr)
189  {
190  auto & jac = rc.sys.get_system_matrix();
191 
192  if (rc.solver->_zero_out_jacobian)
193  jac.zero();
194 
196  *rc.sys.current_local_solution.get(), &R, &jac, rc.sys);
197 
198  jac.close();
200  {
202  jac.close();
203  }
204  }
205 
206  else
207  libmesh_error_msg("Error! Unable to compute residual and/or Jacobian!");
208 
209 
210  // Synchronize PETSc x to local solution since the local solution may be changed due to the constraints
211  PetscVector<Number> & X_sys = *cast_ptr<PetscVector<Number> *>(rc.sys.solution.get());
212  PetscVector<Number> X_global(x, rc.sys.comm());
213 
214  X_global.swap(X_sys);
215  rc.sys.update();
216  X_global.swap(X_sys);
217 
218  R.close();
219 
221  {
223  R.close();
224  }
225 
226  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
227  }
228 
229  //-----------------------------------------------------------------------------------------
230  // this function is called by PETSc to approximate the Jacobian at X via finite differences
231  PetscErrorCode
232  libmesh_petsc_snes_fd_residual (SNES snes, Vec x, Vec r, void * ctx)
233  {
234  PetscFunctionBegin;
235 
237 
238  libmesh_parallel_only(rc.sys.comm());
239 
240  libmesh_assert(r);
241  PetscVector<Number> R(r, rc.sys.comm());
242 
243  if (rc.solver->_zero_out_residual)
244  R.zero();
245 
246  if (rc.solver->fd_residual_object != nullptr)
248 
249  else if (rc.solver->residual_object != nullptr)
251 
252  else
253  libmesh_error_msg("Error! Unable to compute residual for forming finite difference Jacobian!");
254 
255  // Synchronize PETSc x to local solution since the local solution may be changed due to the constraints
256  PetscVector<Number> & X_sys = *cast_ptr<PetscVector<Number> *>(rc.sys.solution.get());
257  PetscVector<Number> X_global(x, rc.sys.comm());
258 
259  X_global.swap(X_sys);
260  rc.sys.update();
261  X_global.swap(X_sys);
262 
263  R.close();
264 
266  {
268  R.close();
269  }
270 
271  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
272  }
273 
274  //----------------------------------------------------------------
275  // this function is called by PETSc to approximate Jacobian-vector
276  // products at X via finite differences
277  PetscErrorCode
278  libmesh_petsc_snes_mffd_residual (SNES snes, Vec x, Vec r, void * ctx)
279  {
280  PetscFunctionBegin;
281 
283 
284  libmesh_parallel_only(rc.sys.comm());
285 
286  libmesh_assert(r);
287  PetscVector<Number> R(r, rc.sys.comm());
288 
289  if (rc.solver->_zero_out_residual)
290  R.zero();
291 
292  if (rc.solver->mffd_residual_object != nullptr)
294 
295  else if (rc.solver->residual_object != nullptr)
297 
298  else
299  libmesh_error_msg("Error! Unable to compute residual for forming finite differenced"
300  "Jacobian-vector products!");
301 
302  // Synchronize PETSc x to local solution since the local solution may be changed due to the constraints
303  PetscVector<Number> & X_sys = *cast_ptr<PetscVector<Number> *>(rc.sys.solution.get());
304  PetscVector<Number> X_global(x, rc.sys.comm());
305 
306  X_global.swap(X_sys);
307  rc.sys.update();
308  X_global.swap(X_sys);
309 
310  R.close();
311 
313  {
315  R.close();
316  }
317 
318  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
319  }
320 
321  //----------------------------------------------------------
322  // this function serves an interface between the petsc layer
323  // and the actual mffd residual computing routine
324  PetscErrorCode
325  libmesh_petsc_snes_mffd_interface (void * ctx, Vec x, Vec r)
326  {
327  PetscFunctionBegin;
328 
329  // No way to safety-check this cast, since we got a void *...
331  static_cast<PetscNonlinearSolver<Number> *> (ctx);
332 
333  LibmeshPetscCall2(solver->comm(), libmesh_petsc_snes_mffd_residual(solver->snes(), x, r, ctx));
334 
335 #if !PETSC_VERSION_LESS_THAN(3,8,4)
336 #ifndef NDEBUG
337 
338  // When the user requested to reuse the nonlinear residual as the base for doing matrix-free
339  // approximation of the Jacobian, we'll do a sanity check to make sure that that was safe to do
340  if (solver->snes_mf_reuse_base() && (solver->comm().size() == 1) && (libMesh::n_threads() == 1))
341  {
342  SNES snes = solver->snes();
343 
344  KSP ksp;
345  LibmeshPetscCall2(solver->comm(), SNESGetKSP(snes, &ksp));
346 
347  PetscInt ksp_it;
348  LibmeshPetscCall2(solver->comm(), KSPGetIterationNumber(ksp, &ksp_it));
349 
350  SNESType snes_type;
351  LibmeshPetscCall2(solver->comm(), SNESGetType(snes, &snes_type));
352 
353  libmesh_assert_msg(snes_type, "We're being called from SNES; snes_type should be non-null");
354 
355  Mat J;
356  LibmeshPetscCall2(solver->comm(), SNESGetJacobian(snes, &J, NULL, NULL, NULL));
357  libmesh_assert_msg(J, "We're being called from SNES; J should be non-null");
358 
359  MatType mat_type;
360  LibmeshPetscCall2(solver->comm(), MatGetType(J, &mat_type));
361  libmesh_assert_msg(mat_type, "We're being called from SNES; mat_type should be non-null");
362 
363  bool is_operator_mffd = strcmp(mat_type, MATMFFD) == 0;
364 
365  if ((ksp_it == PetscInt(0)) && is_operator_mffd)
366  {
367  bool computing_base_vector = solver->computing_base_vector();
368 
369  if (computing_base_vector)
370  {
371  Vec nonlinear_residual;
372 
373  LibmeshPetscCall2(solver->comm(), SNESGetFunction(snes, &nonlinear_residual, NULL, NULL));
374 
375  PetscBool vecs_equal;
376  LibmeshPetscCall2(solver->comm(), VecEqual(r, nonlinear_residual, &vecs_equal));
377 
378  libmesh_error_msg_if(!(vecs_equal == PETSC_TRUE),
379  "You requested to reuse the nonlinear residual vector as the base vector for "
380  "computing the action of the matrix-free Jacobian, but the vectors are not "
381  "the same. Your physics must have states; either remove the states "
382  "from your code or make sure that you set_mf_reuse_base(false)");
383  }
384 
385  // There are always exactly two function evaluations for the zeroth ksp iteration when doing
386  // matrix-free approximation of the Jacobian action: one corresponding to the evaluation of
387  // the base vector, and the other corresponding to evaluation of the perturbed vector. So we
388  // toggle back and forth between states
389  solver->set_computing_base_vector(!computing_base_vector);
390  }
391  }
392 #endif
393 #endif
394 
395  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
396  }
397 
398  //---------------------------------------------------------------
399  // this function is called by PETSc to evaluate the Jacobian at X
400  PetscErrorCode
401  libmesh_petsc_snes_jacobian(SNES snes, Vec x, Mat jac, Mat pc, void * ctx)
402  {
403  PetscFunctionBegin;
404 
405  LOG_SCOPE("jacobian()", "PetscNonlinearSolver");
406 
408 
409  // No way to safety-check this cast, since we got a void *...
411  static_cast<PetscNonlinearSolver<Number> *> (ctx);
412 
413  libmesh_parallel_only(solver->comm());
414 
415  // Get the current iteration number from the snes object,
416  // store it in the PetscNonlinearSolver object for possible use
417  // by the user's Jacobian function.
418  {
419  PetscInt n_iterations = 0;
420  LibmeshPetscCall2(solver->comm(), SNESGetIterationNumber(snes, &n_iterations));
421  solver->_current_nonlinear_iteration_number = cast_int<unsigned>(n_iterations);
422  }
423 
424  //-----------------------------------------------------------------------------
425  // if the user has provided both function pointers and objects only the pointer
426  // will be used, so catch that as an error
427  libmesh_error_msg_if(solver->jacobian && solver->jacobian_object,
428  "ERROR: cannot specify both a function and object to compute the Jacobian!");
429 
430  libmesh_error_msg_if(solver->matvec && solver->residual_and_jacobian_object,
431  "ERROR: cannot specify both a function and object to compute the combined Residual & Jacobian!");
432 
433  NonlinearImplicitSystem & sys = solver->system();
434 
435  PetscMatrixBase<Number> * const PC = pc ? PetscMatrixBase<Number>::get_context(pc, sys.comm()) : nullptr;
436  PetscMatrixBase<Number> * Jac = jac ? PetscMatrixBase<Number>::get_context(jac, sys.comm()) : nullptr;
437  PetscVector<Number> & X_sys = *cast_ptr<PetscVector<Number> *>(sys.solution.get());
438  PetscVector<Number> X_global(x, sys.comm());
439 
440  PetscMFFDMatrix<Number> mffd_jac(sys.comm());
441  PetscBool p_is_shell = PETSC_FALSE;
442  PetscBool j_is_mffd = PETSC_FALSE;
443  PetscBool j_is_shell = PETSC_FALSE;
444  if (pc)
445  LibmeshPetscCall2(sys.comm(), PetscObjectTypeCompare((PetscObject)pc, MATSHELL, &p_is_shell));
446  libmesh_assert(jac);
447  LibmeshPetscCall2(sys.comm(), PetscObjectTypeCompare((PetscObject)jac, MATMFFD, &j_is_mffd));
448  LibmeshPetscCall2(sys.comm(), PetscObjectTypeCompare((PetscObject)jac, MATSHELL, &j_is_shell));
449  if (j_is_mffd == PETSC_TRUE)
450  {
451  libmesh_assert(!Jac);
452  Jac = &mffd_jac;
453  mffd_jac = jac;
454  }
455 
456  // We already computed the Jacobian during the residual evaluation
457  if (solver->residual_and_jacobian_object)
458  {
459  // We could be doing matrix-free in which case we cannot rely on closing of explicit matrices
460  // that occurs during the PETSc residual callback
461  if ((j_is_shell == PETSC_TRUE) || (j_is_mffd == PETSC_TRUE))
462  Jac->close();
463 
464  if (pc && (p_is_shell == PETSC_TRUE))
465  PC->close();
466 
467  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
468  }
469 
470  // Set the dof maps
471  PC->attach_dof_map(sys.get_dof_map());
472  Jac->attach_dof_map(sys.get_dof_map());
473 
474  // Use the systems update() to get a good local version of the parallel solution
475  X_global.swap(X_sys);
476  sys.update();
477  X_global.swap(X_sys);
478 
479  // Enforce constraints (if any) exactly on the
480  // current_local_solution. This is the solution vector that is
481  // actually used in the computation of the residual below, and is
482  // not locked by debug-enabled PETSc the way that "x" is.
483  if (solver->_exact_constraint_enforcement)
485 
486  if (solver->_zero_out_jacobian)
487  PC->zero();
488 
489 
490  if (solver->jacobian != nullptr)
491  solver->jacobian(*sys.current_local_solution.get(), *PC, sys);
492 
493  else if (solver->jacobian_object != nullptr)
494  solver->jacobian_object->jacobian(*sys.current_local_solution.get(), *PC, sys);
495 
496  else if (solver->matvec != nullptr)
497  solver->matvec(*sys.current_local_solution.get(), nullptr, PC, sys);
498 
499  else
500  libmesh_error_msg("Error! Unable to compute residual and/or Jacobian!");
501 
502  PC->close();
503  if (solver->_exact_constraint_enforcement)
504  {
506  PC->close();
507  }
508 
509  if (Jac != PC)
510  {
511  // Assume that shells know what they're doing
512  libmesh_assert(!solver->_exact_constraint_enforcement || (j_is_mffd == PETSC_TRUE) ||
513  (j_is_shell == PETSC_TRUE));
514  Jac->close();
515  }
516 
517  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
518  }
519 
520  // This function gets called by PETSc in place of the standard Petsc line searches
521  // if a linesearch object is supplied to the PetscNonlinearSolver class. It wraps
522  // the linesearch algorithm implemented on the linesearch object.
523  // * "linesearch" is an object that can be used to access the non-linear and linear solution
524  // vectors as well as the residual and SNES object
525  // * "ctx" is the PetscNonlinearSolver context
526  PetscErrorCode libmesh_petsc_linesearch_shellfunc (SNESLineSearch linesearch, void * ctx)
527  {
528  PetscFunctionBegin;
529 
530  // No way to safety-check this cast, since we got a void *...
532  static_cast<PetscNonlinearSolver<Number> *> (ctx);
533 
534  libmesh_parallel_only(solver->comm());
535 
536  solver->linesearch_object->linesearch(linesearch);
537  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
538  }
539 
540  // This function gets called by PETSc after the SNES linesearch is
541  // complete. We use it to exactly enforce any constraints on the
542  // solution which may have drifted during the linear solve. In the
543  // PETSc nomenclature:
544  // * "x" is the old solution vector,
545  // * "y" is the search direction (Newton step) vector,
546  // * "w" is the candidate solution vector, and
547  // the user is responsible for setting changed_y and changed_w
548  // appropriately, depending on whether or not the search
549  // direction or solution vector was changed, respectively.
550  PetscErrorCode libmesh_petsc_snes_postcheck(SNESLineSearch, Vec x, Vec y, Vec w, PetscBool * changed_y, PetscBool * changed_w, void * context)
551  {
552  PetscFunctionBegin;
553 
554  LOG_SCOPE("postcheck()", "PetscNonlinearSolver");
555 
556  // PETSc almost certainly initializes these to false already, but
557  // it doesn't hurt to be explicit.
558  *changed_w = PETSC_FALSE;
559  *changed_y = PETSC_FALSE;
560 
561  libmesh_assert(context);
562 
563  // Cast the context to a NonlinearSolver object.
565  static_cast<PetscNonlinearSolver<Number> *> (context);
566 
567  libmesh_parallel_only(solver->comm());
568 
569  // If the user has provided both postcheck function pointer and
570  // object, this is ambiguous, so throw an error.
571  libmesh_error_msg_if(solver->postcheck && solver->postcheck_object,
572  "ERROR: cannot specify both a function and object for performing the solve postcheck!");
573 
574  // It's also possible that we don't need to do anything at all, in
575  // that case return early...
576  NonlinearImplicitSystem & sys = solver->system();
577 
578  if (!solver->postcheck && !solver->postcheck_object)
579  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
580 
581  // We definitely need to wrap at least "w"
582  PetscVector<Number> petsc_w(w, sys.comm());
583 
584  // The user sets these flags in his/her postcheck function to
585  // indicate whether they changed something.
586  bool
587  changed_search_direction = false,
588  changed_new_soln = false;
589 
590  if (solver->postcheck || solver->postcheck_object)
591  {
592  PetscVector<Number> petsc_x(x, sys.comm());
593  PetscVector<Number> petsc_y(y, sys.comm());
594 
595  if (solver->postcheck)
596  solver->postcheck(petsc_x,
597  petsc_y,
598  petsc_w,
599  changed_search_direction,
600  changed_new_soln,
601  sys);
602 
603  else if (solver->postcheck_object)
604  solver->postcheck_object->postcheck(petsc_x,
605  petsc_y,
606  petsc_w,
607  changed_search_direction,
608  changed_new_soln,
609  sys);
610  }
611 
612  // Record whether the user changed the solution or the search direction.
613  if (changed_search_direction)
614  *changed_y = PETSC_TRUE;
615 
616  if (changed_new_soln)
617  *changed_w = PETSC_TRUE;
618 
619  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
620  }
621 
622  PetscErrorCode libmesh_petsc_snes_precheck(SNESLineSearch, Vec X, Vec Y, PetscBool * changed, void * context)
623  {
624  PetscFunctionBegin;
625 
626  LOG_SCOPE("precheck()", "PetscNonlinearSolver");
627 
628  // PETSc almost certainly initializes these to false already, but
629  // it doesn't hurt to be explicit.
630  *changed = PETSC_FALSE;
631 
632  libmesh_assert(context);
633 
634  // Cast the context to a NonlinearSolver object.
636  static_cast<PetscNonlinearSolver<Number> *> (context);
637 
638  libmesh_parallel_only(solver->comm());
639 
640  // It's possible that we don't need to do anything at all, in
641  // that case return early...
642  if (!solver->precheck_object)
643  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
644 
645  // The user sets these flags in his/her postcheck function to
646  // indicate whether they changed something.
647  bool
648  petsc_changed = false;
649 
650  auto & sys = solver->system();
651  auto & x_sys = *cast_ptr<PetscVector<Number> *>(sys.solution.get());
652  PetscVector<Number> petsc_x(X, sys.comm());
653  PetscVector<Number> petsc_y(Y, sys.comm());
654 
655  // Use the systems update() to get a good local version of the parallel solution
656  petsc_x.swap(x_sys);
657  sys.update();
658  petsc_x.swap(x_sys);
659 
660  // Enforce constraints (if any) exactly on the
661  // current_local_solution. This is the solution vector that is
662  // actually used in the computation of residuals and Jacobians, and is
663  // not locked by debug-enabled PETSc the way that "x" is.
664  libmesh_assert(sys.current_local_solution.get());
665  auto & local_soln = *sys.current_local_solution.get();
666  if (solver->_exact_constraint_enforcement)
667  sys.get_dof_map().enforce_constraints_exactly(sys, &local_soln);
668 
669  solver->precheck_object->precheck(local_soln,
670  petsc_y,
671  petsc_changed,
672  sys);
673 
674  // Record whether the user changed the solution or the search direction.
675  if (petsc_changed)
676  *changed = PETSC_TRUE;
677 
678  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
679  }
680 
681 } // end extern "C"
682 
683 
684 
685 //---------------------------------------------------------------------
686 // PetscNonlinearSolver<> methods
687 template <typename T>
689  NonlinearSolver<T>(system_in),
690  linesearch_object(nullptr),
691  _reason(SNES_CONVERGED_ITERATING/*==0*/), // Arbitrary initial value...
692  _n_linear_iterations(0),
693  _current_nonlinear_iteration_number(0),
694  _zero_out_residual(true),
695  _zero_out_jacobian(true),
696  _default_monitor(true),
697  _snesmf_reuse_base(true),
698  _computing_base_vector(true),
699  _setup_reuse(false),
700  _mffd_jac(this->_communicator)
701 {
702 }
703 
704 
705 
706 template <typename T>
708 
709 
710 
711 template <typename T>
713 {
714  if (this->initialized())
715  {
716  this->_is_initialized = false;
717 
718  // If we don't need the preconditioner next time
719  // retain the original behavior of clearing the data
720  // between solves.
721  if (!(reuse_preconditioner()))
722  {
723  // SNESReset really ought to work but replacing destroy() with
724  // SNESReset causes a very slight change in behavior that
725  // manifests as two failed MOOSE tests...
726  _snes.destroy();
727  }
728 
729  // Reset the nonlinear iteration counter. This information is only relevant
730  // *during* the solve(). After the solve is completed it should return to
731  // the default value of 0.
732  _current_nonlinear_iteration_number = 0;
733  }
734 }
735 
736 template <typename T>
738 {
739  parallel_object_only();
740 
741  // Initialize the data structures if not done so already.
742  if (!this->initialized())
743  {
744  this->_is_initialized = true;
745 
746  // Make only if we don't already have a retained snes
747  // hanging around from the last solve
748  if (!_snes)
749  LibmeshPetscCall(SNESCreate(this->comm().get(), _snes.get()));
750 
751  // I believe all of the following can be safely repeated
752  // even on an old snes instance from the last solve
753 
754  if (name)
755  {
756  libmesh_assert(std::string(name).front() != '-');
757  libmesh_assert(std::string(name).back() == '_');
758  LibmeshPetscCall(SNESSetOptionsPrefix(_snes, name));
759  }
760 
761  // Attaching a DM to SNES.
762 #if defined(LIBMESH_ENABLE_AMR) && defined(LIBMESH_HAVE_METAPHYSICL)
763  bool use_petsc_dm = libMesh::on_command_line(
764  "--" + (name ? std::string(name) : std::string("")) + "use_petsc_dm");
765 
766  // This needs to be called before SNESSetFromOptions
767  if (use_petsc_dm)
768  this->_dm_wrapper.init_and_attach_petscdm(this->system(), _snes);
769  else
770 #endif
771  {
772  WrappedPetsc<DM> dm;
773  LibmeshPetscCall(DMCreate(this->comm().get(), dm.get()));
774  LibmeshPetscCall(DMSetType(dm, DMLIBMESH));
775  LibmeshPetscCall(DMlibMeshSetSystem(dm, this->system()));
776 
777  if (name)
778  LibmeshPetscCall(DMSetOptionsPrefix(dm, name));
779 
780  LibmeshPetscCall(DMSetFromOptions(dm));
781  LibmeshPetscCall(DMSetUp(dm));
782  LibmeshPetscCall(SNESSetDM(_snes, dm));
783  // SNES now owns the reference to dm.
784  }
785 
786  setup_default_monitor();
787 
788  // If the SolverConfiguration object is provided, use it to set
789  // options during solver initialization.
790  if (this->_solver_configuration)
791  {
792  this->_solver_configuration->set_options_during_init();
793  }
794 
795  if (this->_preconditioner)
796  {
797  KSP ksp;
798  LibmeshPetscCall(SNESGetKSP (_snes, &ksp));
799  PC pc;
800  LibmeshPetscCall(KSPGetPC(ksp,&pc));
801 
802  this->_preconditioner->init();
803 
804  LibmeshPetscCall(PCSetType(pc, PCSHELL));
805  LibmeshPetscCall(PCShellSetContext(pc,(void *)this->_preconditioner));
806 
807  //Re-Use the shell functions from petsc_linear_solver
808  LibmeshPetscCall(PCShellSetSetUp(pc,libmesh_petsc_preconditioner_setup));
809  LibmeshPetscCall(PCShellSetApply(pc,libmesh_petsc_preconditioner_apply));
810  }
811  }
812 
813 
814  // Tell PETSc about our linesearch "post-check" function, but only
815  // if the user has provided one. There seem to be extra,
816  // unnecessary residual calculations if a postcheck function is
817  // attached for no reason.
818  if (this->postcheck || this->postcheck_object)
819  {
820  SNESLineSearch linesearch;
821  LibmeshPetscCall(SNESGetLineSearch(_snes, &linesearch));
822 
823  LibmeshPetscCall(SNESLineSearchSetPostCheck(linesearch, libmesh_petsc_snes_postcheck, this));
824  }
825 
826  if (this->precheck_object)
827  {
828  SNESLineSearch linesearch;
829  LibmeshPetscCall(SNESGetLineSearch(_snes, &linesearch));
830 
831  LibmeshPetscCall(SNESLineSearchSetPreCheck(linesearch, libmesh_petsc_snes_precheck, this));
832  }
833 }
834 
835 
836 template <typename T>
838 {
839  this->init(name);
840  return _snes;
841 }
842 
843 
844 
845 template <typename T>
846 void
848  void (*computeSubspace)(std::vector<NumericVector<Number> *> &, sys_type &),
849  MatNullSpace * msp)
850 {
851  parallel_object_only();
852 
853  std::vector<NumericVector<Number> *> sp;
854  if (computeSubspaceObject)
855  (*computeSubspaceObject)(sp, this->system());
856  else
857  (*computeSubspace)(sp, this->system());
858 
859  *msp = LIBMESH_PETSC_NULLPTR;
860  if (sp.size())
861  {
862  PetscInt nmodes = cast_int<PetscInt>(sp.size());
863 
864  std::vector<Vec> modes(nmodes);
865  std::vector<PetscScalar> dots(nmodes);
866 
867  for (PetscInt i=0; i<nmodes; ++i)
868  {
869  auto pv = cast_ptr<PetscVector<T> *>(sp[i]);
870 
871  LibmeshPetscCall(VecDuplicate(pv->vec(), &modes[i]));
872 
873  LibmeshPetscCall(VecCopy(pv->vec(), modes[i]));
874  }
875 
876  // Normalize.
877  LibmeshPetscCall(VecNormalize(modes[0], LIBMESH_PETSC_NULLPTR));
878 
879  for (PetscInt i=1; i<nmodes; i++)
880  {
881  // Orthonormalize vec[i] against vec[0:i-1]
882  LibmeshPetscCall(VecMDot(modes[i], i, modes.data(), dots.data()));
883 
884  for (PetscInt j=0; j<i; j++)
885  dots[j] *= -1.;
886 
887  LibmeshPetscCall(VecMAXPY(modes[i], i, dots.data(), modes.data()));
888 
889  LibmeshPetscCall(VecNormalize(modes[i], LIBMESH_PETSC_NULLPTR));
890  }
891 
892  LibmeshPetscCall(MatNullSpaceCreate(this->comm().get(), PETSC_FALSE, nmodes, modes.data(), msp));
893 
894  for (PetscInt i=0; i<nmodes; ++i)
895  LibmeshPetscCall(VecDestroy(&modes[i]));
896  }
897 }
898 
899 template <typename T>
900 std::pair<unsigned int, Real>
901 PetscNonlinearSolver<T>::solve (SparseMatrix<T> & pre_in, // System Preconditioning Matrix
902  NumericVector<T> & x_in, // Solution vector
903  NumericVector<T> & r_in, // Residual vector
904  const double, // Stopping tolerance
905  const unsigned int)
906 {
907  parallel_object_only();
908 
909  LOG_SCOPE("solve()", "PetscNonlinearSolver");
910  this->init ();
911 
912  // Make sure the data passed in are really of Petsc types
913  PetscMatrixBase<T> * pre = cast_ptr<PetscMatrixBase<T> *>(&pre_in);
914  PetscVector<T> * x = cast_ptr<PetscVector<T> *>(&x_in);
915  PetscVector<T> * r = cast_ptr<PetscVector<T> *>(&r_in);
916 
917  PetscInt n_iterations =0;
918  // Should actually be a PetscReal, but I don't know which version of PETSc first introduced PetscReal
919  Real final_residual_norm=0.;
920 
921  // We don't want to do this twice because it resets
922  // SNESSetLagPreconditioner
923  if ((reuse_preconditioner()) && (!_setup_reuse))
924  {
925  _setup_reuse = true;
926  LibmeshPetscCall(SNESSetLagPreconditionerPersists(_snes, PETSC_TRUE));
927  // According to the PETSC 3.16.5 docs -2 is a magic number which
928  // means "recalculate the next time you need it and then not again"
929  LibmeshPetscCall(SNESSetLagPreconditioner(_snes, -2));
930  // Add in our callback which will trigger recalculating
931  // the preconditioner when we hit reuse_preconditioner_max_linear_its
932  LibmeshPetscCall(SNESMonitorSet(_snes, &libmesh_petsc_recalculate_monitor,
933  this,
934  NULL));
935  }
936  else if (!(reuse_preconditioner()))
937  // This covers the case where it was enabled but was then disabled
938  {
939  LibmeshPetscCall(SNESSetLagPreconditionerPersists(_snes, PETSC_FALSE));
940  if (_setup_reuse)
941  {
942  _setup_reuse = false;
943  LibmeshPetscCall(SNESMonitorCancel(_snes));
944  // Readd default monitor
945  setup_default_monitor();
946  }
947  }
948 
949  LibmeshPetscCall(SNESSetFunction (_snes, r->vec(), libmesh_petsc_snes_residual, this));
950 
951  // Only set the jacobian function if we've been provided with something to call.
952  // This allows a user to set their own jacobian function if they want to
953  if (this->jacobian || this->jacobian_object || this->residual_and_jacobian_object)
954  LibmeshPetscCall(SNESSetJacobian (_snes, pre->mat(), pre->mat(), libmesh_petsc_snes_jacobian, this));
955 
956  // Have the Krylov subspace method use our good initial guess rather than 0
957  KSP ksp;
958  LibmeshPetscCall(SNESGetKSP (_snes, &ksp));
959 
960  // Set the tolerances for the iterative solver. Use the user-supplied
961  // tolerance for the relative residual & leave the others at default values
962  LibmeshPetscCall(KSPSetTolerances (ksp, this->initial_linear_tolerance, PETSC_DEFAULT,
963  PETSC_DEFAULT, this->max_linear_iterations));
964 
965  // Set the tolerances for the non-linear solver.
966  LibmeshPetscCall(SNESSetTolerances(_snes,
967  this->absolute_residual_tolerance,
968  this->relative_residual_tolerance,
969  this->relative_step_tolerance,
970  this->max_nonlinear_iterations,
971  this->max_function_evaluations));
972 
973  // Not supported by PETSc
974  if (this->absolute_step_tolerance != 0) // 0 is default value, both in MOOSE and libMesh
975  libmesh_warning("Setting the absolute step tolerance is not supported with the PETSc nonlinear solver.");
976 
977  // Set the divergence tolerance for the non-linear solver
978 #if !PETSC_VERSION_LESS_THAN(3,8,0)
979  LibmeshPetscCall(SNESSetDivergenceTolerance(_snes, this->divergence_tolerance));
980 #endif
981 
982  //Pull in command-line options
983 #if PETSC_VERSION_LESS_THAN(3,7,0)
984  LibmeshPetscCall(KSPSetFromOptions(ksp));
985 #endif
986  LibmeshPetscCall(SNESSetFromOptions(_snes));
987 
988  PC pc;
989  LibmeshPetscCall(KSPGetPC(ksp, &pc));
990  PetscPreconditioner<T>::set_petsc_aux_data(pc, this->system());
991 
992 #if defined(LIBMESH_HAVE_PETSC_HYPRE) && PETSC_VERSION_LESS_THAN(3, 23, 0) && \
993  !PETSC_VERSION_LESS_THAN(3, 12, 0) && defined(PETSC_HAVE_HYPRE_DEVICE)
994  {
995  // Make sure hypre has been initialized
996  LibmeshPetscCallExternal(HYPRE_Initialize);
997  PetscScalar * dummyarray;
998  PetscMemType mtype;
999  LibmeshPetscCall(VecGetArrayAndMemType(x->vec(), &dummyarray, &mtype));
1000  LibmeshPetscCall(VecRestoreArrayAndMemType(x->vec(), &dummyarray));
1001  if (PetscMemTypeHost(mtype))
1002  LibmeshPetscCallExternal(HYPRE_SetMemoryLocation, HYPRE_MEMORY_HOST);
1003  }
1004 #endif
1005 
1006  if (this->user_presolve)
1007  this->user_presolve(this->system());
1008 
1009  //Set the preconditioning matrix
1010  if (this->_preconditioner)
1011  {
1012  this->_preconditioner->set_matrix(pre_in);
1013  this->_preconditioner->init();
1014  }
1015 
1016  // If the SolverConfiguration object is provided, use it to override
1017  // solver options.
1018  if (this->_solver_configuration)
1019  this->_solver_configuration->configure_solver();
1020 
1021  // In PETSc versions before 3.5.0, it is not possible to call
1022  // SNESSetUp() before the solution and rhs vectors are initialized, as
1023  // this triggers the
1024  //
1025  // "Solution vector cannot be right hand side vector!"
1026  //
1027  // error message. It is also not possible to call SNESSetSolution()
1028  // in those versions of PETSc to work around the problem, since that
1029  // API was removed in 3.0.0 and only restored in 3.6.0. The
1030  // overzealous check was moved out of SNESSetUp in PETSc 3.5.0
1031  // (petsc/petsc@154060b), so this code block should be safe to use
1032  // in 3.5.0 and later.
1033 #if !PETSC_VERSION_LESS_THAN(3,6,0)
1034  LibmeshPetscCall(SNESSetSolution(_snes, x->vec()));
1035 #endif
1036  LibmeshPetscCall(SNESSetUp(_snes));
1037 
1038  Mat J, P;
1039  LibmeshPetscCall(SNESGetJacobian(_snes, &J, &P,
1040  LIBMESH_PETSC_NULLPTR,
1041  LIBMESH_PETSC_NULLPTR));
1042  LibmeshPetscCall(MatMFFDSetFunction(J, libmesh_petsc_snes_mffd_interface, this));
1043 #if !PETSC_VERSION_LESS_THAN(3,8,4)
1044 #ifndef NDEBUG
1045  // If we're in debug mode, do not reuse the nonlinear function evaluation as the base for doing
1046  // matrix-free approximations of the Jacobian action. Instead if the user requested that we reuse
1047  // the base, we'll check the base function evaluation and compare it to the nonlinear residual
1048  // evaluation. If they are different, then we'll error and inform the user that it's unsafe to
1049  // reuse the base
1050  LibmeshPetscCall(MatSNESMFSetReuseBase(J, PETSC_FALSE));
1051 #else
1052  // Resue the residual vector from SNES
1053  LibmeshPetscCall(MatSNESMFSetReuseBase(J, static_cast<PetscBool>(_snesmf_reuse_base)));
1054 #endif
1055 #endif
1056 
1057  // Only set the nullspace if we have a way of computing it and the result is non-empty.
1058  if (this->nullspace || this->nullspace_object)
1059  {
1061  this->build_mat_null_space(this->nullspace_object, this->nullspace, msp.get());
1062  if (msp)
1063  {
1064  LibmeshPetscCall(MatSetNullSpace(J, msp));
1065  if (P != J)
1066  LibmeshPetscCall(MatSetNullSpace(P, msp));
1067  }
1068  }
1069 
1070  // Only set the transpose nullspace if we have a way of computing it and the result is non-empty.
1071  if (this->transpose_nullspace || this->transpose_nullspace_object)
1072  {
1073 #if PETSC_VERSION_LESS_THAN(3,6,0)
1074  libmesh_warning("MatSetTransposeNullSpace is only supported for PETSc >= 3.6, transpose nullspace will be ignored.");
1075 #else
1077  this->build_mat_null_space(this->transpose_nullspace_object, this->transpose_nullspace, msp.get());
1078  if (msp)
1079  {
1080  LibmeshPetscCall(MatSetTransposeNullSpace(J, msp));
1081  if (P != J)
1082  LibmeshPetscCall(MatSetTransposeNullSpace(P, msp));
1083  }
1084 #endif
1085  }
1086 
1087  // Only set the nearnullspace if we have a way of computing it and the result is non-empty.
1088  if (this->nearnullspace || this->nearnullspace_object)
1089  {
1091  this->build_mat_null_space(this->nearnullspace_object, this->nearnullspace, msp.get());
1092 
1093  if (msp)
1094  {
1095  LibmeshPetscCall(MatSetNearNullSpace(J, msp));
1096  if (P != J)
1097  LibmeshPetscCall(MatSetNearNullSpace(P, msp));
1098  }
1099  }
1100 
1101  SNESLineSearch linesearch;
1102  if (linesearch_object)
1103  {
1104  LibmeshPetscCall(SNESGetLineSearch(_snes, &linesearch));
1105  LibmeshPetscCall(SNESLineSearchSetType(linesearch, SNESLINESEARCHSHELL));
1106 #if PETSC_RELEASE_GREATER_EQUALS(3, 21, 0)
1107  LibmeshPetscCall(SNESLineSearchShellSetApply(linesearch, libmesh_petsc_linesearch_shellfunc, this));
1108 #else
1109  LibmeshPetscCall(SNESLineSearchShellSetUserFunc(linesearch, libmesh_petsc_linesearch_shellfunc, this));
1110 #endif
1111  }
1112 
1113  LibmeshPetscCall(SNESSolve (_snes, LIBMESH_PETSC_NULLPTR, x->vec()));
1114 
1115  LibmeshPetscCall(SNESGetIterationNumber(_snes, &n_iterations));
1116 
1117  LibmeshPetscCall(SNESGetLinearSolveIterations(_snes, &_n_linear_iterations));
1118 
1119  // SNESGetFunction has been around forever and should work on all
1120  // versions of PETSc. This is also now the recommended approach
1121  // according to the documentation for the PETSc 3.5.1 release:
1122  // http://www.mcs.anl.gov/petsc/documentation/changes/35.html
1123  Vec f;
1124  LibmeshPetscCall(SNESGetFunction(_snes, &f, 0, 0));
1125  LibmeshPetscCall(VecNorm(f, NORM_2, pPR(&final_residual_norm)));
1126 
1127  // Get and store the reason for convergence
1128  LibmeshPetscCall(SNESGetConvergedReason(_snes, &_reason));
1129 
1130  //Based on Petsc 2.3.3 documentation all diverged reasons are negative
1131  this->converged = (_reason >= 0);
1132 
1133  // Reset data structure
1134  this->clear();
1135 
1136  // return the # of its. and the final residual norm.
1137  return std::make_pair(n_iterations, final_residual_norm);
1138 }
1139 
1140 
1141 
1142 template <typename T>
1144 {
1145 
1146  libMesh::out << "Nonlinear solver convergence/divergence reason: "
1147  << SNESConvergedReasons[this->get_converged_reason()] << std::endl;
1148 }
1149 
1150 
1151 
1152 template <typename T>
1154 {
1155  if (this->initialized())
1156  LibmeshPetscCall(SNESGetConvergedReason(_snes, &_reason));
1157 
1158  return _reason;
1159 }
1160 
1161 template <typename T>
1163 {
1164  return _n_linear_iterations;
1165 }
1166 
1167 template <typename T>
1169 {
1170  if (_default_monitor)
1171  LibmeshPetscCall(
1172  SNESMonitorSet(_snes, libmesh_petsc_snes_monitor, this, LIBMESH_PETSC_NULLPTR));
1173 }
1174 
1175 template <typename T>
1177 {
1178  return this->_reuse_preconditioner;
1179 }
1180 
1181 template <typename T>
1183 {
1184  return this->_reuse_preconditioner_max_linear_its;
1185 }
1186 
1187 template <typename T>
1189 {
1190  // Easiest way is just to clear everything out
1191  this->_is_initialized = false;
1192  _snes.destroy();
1193  _setup_reuse = false;
1194 }
1195 
1196 //------------------------------------------------------------------
1197 // Explicit instantiations
1198 template class LIBMESH_EXPORT PetscNonlinearSolver<Number>;
1199 
1200 } // namespace libMesh
1201 
1202 
1203 
1204 #endif // #ifdef LIBMESH_HAVE_PETSC
unsigned _current_nonlinear_iteration_number
Stores the current nonlinear iteration number.
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
Definition: elem_quality.C:42
PetscNonlinearSolver< Number > * solver
SNES snes(const char *name=nullptr)
PetscReal * pPR(T *ptr)
Definition: petsc_macro.h:186
This class provides a nice interface to PETSc&#39;s Vec object.
Definition: petsc_vector.h:73
void(* residual)(const NumericVector< Number > &X, NumericVector< Number > &R, sys_type &S)
Function that computes the residual R(X) of the nonlinear system at the input iterate X...
This class provides an interface to the suite of preconditioners available from PETSc.
virtual unsigned int reuse_preconditioner_max_linear_its() const override
Getter for the maximum iterations flag for preconditioner reuse.
NonlinearImplicitSystem::ComputeResidualandJacobian * residual_and_jacobian_object
Object that computes either the residual or the Jacobian of the nonlinear system at the input itera...
unsigned int n_threads()
Definition: libmesh_base.h:109
virtual void residual(const NumericVector< Number > &X, NumericVector< Number > &R, sys_type &S)=0
Residual function.
PetscErrorCode libmesh_petsc_snes_fd_residual(SNES, Vec x, Vec r, void *ctx)
virtual void zero() override
Set all entries to zero.
Definition: petsc_vector.h:954
PetscNonlinearSolver(sys_type &system)
Constructor.
PETSC_EXTERN PetscErrorCode DMlibMeshSetSystem(DM, libMesh::NonlinearImplicitSystem &)
Any functional implementation of the DMlibMesh API must compose the following functions with the DM o...
NonlinearImplicitSystem & sys
PetscErrorCode libmesh_petsc_preconditioner_apply(PC, Vec x, Vec y)
This function is called by PETSc to actually apply the preconditioner.
const Parallel::Communicator & comm() const
This base class can be inherited from to provide interfaces to nonlinear solvers from different packa...
static PetscMatrixBase< T > * get_context(Mat mat, const TIMPI::Communicator &comm)
PetscErrorCode libmesh_petsc_snes_postcheck(SNESLineSearch, Vec x, Vec y, Vec w, PetscBool *changed_y, PetscBool *changed_w, void *context)
bool _zero_out_residual
true to zero out residual before going into application level call-back, otherwise false ...
The libMesh namespace provides an interface to certain functionality in the library.
NonlinearImplicitSystem::ComputeResidual * residual_object
Object that computes the residual R(X) of the nonlinear system at the input iterate X...
void(* jacobian)(const NumericVector< Number > &X, SparseMatrix< Number > &J, sys_type &S)
Function that computes the Jacobian J(X) of the nonlinear system at the input iterate X...
PetscErrorCode libmesh_petsc_snes_monitor(SNES, PetscInt its, PetscReal fnorm, void *)
virtual void postcheck(const NumericVector< Number > &old_soln, NumericVector< Number > &search_direction, NumericVector< Number > &new_soln, bool &changed_search_direction, bool &changed_new_soln, sys_type &S)=0
This interface, which is inspired by PETSc&#39;s, passes the user: .) A constant reference to the "old" s...
virtual void swap(NumericVector< T > &v) override
Swaps the contents of this with v.
Generic sparse matrix.
Definition: vector_fe_ex5.C:46
PetscErrorCode libmesh_petsc_snes_mffd_residual(SNES snes, Vec x, Vec r, void *ctx)
void enforce_constraints_on_residual(const NonlinearImplicitSystem &system, NumericVector< Number > *rhs, NumericVector< Number > const *solution, bool homogeneous=true) const
Definition: dof_map.h:2527
processor_id_type size() const
const sys_type & system() const
NonlinearImplicitSystem::ComputeJacobian * jacobian_object
Object that computes the Jacobian J(X) of the nonlinear system at the input iterate X...
virtual void zero()=0
Set all entries to 0.
bool _is_initialized
Flag that tells if init() has been called.
Definition: libmesh.C:305
bool _zero_out_jacobian
true to zero out jacobian before going into application level call-back, otherwise false ...
bool _exact_constraint_enforcement
Whether we should enforce exact constraints globally during a solve.
virtual void jacobian(const NumericVector< Number > &X, SparseMatrix< Number > &J, sys_type &S)=0
Jacobian function.
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition: system.h:1655
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
libmesh_assert(ctx)
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and non-linear solv...
ResidualContext(PetscNonlinearSolver< Number > *solver_in, NonlinearImplicitSystem &sys_in)
ResidualContext libmesh_petsc_snes_residual_helper(SNES snes, Vec x, void *ctx)
virtual void close() override
Calls the SparseMatrix&#39;s internal assembly routines, ensuring that the values are consistent across p...
PetscErrorCode libmesh_petsc_snes_mffd_interface(void *ctx, Vec x, Vec r)
void attach_dof_map(const DofMap &dof_map)
Set a pointer to the DofMap to use.
virtual void update()
Update the local values to reflect the solution on neighboring processors.
Definition: system.C:498
PetscErrorCode libmesh_petsc_preconditioner_setup(PC)
This function is called by PETSc to initialize the preconditioner.
PetscErrorCode libmesh_petsc_linesearch_shellfunc(SNESLineSearch linesearch, void *ctx)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::unique_ptr< ComputeLineSearchObject > linesearch_object
A callable object that can be used to specify a custom line-search.
NonlinearImplicitSystem::ComputePostCheck * postcheck_object
A callable object that is executed after each nonlinear iteration.
PetscErrorCode libmesh_petsc_snes_jacobian(SNES, Vec x, Mat jac, Mat pc, void *ctx)
PetscErrorCode libmesh_petsc_snes_precheck(SNESLineSearch, Vec X, Vec Y, PetscBool *changed, void *context)
OStreamProxy out
virtual void precheck(const NumericVector< Number > &precheck_soln, NumericVector< Number > &search_direction, bool &changed, sys_type &S)=0
Abstract precheck method that users must override.
NonlinearImplicitSystem::ComputeResidual * mffd_residual_object
Object that computes the residual R(X) of the nonlinear system at the input iterate X for the purpose...
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
Definition: system.h:1667
bool initialized()
Checks that library initialization has been done.
Definition: libmesh.C:324
void(* postcheck)(const NumericVector< Number > &old_soln, NumericVector< Number > &search_direction, NumericVector< Number > &new_soln, bool &changed_search_direction, bool &changed_new_soln, sys_type &S)
Function that performs a "check" on the Newton search direction and solution after each nonlinear ste...
void * ctx
bool on_command_line(std::string arg)
Definition: libmesh.C:934
NonlinearImplicitSystem::ComputePreCheck * precheck_object
PetscFunctionReturn(LIBMESH_PETSC_SUCCESS)
void set_computing_base_vector(bool computing_base_vector)
Set whether we are computing the base vector for matrix-free finite-differencing. ...
const DofMap & get_dof_map() const
Definition: system.h:2417
const SparseMatrix< Number > & get_system_matrix() const
PetscErrorCode libmesh_petsc_snes_residual(SNES, Vec x, Vec r, void *ctx)
virtual void residual_and_jacobian(const NumericVector< Number > &X, NumericVector< Number > *R, SparseMatrix< Number > *J, sys_type &S)=0
Residual & Jacobian function, calculated simultaneously.
PetscErrorCode libmesh_petsc_recalculate_monitor(SNES snes, PetscInt it, PetscReal norm, void *mctx)
void(* matvec)(const NumericVector< Number > &X, NumericVector< Number > *R, SparseMatrix< Number > *J, sys_type &S)
Function that computes either the residual or the Jacobian of the nonlinear system at the input ite...
NonlinearImplicitSystem::ComputeResidual * fd_residual_object
Object that computes the residual R(X) of the nonlinear system at the input iterate X for the purpose...
void enforce_constraints_exactly(const System &system, NumericVector< Number > *v=nullptr, bool homogeneous=false) const
Constrains the numeric vector v, which represents a solution defined on the mesh. ...
Definition: dof_map.h:2518
Callable abstract base class to be used as a callback to provide the solver with a basis for the syst...
void enforce_constraints_on_jacobian(const NonlinearImplicitSystem &system, SparseMatrix< Number > *jac) const
Definition: dof_map.h:2533