1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2020 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 #ifndef dealii_mg_transfer_global_coarsening_h
17 #define dealii_mg_transfer_global_coarsening_h
18
19 #include <deal.II/base/mg_level_object.h>
20
21 #include <deal.II/dofs/dof_handler.h>
22
23 #include <deal.II/lac/affine_constraints.h>
24 #include <deal.II/lac/la_parallel_vector.h>
25
26 #include <deal.II/multigrid/mg_base.h>
27
28 DEAL_II_NAMESPACE_OPEN
29
30 // Forward declarations
31 #ifndef DOXYGEN
32 namespace internal
33 {
34 class MGTwoLevelTransferImplementation;
35 }
36 #endif
37
38
39
40 /**
41 * Class for transfer between two multigrid levels for p or global coarsening.
42 */
43 template <int dim, typename VectorType>
44 class MGTwoLevelTransfer
45 {
46 public:
47 /**
48 * Perform prolongation.
49 */
50 void
51 prolongate(VectorType &dst, const VectorType &src) const;
52
53 /**
54 * Perform restriction.
55 */
56 void
57 restrict_and_add(VectorType &dst, const VectorType &src) const;
58 };
59
60
61
62 /**
63 * Class for transfer between two multigrid levels for p or global coarsening.
64 * Specialization for LinearAlgebra::distributed::Vector.
65 */
66 template <int dim, typename Number>
67 class MGTwoLevelTransfer<dim, LinearAlgebra::distributed::Vector<Number>>
68 {
69 public:
70 /**
71 * Set up global coarsening transfer @p transfer between the given
72 * dof-handlers.
73 */
74 void
75 reinit_geometric_transfer(const DoFHandler<dim> & dof_handler_fine,
76 const DoFHandler<dim> & dof_handler_coarse,
77 const AffineConstraints<Number> &constraint_fine,
78 const AffineConstraints<Number> &constraint_coarse);
79
80 /**
81 * Set up polynomial coarsening transfer @p transfer between the given
82 * dof-handlers.
83 *
84 * @note The function polynomial_transfer_supported() can be used to
85 * check if the given polynomial coarsening strategy is supported.
86 */
87 void
88 reinit_polynomial_transfer(
89 const DoFHandler<dim> & dof_handler_fine,
90 const DoFHandler<dim> & dof_handler_coarse,
91 const AffineConstraints<Number> &constraint_fine,
92 const AffineConstraints<Number> &constraint_coarse);
93
94 /**
95 * Check if a fast templated version of the polynomial transfer between
96 * @p fe_degree_fine and @p fe_degree_coarse is available.
97 *
98 * @note Currently, the polynomial coarsening strategies: 1) go-to-one,
99 * 2) bisect, and 3) decrease-by-one are precompiled with templates for
100 * degrees up to 9.
101 */
102 static bool
103 fast_polynomial_transfer_supported(const unsigned int fe_degree_fine,
104 const unsigned int fe_degree_coarse);
105
106 /**
107 * Perform prolongation.
108 */
109 void
110 prolongate(LinearAlgebra::distributed::Vector<Number> & dst,
111 const LinearAlgebra::distributed::Vector<Number> &src) const;
112
113 /**
114 * Perform restriction.
115 */
116 void
117 restrict_and_add(LinearAlgebra::distributed::Vector<Number> & dst,
118 const LinearAlgebra::distributed::Vector<Number> &src) const;
119
120 /**
121 * Print internal data structures to stream @p out.
122 */
123 template <typename Stream>
124 void
125 print_internal(Stream &out) const;
126
127 private:
128 /**
129 * A multigrid transfer scheme. A multrigrid transfer class can have different
130 * transfer schemes to enable p-adaptivity (one transfer scheme per
131 * polynomial degree pair) and to enable global coarsening (one transfer
132 * scheme for transfer between children and parent cells, as well as, one
133 * transfer scheme for cells that are not refined).
134 */
135 struct MGTransferScheme
136 {
137 /**
138 * Number of coarse cells.
139 */
140 unsigned int n_coarse_cells;
141
142 /**
143 * Number of degrees of freedom of a coarse cell.
144 */
145 unsigned int dofs_per_cell_coarse;
146
147 /**
148 * Number of degrees of freedom of fine cell.
149 */
150 unsigned int dofs_per_cell_fine;
151
152 /**
153 * Polynomial degree of the finite element of the coarse cells.
154 */
155 unsigned int degree_coarse;
156
157 /**
158 * Polynomial degree of the finite element of the fine cells.
159 */
160 unsigned int degree_fine;
161
162 /**
163 * Flag if the finite element on the fine cells are continuous. If yes,
164 * the multiplicity of DoF sharing a vertex/line as well as constraints have
165 * to be taken in account via weights.
166 */
167 bool fine_element_is_continuous;
168
169 /**
170 * Weights for continuous elements.
171 */
172 std::vector<Number> weights;
173
174 /**
175 * 1D prolongation matrix.
176 */
177 AlignedVector<VectorizedArray<Number>> prolongation_matrix_1d;
178
179 /**
180 * DoF indices of the coarse cells, expressed in indices local to the MPI
181 * rank.
182 */
183 std::vector<unsigned int> level_dof_indices_coarse;
184
185 /**
186 * DoF indices of the fine cells, expressed in indices local to the MPI
187 * rank.
188 */
189 std::vector<unsigned int> level_dof_indices_fine;
190
191 /**
192 * Print internal data structures to stream @p out.
193 */
194 template <typename Stream>
195 void
196 print(Stream &out) const;
197 };
198
199 /**
200 * Transfer schemes.
201 */
202 std::vector<MGTransferScheme> schemes;
203
204 /**
205 * Partitioner needed by the intermediate vector.
206 */
207 std::shared_ptr<const Utilities::MPI::Partitioner> partitioner_fine;
208
209 /**
210 * Partitioner needed by the intermediate vector.
211 */
212 std::shared_ptr<const Utilities::MPI::Partitioner> partitioner_coarse;
213
214 /**
215 * Internal vector needed for collecting all degrees of freedom of the
216 * fine cells.
217 */
218 mutable LinearAlgebra::distributed::Vector<Number> vec_fine;
219
220 /**
221 * Internal vector on that the actual prolongation/restriction is performed.
222 */
223 mutable LinearAlgebra::distributed::Vector<Number> vec_coarse;
224
225 /**
226 * Constraint matrix on coarse level.
227 */
228 AffineConstraints<Number> constraint_coarse;
229
230 /**
231 * Number of components.
232 */
233 unsigned int n_components;
234
235 friend class internal::MGTwoLevelTransferImplementation;
236 };
237
238
239
240 /**
241 * Implementation of the MGTransferBase. In contrast to
242 * other multigrid transfer operators, the user can provide separate
243 * transfer operators of type MGTwoLevelTransfer between each level.
244 *
245 * This class currently only works for tensor-product finite elements based on
246 * FE_Q and FE_DGQ elements. Systems involving multiple components of
247 * one of these element, as well as, systems with different elements or other
248 * elements are currently not implemented.
249 */
250 template <typename MatrixType, typename VectorType>
251 class MGTransferGlobalCoarsening : public dealii::MGTransferBase<VectorType>
252 {
253 public:
254 static_assert(std::is_same<typename MatrixType::value_type,
255 typename VectorType::value_type>::value,
256 "Types do not match.");
257
258 /**
259 * Dimension.
260 */
261 static const int dim = MatrixType::dim;
262
263 /**
264 * Value type.
265 */
266 using Number = typename MatrixType::value_type;
267
268 /**
269 * Constructor taking an operator for each level (minimum requirement is
270 * that the operator provides the function initialize_dof_vector()) and
271 * transfer operators (with the coarsest level kept empty in @p transfer).
272 */
273 MGTransferGlobalCoarsening(
274 const MGLevelObject<MatrixType> & matrices,
275 const MGLevelObject<MGTwoLevelTransfer<dim, VectorType>> &transfer);
276
277 /**
278 * Perform prolongation.
279 */
280 void
281 prolongate(const unsigned int to_level,
282 VectorType & dst,
283 const VectorType & src) const;
284
285 /**
286 * Perform restriction.
287 */
288 virtual void
289 restrict_and_add(const unsigned int from_level,
290 VectorType & dst,
291 const VectorType & src) const;
292
293 /**
294 * Initialize internal vectors and copy @p src vector to the finest
295 * multigrid level.
296 *
297 * @note DoFHandler is not needed here, but is required by the interface.
298 */
299 template <class InVector, int spacedim>
300 void
301 copy_to_mg(const DoFHandler<dim, spacedim> &dof_handler,
302 MGLevelObject<VectorType> & dst,
303 const InVector & src) const;
304
305 /**
306 * Initialize internal vectors and copy the values on the finest
307 * multigrid level to @p dst vector.
308 *
309 * @note DoFHandler is not needed here, but is required by the interface.
310 */
311 template <class OutVector, int spacedim>
312 void
313 copy_from_mg(const DoFHandler<dim, spacedim> &dof_handler,
314 OutVector & dst,
315 const MGLevelObject<VectorType> &src) const;
316
317 private:
318 const MGLevelObject<MatrixType> & matrices;
319 const MGLevelObject<MGTwoLevelTransfer<dim, VectorType>> &transfer;
320 };
321
322
323
324 #ifndef DOXYGEN
325
326 /* ----------------------- Inline functions --------------------------------- */
327
328
329
330 template <int dim, typename Number>
331 template <typename Stream>
332 void
333 MGTwoLevelTransfer<dim, LinearAlgebra::distributed::Vector<Number>>::
print(Stream & out)334 MGTransferScheme::print(Stream &out) const
335 {
336 out << "weights:" << std::endl;
337 for (const auto w : weights)
338 out << w << " ";
339 out << std::endl;
340
341 out << "level_dof_indices_fine:" << std::endl;
342 for (const auto w : level_dof_indices_fine)
343 out << w << " ";
344 out << std::endl;
345
346 out << "level_dof_indices_coarse:" << std::endl;
347 for (const auto w : level_dof_indices_coarse)
348 out << w << " ";
349 out << std::endl;
350
351 out << "prolongation_matrix_1d:" << std::endl;
352 for (const auto w : prolongation_matrix_1d)
353 out << w[0] << " ";
354 out << std::endl;
355 }
356
357
358
359 template <int dim, typename Number>
360 template <typename Stream>
361 void
362 MGTwoLevelTransfer<dim, LinearAlgebra::distributed::Vector<Number>>::
print_internal(Stream & out)363 print_internal(Stream &out) const
364 {
365 for (const auto &scheme : schemes)
366 scheme.print(out);
367 }
368
369
370
371 template <typename MatrixType, typename VectorType>
MGTransferGlobalCoarsening(const MGLevelObject<MatrixType> & matrices,const MGLevelObject<MGTwoLevelTransfer<dim,VectorType>> & transfer)372 MGTransferGlobalCoarsening<MatrixType, VectorType>::MGTransferGlobalCoarsening(
373 const MGLevelObject<MatrixType> & matrices,
374 const MGLevelObject<MGTwoLevelTransfer<dim, VectorType>> &transfer)
375 : matrices(matrices)
376 , transfer(transfer)
377 {
378 AssertDimension(matrices.max_level() - matrices.min_level(),
379 transfer.max_level() - transfer.min_level());
380 }
381
382
383
384 template <typename MatrixType, typename VectorType>
385 void
prolongate(const unsigned int to_level,VectorType & dst,const VectorType & src)386 MGTransferGlobalCoarsening<MatrixType, VectorType>::prolongate(
387 const unsigned int to_level,
388 VectorType & dst,
389 const VectorType & src) const
390 {
391 this->transfer[to_level].prolongate(dst, src);
392 }
393
394
395
396 template <typename MatrixType, typename VectorType>
397 void
restrict_and_add(const unsigned int from_level,VectorType & dst,const VectorType & src)398 MGTransferGlobalCoarsening<MatrixType, VectorType>::restrict_and_add(
399 const unsigned int from_level,
400 VectorType & dst,
401 const VectorType & src) const
402 {
403 this->transfer[from_level].restrict_and_add(dst, src);
404 }
405
406
407
408 template <typename MatrixType, typename VectorType>
409 template <class InVector, int spacedim>
410 void
copy_to_mg(const DoFHandler<dim,spacedim> & dof_handler,MGLevelObject<VectorType> & dst,const InVector & src)411 MGTransferGlobalCoarsening<MatrixType, VectorType>::copy_to_mg(
412 const DoFHandler<dim, spacedim> &dof_handler,
413 MGLevelObject<VectorType> & dst,
414 const InVector & src) const
415 {
416 (void)dof_handler;
417
418 for (unsigned int level = dst.min_level(); level <= dst.max_level(); ++level)
419 matrices[level].initialize_dof_vector(dst[level]);
420
421 dst[dst.max_level()].copy_locally_owned_data_from(src);
422 }
423
424
425
426 template <typename MatrixType, typename VectorType>
427 template <class OutVector, int spacedim>
428 void
copy_from_mg(const DoFHandler<dim,spacedim> & dof_handler,OutVector & dst,const MGLevelObject<VectorType> & src)429 MGTransferGlobalCoarsening<MatrixType, VectorType>::copy_from_mg(
430 const DoFHandler<dim, spacedim> &dof_handler,
431 OutVector & dst,
432 const MGLevelObject<VectorType> &src) const
433 {
434 (void)dof_handler;
435
436 dst.copy_locally_owned_data_from(src[src.max_level()]);
437 }
438
439 #endif
440
441 DEAL_II_NAMESPACE_CLOSE
442
443 #endif
444