1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2016 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 /*
17  * Rather than using ifdefs everywhere, try to wrap older versions of PETSc
18  * functions in one place.
19  */
20 #ifndef dealii_petsc_compatibility_h
21 #define dealii_petsc_compatibility_h
22 
23 #include <deal.II/base/config.h>
24 
25 #include <deal.II/lac/exceptions.h>
26 
27 #ifdef DEAL_II_WITH_PETSC
28 
29 #  include <petscconf.h>
30 #  include <petscksp.h>
31 #  include <petscmat.h>
32 #  include <petscpc.h>
33 
34 #  include <string>
35 
36 DEAL_II_NAMESPACE_OPEN
37 
38 namespace PETScWrappers
39 {
40   /**
41    * Set an option in the global PETSc database. This function just wraps
42    * PetscOptionsSetValue with a version check (the signature of this function
43    * changed in PETSc 3.7.0).
44    */
45   inline void
set_option_value(const std::string & name,const std::string & value)46   set_option_value(const std::string &name, const std::string &value)
47   {
48 #  if DEAL_II_PETSC_VERSION_LT(3, 7, 0)
49     const PetscErrorCode ierr =
50       PetscOptionsSetValue(name.c_str(), value.c_str());
51 #  else
52     const PetscErrorCode ierr =
53       PetscOptionsSetValue(nullptr, name.c_str(), value.c_str());
54 #  endif
55     AssertThrow(ierr == 0, ExcPETScError(ierr));
56   }
57 
58 
59 
60   /**
61    * Destroy a PETSc matrix. This function wraps MatDestroy with a version
62    * check (the signature of this function changed in PETSc 3.2.0).
63    *
64    * @warning Since the primary intent of this function is to enable RAII
65    * semantics in the PETSc wrappers, this function will not throw an
66    * exception if an error occurs, but instead just returns the error code
67    * given by MatDestroy.
68    */
69   inline PetscErrorCode
destroy_matrix(Mat & matrix)70   destroy_matrix(Mat &matrix)
71   {
72     // PETSc will check whether or not matrix is nullptr.
73     return MatDestroy(&matrix);
74   }
75 
76 
77 
78   /**
79    * Destroy a Krylov Subspace (KSP) PETSc solver. This function wraps
80    * KSPDestroy with a version check (the signature of this function changed
81    * in PETSc 3.2.0).
82    *
83    * @warning Since the primary intent of this function is to enable RAII
84    * semantics in the PETSc wrappers, this function will not throw an
85    * exception if an error occurs, but instead just returns the error code
86    * given by MatDestroy.
87    */
88   inline PetscErrorCode
destroy_krylov_solver(KSP & krylov_solver)89   destroy_krylov_solver(KSP &krylov_solver)
90   {
91     // PETSc will check whether or not matrix is nullptr.
92     return KSPDestroy(&krylov_solver);
93   }
94 
95 
96 
97   /**
98    * Set a PETSc matrix option. This function wraps MatSetOption with a
99    * version check.
100    *
101    * @warning The argument option_value is ignored in versions of PETSc
102    * before 3.0.0 since the corresponding function did not take this argument.
103    */
104   inline void
105   set_matrix_option(Mat &           matrix,
106                     const MatOption option_name,
107                     const PetscBool option_value = PETSC_FALSE)
108   {
109     const PetscErrorCode ierr = MatSetOption(matrix, option_name, option_value);
110     AssertThrow(ierr == 0, ExcPETScError(ierr));
111   }
112 
113 
114 
115   /**
116    * Tell PETSc that we are not planning on adding new entries to the
117    * matrix. Generate errors in debug mode.
118    */
119   inline void
close_matrix(Mat & matrix)120   close_matrix(Mat &matrix)
121   {
122 #  ifdef DEBUG
123     set_matrix_option(matrix, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE);
124 #  else
125     set_matrix_option(matrix, MAT_NEW_NONZERO_LOCATIONS, PETSC_FALSE);
126 #  endif
127   }
128 
129 
130 
131   /**
132    * Tell PETSc to keep the SparsityPattern entries even if we delete a
133    * row with clear_rows() which calls MatZeroRows(). Otherwise one can
134    * not write into that row afterwards.
135    */
136   inline void
set_keep_zero_rows(Mat & matrix)137   set_keep_zero_rows(Mat &matrix)
138   {
139     set_matrix_option(matrix, MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE);
140   }
141 } // namespace PETScWrappers
142 
143 DEAL_II_NAMESPACE_CLOSE
144 
145 #endif // DEAL_II_WITH_PETSC
146 #endif // dealii_petsc_compatibility_h
147