1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1999 - 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 #ifndef dealii_full_matrix_h
17 #define dealii_full_matrix_h
18
19
20 #include <deal.II/base/config.h>
21
22 #include <deal.II/base/numbers.h>
23 #include <deal.II/base/table.h>
24 #include <deal.II/base/tensor.h>
25
26 #include <deal.II/differentiation/ad/ad_number_traits.h>
27
28 #include <deal.II/lac/exceptions.h>
29 #include <deal.II/lac/identity_matrix.h>
30
31 #include <cstring>
32 #include <iomanip>
33 #include <vector>
34
35 DEAL_II_NAMESPACE_OPEN
36
37
38 // forward declarations
39 #ifndef DOXYGEN
40 template <typename number>
41 class Vector;
42 template <typename number>
43 class LAPACKFullMatrix;
44 #endif
45
46 /*! @addtogroup Matrix1
47 *@{
48 */
49
50
51 /**
52 * Implementation of a classical rectangular scheme of numbers. The data type
53 * of the entries is provided in the template argument <tt>number</tt>. The
54 * interface is quite fat and in fact has grown every time a new feature was
55 * needed. So, a lot of functions are provided.
56 *
57 * Internal calculations are usually done with the accuracy of the vector
58 * argument to functions. If there is no argument with a number type, the
59 * matrix number type is used.
60 *
61 * @note Instantiations for this template are provided for <tt>@<float@>,
62 * @<double@>, @<std::complex@<float@>@>,
63 * @<std::complex@<double@>@></tt>. Others can be generated in application
64 * programs, see
65 * @ref Instantiations
66 * for details.
67 */
68 template <typename number>
69 class FullMatrix : public Table<2, number>
70 {
71 public:
72 // The assertion in full_matrix.templates.h for whether or not a number is
73 // finite is not compatible for AD number types.
74 static_assert(
75 !Differentiation::AD::is_ad_number<number>::value,
76 "The FullMatrix class does not support auto-differentiable numbers.");
77
78 /**
79 * A type of used to index into this container.
80 */
81 using size_type = std::size_t;
82
83 /**
84 * Type of matrix entries. This alias is analogous to <tt>value_type</tt>
85 * in the standard library containers.
86 */
87 using value_type = number;
88
89 /**
90 * Use the base class mutable iterator type.
91 */
92 using iterator = typename Table<2, number>::iterator;
93
94 /**
95 * Use the base class constant iterator type.
96 */
97 using const_iterator = typename Table<2, number>::const_iterator;
98
99 /**
100 * Use the base class iterator functions.
101 */
102 using Table<2, number>::begin;
103
104 /**
105 * Use the base class iterator functions
106 */
107 using Table<2, number>::end;
108
109 /**
110 * Declare a type that has holds real-valued numbers with the same precision
111 * as the template argument to this class. If the template argument of this
112 * class is a real data type, then real_type equals the template argument.
113 * If the template argument is a std::complex type then real_type equals the
114 * type underlying the complex numbers.
115 *
116 * This alias is used to represent the return type of norms.
117 */
118 using real_type = typename numbers::NumberTraits<number>::real_type;
119
120 /**
121 * @name Constructors and initialization. See also the base class Table.
122 */
123 //@{
124
125 /**
126 * Constructor. Initialize the matrix as a square matrix with dimension
127 * <tt>n</tt>.
128 *
129 * In order to avoid the implicit conversion of integers and other types to
130 * a matrix, this constructor is declared <tt>explicit</tt>.
131 *
132 * By default, no memory is allocated.
133 */
134 explicit FullMatrix(const size_type n = 0);
135
136 /**
137 * Constructor. Initialize the matrix as a rectangular matrix.
138 */
139 FullMatrix(const size_type rows, const size_type cols);
140
141 /**
142 * Constructor initializing from an array of numbers. The array is arranged
143 * line by line. No range checking is performed.
144 */
145 FullMatrix(const size_type rows, const size_type cols, const number *entries);
146
147 /**
148 * Construct a full matrix that equals the identity matrix of the size of
149 * the argument. Using this constructor, one can easily create an identity
150 * matrix of size <code>n</code> by saying
151 * @code
152 * FullMatrix<double> M(IdentityMatrix(n));
153 * @endcode
154 */
155 FullMatrix(const IdentityMatrix &id);
156 /**
157 * @}
158 */
159
160 /**
161 * @name Copying into and out of other matrices
162 */
163 /**
164 * @{
165 */
166
167 /**
168 * Variable assignment operator.
169 */
170 template <typename number2>
171 FullMatrix<number> &
172 operator=(const FullMatrix<number2> &);
173
174 /**
175 * This operator assigns a scalar to a matrix. To avoid confusion with the
176 * semantics of this function, zero is the only value allowed for
177 * <tt>d</tt>, allowing you to clear a matrix in an intuitive way.
178 *
179 * @dealiiOperationIsMultithreaded
180 */
181 FullMatrix<number> &
182 operator=(const number d);
183
184 /**
185 * Copy operator to create a full matrix that equals the identity matrix of
186 * the size of the argument. This way, one can easily create an identity
187 * matrix of size <code>n</code> by saying
188 * @code
189 * M = IdentityMatrix(n);
190 * @endcode
191 */
192 FullMatrix<number> &
193 operator=(const IdentityMatrix &id);
194
195 /**
196 * Assignment operator for a LapackFullMatrix. The calling matrix must be of
197 * the same size as the LAPACK matrix.
198 */
199 template <typename number2>
200 FullMatrix<number> &
201 operator=(const LAPACKFullMatrix<number2> &);
202
203
204 /**
205 * Assignment from different matrix classes. This assignment operator uses
206 * iterators of the typename MatrixType. Therefore, sparse matrices are
207 * possible sources.
208 */
209 template <typename MatrixType>
210 void
211 copy_from(const MatrixType &);
212
213 /**
214 * Transposing assignment from different matrix classes. This assignment
215 * operator uses iterators of the typename MatrixType. Therefore, sparse
216 * matrices are possible sources.
217 */
218 template <typename MatrixType>
219 void
220 copy_transposed(const MatrixType &);
221
222 /**
223 * Fill matrix with elements extracted from a tensor, taking rows included
224 * between <tt>r_i</tt> and <tt>r_j</tt> and columns between <tt>c_i</tt>
225 * and <tt>c_j</tt>. The resulting matrix is then inserted in the
226 * destination matrix at position <tt>(dst_r, dst_c)</tt> Checks on the
227 * indices are made.
228 */
229 template <int dim>
230 void
231 copy_from(const Tensor<2, dim> &T,
232 const unsigned int src_r_i = 0,
233 const unsigned int src_r_j = dim - 1,
234 const unsigned int src_c_i = 0,
235 const unsigned int src_c_j = dim - 1,
236 const size_type dst_r = 0,
237 const size_type dst_c = 0);
238
239 /**
240 * Insert a submatrix (also rectangular) into a tensor, putting its upper
241 * left element at the specified position <tt>(dst_r, dst_c)</tt> and the
242 * other elements consequently. Default values are chosen so that no
243 * parameter needs to be specified if the size of the tensor and that of the
244 * matrix coincide.
245 */
246 template <int dim>
247 void copy_to(Tensor<2, dim> & T,
248 const size_type src_r_i = 0,
249 const size_type src_r_j = dim - 1,
250 const size_type src_c_i = 0,
251 const size_type src_c_j = dim - 1,
252 const unsigned int dst_r = 0,
253 const unsigned int dst_c = 0) const;
254
255 /**
256 * Copy a subset of the rows and columns of another matrix into the current
257 * object.
258 *
259 * @param matrix The matrix from which a subset is to be taken from.
260 * @param row_index_set The set of rows of @p matrix from which to extract.
261 * @param column_index_set The set of columns of @p matrix from which to
262 * extract. @pre The number of elements in @p row_index_set and @p
263 * column_index_set shall be equal to the number of rows and columns in the
264 * current object. In other words, the current object is not resized for
265 * this operation.
266 */
267 template <typename MatrixType, typename index_type>
268 void
269 extract_submatrix_from(const MatrixType & matrix,
270 const std::vector<index_type> &row_index_set,
271 const std::vector<index_type> &column_index_set);
272
273 /**
274 * Copy the elements of the current matrix object into a specified set of
275 * rows and columns of another matrix. Thus, this is a scatter operation.
276 *
277 * @param row_index_set The rows of @p matrix into which to write.
278 * @param column_index_set The columns of @p matrix into which to write.
279 * @param matrix The matrix within which certain elements are to be
280 * replaced. @pre The number of elements in @p row_index_set and @p
281 * column_index_set shall be equal to the number of rows and columns in the
282 * current object. In other words, the current object is not resized for
283 * this operation.
284 */
285 template <typename MatrixType, typename index_type>
286 void
287 scatter_matrix_to(const std::vector<index_type> &row_index_set,
288 const std::vector<index_type> &column_index_set,
289 MatrixType & matrix) const;
290
291 /**
292 * Fill rectangular block.
293 *
294 * A rectangular block of the matrix <tt>src</tt> is copied into
295 * <tt>this</tt>. The upper left corner of the block being copied is
296 * <tt>(src_offset_i,src_offset_j)</tt>. The upper left corner of the
297 * copied block is <tt>(dst_offset_i,dst_offset_j)</tt>. The size of the
298 * rectangular block being copied is the maximum size possible, determined
299 * either by the size of <tt>this</tt> or <tt>src</tt>.
300 */
301 template <typename number2>
302 void
303 fill(const FullMatrix<number2> &src,
304 const size_type dst_offset_i = 0,
305 const size_type dst_offset_j = 0,
306 const size_type src_offset_i = 0,
307 const size_type src_offset_j = 0);
308
309
310 /**
311 * Make function of base class available.
312 */
313 template <typename number2>
314 void
315 fill(const number2 *);
316
317 /**
318 * Fill with permutation of another matrix.
319 *
320 * The matrix <tt>src</tt> is copied into the target. The two permutation
321 * <tt>p_r</tt> and <tt>p_c</tt> operate in a way, such that <tt>result(i,j)
322 * = src(p_r[i], p_c[j])</tt>.
323 *
324 * The vectors may also be a selection from a larger set of integers, if the
325 * matrix <tt>src</tt> is bigger. It is also possible to duplicate rows or
326 * columns by this method.
327 */
328 template <typename number2>
329 void
330 fill_permutation(const FullMatrix<number2> & src,
331 const std::vector<size_type> &p_rows,
332 const std::vector<size_type> &p_cols);
333
334 /**
335 * Set a particular entry of the matrix to a value. Thus, calling
336 * <code>A.set(1,2,3.141);</code> is entirely equivalent to the operation
337 * <code>A(1,2) = 3.141;</code>. This function exists for compatibility with
338 * the various sparse matrix objects.
339 *
340 * @param i The row index of the element to be set.
341 * @param j The columns index of the element to be set.
342 * @param value The value to be written into the element.
343 */
344 void
345 set(const size_type i, const size_type j, const number value);
346 /**
347 * @}
348 */
349 /**
350 * @name Non-modifying operators
351 */
352 /**
353 * @{
354 */
355
356 /**
357 * Comparison operator. Be careful with this thing, it may eat up huge
358 * amounts of computing time! It is most commonly used for internal
359 * consistency checks of programs.
360 */
361 bool
362 operator==(const FullMatrix<number> &) const;
363
364 /**
365 * Number of rows of this matrix. Note that the matrix is of dimension <i>m
366 * x n</i>.
367 */
368 size_type
369 m() const;
370
371 /**
372 * Number of columns of this matrix. Note that the matrix is of dimension
373 * <i>m x n</i>.
374 */
375 size_type
376 n() const;
377
378 /**
379 * Return whether the matrix contains only elements with value zero. This
380 * function is mainly for internal consistency checks and should seldom be
381 * used when not in debug mode since it uses quite some time.
382 */
383 bool
384 all_zero() const;
385
386 /**
387 * Return the square of the norm of the vector <tt>v</tt> induced by this
388 * matrix, i.e. <i>(v,Mv)</i>. This is useful, e.g. in the finite element
389 * context, where the <i>L<sup>2</sup></i> norm of a function equals the
390 * matrix norm with respect to the mass matrix of the vector representing
391 * the nodal values of the finite element function.
392 *
393 * Obviously, the matrix needs to be quadratic for this operation, and for
394 * the result to actually be a norm it also needs to be either real
395 * symmetric or complex hermitian.
396 *
397 * The underlying template types of both this matrix and the given vector
398 * should either both be real or complex-valued, but not mixed, for this
399 * function to make sense.
400 */
401 template <typename number2>
402 number2
403 matrix_norm_square(const Vector<number2> &v) const;
404
405 /**
406 * Build the matrix scalar product <tt>u<sup>T</sup> M v</tt>. This function
407 * is mostly useful when building the cellwise scalar product of two
408 * functions in the finite element context.
409 *
410 * The underlying template types of both this matrix and the given vector
411 * should either both be real or complex-valued, but not mixed, for this
412 * function to make sense.
413 */
414 template <typename number2>
415 number2
416 matrix_scalar_product(const Vector<number2> &u,
417 const Vector<number2> &v) const;
418
419 /**
420 * Return the <i>l<sub>1</sub></i>-norm of the matrix, where $||M||_1 =
421 * \max_j \sum_i |M_{ij}|$ (maximum of the sums over columns).
422 */
423 real_type
424 l1_norm() const;
425
426 /**
427 * Return the $l_\infty$-norm of the matrix, where $||M||_\infty = \max_i
428 * \sum_j |M_{ij}|$ (maximum of the sums over rows).
429 */
430 real_type
431 linfty_norm() const;
432
433 /**
434 * Compute the Frobenius norm of the matrix. Return value is the root of
435 * the square sum of all matrix entries.
436 *
437 * @note For the timid among us: this norm is not the norm compatible with
438 * the <i>l<sub>2</sub></i>-norm of the vector space.
439 */
440 real_type
441 frobenius_norm() const;
442
443 /**
444 * Compute the relative norm of the skew-symmetric part. The return value is
445 * the Frobenius norm of the skew-symmetric part of the matrix divided by
446 * that of the matrix.
447 *
448 * Main purpose of this function is to check, if a matrix is symmetric
449 * within a certain accuracy, or not.
450 */
451 real_type
452 relative_symmetry_norm2() const;
453
454 /**
455 * Compute the determinant of a matrix. This is only implemented for one,
456 * two, and three dimensions, since for higher dimensions the numerical work
457 * explodes. Obviously, the matrix needs to be quadratic for this function.
458 */
459 number
460 determinant() const;
461
462 /**
463 * Return the trace of the matrix, i.e. the sum of the diagonal values
464 * (which happens to also equal the sum of the eigenvalues of a matrix).
465 * Obviously, the matrix needs to be quadratic for this function.
466 */
467 number
468 trace() const;
469
470 /**
471 * Output of the matrix in user-defined format given by the specified
472 * precision and width. This function saves width and precision of the
473 * stream before setting these given values for output, and restores the
474 * previous values after output.
475 */
476 template <class StreamType>
477 void
478 print(StreamType & s,
479 const unsigned int width = 5,
480 const unsigned int precision = 2) const;
481
482 /**
483 * Print the matrix and allow formatting of entries.
484 *
485 * The parameters allow for a flexible setting of the output format:
486 *
487 * @arg <tt>precision</tt> denotes the number of trailing digits.
488 *
489 * @arg <tt>scientific</tt> is used to determine the number format, where
490 * <tt>scientific</tt> = <tt>false</tt> means fixed point notation.
491 *
492 * @arg <tt>width</tt> denotes the with of each column. A zero entry for
493 * <tt>width</tt> makes the function compute a width, but it may be changed
494 * to a positive value, if output is crude.
495 *
496 * @arg <tt>zero_string</tt> specifies a string printed for zero entries.
497 *
498 * @arg <tt>denominator</tt> Multiply the whole matrix by this common
499 * denominator to get nicer numbers.
500 *
501 * @arg <tt>threshold</tt>: all entries with absolute value smaller than
502 * this are considered zero.
503 */
504 void
505 print_formatted(std::ostream & out,
506 const unsigned int precision = 3,
507 const bool scientific = true,
508 const unsigned int width = 0,
509 const char * zero_string = " ",
510 const double denominator = 1.,
511 const double threshold = 0.) const;
512
513 /**
514 * Determine an estimate for the memory consumption (in bytes) of this
515 * object.
516 */
517 std::size_t
518 memory_consumption() const;
519
520 //@}
521 ///@name Iterator functions
522 //@{
523
524 /**
525 * Mutable iterator starting at the first entry of row <tt>r</tt>.
526 */
527 iterator
528 begin(const size_type r);
529
530 /**
531 * One past the end mutable iterator of row <tt>r</tt>.
532 */
533 iterator
534 end(const size_type r);
535
536 /**
537 * Constant iterator starting at the first entry of row <tt>r</tt>.
538 */
539 const_iterator
540 begin(const size_type r) const;
541
542 /**
543 * One past the end constant iterator of row <tt>r</tt>.
544 */
545 const_iterator
546 end(const size_type r) const;
547
548 //@}
549 ///@name Modifying operators
550 //@{
551
552 /**
553 * Scale the entire matrix by a fixed factor.
554 */
555 FullMatrix &
556 operator*=(const number factor);
557
558 /**
559 * Scale the entire matrix by the inverse of the given factor.
560 */
561 FullMatrix &
562 operator/=(const number factor);
563
564 /**
565 * Simple addition of a scaled matrix, i.e. <tt>*this += a*A</tt>.
566 *
567 * The matrix <tt>A</tt> may be a full matrix over an arbitrary underlying
568 * scalar type, as long as its data type is convertible to the data type of
569 * this matrix.
570 */
571 template <typename number2>
572 void
573 add(const number a, const FullMatrix<number2> &A);
574
575 /**
576 * Multiple addition of scaled matrices, i.e. <tt>*this += a*A + b*B</tt>.
577 *
578 * The matrices <tt>A</tt> and <tt>B</tt> may be a full matrix over an
579 * arbitrary underlying scalar type, as long as its data type is convertible
580 * to the data type of this matrix.
581 */
582 template <typename number2>
583 void
584 add(const number a,
585 const FullMatrix<number2> &A,
586 const number b,
587 const FullMatrix<number2> &B);
588
589 /**
590 * Multiple addition of scaled matrices, i.e. <tt>*this += a*A + b*B +
591 * c*C</tt>.
592 *
593 * The matrices <tt>A</tt>, <tt>B</tt> and <tt>C</tt> may be a full matrix
594 * over an arbitrary underlying scalar type, as long as its data type is
595 * convertible to the data type of this matrix.
596 */
597 template <typename number2>
598 void
599 add(const number a,
600 const FullMatrix<number2> &A,
601 const number b,
602 const FullMatrix<number2> &B,
603 const number c,
604 const FullMatrix<number2> &C);
605
606 /**
607 * Add rectangular block.
608 *
609 * A rectangular block of the matrix <tt>src</tt> is added to <tt>this</tt>.
610 * The upper left corner of the block being copied is
611 * <tt>(src_offset_i,src_offset_j)</tt>. The upper left corner of the
612 * copied block is <tt>(dst_offset_i,dst_offset_j)</tt>. The size of the
613 * rectangular block being copied is the maximum size possible, determined
614 * either by the size of <tt>this</tt> or <tt>src</tt> and the given
615 * offsets.
616 */
617 template <typename number2>
618 void
619 add(const FullMatrix<number2> &src,
620 const number factor,
621 const size_type dst_offset_i = 0,
622 const size_type dst_offset_j = 0,
623 const size_type src_offset_i = 0,
624 const size_type src_offset_j = 0);
625
626 /**
627 * Weighted addition of the transpose of <tt>B</tt> to <tt>this</tt>.
628 *
629 * <i>A += s B<sup>T</sup></i>
630 */
631 template <typename number2>
632 void
633 Tadd(const number s, const FullMatrix<number2> &B);
634
635 /**
636 * Add transpose of a rectangular block.
637 *
638 * A rectangular block of the matrix <tt>src</tt> is transposed and
639 * addedadded to <tt>this</tt>. The upper left corner of the block being
640 * copied is <tt>(src_offset_i,src_offset_j)</tt> in the coordinates of the
641 * <b>non</b>-transposed matrix. The upper left corner of the copied block
642 * is <tt>(dst_offset_i,dst_offset_j)</tt>. The size of the rectangular
643 * block being copied is the maximum size possible, determined either by the
644 * size of <tt>this</tt> or <tt>src</tt>.
645 */
646 template <typename number2>
647 void
648 Tadd(const FullMatrix<number2> &src,
649 const number factor,
650 const size_type dst_offset_i = 0,
651 const size_type dst_offset_j = 0,
652 const size_type src_offset_i = 0,
653 const size_type src_offset_j = 0);
654
655 /**
656 * Add a single element at the given position.
657 */
658 void
659 add(const size_type row, const size_type column, const number value);
660
661 /**
662 * Add an array of values given by <tt>values</tt> in the given global
663 * matrix row at columns specified by col_indices in the full matrix. This
664 * function is present for compatibility with the various sparse matrices in
665 * deal.II. In particular, the two boolean fields @p elide_zero_values and
666 * @p col_indices_are_sorted do not impact the performance of this routine,
667 * as opposed to the sparse matrix case and are indeed ignored in the
668 * implementation.
669 */
670 template <typename number2, typename index_type>
671 void
672 add(const size_type row,
673 const size_type n_cols,
674 const index_type *col_indices,
675 const number2 * values,
676 const bool elide_zero_values = true,
677 const bool col_indices_are_sorted = false);
678
679 /**
680 * <i>A(i,1...n) += s*A(j,1...n)</i>. Simple addition of rows of this
681 */
682 void
683 add_row(const size_type i, const number s, const size_type j);
684
685 /**
686 * <i>A(i,1...n) += s*A(j,1...n) + t*A(k,1...n)</i>. Multiple addition of
687 * rows of this.
688 */
689 void
690 add_row(const size_type i,
691 const number s,
692 const size_type j,
693 const number t,
694 const size_type k);
695
696 /**
697 * <i>A(1...n,i) += s*A(1...n,j)</i>. Simple addition of columns of this.
698 */
699 void
700 add_col(const size_type i, const number s, const size_type j);
701
702 /**
703 * <i>A(1...n,i) += s*A(1...n,j) + t*A(1...n,k)</i>. Multiple addition of
704 * columns of this.
705 */
706 void
707 add_col(const size_type i,
708 const number s,
709 const size_type j,
710 const number t,
711 const size_type k);
712
713 /**
714 * Swap <i>A(i,1...n) <-> A(j,1...n)</i>. Swap rows i and j of this
715 */
716 void
717 swap_row(const size_type i, const size_type j);
718
719 /**
720 * Swap <i>A(1...n,i) <-> A(1...n,j)</i>. Swap columns i and j of this
721 */
722 void
723 swap_col(const size_type i, const size_type j);
724
725 /**
726 * Add constant to diagonal elements of this, i.e. add a multiple of the
727 * identity matrix.
728 */
729 void
730 diagadd(const number s);
731
732 /**
733 * Assignment <tt>*this = a*A</tt>.
734 */
735 template <typename number2>
736 void
737 equ(const number a, const FullMatrix<number2> &A);
738
739 /**
740 * Assignment <tt>*this = a*A + b*B</tt>.
741 */
742 template <typename number2>
743 void
744 equ(const number a,
745 const FullMatrix<number2> &A,
746 const number b,
747 const FullMatrix<number2> &B);
748
749 /**
750 * Assignment <tt>*this = a*A + b*B + c*C</tt>.
751 */
752 template <typename number2>
753 void
754 equ(const number a,
755 const FullMatrix<number2> &A,
756 const number b,
757 const FullMatrix<number2> &B,
758 const number c,
759 const FullMatrix<number2> &C);
760
761 /**
762 * Symmetrize the matrix by forming the mean value between the existing
763 * matrix and its transpose, <i>A = 1/2(A+A<sup>T</sup>)</i>.
764 *
765 * Obviously the matrix must be quadratic for this operation.
766 */
767 void
768 symmetrize();
769
770 /**
771 * A=Inverse(A). A must be a square matrix. Inversion of this matrix by
772 * Gauss-Jordan algorithm with partial pivoting. This process is well-
773 * behaved for positive definite matrices, but be aware of round-off errors
774 * in the indefinite case.
775 *
776 * In case deal.II was configured with LAPACK, the functions Xgetrf and
777 * Xgetri build an LU factorization and invert the matrix upon that
778 * factorization, providing best performance up to matrices with a few
779 * hundreds rows and columns.
780 *
781 * The numerical effort to invert an <tt>n x n</tt> matrix is of the order
782 * <tt>n**3</tt>.
783 */
784 void
785 gauss_jordan();
786
787 /**
788 * Assign the inverse of the given matrix to <tt>*this</tt>. This function
789 * is hardcoded for quadratic matrices of dimension one to four. However,
790 * since the amount of code needed grows quickly, the method gauss_jordan()
791 * is invoked implicitly if the dimension is larger.
792 */
793 template <typename number2>
794 void
795 invert(const FullMatrix<number2> &M);
796
797 /**
798 * Assign the Cholesky decomposition $A=:L L^T$ of the given matrix $A$ to
799 * <tt>*this</tt>, where $L$ is lower triangular matrix. The given matrix must
800 * be symmetric positive definite.
801 *
802 * ExcMatrixNotPositiveDefinite will be thrown in the case that the matrix
803 * is not positive definite.
804 */
805 template <typename number2>
806 void
807 cholesky(const FullMatrix<number2> &A);
808
809 /**
810 * <tt>*this(i,j)</tt> = $V(i) W(j)$ where $V,W$ are vectors of the same
811 * length.
812 */
813 template <typename number2>
814 void
815 outer_product(const Vector<number2> &V, const Vector<number2> &W);
816
817 /**
818 * Assign the left_inverse of the given matrix to <tt>*this</tt>. The
819 * calculation being performed is <i>(A<sup>T</sup>*A)<sup>-1</sup>
820 * *A<sup>T</sup></i>.
821 */
822 template <typename number2>
823 void
824 left_invert(const FullMatrix<number2> &M);
825
826 /**
827 * Assign the right_inverse of the given matrix to <tt>*this</tt>. The
828 * calculation being performed is <i>A<sup>T</sup>*(A*A<sup>T</sup>)
829 * <sup>-1</sup></i>.
830 */
831 template <typename number2>
832 void
833 right_invert(const FullMatrix<number2> &M);
834
835 //@}
836 ///@name Multiplications
837 //@{
838
839 /**
840 * Matrix-matrix-multiplication.
841 *
842 * The optional parameter <tt>adding</tt> determines, whether the result is
843 * stored in <tt>C</tt> or added to <tt>C</tt>.
844 *
845 * if (adding) <i>C += A*B</i>
846 *
847 * if (!adding) <i>C = A*B</i>
848 *
849 * Assumes that <tt>A</tt> and <tt>B</tt> have compatible sizes and that
850 * <tt>C</tt> already has the right size.
851 *
852 * This function uses the BLAS function Xgemm if the product of the three
853 * matrix dimensions is larger than 300 and BLAS was detected during
854 * configuration. Using BLAS usually results in considerable performance
855 * gains.
856 */
857 template <typename number2>
858 void
859 mmult(FullMatrix<number2> & C,
860 const FullMatrix<number2> &B,
861 const bool adding = false) const;
862
863 /**
864 * Matrix-matrix-multiplication using transpose of <tt>this</tt>.
865 *
866 * The optional parameter <tt>adding</tt> determines, whether the result is
867 * stored in <tt>C</tt> or added to <tt>C</tt>.
868 *
869 * if (adding) <i>C += A<sup>T</sup>*B</i>
870 *
871 * if (!adding) <i>C = A<sup>T</sup>*B</i>
872 *
873 * Assumes that <tt>A</tt> and <tt>B</tt> have compatible sizes and that
874 * <tt>C</tt> already has the right size.
875 *
876 * This function uses the BLAS function Xgemm if the product of the three
877 * matrix dimensions is larger than 300 and BLAS was detected during
878 * configuration. Using BLAS usually results in considerable performance
879 * gains.
880 */
881 template <typename number2>
882 void
883 Tmmult(FullMatrix<number2> & C,
884 const FullMatrix<number2> &B,
885 const bool adding = false) const;
886
887 /**
888 * Matrix-matrix-multiplication using transpose of <tt>B</tt>.
889 *
890 * The optional parameter <tt>adding</tt> determines, whether the result is
891 * stored in <tt>C</tt> or added to <tt>C</tt>.
892 *
893 * if (adding) <i>C += A*B<sup>T</sup></i>
894 *
895 * if (!adding) <i>C = A*B<sup>T</sup></i>
896 *
897 * Assumes that <tt>A</tt> and <tt>B</tt> have compatible sizes and that
898 * <tt>C</tt> already has the right size.
899 *
900 * This function uses the BLAS function Xgemm if the product of the three
901 * matrix dimensions is larger than 300 and BLAS was detected during
902 * configuration. Using BLAS usually results in considerable performance
903 * gains.
904 */
905 template <typename number2>
906 void
907 mTmult(FullMatrix<number2> & C,
908 const FullMatrix<number2> &B,
909 const bool adding = false) const;
910
911 /**
912 * Matrix-matrix-multiplication using transpose of <tt>this</tt> and
913 * <tt>B</tt>.
914 *
915 * The optional parameter <tt>adding</tt> determines, whether the result is
916 * stored in <tt>C</tt> or added to <tt>C</tt>.
917 *
918 * if (adding) <i>C += A<sup>T</sup>*B<sup>T</sup></i>
919 *
920 * if (!adding) <i>C = A<sup>T</sup>*B<sup>T</sup></i>
921 *
922 * Assumes that <tt>A</tt> and <tt>B</tt> have compatible sizes and that
923 * <tt>C</tt> already has the right size.
924 *
925 * This function uses the BLAS function Xgemm if the product of the three
926 * matrix dimensions is larger than 300 and BLAS was detected during
927 * configuration. Using BLAS usually results in considerable performance
928 * gains.
929 */
930 template <typename number2>
931 void
932 TmTmult(FullMatrix<number2> & C,
933 const FullMatrix<number2> &B,
934 const bool adding = false) const;
935
936 /**
937 * Add to the current matrix the triple product <b>B A D</b>. Optionally,
938 * use the transposes of the matrices <b>B</b> and <b>D</b>. The scaling
939 * factor scales the whole product, which is helpful when adding a multiple
940 * of the triple product to the matrix.
941 *
942 * This product was written with the Schur complement <b>B<sup>T</sup>
943 * A<sup>-1</sup> D</b> in mind. Note that in this case the argument for
944 * <tt>A</tt> must be the inverse of the matrix <b>A</b>.
945 */
946 void
947 triple_product(const FullMatrix<number> &A,
948 const FullMatrix<number> &B,
949 const FullMatrix<number> &D,
950 const bool transpose_B = false,
951 const bool transpose_D = false,
952 const number scaling = number(1.));
953
954 /**
955 * Matrix-vector-multiplication.
956 *
957 * The optional parameter <tt>adding</tt> determines, whether the result is
958 * stored in <tt>w</tt> or added to <tt>w</tt>.
959 *
960 * if (adding) <i>w += A*v</i>
961 *
962 * if (!adding) <i>w = A*v</i>
963 *
964 * Source and destination must not be the same vector.
965 */
966 template <typename number2>
967 void
968 vmult(Vector<number2> & w,
969 const Vector<number2> &v,
970 const bool adding = false) const;
971
972 /**
973 * Adding Matrix-vector-multiplication. <i>w += A*v</i>
974 *
975 * Source and destination must not be the same vector.
976 */
977 template <typename number2>
978 void
979 vmult_add(Vector<number2> &w, const Vector<number2> &v) const;
980
981 /**
982 * Transpose matrix-vector-multiplication.
983 *
984 * The optional parameter <tt>adding</tt> determines, whether the result is
985 * stored in <tt>w</tt> or added to <tt>w</tt>.
986 *
987 * if (adding) <i>w += A<sup>T</sup>*v</i>
988 *
989 * if (!adding) <i>w = A<sup>T</sup>*v</i>
990 *
991 *
992 * Source and destination must not be the same vector.
993 */
994 template <typename number2>
995 void
996 Tvmult(Vector<number2> & w,
997 const Vector<number2> &v,
998 const bool adding = false) const;
999
1000 /**
1001 * Adding transpose matrix-vector-multiplication. <i>w +=
1002 * A<sup>T</sup>*v</i>
1003 *
1004 * Source and destination must not be the same vector.
1005 */
1006 template <typename number2>
1007 void
1008 Tvmult_add(Vector<number2> &w, const Vector<number2> &v) const;
1009
1010 /**
1011 * Apply the Jacobi preconditioner, which multiplies every element of the
1012 * <tt>src</tt> vector by the inverse of the respective diagonal element and
1013 * multiplies the result with the damping factor <tt>omega</tt>.
1014 */
1015 template <typename somenumber>
1016 void
1017 precondition_Jacobi(Vector<somenumber> & dst,
1018 const Vector<somenumber> &src,
1019 const number omega = 1.) const;
1020
1021 /**
1022 * <i>dst=b-A*x</i>. Residual calculation, returns the
1023 * <i>l<sub>2</sub></i>-norm |<i>dst</i>|.
1024 *
1025 * Source <i>x</i> and destination <i>dst</i> must not be the same vector.
1026 */
1027 template <typename number2, typename number3>
1028 number
1029 residual(Vector<number2> & dst,
1030 const Vector<number2> &x,
1031 const Vector<number3> &b) const;
1032
1033 /**
1034 * Forward elimination of lower triangle. Inverts the lower triangle of a
1035 * rectangular matrix for a given right hand side.
1036 *
1037 * If the matrix has more columns than rows, this function only operates on
1038 * the left quadratic submatrix. If there are more rows, the upper quadratic
1039 * part of the matrix is considered.
1040 *
1041 * @note It is safe to use the same object for @p dst and @p src.
1042 */
1043 template <typename number2>
1044 void
1045 forward(Vector<number2> &dst, const Vector<number2> &src) const;
1046
1047 /**
1048 * Backward elimination of upper triangle.
1049 *
1050 * See forward()
1051 *
1052 * @note It is safe to use the same object for @p dst and @p src.
1053 */
1054 template <typename number2>
1055 void
1056 backward(Vector<number2> &dst, const Vector<number2> &src) const;
1057
1058 //@}
1059
1060 /**
1061 * @addtogroup Exceptions
1062 * @{
1063 */
1064
1065 /**
1066 * Exception
1067 */
1068 DeclException0(ExcEmptyMatrix);
1069
1070 /**
1071 * Exception
1072 */
1073 DeclException1(
1074 ExcNotRegular,
1075 number,
1076 << "The maximal pivot is " << arg1
1077 << ", which is below the threshold. The matrix may be singular.");
1078 /**
1079 * Exception
1080 */
1081 DeclException3(ExcInvalidDestination,
1082 size_type,
1083 size_type,
1084 size_type,
1085 << "Target region not in matrix: size in this direction="
1086 << arg1 << ", size of new matrix=" << arg2
1087 << ", offset=" << arg3);
1088 /**
1089 * Exception
1090 */
1091 DeclExceptionMsg(ExcSourceEqualsDestination,
1092 "You are attempting an operation on two matrices that "
1093 "are the same object, but the operation requires that the "
1094 "two objects are in fact different.");
1095 /**
1096 * Exception
1097 */
1098 DeclException0(ExcMatrixNotPositiveDefinite);
1099 //@}
1100 };
1101
1102 /**@}*/
1103
1104 #ifndef DOXYGEN
1105 /*-------------------------Inline functions -------------------------------*/
1106
1107
1108
1109 template <typename number>
1110 inline typename FullMatrix<number>::size_type
m()1111 FullMatrix<number>::m() const
1112 {
1113 return this->n_rows();
1114 }
1115
1116
1117
1118 template <typename number>
1119 inline typename FullMatrix<number>::size_type
n()1120 FullMatrix<number>::n() const
1121 {
1122 return this->n_cols();
1123 }
1124
1125
1126
1127 template <typename number>
1128 FullMatrix<number> &
1129 FullMatrix<number>::operator=(const number d)
1130 {
1131 Assert(d == number(0), ExcScalarAssignmentOnlyForZeroValue());
1132 (void)d; // removes -Wunused-parameter warning in optimized mode
1133
1134 if (this->n_elements() != 0)
1135 this->reset_values();
1136
1137 return *this;
1138 }
1139
1140
1141
1142 template <typename number>
1143 template <typename number2>
1144 inline void
fill(const number2 * src)1145 FullMatrix<number>::fill(const number2 *src)
1146 {
1147 Table<2, number>::fill(src);
1148 }
1149
1150
1151
1152 template <typename number>
1153 template <typename MatrixType>
1154 void
copy_from(const MatrixType & M)1155 FullMatrix<number>::copy_from(const MatrixType &M)
1156 {
1157 this->reinit(M.m(), M.n());
1158
1159 // loop over the elements of the argument matrix row by row, as suggested
1160 // in the documentation of the sparse matrix iterator class, and
1161 // copy them into the current object
1162 for (size_type row = 0; row < M.m(); ++row)
1163 {
1164 const typename MatrixType::const_iterator end_row = M.end(row);
1165 for (typename MatrixType::const_iterator entry = M.begin(row);
1166 entry != end_row;
1167 ++entry)
1168 this->el(row, entry->column()) = entry->value();
1169 }
1170 }
1171
1172
1173
1174 template <typename number>
1175 template <typename MatrixType>
1176 void
copy_transposed(const MatrixType & M)1177 FullMatrix<number>::copy_transposed(const MatrixType &M)
1178 {
1179 this->reinit(M.n(), M.m());
1180
1181 // loop over the elements of the argument matrix row by row, as suggested
1182 // in the documentation of the sparse matrix iterator class, and
1183 // copy them into the current object
1184 for (size_type row = 0; row < M.m(); ++row)
1185 {
1186 const typename MatrixType::const_iterator end_row = M.end(row);
1187 for (typename MatrixType::const_iterator entry = M.begin(row);
1188 entry != end_row;
1189 ++entry)
1190 this->el(entry->column(), row) = entry->value();
1191 }
1192 }
1193
1194
1195
1196 template <typename number>
1197 template <typename MatrixType, typename index_type>
1198 inline void
extract_submatrix_from(const MatrixType & matrix,const std::vector<index_type> & row_index_set,const std::vector<index_type> & column_index_set)1199 FullMatrix<number>::extract_submatrix_from(
1200 const MatrixType & matrix,
1201 const std::vector<index_type> &row_index_set,
1202 const std::vector<index_type> &column_index_set)
1203 {
1204 AssertDimension(row_index_set.size(), this->n_rows());
1205 AssertDimension(column_index_set.size(), this->n_cols());
1206
1207 const size_type n_rows_submatrix = row_index_set.size();
1208 const size_type n_cols_submatrix = column_index_set.size();
1209
1210 for (size_type sub_row = 0; sub_row < n_rows_submatrix; ++sub_row)
1211 for (size_type sub_col = 0; sub_col < n_cols_submatrix; ++sub_col)
1212 (*this)(sub_row, sub_col) =
1213 matrix.el(row_index_set[sub_row], column_index_set[sub_col]);
1214 }
1215
1216
1217
1218 template <typename number>
1219 template <typename MatrixType, typename index_type>
1220 inline void
scatter_matrix_to(const std::vector<index_type> & row_index_set,const std::vector<index_type> & column_index_set,MatrixType & matrix)1221 FullMatrix<number>::scatter_matrix_to(
1222 const std::vector<index_type> &row_index_set,
1223 const std::vector<index_type> &column_index_set,
1224 MatrixType & matrix) const
1225 {
1226 AssertDimension(row_index_set.size(), this->n_rows());
1227 AssertDimension(column_index_set.size(), this->n_cols());
1228
1229 const size_type n_rows_submatrix = row_index_set.size();
1230 const size_type n_cols_submatrix = column_index_set.size();
1231
1232 for (size_type sub_row = 0; sub_row < n_rows_submatrix; ++sub_row)
1233 for (size_type sub_col = 0; sub_col < n_cols_submatrix; ++sub_col)
1234 matrix.set(row_index_set[sub_row],
1235 column_index_set[sub_col],
1236 (*this)(sub_row, sub_col));
1237 }
1238
1239
1240 template <typename number>
1241 inline void
set(const size_type i,const size_type j,const number value)1242 FullMatrix<number>::set(const size_type i,
1243 const size_type j,
1244 const number value)
1245 {
1246 (*this)(i, j) = value;
1247 }
1248
1249
1250
1251 template <typename number>
1252 template <typename number2>
1253 void
vmult_add(Vector<number2> & w,const Vector<number2> & v)1254 FullMatrix<number>::vmult_add(Vector<number2> & w,
1255 const Vector<number2> &v) const
1256 {
1257 vmult(w, v, true);
1258 }
1259
1260
1261 template <typename number>
1262 template <typename number2>
1263 void
Tvmult_add(Vector<number2> & w,const Vector<number2> & v)1264 FullMatrix<number>::Tvmult_add(Vector<number2> & w,
1265 const Vector<number2> &v) const
1266 {
1267 Tvmult(w, v, true);
1268 }
1269
1270
1271 //---------------------------------------------------------------------------
1272 template <typename number>
1273 inline typename FullMatrix<number>::iterator
begin(const size_type r)1274 FullMatrix<number>::begin(const size_type r)
1275 {
1276 AssertIndexRange(r, m());
1277 return iterator(this, r, 0);
1278 }
1279
1280
1281
1282 template <typename number>
1283 inline typename FullMatrix<number>::iterator
end(const size_type r)1284 FullMatrix<number>::end(const size_type r)
1285 {
1286 AssertIndexRange(r, m());
1287 return iterator(this, r + 1, 0);
1288 }
1289
1290
1291
1292 template <typename number>
1293 inline typename FullMatrix<number>::const_iterator
begin(const size_type r)1294 FullMatrix<number>::begin(const size_type r) const
1295 {
1296 AssertIndexRange(r, m());
1297 return const_iterator(this, r, 0);
1298 }
1299
1300
1301
1302 template <typename number>
1303 inline typename FullMatrix<number>::const_iterator
end(const size_type r)1304 FullMatrix<number>::end(const size_type r) const
1305 {
1306 AssertIndexRange(r, m());
1307 return const_iterator(this, r + 1, 0);
1308 }
1309
1310
1311
1312 template <typename number>
1313 inline void
add(const size_type r,const size_type c,const number v)1314 FullMatrix<number>::add(const size_type r, const size_type c, const number v)
1315 {
1316 AssertIndexRange(r, this->m());
1317 AssertIndexRange(c, this->n());
1318
1319 this->operator()(r, c) += v;
1320 }
1321
1322
1323
1324 template <typename number>
1325 template <typename number2, typename index_type>
1326 inline void
add(const size_type row,const size_type n_cols,const index_type * col_indices,const number2 * values,const bool,const bool)1327 FullMatrix<number>::add(const size_type row,
1328 const size_type n_cols,
1329 const index_type *col_indices,
1330 const number2 * values,
1331 const bool,
1332 const bool)
1333 {
1334 AssertIndexRange(row, this->m());
1335 for (size_type col = 0; col < n_cols; ++col)
1336 {
1337 AssertIndexRange(col_indices[col], this->n());
1338 this->operator()(row, col_indices[col]) += values[col];
1339 }
1340 }
1341
1342
1343 template <typename number>
1344 template <class StreamType>
1345 inline void
print(StreamType & s,const unsigned int w,const unsigned int p)1346 FullMatrix<number>::print(StreamType & s,
1347 const unsigned int w,
1348 const unsigned int p) const
1349 {
1350 Assert(!this->empty(), ExcEmptyMatrix());
1351
1352 // save the state of out stream
1353 const std::streamsize old_precision = s.precision(p);
1354 const std::streamsize old_width = s.width(w);
1355
1356 for (size_type i = 0; i < this->m(); ++i)
1357 {
1358 for (size_type j = 0; j < this->n(); ++j)
1359 {
1360 s.width(w);
1361 s.precision(p);
1362 s << this->el(i, j);
1363 }
1364 s << std::endl;
1365 }
1366
1367 // reset output format
1368 s.precision(old_precision);
1369 s.width(old_width);
1370 }
1371
1372
1373 #endif // DOXYGEN
1374
1375 DEAL_II_NAMESPACE_CLOSE
1376
1377 #endif
1378