1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2009 - 2019 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 #ifndef dealii_slepc_spectral_transformation_h
18 #  define dealii_slepc_spectral_transformation_h
19 
20 
21 #  include <deal.II/base/config.h>
22 
23 #  ifdef DEAL_II_WITH_SLEPC
24 
25 #    include <deal.II/lac/exceptions.h>
26 #    include <deal.II/lac/petsc_solver.h>
27 
28 #    include <petscksp.h>
29 
30 #    include <slepceps.h>
31 
32 #    include <memory>
33 
34 DEAL_II_NAMESPACE_OPEN
35 
36 // Forward declaration
37 #    ifndef DOXYGEN
38 namespace PETScWrappers
39 {
40   // forward declarations
41   class SolverBase;
42 } // namespace PETScWrappers
43 #    endif
44 
45 namespace SLEPcWrappers
46 {
47   // forward declaration
48   class SolverBase;
49 
50   /**
51    * Base class for spectral transformation classes using the SLEPc solvers
52    * which are selected based on flags passed to the spectral transformation.
53    *
54    * <code>SLEPcWrappers::TransformationXXX</code>, where <code>XXX</code> is
55    * your favourite transformation type, can then be implemented in
56    * application codes in the following way for <code>XXX=INVERT</code> with
57    * the solver object <code>eigensolver</code>:
58    * @code
59    * // Set a transformation, this one shifts the eigenspectrum by 3.142..
60    * SLEPcWrappers::TransformationShift::AdditionalData
61    *   additional_data(3.142);
62    * SLEPcWrappers::TransformationShift shift(mpi_communicator,additional_data);
63    * eigensolver.set_transformation(shift);
64    * @endcode
65    * and later calling the <code>solve()</code> function as usual:
66    * @code
67    * SolverControl solver_control (1000, 1e-9);
68    * SolverArnoldi system (solver_control, mpi_communicator);
69    * eigensolver.solve (A, B, lambda, x, size_of_spectrum);
70    * @endcode
71    *
72    * @note These options can also be set at the command line.
73    *
74    * @ingroup SLEPcWrappers
75    */
76   class TransformationBase
77   {
78   protected:
79     /**
80      * Constructor.
81      */
82     TransformationBase(const MPI_Comm &mpi_communicator);
83 
84   public:
85     /**
86      * Destructor.
87      */
88     virtual ~TransformationBase();
89 
90     /**
91      * Set a flag to indicate how the transformed matrices are being stored in
92      * the spectral transformations.
93      *
94      * The possible values are given by the enumerator STMatMode in the SLEPc
95      * library
96      * http://www.grycap.upv.es/slepc/documentation/current/docs/manualpages/ST/STMatMode.html
97      */
98     void
99     set_matrix_mode(const STMatMode mode);
100 
101     /**
102      * Set solver to be used when solving a system of linear algebraic
103      * equations inside the eigensolver.
104      */
105     void
106     set_solver(const PETScWrappers::SolverBase &solver);
107 
108   protected:
109     /**
110      * SLEPc spectral transformation object.
111      */
112     ST st;
113 
114     // Make the solver class a friend, since it needs to set spectral
115     // transformation object.
116     friend class SolverBase;
117   };
118 
119   /**
120    * An implementation of the transformation interface using the SLEPc Shift.
121    *
122    * @ingroup SLEPcWrappers
123    */
124   class TransformationShift : public TransformationBase
125   {
126   public:
127     /**
128      * Standardized data struct to pipe additional data to the solver.
129      */
130     struct AdditionalData
131     {
132       /**
133        * Constructor. By default, set the shift parameter to zero.
134        */
135       AdditionalData(const double shift_parameter = 0);
136 
137       /**
138        * Shift parameter.
139        */
140       const double shift_parameter;
141     };
142 
143 
144     /**
145      * Constructor.
146      */
147     TransformationShift(const MPI_Comm &      mpi_communicator,
148                         const AdditionalData &data = AdditionalData());
149 
150 
151   protected:
152     /**
153      * Store a copy of the flags for this particular solver.
154      */
155     const AdditionalData additional_data;
156   };
157 
158   /**
159    * An implementation of the transformation interface using the SLEPc Shift
160    * and Invert.
161    *
162    * @ingroup SLEPcWrappers
163    */
164   class TransformationShiftInvert : public TransformationBase
165   {
166   public:
167     /**
168      * Standardized data struct to pipe additional data to the solver.
169      */
170     struct AdditionalData
171     {
172       /**
173        * Constructor. By default, set the shift parameter to zero.
174        */
175       AdditionalData(const double shift_parameter = 0);
176 
177       /**
178        * Shift parameter.
179        */
180       const double shift_parameter;
181     };
182 
183 
184     /**
185      * Constructor.
186      */
187     TransformationShiftInvert(const MPI_Comm &      mpi_communicator,
188                               const AdditionalData &data = AdditionalData());
189 
190   protected:
191     /**
192      * Store a copy of the flags for this particular solver.
193      */
194     const AdditionalData additional_data;
195 
196     // Make the solver class a friend, since it may need to set target
197     // equal the provided shift value.
198     friend class SolverBase;
199   };
200 
201   /**
202    * An implementation of the transformation interface using the SLEPc
203    * Spectrum Folding. This transformation type has been removed in SLEPc
204    * 3.5.0 and thus cannot be used in the newer versions.
205    *
206    * @ingroup SLEPcWrappers
207    */
208   class TransformationSpectrumFolding : public TransformationBase
209   {
210   public:
211     /**
212      * Standardized data struct to pipe additional data to the solver.
213      */
214     struct AdditionalData
215     {
216       /**
217        * Constructor. By default, set the shift parameter to zero.
218        */
219       AdditionalData(const double shift_parameter = 0);
220 
221       /**
222        * Shift parameter.
223        */
224       const double shift_parameter;
225     };
226 
227 
228     /**
229      * Constructor.
230      */
231     TransformationSpectrumFolding(
232       const MPI_Comm &      mpi_communicator,
233       const AdditionalData &data = AdditionalData());
234 
235   protected:
236     /**
237      * Store a copy of the flags for this particular solver.
238      */
239     const AdditionalData additional_data;
240   };
241 
242   /**
243    * An implementation of the transformation interface using the SLEPc Cayley.
244    *
245    * @ingroup SLEPcWrappers
246    */
247   class TransformationCayley : public TransformationBase
248   {
249   public:
250     /**
251      * Standardized data struct to pipe additional data to the solver.
252      */
253     struct AdditionalData
254     {
255       /**
256        * Constructor. Requires two shift parameters
257        */
258       AdditionalData(const double shift_parameter     = 0,
259                      const double antishift_parameter = 0);
260 
261       /**
262        * Shift parameter.
263        */
264       const double shift_parameter;
265 
266       /**
267        * Antishift parameter.
268        */
269       const double antishift_parameter;
270     };
271 
272 
273     /**
274      * Constructor.
275      */
276     TransformationCayley(const MPI_Comm &      mpi_communicator,
277                          const AdditionalData &data = AdditionalData());
278 
279   protected:
280     /**
281      * Store a copy of the flags for this particular solver.
282      */
283     const AdditionalData additional_data;
284   };
285 
286 } // namespace SLEPcWrappers
287 
288 DEAL_II_NAMESPACE_CLOSE
289 
290 #  endif // DEAL_II_WITH_SLEPC
291 
292 /*--------------------   slepc_spectral_transformation.h   ------------------*/
293 
294 #endif
295 
296 /*--------------------   slepc_spectral_transformation.h   ------------------*/
297