libMesh
petsc_preconditioner.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 #include "libmesh/libmesh_common.h"
19 
20 #ifdef LIBMESH_HAVE_PETSC
21 
22 // Local Includes
23 #include "libmesh/petsc_preconditioner.h"
24 #include "libmesh/petsc_macro.h"
25 #include "libmesh/petsc_matrix.h"
26 #include "libmesh/petsc_vector.h"
27 #include "libmesh/libmesh_common.h"
28 #include "libmesh/enum_preconditioner_type.h"
29 #include "libmesh/elem.h"
30 #include "libmesh/equation_systems.h"
31 #include "libmesh/dof_map.h"
32 
33 namespace libMesh
34 {
35 
36 template <typename T>
38  Preconditioner<T>(comm_in)
39 {}
40 
41 
42 
43 template <typename T>
45 {
46  PetscVector<T> & x_pvec = cast_ref<PetscVector<T> &>(const_cast<NumericVector<T> &>(x));
47  PetscVector<T> & y_pvec = cast_ref<PetscVector<T> &>(const_cast<NumericVector<T> &>(y));
48 
49  Vec x_vec = x_pvec.vec();
50  Vec y_vec = y_pvec.vec();
51 
52  LibmeshPetscCall(PCApply(_pc, x_vec, y_vec));
53 }
54 
55 
56 
57 
58 template <typename T>
60 {
61  libmesh_error_msg_if(!this->_matrix, "ERROR: No matrix set for PetscPreconditioner, but init() called");
62 
63  // Clear the preconditioner in case it has been created in the past
64  if (!this->_is_initialized)
65  {
66  // Should probably use PCReset(), but it's not working at the moment so we'll destroy instead
67  if (_pc)
68  _pc.destroy();
69 
70  LibmeshPetscCall(PCCreate(this->comm().get(), _pc.get()));
71 
72  auto pmatrix = cast_ptr<PetscMatrixBase<T> *>(this->_matrix);
73  _mat = pmatrix->mat();
74  }
75 
76  LibmeshPetscCall(PCSetOperators(_pc, _mat, _mat));
77 
78  // Set the PCType. Note: this used to be done *before* the call to
79  // PCSetOperators(), and only when !_is_initialized, but
80  // 1.) Some preconditioners (those employing sub-preconditioners,
81  // for example) have to call PCSetUp(), and can only do this after
82  // the operators have been set.
83  // 2.) It should be safe to call set_petsc_preconditioner_type()
84  // multiple times.
85  set_petsc_preconditioner_type(this->_preconditioner_type, *_pc);
86 
87  this->_is_initialized = true;
88 }
89 
90 
91 
92 template <typename T>
94 {
95  // Calls custom deleter
96  _pc.destroy();
97 }
98 
99 
100 
101 template <typename T>
103 {
104  return _pc;
105 }
106 
107 
108 
109 template <typename T>
111 {
112  // get the communicator from the PETSc object
113  Parallel::communicator comm;
114  PetscErrorCode ierr = PetscObjectGetComm((PetscObject)pc, & comm);
115  if (ierr != LIBMESH_PETSC_SUCCESS)
116  libmesh_error_msg("Error retrieving communicator");
117 
118  #define CasePCSetType(PreconditionerType, PCType) \
119  case PreconditionerType: \
120  LibmeshPetscCallA(comm, PCSetType (pc, const_cast<KSPType>(PCType))); \
121  break;
122 
123  switch (preconditioner_type)
124  {
125  CasePCSetType(IDENTITY_PRECOND, PCNONE)
126  CasePCSetType(CHOLESKY_PRECOND, PCCHOLESKY)
127  CasePCSetType(ICC_PRECOND, PCICC)
128  CasePCSetType(ILU_PRECOND, PCILU)
129  CasePCSetType(LU_PRECOND, PCLU)
130  CasePCSetType(ASM_PRECOND, PCASM)
131  CasePCSetType(JACOBI_PRECOND, PCJACOBI)
132  CasePCSetType(BLOCK_JACOBI_PRECOND, PCBJACOBI)
133  CasePCSetType(SOR_PRECOND, PCSOR)
134  CasePCSetType(EISENSTAT_PRECOND, PCEISENSTAT)
135  CasePCSetType(AMG_PRECOND, PCHYPRE)
136  CasePCSetType(SVD_PRECOND, PCSVD)
137  CasePCSetType(USER_PRECOND, PCMAT)
138  CasePCSetType(SHELL_PRECOND, PCSHELL)
139 
140  default:
141  libMesh::err << "ERROR: Unsupported PETSC Preconditioner: "
142  << Utility::enum_to_string(preconditioner_type) << std::endl
143  << "Continuing with PETSC defaults" << std::endl;
144  }
145 
146  // Set additional options if we are doing AMG and
147  // HYPRE is available
148 #ifdef LIBMESH_HAVE_PETSC_HYPRE
149  if (preconditioner_type == AMG_PRECOND)
150  LibmeshPetscCallA(comm, PCHYPRESetType(pc, "boomeramg"));
151 #endif
152 
153  // Let the commandline override stuff
154  LibmeshPetscCallA(comm, PCSetFromOptions(pc));
155 }
156 
157 
158 
159 #ifdef LIBMESH_HAVE_PETSC_HYPRE
160 template <typename T>
161 void PetscPreconditioner<T>::set_petsc_aux_data(PC & pc, System & sys, const unsigned v)
162 {
163  // Get the communicator from the PETSc object
164  Parallel::communicator comm;
165  PetscErrorCode ierr = PetscObjectGetComm((PetscObject)pc, &comm);
166  libmesh_error_msg_if(ierr != LIBMESH_PETSC_SUCCESS,
167  "Error retrieving communicator");
168 
169  // Make sure the preconditioner options are set
170  LibmeshPetscCallA(comm, PCSetFromOptions(pc));
171 
172  // Get the type of preconditioner we are using
173  PCType pc_type = nullptr;
174  LibmeshPetscCallA(comm, PCGetType(pc, &pc_type));
175 
176  // Check if hypre ams/ads, otherwise we quit with nothing to do
177  if (pc_type && std::string(pc_type) == PCHYPRE)
178  {
179  // Get the hypre preconditioner we are using
180  PCType hypre_type = nullptr;
181  LibmeshPetscCallA(comm, PCHYPREGetType(pc, &hypre_type));
182 
183  // If not ams/ads, we quit with nothing to do
184  if (std::string(hypre_type) == "ams")
185  {
186  // If multiple variables, we error out as senseless
187  libmesh_error_msg_if(sys.n_vars() > 1,
188  "Error applying hypre AMS to a system with multiple "
189  "variables");
190  // If not a 1st order Nédélec or a 2d 1st order Raviart-Thomas system, we
191  // error out as we do not support anything else at the moment
192  libmesh_error_msg_if(sys.variable(v).type() != FEType(1, NEDELEC_ONE) &&
193  (sys.variable(v).type() != FEType(1, RAVIART_THOMAS) ||
194  sys.get_mesh().mesh_dimension() != 2),
195  "Error applying hypre AMS to a system "
196  "whose variable is not 1st order Nedelec or 1st "
197  "order Raviart-Thomas on a 2d mesh");
198  set_hypre_ams_data(pc, sys, v);
199  }
200  else if (std::string(hypre_type) == "ads")
201  {
202  // If multiple variables, we error out as senseless
203  libmesh_error_msg_if(sys.n_vars() > 1,
204  "Error applying hypre ADS to a system with multiple "
205  "variables");
206  // If not a 3d 1st order Raviart-Thomas system, we error out as we do not
207  // support anything else at the moment
208  libmesh_error_msg_if(sys.variable(v).type() != FEType(1, RAVIART_THOMAS) ||
209  sys.get_mesh().mesh_dimension() != 3,
210  "Error applying hypre ADS to a system "
211  "whose variable is not 1st "
212  "order Raviart-Thomas on a 3d mesh");
213  set_hypre_ads_data(pc, sys, v);
214  }
215  }
216 }
217 
218 
219 
220 template <typename T>
221 void PetscPreconditioner<T>::set_hypre_ams_data(PC & pc, System & sys, const unsigned v)
222 {
223  // Get the communicator from the PETSc object
224  Parallel::communicator comm;
225  PetscErrorCode ierr = PetscObjectGetComm((PetscObject)pc, &comm);
226  libmesh_error_msg_if(ierr != LIBMESH_PETSC_SUCCESS,
227  "Error retrieving communicator");
228  Parallel::Communicator Comm(comm);
229 
230  // The mesh/problem dimension
231  const unsigned dim = sys.get_mesh().mesh_dimension();
232 
233  // Dummy Lagrange system defined over the same mesh so we can enumerate the vertices
234  System & lagrange_sys = sys.get_equation_systems().add_system<System>("__hypre_ams_vertices");
235  lagrange_sys.hide_output() = true;
236  lagrange_sys.add_variable("__lagrange");
237  lagrange_sys.reinit_mesh();
238 
239  // Global (i.e. total) and local (i.e. to this processor) number of edges and vertices
240  const std::vector<dof_id_type> n_all_edges = sys.get_dof_map().n_dofs_per_processor(v);
241  const dof_id_type n_glb_edges = std::accumulate(n_all_edges.begin(), n_all_edges.end(), 0);
242  const dof_id_type n_loc_edges = n_all_edges[global_processor_id()];
243  const dof_id_type n_glb_verts = lagrange_sys.n_dofs();
244  const dof_id_type n_loc_verts = lagrange_sys.n_local_dofs();
245 
246  // We require local indexing through the vertices and contiguous indexing
247  // through the edges: since the vertices are enumerated on their own system,
248  // a local index can simply be obtained by subtracting those vertices in all
249  // preceding processors; for the edges, if the system we are given by the
250  // user has multiple variables/splits, we effectively need to add local edge
251  // numbers to those edges in all preceding processors
252 
253  // The number of vertices and edges in all preceding processors
254  dof_id_signed_type vert_offset = -lagrange_sys.get_dof_map().first_dof();
255  dof_id_signed_type edge_offset =
256  std::accumulate(n_all_edges.begin(), n_all_edges.begin() + global_processor_id(), 0);
257 
258  // Whether dofs are in variable-major or node-major order
259  bool var_major = !libMesh::on_command_line("--node-major-dofs");
260 
261  // If variable-major order, we need only subtract all the preceding dofs; but
262  // if node-major order, we need to enumerate the dofs on this processor
263  std::vector<dof_id_type> idx_edges;
264  if (var_major)
265  {
266  edge_offset -= sys.get_dof_map().first_dof();
267  for (auto i : make_range(v))
268  edge_offset -= sys.get_dof_map().n_local_dofs(i);
269  }
270  else
271  sys.get_dof_map().local_variable_indices(idx_edges, sys.get_mesh(), v);
272 
273  // Create the discrete grandient matrix, representing the edges in terms of its vertices
274  // Preallocate 2 diagonal + 2 off-diagonal nonzeros as the vertices could fall on either
275  PetscMatrix<Real> G(Comm, n_glb_edges, n_glb_verts, n_loc_edges, n_loc_verts, 2, 2);
276 
277  // Create array for the coordinates of the local vertices
278  PetscReal * coords;
279  LibmeshPetscCallA(comm, PetscMalloc1(dim * n_loc_verts, &coords));
280 
281  // Populate the discrete gradient matrix and the coordinates array
282  for (const auto & elem : sys.get_mesh().active_local_element_ptr_range())
283  for (auto edge : make_range(elem->n_edges()))
284  {
285  // The edge's two vertices
286  dof_id_type vert_dofs[2];
287  for (auto vert : make_range(2))
288  {
289  const unsigned loc_vert_node_id = elem->local_edge_node(edge, vert);
290  libmesh_assert(elem->is_vertex(loc_vert_node_id));
291 
292  const Node & vert_node = elem->node_ref(loc_vert_node_id);
293  vert_dofs[vert] = vert_node.dof_number(lagrange_sys.number(), 0, 0);
294 
295  // If owned, populate coordinates array
296  if (vert_node.processor_id() == global_processor_id())
297  {
298  const dof_id_type loc_vert_dof = vert_offset + vert_dofs[vert];
299  libmesh_assert(loc_vert_dof < n_loc_verts);
300 
301  for (auto d : make_range(dim))
302  coords[dim * loc_vert_dof + d] = vert_node(d);
303  }
304  }
305 
306  // The edge's (middle) node
307  const unsigned loc_edge_node_id = elem->local_edge_node(edge, 2);
308  libmesh_assert(elem->is_edge(loc_edge_node_id));
309 
310  const Node & edge_node = elem->node_ref(loc_edge_node_id);
311 
312  // If owned, populate discrete gradient matrix
313  if (edge_node.processor_id() == global_processor_id())
314  {
315  const dof_id_type edge_dof = edge_node.dof_number(sys.number(), v, 0);
316 
317  const dof_id_type cont_edge_dof = edge_offset +
318  (var_major ? edge_dof
319  : std::distance(idx_edges.begin(),
320  std::find(idx_edges.begin(), idx_edges.end(), edge_dof)));
321 
322  const Real sign = elem->positive_edge_orientation(edge) ? 1 : -1;
323 
324  libmesh_assert(cont_edge_dof >= G.row_start());
325  libmesh_assert(cont_edge_dof < G.row_stop());
326  G.set(cont_edge_dof, vert_dofs[0], sign);
327  G.set(cont_edge_dof, vert_dofs[1], -sign);
328  }
329  }
330 
331  // Assemble the discrete gradient matrix
332  G.close();
333 
334  // Hand over the matrix and coordinates array
335  LibmeshPetscCallA(comm, PCHYPRESetDiscreteGradient(pc, G.mat()));
336  LibmeshPetscCallA(comm, PCSetCoordinates(pc, dim, n_loc_verts, coords));
337 
338  // Free allocated memory for the coordinates array
339  LibmeshPetscCallA(comm, PetscFree(coords));
340 }
341 
342 
343 
344 template <typename T>
345 void PetscPreconditioner<T>::set_hypre_ads_data(PC & pc, System & sys, const unsigned v)
346 {
347  // Get the communicator from the PETSc object
348  Parallel::communicator comm;
349  PetscErrorCode ierr = PetscObjectGetComm((PetscObject)pc, &comm);
350  libmesh_error_msg_if(ierr != LIBMESH_PETSC_SUCCESS,
351  "Error retrieving communicator");
352  Parallel::Communicator Comm(comm);
353 
354  // The mesh/problem dimension
355  const unsigned dim = sys.get_mesh().mesh_dimension();
356 
357  // Dummy Lagrange and Nédélec systems defined over the same mesh so we can
358  // enumerate the vertices and edges, respectively
359  System & lagrange_sys = sys.get_equation_systems().add_system<System>("__hypre_ads_vertices");
360  lagrange_sys.hide_output() = true;
361  lagrange_sys.add_variable("__lagrange");
362  lagrange_sys.reinit_mesh();
363  System & nedelec_sys = sys.get_equation_systems().add_system<System>("__hypre_ads_edges");
364  nedelec_sys.hide_output() = true;
365  nedelec_sys.add_variable("__nedelec", FIRST, NEDELEC_ONE);
366  nedelec_sys.reinit_mesh();
367 
368  // Global (i.e. total) and local (i.e. to this processor) number of faces,
369  // edges and vertices
370  const std::vector<dof_id_type> n_all_faces = sys.get_dof_map().n_dofs_per_processor(v);
371  const dof_id_type n_glb_faces = std::accumulate(n_all_faces.begin(), n_all_faces.end(), 0);
372  const dof_id_type n_loc_faces = n_all_faces[global_processor_id()];
373  const dof_id_type n_glb_edges = nedelec_sys.n_dofs();
374  const dof_id_type n_loc_edges = nedelec_sys.n_local_dofs();
375  const dof_id_type n_glb_verts = lagrange_sys.n_dofs();
376  const dof_id_type n_loc_verts = lagrange_sys.n_local_dofs();
377 
378  // We require local indexing through the vertices and contiguous indexing
379  // through the edges and faces: since the vertices are enumerated on their own
380  // system, a local index can simply be obtained by subtracting those vertices
381  // in all preceding processors; since the edges are enumerated on their own
382  // system, we already have contiguous indexing; for the faces, if the system
383  // we are given by the user has multiple variables/splits, we effectively need
384  // to add local face numbers to those faces in all preceding processors
385 
386  // The number of vertices and faces in all preceding processors
387  dof_id_signed_type vert_offset = -lagrange_sys.get_dof_map().first_dof();
388  dof_id_signed_type face_offset =
389  std::accumulate(n_all_faces.begin(), n_all_faces.begin() + global_processor_id(), 0);
390 
391  // Whether dofs are in variable-major or node-major order
392  bool var_major = !libMesh::on_command_line("--node-major-dofs");
393 
394  // If variable-major order, we need only subtract all the preceding dofs; but
395  // if node-major order, we need to enumerate the dofs on this processor
396  std::vector<dof_id_type> idx_faces;
397  if (var_major)
398  {
399  face_offset -= sys.get_dof_map().first_dof();
400  for (auto i : make_range(v))
401  face_offset -= sys.get_dof_map().n_local_dofs(i);
402  }
403  else
404  sys.get_dof_map().local_variable_indices(idx_faces, sys.get_mesh(), v);
405 
406  // Create the discrete grandient matrix, representing the edges in terms of its vertices
407  // Preallocate 2 diagonal + 2 off-diagonal nonzeros as the vertices could fall on either
408  PetscMatrix<Real> G(Comm, n_glb_edges, n_glb_verts, n_loc_edges, n_loc_verts, 2, 2);
409 
410  // Create the discrete curl matrix, representing the faces in terms of its edges
411  // Preallocate 4 diagonal + 4 off-diagonal nonzeros as the edges could fall on either
412  PetscMatrix<Real> C(Comm, n_glb_faces, n_glb_edges, n_loc_faces, n_loc_edges, 4, 4);
413 
414  // Create array for the coordinates of the local vertices
415  PetscReal * coords;
416  LibmeshPetscCallA(comm, PetscMalloc1(dim * n_loc_verts, &coords));
417 
418  // Populate the discrete gradient matrix and the coordinates array
419  for (const auto & elem : sys.get_mesh().active_local_element_ptr_range())
420  for (auto face : make_range(elem->n_faces()))
421  {
422  // The number of edges on this face
423  const unsigned n_face_edges = Elem::type_to_n_sides_map[elem->side_type(face)];
424 
425  // The faces's three/four edges
426  std::vector<dof_id_type> edge_dofs(n_face_edges);
427  std::vector<bool> edge_orients(n_face_edges);
428  for (auto face_edge : make_range(n_face_edges))
429  {
430  // Convert from face-wise to element-wise edge id
431  const unsigned edge = elem->local_side_node(face, n_face_edges + face_edge)
432  - elem->n_vertices();
433  libmesh_assert(elem->is_edge_on_side(edge, face));
434 
435  // The edge's two vertices
436  dof_id_type vert_dofs[2];
437  for (auto vert : make_range(2))
438  {
439  const unsigned loc_vert_node_id = elem->local_edge_node(edge, vert);
440  libmesh_assert(elem->is_vertex(loc_vert_node_id));
441 
442  const Node & vert_node = elem->node_ref(loc_vert_node_id);
443  vert_dofs[vert] = vert_node.dof_number(lagrange_sys.number(), 0, 0);
444 
445  // If owned, populate coordinates array
446  if (vert_node.processor_id() == global_processor_id())
447  {
448  const dof_id_type loc_vert_dof = vert_offset + vert_dofs[vert];
449  libmesh_assert(loc_vert_dof < n_loc_verts);
450 
451  for (auto d : make_range(dim))
452  coords[dim * loc_vert_dof + d] = vert_node(d);
453  }
454  }
455 
456  // The edge's (middle) node
457  const unsigned loc_edge_node_id = elem->local_edge_node(edge, 2);
458  libmesh_assert(elem->is_edge(loc_edge_node_id));
459 
460  const Node & edge_node = elem->node_ref(loc_edge_node_id);
461  edge_dofs[face_edge] = edge_node.dof_number(nedelec_sys.number(), 0, 0);
462  edge_orients[face_edge] = elem->positive_edge_orientation(edge) ^
463  elem->relative_edge_face_order(edge, face);
464 
465  // If owned, populate discrete gradient matrix
466  if (edge_node.processor_id() == global_processor_id())
467  {
468  const Real sign = elem->positive_edge_orientation(edge) ? 1 : -1;
469 
470  libmesh_assert(edge_dofs[face_edge] >= G.row_start());
471  libmesh_assert(edge_dofs[face_edge] < G.row_stop());
472  G.set(edge_dofs[face_edge], vert_dofs[0], sign);
473  G.set(edge_dofs[face_edge], vert_dofs[1], -sign);
474  }
475  }
476 
477  // The faces's (middle) node
478  const unsigned loc_face_node_id = elem->local_side_node(face, 2 * n_face_edges);
479  libmesh_assert(elem->is_face(loc_face_node_id));
480 
481  const Node & face_node = elem->node_ref(loc_face_node_id);
482 
483  // If owned, populate discrete curl matrix
484  if (face_node.processor_id() == global_processor_id())
485  {
486  const dof_id_type face_dof = face_node.dof_number(sys.number(), v, 0);
487 
488  const dof_id_type cont_face_dof = face_offset +
489  (var_major ? face_dof
490  : std::distance(idx_faces.begin(),
491  std::find(idx_faces.begin(), idx_faces.end(), face_dof)));
492 
493  const bool face_orient = elem->positive_face_orientation(face);
494 
495  for (auto face_edge : make_range(n_face_edges))
496  {
497  const Real sign = face_orient ^ edge_orients[face_edge] ? 1 : -1;
498 
499  libmesh_assert(cont_face_dof >= C.row_start());
500  libmesh_assert(cont_face_dof < C.row_stop());
501  C.set(cont_face_dof, edge_dofs[face_edge], sign);
502  }
503  }
504  }
505 
506  // Assemble the discrete gradient and discrete curl matrices
507  G.close();
508  C.close();
509 
510 #ifndef NDEBUG
511  // The product CG of the two matrices should be the zero matrix
512  PetscMatrix<Real> CG(Comm);
513  C.matrix_matrix_mult(G, CG);
514  libmesh_assert(CG.linfty_norm() == 0);
515 #endif
516 
517  // Hand over the matrices and coordinates array
518  LibmeshPetscCallA(comm, PCHYPRESetDiscreteGradient(pc, G.mat()));
519  LibmeshPetscCallA(comm, PCHYPRESetDiscreteCurl(pc, C.mat()));
520  LibmeshPetscCallA(comm, PCSetCoordinates(pc, dim, n_loc_verts, coords));
521 
522  // Free allocated memory for the coordinates array
523  LibmeshPetscCallA(comm, PetscFree(coords));
524 }
525 #endif
526 
527 
528 //------------------------------------------------------------------
529 // Explicit instantiations
530 template class LIBMESH_EXPORT PetscPreconditioner<Number>;
531 
532 } // namespace libMesh
533 
534 #endif // #ifdef LIBMESH_HAVE_PETSC
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:196
OStreamProxy err
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
Definition: dof_object.h:1008
This class provides a nice interface to PETSc&#39;s Vec object.
Definition: petsc_vector.h:73
virtual numeric_index_type row_stop() const override
A Node is like a Point, but with more information.
Definition: node.h:52
This class provides an interface to the suite of preconditioners available from PETSc.
const Variable & variable(unsigned int var) const
Return a constant reference to Variable var.
Definition: system.C:2704
static const unsigned int type_to_n_sides_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the number of sides on the element...
Definition: elem.h:678
unsigned int dim
void local_variable_indices(T &idx, const MeshBase &mesh, unsigned int var_num) const
If T == dof_id_type, counts, if T == std::vector<dof_id_type>, fills an array of, those dof indices w...
Definition: dof_map.C:1122
virtual void init() override
Initialize data structures if not done so already.
static void set_hypre_ads_data(PC &pc, System &sys, const unsigned v)
const EquationSystems & get_equation_systems() const
Definition: system.h:767
Provides a uniform interface to vector storage schemes for different linear algebra libraries...
Definition: vector_fe_ex5.C:44
The libMesh namespace provides an interface to certain functionality in the library.
dof_id_type n_local_dofs() const
Definition: system.C:155
dof_id_type n_local_dofs(const unsigned int vn) const
Definition: dof_map.h:794
const MeshBase & get_mesh() const
Definition: system.h:2401
Real distance(const Point &p)
dof_id_type n_dofs() const
Definition: system.C:118
virtual void apply(const NumericVector< T > &x, NumericVector< T > &y) override
Computes the preconditioned vector y based on input vector x.
This class provides a uniform interface for preconditioners.
unsigned int number() const
Definition: system.h:2393
bool _is_initialized
Flag that tells if init() has been called.
Definition: libmesh.C:305
Manages consistently variables, degrees of freedom, and coefficient vectors.
Definition: system.h:98
bool & hide_output()
Definition: system.h:1852
libmesh_assert(ctx)
int8_t dof_id_signed_type
Definition: id_types.h:68
unsigned int add_variable(std::string_view var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
Adds the variable var to the list of variables for this system.
Definition: system.C:1344
PetscPreconditioner(const libMesh::Parallel::Communicator &comm_in)
Constructor.
virtual void close() override
Calls the SparseMatrix&#39;s internal assembly routines, ensuring that the values are consistent across p...
virtual void clear() override
Release all memory and clear data structures.
virtual void reinit_mesh()
Reinitializes the system with a new mesh.
Definition: system.C:289
static void set_petsc_preconditioner_type(const PreconditionerType &preconditioner_type, PC &pc)
Tells PETSc to use the user-specified preconditioner.
PreconditionerType
Defines an enum for preconditioner types.
std::string enum_to_string(const T e)
virtual void matrix_matrix_mult(SparseMatrix< T > &X, SparseMatrix< T > &Y, bool reuse=false) override
Compute Y = A*X for matrix X.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
processor_id_type global_processor_id()
Definition: libmesh_base.h:98
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition: int_range.h:176
static void set_petsc_aux_data(PC &pc, System &sys, const unsigned v=0)
Builds PETSc auxiliary data needed by preconditioners such as hypre ams/ads.
unsigned int mesh_dimension() const
Definition: mesh_base.C:430
virtual void set(const numeric_index_type i, const numeric_index_type j, const T value) override
Set the element (i,j) to value.
Definition: petsc_matrix.C:972
virtual numeric_index_type row_start() const override
This class provides a nice interface to the PETSc C-based AIJ data structures for parallel...
Definition: petsc_matrix.h:61
bool on_command_line(std::string arg)
Definition: libmesh.C:934
dof_id_type first_dof(const processor_id_type proc) const
Definition: dof_map_base.h:185
unsigned int n_vars() const
Definition: system.C:2674
virtual System & add_system(std::string_view system_type, std::string_view name)
Add the system of type system_type named name to the systems array.
const DofMap & get_dof_map() const
Definition: system.h:2417
static void set_hypre_ams_data(PC &pc, System &sys, const unsigned v)
std::vector< dof_id_type > n_dofs_per_processor(const unsigned int vn) const
Definition: dof_map.h:805
uint8_t dof_id_type
Definition: id_types.h:67
const FEType & type() const
Definition: variable.h:144