18#include "libmesh/libmesh_common.h"
20#ifdef LIBMESH_HAVE_PETSC
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"
49 Vec x_vec = x_pvec.
vec();
50 Vec y_vec = y_pvec.
vec();
52 LibmeshPetscCall(PCApply(_pc, x_vec, y_vec));
61 libmesh_error_msg_if(!this->_matrix,
"ERROR: No matrix set for PetscPreconditioner, but init() called");
64 if (!this->_is_initialized)
70 LibmeshPetscCall(PCCreate(this->comm().get(), _pc.get()));
72 auto pmatrix = cast_ptr<PetscMatrixBase<T> *>(this->_matrix);
73 _mat = pmatrix->mat();
76 LibmeshPetscCall(PCSetOperators(_pc, _mat, _mat));
85 set_petsc_preconditioner_type(this->_preconditioner_type, *_pc);
87 this->_is_initialized =
true;
114 PetscErrorCode ierr = PetscObjectGetComm((PetscObject)pc, & comm);
115 if (ierr != LIBMESH_PETSC_SUCCESS)
116 libmesh_error_msg(
"Error retrieving communicator");
118 #define CasePCSetType(PreconditionerType, PCType) \
119 case PreconditionerType: \
120 LibmeshPetscCallA(comm, PCSetType (pc, const_cast<KSPType>(PCType))); \
123 switch (preconditioner_type)
141 libMesh::err <<
"ERROR: Unsupported PETSC Preconditioner: "
143 <<
"Continuing with PETSC defaults" << std::endl;
148#ifdef LIBMESH_HAVE_PETSC_HYPRE
150 LibmeshPetscCallA(comm, PCHYPRESetType(pc,
"boomeramg"));
154 LibmeshPetscCallA(comm, PCSetFromOptions(pc));
159#ifdef LIBMESH_HAVE_PETSC_HYPRE
165 PetscErrorCode ierr = PetscObjectGetComm((PetscObject)pc, &comm);
166 libmesh_error_msg_if(ierr != LIBMESH_PETSC_SUCCESS,
167 "Error retrieving communicator");
170 LibmeshPetscCallA(comm, PCSetFromOptions(pc));
173 PCType pc_type =
nullptr;
174 LibmeshPetscCallA(comm, PCGetType(pc, &pc_type));
177 if (pc_type && std::string(pc_type) == PCHYPRE)
180 PCType hypre_type =
nullptr;
181 LibmeshPetscCallA(comm, PCHYPREGetType(pc, &hypre_type));
184 if (std::string(hypre_type) ==
"ams")
187 libmesh_error_msg_if(sys.
n_vars() > 1,
188 "Error applying hypre AMS to a system with multiple "
193 const bool first_order_nedelec =
195 const bool first_order_raviart_thomas =
198 libmesh_error_msg_if(!first_order_nedelec &&
199 (!first_order_raviart_thomas ||
201 "Error applying hypre AMS to a system "
202 "whose variable is not 1st order Nedelec or 1st "
203 "order Raviart-Thomas on a 2d mesh");
204 set_hypre_ams_data(pc, sys, v);
206 else if (std::string(hypre_type) ==
"ads")
209 libmesh_error_msg_if(sys.
n_vars() > 1,
210 "Error applying hypre ADS to a system with multiple "
215 const bool first_order_raviart_thomas =
218 libmesh_error_msg_if(!first_order_raviart_thomas ||
220 "Error applying hypre ADS to a system "
221 "whose variable is not 1st "
222 "order Raviart-Thomas on a 3d mesh");
223 set_hypre_ads_data(pc, sys, v);
235 PetscErrorCode ierr = PetscObjectGetComm((PetscObject)pc, &comm);
236 libmesh_error_msg_if(ierr != LIBMESH_PETSC_SUCCESS,
237 "Error retrieving communicator");
251 const dof_id_type n_glb_edges = std::accumulate(n_all_edges.begin(), n_all_edges.end(), 0);
273 std::vector<dof_id_type> idx_edges;
285 PetscMatrix<Real> G(Comm, n_glb_edges, n_glb_verts, n_loc_edges, n_loc_verts, 2, 2);
289 LibmeshPetscCallA(comm, PetscMalloc1(
dim * n_loc_verts, &coords));
292 for (
const auto & elem : sys.
get_mesh().active_local_element_ptr_range())
299 const unsigned loc_vert_node_id = elem->local_edge_node(edge, vert);
302 const Node & vert_node = elem->node_ref(loc_vert_node_id);
308 const dof_id_type loc_vert_dof = vert_offset + vert_dofs[vert];
312 coords[
dim * loc_vert_dof + d] = vert_node(d);
317 const unsigned loc_edge_node_id = elem->local_edge_node(edge, 2);
320 const Node & edge_node = elem->node_ref(loc_edge_node_id);
328 (var_major ? edge_dof
329 : std::distance(idx_edges.begin(),
330 std::find(idx_edges.begin(), idx_edges.end(), edge_dof)));
332 const Real sign = elem->positive_edge_orientation(edge) ? 1 : -1;
336 G.
set(cont_edge_dof, vert_dofs[0], sign);
337 G.
set(cont_edge_dof, vert_dofs[1], -sign);
345 LibmeshPetscCallA(comm, PCHYPRESetDiscreteGradient(pc, G.
mat()));
346 LibmeshPetscCallA(comm, PCSetCoordinates(pc,
dim, n_loc_verts, coords));
349 LibmeshPetscCallA(comm, PetscFree(coords));
359 PetscErrorCode ierr = PetscObjectGetComm((PetscObject)pc, &comm);
360 libmesh_error_msg_if(ierr != LIBMESH_PETSC_SUCCESS,
361 "Error retrieving communicator");
381 const dof_id_type n_glb_faces = std::accumulate(n_all_faces.begin(), n_all_faces.end(), 0);
406 std::vector<dof_id_type> idx_faces;
418 PetscMatrix<Real> G(Comm, n_glb_edges, n_glb_verts, n_loc_edges, n_loc_verts, 2, 2);
422 PetscMatrix<Real> C(Comm, n_glb_faces, n_glb_edges, n_loc_faces, n_loc_edges, 4, 4);
426 LibmeshPetscCallA(comm, PetscMalloc1(
dim * n_loc_verts, &coords));
429 for (
const auto & elem : sys.
get_mesh().active_local_element_ptr_range())
436 std::vector<dof_id_type> edge_dofs(n_face_edges);
437 std::vector<bool> edge_orients(n_face_edges);
438 for (
auto face_edge :
make_range(n_face_edges))
441 const unsigned edge = elem->local_side_node(face, n_face_edges + face_edge)
442 - elem->n_vertices();
449 const unsigned loc_vert_node_id = elem->local_edge_node(edge, vert);
452 const Node & vert_node = elem->node_ref(loc_vert_node_id);
458 const dof_id_type loc_vert_dof = vert_offset + vert_dofs[vert];
462 coords[
dim * loc_vert_dof + d] = vert_node(d);
467 const unsigned loc_edge_node_id = elem->local_edge_node(edge, 2);
470 const Node & edge_node = elem->node_ref(loc_edge_node_id);
472 edge_orients[face_edge] = elem->positive_edge_orientation(edge) ^
473 elem->relative_edge_face_order(edge, face);
478 const Real sign = elem->positive_edge_orientation(edge) ? 1 : -1;
482 G.
set(edge_dofs[face_edge], vert_dofs[0], sign);
483 G.
set(edge_dofs[face_edge], vert_dofs[1], -sign);
488 const unsigned loc_face_node_id = elem->local_side_node(face, 2 * n_face_edges);
491 const Node & face_node = elem->node_ref(loc_face_node_id);
499 (var_major ? face_dof
500 : std::distance(idx_faces.begin(),
501 std::find(idx_faces.begin(), idx_faces.end(), face_dof)));
503 const bool face_orient = elem->positive_face_orientation(face);
505 for (
auto face_edge :
make_range(n_face_edges))
507 const Real sign = face_orient ^ edge_orients[face_edge] ? 1 : -1;
511 C.
set(cont_face_dof, edge_dofs[face_edge], sign);
528 LibmeshPetscCallA(comm, PCHYPRESetDiscreteGradient(pc, G.
mat()));
529 LibmeshPetscCallA(comm, PCHYPRESetDiscreteCurl(pc, C.
mat()));
530 LibmeshPetscCallA(comm, PCSetCoordinates(pc,
dim, n_loc_verts, coords));
533 LibmeshPetscCallA(comm, PetscFree(coords));
dof_id_type first_dof(const processor_id_type proc) const
std::vector< dof_id_type > n_dofs_per_processor(const unsigned int vn) const
dof_id_type n_local_dofs(const unsigned int vn) const
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...
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
processor_id_type processor_id() const
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...
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.
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
OrderWrapper order
The approximation order of the element (at 0 p-refinement level).
FEFamily family
The type of finite element.
unsigned int mesh_dimension() const
A Node is like a Point, but with more information.
Provides a uniform interface to vector storage schemes for different linear algebra libraries.
virtual void close() override
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
virtual numeric_index_type row_start() const override
virtual numeric_index_type row_stop() const override
This class provides a nice interface to the PETSc C-based AIJ data structures for parallel,...
virtual void matrix_matrix_mult(SparseMatrix< T > &X, SparseMatrix< T > &Y, bool reuse=false) override
Compute Y = A*X for matrix X.
virtual void set(const numeric_index_type i, const numeric_index_type j, const T value) override
Set the element (i,j) to value.
This class provides an interface to the suite of preconditioners available from PETSc.
PetscPreconditioner(const libMesh::Parallel::Communicator &comm_in)
Constructor.
virtual void apply(const NumericVector< T > &x, NumericVector< T > &y) override
Computes the preconditioned vector y based on input vector x.
virtual void clear() override
Release all memory and clear data structures.
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.
static void set_hypre_ams_data(PC &pc, System &sys, const unsigned v)
static void set_petsc_preconditioner_type(const PreconditionerType &preconditioner_type, PC &pc)
Tells PETSc to use the user-specified preconditioner.
static void set_hypre_ads_data(PC &pc, System &sys, const unsigned v)
virtual void init() override
Initialize data structures if not done so already.
This class provides a nice interface to PETSc's Vec object.
This class provides a uniform interface for preconditioners.
Manages consistently variables, degrees of freedom, and coefficient vectors.
const Variable & variable(unsigned int var) const
Return a constant reference to Variable var.
dof_id_type n_dofs() const
virtual void reinit_mesh()
Reinitializes the system with a new mesh.
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.
dof_id_type n_local_dofs() const
unsigned int n_vars() const
const DofMap & get_dof_map() const
unsigned int number() const
const EquationSystems & get_equation_systems() const
const MeshBase & get_mesh() const
const FEType & type() const
DIE A HORRIBLE DEATH HERE typedef MPI_Comm communicator
std::string enum_to_string(const T e)
The libMesh namespace provides an interface to certain functionality in the library.
processor_id_type global_processor_id()
int8_t dof_id_signed_type
PreconditionerType
Defines an enum for preconditioner types.
bool on_command_line(std::string arg)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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...