1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1999 - 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_relaxation_block_templates_h
17 #define dealii_relaxation_block_templates_h
18
19 #include <deal.II/base/config.h>
20
21 #include <deal.II/lac/full_matrix.h>
22 #include <deal.II/lac/relaxation_block.h>
23 #include <deal.II/lac/trilinos_vector.h>
24 #include <deal.II/lac/vector_memory.h>
25
26 DEAL_II_NAMESPACE_OPEN
27
28 template <typename MatrixType, typename InverseNumberType, typename VectorType>
29 inline RelaxationBlock<MatrixType, InverseNumberType, VectorType>::
AdditionalData(const double relaxation,const bool invert_diagonal,const bool same_diagonal,const typename PreconditionBlockBase<InverseNumberType>::Inversion inversion,const double threshold,VectorType * temp_ghost_vector)30 AdditionalData::AdditionalData(
31 const double relaxation,
32 const bool invert_diagonal,
33 const bool same_diagonal,
34 const typename PreconditionBlockBase<InverseNumberType>::Inversion
35 inversion,
36 const double threshold,
37 VectorType * temp_ghost_vector)
38 : relaxation(relaxation)
39 , invert_diagonal(invert_diagonal)
40 , same_diagonal(same_diagonal)
41 , inversion(inversion)
42 , threshold(threshold)
43 , temp_ghost_vector(temp_ghost_vector)
44 {}
45
46
47 template <typename MatrixType, typename InverseNumberType, typename VectorType>
48 inline std::size_t
49 RelaxationBlock<MatrixType, InverseNumberType, VectorType>::AdditionalData::
memory_consumption()50 memory_consumption() const
51 {
52 return sizeof(*this) + block_list.memory_consumption() - sizeof(block_list) +
53 MemoryConsumption::memory_consumption(order);
54 }
55
56
57 template <typename MatrixType, typename InverseNumberType, typename VectorType>
58 inline void
initialize(const MatrixType & M,const AdditionalData & parameters)59 RelaxationBlock<MatrixType, InverseNumberType, VectorType>::initialize(
60 const MatrixType & M,
61 const AdditionalData ¶meters)
62 {
63 Assert(parameters.invert_diagonal, ExcNotImplemented());
64
65 clear();
66 // Assert (M.m() == M.n(), ExcNotQuadratic());
67 A = &M;
68 additional_data = ¶meters;
69 this->inversion = parameters.inversion;
70
71 this->reinit(additional_data->block_list.n_rows(),
72 0,
73 additional_data->same_diagonal,
74 additional_data->inversion);
75
76 if (additional_data->invert_diagonal)
77 invert_diagblocks();
78 }
79
80
81 template <typename MatrixType, typename InverseNumberType, typename VectorType>
82 inline void
clear()83 RelaxationBlock<MatrixType, InverseNumberType, VectorType>::clear()
84 {
85 A = nullptr;
86 additional_data = nullptr;
87 PreconditionBlockBase<InverseNumberType>::clear();
88 }
89
90
91 template <typename MatrixType, typename InverseNumberType, typename VectorType>
92 inline void
invert_diagblocks()93 RelaxationBlock<MatrixType, InverseNumberType, VectorType>::invert_diagblocks()
94 {
95 if (this->same_diagonal())
96 {
97 Assert(false, ExcNotImplemented());
98 }
99 else
100 {
101 // compute blocks in parallel
102 parallel::apply_to_subranges(0,
103 this->additional_data->block_list.n_rows(),
104 [this](const size_type block_begin,
105 const size_type block_end) {
106 this->block_kernel(block_begin, block_end);
107 },
108 16);
109 }
110 this->inverses_computed(true);
111 }
112
113
114 template <typename MatrixType, typename InverseNumberType, typename VectorType>
115 inline void
block_kernel(const size_type block_begin,const size_type block_end)116 RelaxationBlock<MatrixType, InverseNumberType, VectorType>::block_kernel(
117 const size_type block_begin,
118 const size_type block_end)
119 {
120 const MatrixType & M = *(this->A);
121 FullMatrix<InverseNumberType> M_cell;
122
123 for (size_type block = block_begin; block < block_end; ++block)
124 {
125 const size_type bs = this->additional_data->block_list.row_length(block);
126 M_cell.reinit(bs, bs);
127
128 // Copy rows for this block into the matrix for the diagonal block
129 SparsityPattern::iterator row =
130 this->additional_data->block_list.begin(block);
131 for (size_type row_cell = 0; row_cell < bs; ++row_cell, ++row)
132 {
133 for (typename MatrixType::const_iterator entry =
134 M.begin(row->column());
135 entry != M.end(row->column());
136 ++entry)
137 {
138 const size_type column = entry->column();
139 const size_type col_cell =
140 this->additional_data->block_list.row_position(block, column);
141 if (col_cell != numbers::invalid_size_type)
142 M_cell(row_cell, col_cell) = entry->value();
143 }
144 }
145 // Now M_cell contains the diagonal block. Now store it and its
146 // inverse, if so requested.
147 if (this->store_diagonals())
148 {
149 this->diagonal(block).reinit(bs, bs);
150 this->diagonal(block) = M_cell;
151 }
152 switch (this->inversion)
153 {
154 case PreconditionBlockBase<InverseNumberType>::gauss_jordan:
155 this->inverse(block).reinit(bs, bs);
156 this->inverse(block).invert(M_cell);
157 break;
158 case PreconditionBlockBase<InverseNumberType>::householder:
159 this->inverse_householder(block).initialize(M_cell);
160 break;
161 case PreconditionBlockBase<InverseNumberType>::svd:
162 this->inverse_svd(block).reinit(bs, bs);
163 this->inverse_svd(block) = M_cell;
164 if (this->additional_data->kernel_size > 0)
165 this->inverse_svd(block).compute_inverse_svd_with_kernel(
166 this->additional_data->kernel_size);
167 else
168 this->inverse_svd(block).compute_inverse_svd(
169 this->additional_data->threshold);
170 break;
171 default:
172 Assert(false, ExcNotImplemented());
173 }
174 }
175 }
176
177 namespace internal
178 {
179 /**
180 * Default implementation for serial vectors. Here we don't need to make a
181 * copy into a ghosted vector, so just return a reference to @p prev.
182 */
183 template <class VectorType>
184 const VectorType &
prepare_ghost_vector(const VectorType & prev,VectorType * other)185 prepare_ghost_vector(const VectorType &prev, VectorType *other)
186 {
187 // If the following Assertion triggers, you either set temp_ghost_vector
188 // for a serial computation (don't!), or nobody implemented, instantiated,
189 // and tested the parallel version for your vector type.
190 Assert(other == nullptr, ExcNotImplemented());
191 (void)other;
192 return prev;
193 }
194
195 #ifdef DEAL_II_WITH_TRILINOS
196 /**
197 * Specialization for Trilinos. Use the ghosted vector.
198 */
199 template <>
200 const TrilinosWrappers::MPI::Vector &
prepare_ghost_vector(const TrilinosWrappers::MPI::Vector & prev,TrilinosWrappers::MPI::Vector * other)201 prepare_ghost_vector(const TrilinosWrappers::MPI::Vector &prev,
202 TrilinosWrappers::MPI::Vector * other)
203 {
204 Assert(
205 other != nullptr,
206 ExcMessage(
207 "You need to provide a ghosted vector in RelaxationBlock::AdditionalData::temp_trilinos_ghost_vector."));
208 Assert(other->size() == prev.size(), ExcInternalError());
209
210 // import ghost values:
211 *other = prev;
212 return *other;
213 }
214 #endif // DEAL_II_WITH_TRILINOS
215 } // end namespace internal
216
217 template <typename MatrixType, typename InverseNumberType, typename VectorType>
218 inline void
do_step(VectorType & dst,const VectorType & prev,const VectorType & src,const bool backward)219 RelaxationBlock<MatrixType, InverseNumberType, VectorType>::do_step(
220 VectorType & dst,
221 const VectorType &prev,
222 const VectorType &src,
223 const bool backward) const
224 {
225 Assert(additional_data->invert_diagonal, ExcNotImplemented());
226
227 const VectorType &ghosted_prev =
228 internal::prepare_ghost_vector(prev, additional_data->temp_ghost_vector);
229
230 const MatrixType & M = *this->A;
231 Vector<typename VectorType::value_type> b_cell, x_cell;
232
233 const bool permutation_empty = additional_data->order.size() == 0;
234 const unsigned int n_permutations =
235 (permutation_empty) ? 1U : additional_data->order.size();
236 const size_type n_blocks = additional_data->block_list.n_rows();
237
238 if (!permutation_empty)
239 for (unsigned int i = 0; i < additional_data->order.size(); ++i)
240 AssertDimension(additional_data->order[i].size(), this->size());
241
242 for (unsigned int perm = 0; perm < n_permutations; ++perm)
243 {
244 for (unsigned int bi = 0; bi < n_blocks; ++bi)
245 {
246 const unsigned int raw_block = backward ? (n_blocks - bi - 1) : bi;
247 const unsigned int block =
248 permutation_empty ?
249 raw_block :
250 (backward ? (additional_data
251 ->order[n_permutations - 1 - perm][raw_block]) :
252 (additional_data->order[perm][raw_block]));
253
254 const size_type bs = additional_data->block_list.row_length(block);
255
256 b_cell.reinit(bs);
257 x_cell.reinit(bs);
258 // Collect off-diagonal parts
259 SparsityPattern::iterator row =
260 additional_data->block_list.begin(block);
261 for (size_type row_cell = 0; row_cell < bs; ++row_cell, ++row)
262 {
263 b_cell(row_cell) = src(row->column());
264 for (typename MatrixType::const_iterator entry =
265 M.begin(row->column());
266 entry != M.end(row->column());
267 ++entry)
268 b_cell(row_cell) -=
269 entry->value() * ghosted_prev(entry->column());
270 }
271 // Apply inverse diagonal
272 this->inverse_vmult(block, x_cell, b_cell);
273 #ifdef DEBUG
274 for (unsigned int i = 0; i < x_cell.size(); ++i)
275 {
276 AssertIsFinite(x_cell(i));
277 }
278 #endif
279 // Store in result vector
280 row = additional_data->block_list.begin(block);
281 for (size_type row_cell = 0; row_cell < bs; ++row_cell, ++row)
282 dst(row->column()) +=
283 additional_data->relaxation * x_cell(row_cell);
284 }
285 }
286 dst.compress(dealii::VectorOperation::add);
287 }
288
289
290 //----------------------------------------------------------------------//
291
292 template <typename MatrixType, typename InverseNumberType, typename VectorType>
293 void
step(VectorType & dst,const VectorType & src)294 RelaxationBlockJacobi<MatrixType, InverseNumberType, VectorType>::step(
295 VectorType & dst,
296 const VectorType &src) const
297 {
298 GrowingVectorMemory<VectorType> mem;
299 typename VectorMemory<VectorType>::Pointer aux(mem);
300 aux->reinit(dst, false);
301 *aux = dst;
302 this->do_step(dst, *aux, src, false);
303 }
304
305
306 template <typename MatrixType, typename InverseNumberType, typename VectorType>
307 void
Tstep(VectorType & dst,const VectorType & src)308 RelaxationBlockJacobi<MatrixType, InverseNumberType, VectorType>::Tstep(
309 VectorType & dst,
310 const VectorType &src) const
311 {
312 GrowingVectorMemory<VectorType> mem;
313 typename VectorMemory<VectorType>::Pointer aux(mem);
314 aux->reinit(dst, false);
315 *aux = dst;
316 this->do_step(dst, *aux, src, true);
317 }
318
319
320 template <typename MatrixType, typename InverseNumberType, typename VectorType>
321 void
vmult(VectorType & dst,const VectorType & src)322 RelaxationBlockJacobi<MatrixType, InverseNumberType, VectorType>::vmult(
323 VectorType & dst,
324 const VectorType &src) const
325 {
326 GrowingVectorMemory<VectorType> mem;
327 typename VectorMemory<VectorType>::Pointer aux(mem);
328 dst = 0;
329 aux->reinit(dst);
330 this->do_step(dst, *aux, src, false);
331 }
332
333
334 template <typename MatrixType, typename InverseNumberType, typename VectorType>
335 void
Tvmult(VectorType & dst,const VectorType & src)336 RelaxationBlockJacobi<MatrixType, InverseNumberType, VectorType>::Tvmult(
337 VectorType & dst,
338 const VectorType &src) const
339 {
340 GrowingVectorMemory<VectorType> mem;
341 typename VectorMemory<VectorType>::Pointer aux(mem);
342 dst = 0;
343 aux->reinit(dst);
344 this->do_step(dst, *aux, src, true);
345 }
346
347
348 //----------------------------------------------------------------------//
349
350 template <typename MatrixType, typename InverseNumberType, typename VectorType>
351 void
step(VectorType & dst,const VectorType & src)352 RelaxationBlockSOR<MatrixType, InverseNumberType, VectorType>::step(
353 VectorType & dst,
354 const VectorType &src) const
355 {
356 this->do_step(dst, dst, src, false);
357 }
358
359
360 template <typename MatrixType, typename InverseNumberType, typename VectorType>
361 void
Tstep(VectorType & dst,const VectorType & src)362 RelaxationBlockSOR<MatrixType, InverseNumberType, VectorType>::Tstep(
363 VectorType & dst,
364 const VectorType &src) const
365 {
366 this->do_step(dst, dst, src, true);
367 }
368
369
370 template <typename MatrixType, typename InverseNumberType, typename VectorType>
371 void
vmult(VectorType & dst,const VectorType & src)372 RelaxationBlockSOR<MatrixType, InverseNumberType, VectorType>::vmult(
373 VectorType & dst,
374 const VectorType &src) const
375 {
376 dst = 0;
377 this->do_step(dst, dst, src, false);
378 }
379
380
381 template <typename MatrixType, typename InverseNumberType, typename VectorType>
382 void
Tvmult(VectorType & dst,const VectorType & src)383 RelaxationBlockSOR<MatrixType, InverseNumberType, VectorType>::Tvmult(
384 VectorType & dst,
385 const VectorType &src) const
386 {
387 dst = 0;
388 this->do_step(dst, dst, src, true);
389 }
390
391
392 //----------------------------------------------------------------------//
393
394 template <typename MatrixType, typename InverseNumberType, typename VectorType>
395 void
step(VectorType & dst,const VectorType & src)396 RelaxationBlockSSOR<MatrixType, InverseNumberType, VectorType>::step(
397 VectorType & dst,
398 const VectorType &src) const
399 {
400 this->do_step(dst, dst, src, false);
401 this->do_step(dst, dst, src, true);
402 }
403
404
405 template <typename MatrixType, typename InverseNumberType, typename VectorType>
406 void
Tstep(VectorType & dst,const VectorType & src)407 RelaxationBlockSSOR<MatrixType, InverseNumberType, VectorType>::Tstep(
408 VectorType & dst,
409 const VectorType &src) const
410 {
411 this->do_step(dst, dst, src, true);
412 this->do_step(dst, dst, src, false);
413 }
414
415
416 template <typename MatrixType, typename InverseNumberType, typename VectorType>
417 void
vmult(VectorType & dst,const VectorType & src)418 RelaxationBlockSSOR<MatrixType, InverseNumberType, VectorType>::vmult(
419 VectorType & dst,
420 const VectorType &src) const
421 {
422 dst = 0;
423 this->do_step(dst, dst, src, false);
424 this->do_step(dst, dst, src, true);
425 }
426
427
428 template <typename MatrixType, typename InverseNumberType, typename VectorType>
429 void
Tvmult(VectorType & dst,const VectorType & src)430 RelaxationBlockSSOR<MatrixType, InverseNumberType, VectorType>::Tvmult(
431 VectorType & dst,
432 const VectorType &src) const
433 {
434 dst = 0;
435 this->do_step(dst, dst, src, true);
436 this->do_step(dst, dst, src, false);
437 }
438
439
440
441 DEAL_II_NAMESPACE_CLOSE
442
443
444 #endif
445