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");
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);
101 template <
typename T>
109 template <
typename T>
113 Parallel::communicator comm;
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 160 template <
typename T>
164 Parallel::communicator comm;
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 " 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);
200 else if (std::string(hypre_type) ==
"ads")
203 libmesh_error_msg_if(sys.
n_vars() > 1,
204 "Error applying hypre ADS to a system with multiple " 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);
220 template <
typename T>
224 Parallel::communicator comm;
225 PetscErrorCode ierr = PetscObjectGetComm((PetscObject)pc, &comm);
226 libmesh_error_msg_if(ierr != LIBMESH_PETSC_SUCCESS,
227 "Error retrieving communicator");
241 const dof_id_type n_glb_edges = std::accumulate(n_all_edges.begin(), n_all_edges.end(), 0);
263 std::vector<dof_id_type> idx_edges;
275 PetscMatrix<Real> G(Comm, n_glb_edges, n_glb_verts, n_loc_edges, n_loc_verts, 2, 2);
279 LibmeshPetscCallA(comm, PetscMalloc1(
dim * n_loc_verts, &coords));
282 for (
const auto & elem : sys.
get_mesh().active_local_element_ptr_range())
289 const unsigned loc_vert_node_id = elem->local_edge_node(edge, vert);
292 const Node & vert_node = elem->node_ref(loc_vert_node_id);
298 const dof_id_type loc_vert_dof = vert_offset + vert_dofs[vert];
302 coords[
dim * loc_vert_dof + d] = vert_node(d);
307 const unsigned loc_edge_node_id = elem->local_edge_node(edge, 2);
310 const Node & edge_node = elem->node_ref(loc_edge_node_id);
318 (var_major ? edge_dof
320 std::find(idx_edges.begin(), idx_edges.end(), edge_dof)));
322 const Real sign = elem->positive_edge_orientation(edge) ? 1 : -1;
326 G.
set(cont_edge_dof, vert_dofs[0], sign);
327 G.
set(cont_edge_dof, vert_dofs[1], -sign);
335 LibmeshPetscCallA(comm, PCHYPRESetDiscreteGradient(pc, G.
mat()));
336 LibmeshPetscCallA(comm, PCSetCoordinates(pc,
dim, n_loc_verts, coords));
339 LibmeshPetscCallA(comm, PetscFree(coords));
344 template <
typename T>
348 Parallel::communicator comm;
349 PetscErrorCode ierr = PetscObjectGetComm((PetscObject)pc, &comm);
350 libmesh_error_msg_if(ierr != LIBMESH_PETSC_SUCCESS,
351 "Error retrieving communicator");
371 const dof_id_type n_glb_faces = std::accumulate(n_all_faces.begin(), n_all_faces.end(), 0);
396 std::vector<dof_id_type> idx_faces;
408 PetscMatrix<Real> G(Comm, n_glb_edges, n_glb_verts, n_loc_edges, n_loc_verts, 2, 2);
412 PetscMatrix<Real> C(Comm, n_glb_faces, n_glb_edges, n_loc_faces, n_loc_edges, 4, 4);
416 LibmeshPetscCallA(comm, PetscMalloc1(
dim * n_loc_verts, &coords));
419 for (
const auto & elem : sys.
get_mesh().active_local_element_ptr_range())
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))
431 const unsigned edge = elem->local_side_node(face, n_face_edges + face_edge)
432 - elem->n_vertices();
439 const unsigned loc_vert_node_id = elem->local_edge_node(edge, vert);
442 const Node & vert_node = elem->node_ref(loc_vert_node_id);
448 const dof_id_type loc_vert_dof = vert_offset + vert_dofs[vert];
452 coords[
dim * loc_vert_dof + d] = vert_node(d);
457 const unsigned loc_edge_node_id = elem->local_edge_node(edge, 2);
460 const Node & edge_node = elem->node_ref(loc_edge_node_id);
462 edge_orients[face_edge] = elem->positive_edge_orientation(edge) ^
463 elem->relative_edge_face_order(edge, face);
468 const Real sign = elem->positive_edge_orientation(edge) ? 1 : -1;
472 G.
set(edge_dofs[face_edge], vert_dofs[0], sign);
473 G.
set(edge_dofs[face_edge], vert_dofs[1], -sign);
478 const unsigned loc_face_node_id = elem->local_side_node(face, 2 * n_face_edges);
481 const Node & face_node = elem->node_ref(loc_face_node_id);
489 (var_major ? face_dof
491 std::find(idx_faces.begin(), idx_faces.end(), face_dof)));
493 const bool face_orient = elem->positive_face_orientation(face);
495 for (
auto face_edge :
make_range(n_face_edges))
497 const Real sign = face_orient ^ edge_orients[face_edge] ? 1 : -1;
501 C.
set(cont_face_dof, edge_dofs[face_edge], sign);
518 LibmeshPetscCallA(comm, PCHYPRESetDiscreteGradient(pc, G.
mat()));
519 LibmeshPetscCallA(comm, PCHYPRESetDiscreteCurl(pc, C.
mat()));
520 LibmeshPetscCallA(comm, PCSetCoordinates(pc,
dim, n_loc_verts, coords));
523 LibmeshPetscCallA(comm, PetscFree(coords));
534 #endif // #ifdef LIBMESH_HAVE_PETSC class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
This class provides a nice interface to PETSc's Vec object.
virtual numeric_index_type row_stop() const override
A Node is like a Point, but with more information.
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.
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...
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...
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
Provides a uniform interface to vector storage schemes for different linear algebra libraries...
The libMesh namespace provides an interface to certain functionality in the library.
dof_id_type n_local_dofs() const
dof_id_type n_local_dofs(const unsigned int vn) const
const MeshBase & get_mesh() const
Real distance(const Point &p)
dof_id_type n_dofs() const
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
bool _is_initialized
Flag that tells if init() has been called.
Manages consistently variables, degrees of freedom, and coefficient vectors.
int8_t dof_id_signed_type
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.
PetscPreconditioner(const libMesh::Parallel::Communicator &comm_in)
Constructor.
virtual void close() override
Calls the SparseMatrix'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.
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()
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...
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
virtual void set(const numeric_index_type i, const numeric_index_type j, const T value) override
Set the element (i,j) to value.
virtual numeric_index_type row_start() const override
This class provides a nice interface to the PETSc C-based AIJ data structures for parallel...
bool on_command_line(std::string arg)
dof_id_type first_dof(const processor_id_type proc) const
unsigned int n_vars() const
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
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
const FEType & type() const