matrices.h
Go to the documentation of this file.
1// LIC// ====================================================================
2// LIC// This file forms part of oomph-lib, the object-oriented,
3// LIC// multi-physics finite-element library, available
4// LIC// at http://www.oomph-lib.org.
5// LIC//
6// LIC// Copyright (C) 2006-2026 Matthias Heil and Andrew Hazel
7// LIC//
8// LIC// This library is free software; you can redistribute it and/or
9// LIC// modify it under the terms of the GNU Lesser General Public
10// LIC// License as published by the Free Software Foundation; either
11// LIC// version 2.1 of the License, or (at your option) any later version.
12// LIC//
13// LIC// This library is distributed in the hope that it will be useful,
14// LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16// LIC// Lesser General Public License for more details.
17// LIC//
18// LIC// You should have received a copy of the GNU Lesser General Public
19// LIC// License along with this library; if not, write to the Free Software
20// LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21// LIC// 02110-1301 USA.
22// LIC//
23// LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24// LIC//
25// LIC//====================================================================
26// This header file contains classes and inline function definitions for
27// matrices and their derived types
28
29// Include guards to prevent multiple inclusion of the header
30#ifndef OOMPH_MATRICES_HEADER
31#define OOMPH_MATRICES_HEADER
32
33// Config header
34#ifdef HAVE_CONFIG_H
35#include <oomph-lib-config.h>
36#endif
37
38#ifdef OOMPH_HAS_MPI
39#include "mpi.h"
40#endif
41
42
43// Needed for g++ in some cases
44#include <iomanip>
45
46// oomph-lib headers
47#include "Vector.h"
48#include "oomph_utilities.h"
50#include "double_vector.h"
51
52
53#ifdef OOMPH_HAS_TRILINOS
54#include "trilinos_helpers.h"
55#endif
56
57namespace oomph
58{
59// Initialise dense pointer-based matrices/tensors?
60#define OOMPH_INITIALISE_DENSE_MATRICES
61#undef OOMPH_INITIALISE_DENSE_MATRICES
62
63
64 //=================================================================
65 /// Abstract base class for matrices, templated by
66 /// the type of object that is stored in them and the type of matrix.
67 /// The MATRIX_TYPE template argument is used as part of the
68 /// Curiously Recurring Template Pattern, see
69 /// http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern
70 /// The pattern is used to force the inlining of the round bracket access
71 /// functions by ensuring that they are NOT virtual functions.
72 //=================================================================
73 template<class T, class MATRIX_TYPE>
74 class Matrix
75 {
76 protected:
77 /// Range check to catch when an index is out of bounds, if so, it
78 /// issues a warning message and dies by throwing an \c OomphLibError
79 void range_check(const unsigned long& i, const unsigned long& j) const
80 {
81 if (i >= nrow())
82 {
83 std::ostringstream error_message;
84 error_message << "Range Error: i=" << i << " is not in the range (0,"
85 << nrow() - 1 << ")." << std::endl;
86
87 throw OomphLibError(error_message.str(),
90 }
91 else if (j >= ncol())
92 {
93 std::ostringstream error_message;
94 error_message << "Range Error: j=" << j << " is not in the range (0,"
95 << ncol() - 1 << ")." << std::endl;
96
97 throw OomphLibError(error_message.str(),
100 }
101 }
102
103
104 public:
105 /// (Empty) constructor
107
108 /// Broken copy constructor
109 Matrix(const Matrix& matrix) = delete;
110
111 /// Broken assignment operator
112 void operator=(const Matrix&) = delete;
113
114 /// Virtual (empty) destructor
115 virtual ~Matrix() {}
116
117 /// Return the number of rows of the matrix
118 virtual unsigned long nrow() const = 0;
119
120 /// Return the number of columns of the matrix
121 virtual unsigned long ncol() const = 0;
122
123 /// Round brackets to give access as a(i,j) for read only
124 /// (we're not providing a general interface for component-wise write
125 /// access since not all matrix formats allow efficient direct access!)
126 /// The function uses the MATRIX_TYPE template parameter to call the
127 /// get_entry() function which must be defined in all derived classes
128 /// that are to be fully instantiated.
129 inline T operator()(const unsigned long& i, const unsigned long& j) const
130 {
131 return static_cast<MATRIX_TYPE const*>(this)->get_entry(i, j);
132 }
133
134 /// Round brackets to give access as a(i,j) for read-write
135 /// access.
136 /// The function uses the MATRIX_TYPE template parameter to call the
137 /// entry() function which must be defined in all derived classes
138 /// that are to be fully instantiated. If the particular Matrix does
139 /// not allow write access, the function should break with an error
140 /// message.
141 inline T& operator()(const unsigned long& i, const unsigned long& j)
142 {
143 return static_cast<MATRIX_TYPE*>(this)->entry(i, j);
144 }
145
146 /// Output function to print a matrix row-by-row, in the form
147 /// a(0,0) a(0,1) ...
148 /// a(1,0) a(1,1) ...
149 /// ...
150 /// to the stream outfile.
151 /// Broken virtual since it might not be sensible to implement this for
152 /// some sparse matrices.
153 virtual void output(std::ostream& outfile) const
154 {
155 throw OomphLibError(
156 "Output function is not implemented for this matrix class",
159 }
160
161 /// Output the "bottom right" entry regardless of it being
162 /// zero or not (this allows automatic detection of matrix size in
163 /// e.g. matlab, python).
164 /// This functionality was moved from the function
165 /// sparse_indexed_output(...) because at the moment, generalisation of
166 /// this functionality does not work in parallel. CRDoubleMatrix has an
167 /// nrow() function but it should it should use nrow_local() - which is the
168 /// N variable in the underlaying CRMatrix.
170 std::ostream& outfile) const = 0;
171
172 /// Indexed output function to print a matrix to the stream outfile
173 /// as i,j,a(i,j) for a(i,j)!=0 only. Final optional argument
174 /// specifies max. size of entries which are set to zero on output.
176 std::ostream& outfile, const double& cutoff = 0.0) const = 0;
177
178 /// Indexed output function to print a matrix to the stream outfile
179 /// as i,j,a(i,j) for a(i,j)!=0 only with specified precision (if
180 /// precision=0 then nothing is changed). If optional boolean flag is set
181 /// to true we also output the "bottom right" entry regardless of it being
182 /// zero or not (this allows automatic detection of matrix size in
183 /// e.g. matlab, python). Final optional argument
184 /// specifies max. size of entries which are set to zero on output.
185 void sparse_indexed_output(std::ostream& outfile,
186 const unsigned& precision = 0,
187 const bool& output_bottom_right_zero = false,
188 const double& cutoff = 0.0) const
189 {
190 // Implemented as a wrapper around "sparse_indexed_output(std::ostream)"
191 // so that only one output helper function is needed in derived classes.
192
193 // We can't have separate functions for only "output_bottom_right_zero"
194 // because people often write false as "0" and then C++ would pick the
195 // wrong function.
196
197 // If requested set the new precision and store the previous value.
198 unsigned old_precision = 0;
199 if (precision != 0)
200 {
201 old_precision = outfile.precision();
202 outfile.precision(precision);
203 }
204
205 // Output as normal using the helper function defined in each matrix class
207
208 // If requested and there is no output for the last entry then output a
209 // zero entry.
210 if (output_bottom_right_zero && ncol() > 0 && nrow() > 0)
211 {
212 // Output as normal using the helper function defined
213 // in each matrix class
215 }
216
217 // Restore the old value of the precision if we changed it
218 if (precision != 0)
219 {
220 outfile.precision(old_precision);
221 }
222 }
223
224
225 /// Indexed output function to print a matrix to the file named
226 /// filename as i,j,a(i,j) for a(i,j)!=0 only with specified precision. If
227 /// optional boolean flag is set to true we also output the "bottom right"
228 /// entry regardless of it being zero or not (this allows automatic
229 /// detection of matrix size in e.g. matlab, python). Final optional
230 /// argument specifies max. size of entries which are set to zero on output.
232 const unsigned& precision = 0,
233 const bool& output_bottom_right_zero = false,
234 const double& cutoff = 0.0) const
235 {
236 // Implemented as a wrapper around "sparse_indexed_output(std::ostream)"
237 // so that only one output function needs to be written in matrix
238 // subclasses.
239
240 // Open file
241 std::ofstream some_file(filename.c_str());
242
243 // Output as normal
246
247 // Close file
248 some_file.close();
249 }
250
251 /// Indexed output function to print a matrix to the stream outfile
252 /// as i,j,a(i,j) for a(i,j)!=0. Final optional argument
253 /// specifies max. size of entries which are set to zero on output.
255 const double& cutoff = 0.0) const
256 {
257 unsigned precision = 0;
258 bool output_bottom_right_zero = false;
261 }
262
263 /// Indexed output function to print a matrix to the stream outfile
264 /// as i,j,a(i,j) for a(i,j)!=0. Final optional argument
265 /// specifies max. size of entries which are set to zero on output.
267 const double& cutoff = 0.0) const
268 {
269 unsigned precision = 0;
270 bool output_bottom_right_zero = false;
273 }
274 };
275
276
277 /////////////////////////////////////////////////////////////////////
278 /////////////////////////////////////////////////////////////////////
279 /////////////////////////////////////////////////////////////////////
280
281
282 // Forward definition of the linear solver class
283 class LinearSolver;
284
285 //=============================================================================
286 /// Abstract base class for matrices of doubles -- adds
287 /// abstract interfaces for solving, LU decomposition and
288 /// multiplication by vectors.
289 //=============================================================================
291 {
292 protected:
293 // Pointer to a linear solver
295
296 // Pointer to a default linear solver
298
299 public:
300 /// (Empty) constructor.
302
303 /// Broken copy constructor
305
306 /// Broken assignment operator
307 void operator=(const DoubleMatrixBase&) = delete;
308
309 /// Return the number of rows of the matrix
310 virtual unsigned long nrow() const = 0;
311
312 /// Return the number of columns of the matrix
313 virtual unsigned long ncol() const = 0;
314
315 /// virtual (empty) destructor
316 virtual ~DoubleMatrixBase() {}
317
318 /// Round brackets to give access as a(i,j) for read only
319 /// (we're not providing a general interface for component-wise write
320 /// access since not all matrix formats allow efficient direct access!)
321 virtual double operator()(const unsigned long& i,
322 const unsigned long& j) const = 0;
323
324
325 /// Return a pointer to the linear solver object
327 {
328 return Linear_solver_pt;
329 }
330
331 /// Return a pointer to the linear solver object (const version)
333 {
334 return Linear_solver_pt;
335 }
336
337 /// Complete LU solve (replaces matrix by its LU decomposition
338 /// and overwrites RHS with solution). The default should not need
339 /// to be over-written
340 void solve(DoubleVector& rhs);
341
342 /// Complete LU solve (Nothing gets overwritten!). The default should
343 /// not need to be overwritten
344 void solve(const DoubleVector& rhs, DoubleVector& soln);
345
346 /// Complete LU solve (replaces matrix by its LU decomposition
347 /// and overwrites RHS with solution). The default should not need
348 /// to be over-written
349 void solve(Vector<double>& rhs);
350
351 /// Complete LU solve (Nothing gets overwritten!). The default should
352 /// not need to be overwritten
354
355 /// Find the residual, i.e. r=b-Ax the residual
356 virtual void residual(const DoubleVector& x,
357 const DoubleVector& b,
359 {
360 // compute residual = Ax
361 this->multiply(x, residual_);
362
363 // set residual to -residual (-Ax)
364 unsigned nrow_local = residual_.nrow_local();
365 double* residual_pt = residual_.values_pt();
366 for (unsigned i = 0; i < nrow_local; i++)
367 {
369 }
370
371 // set residual = b + residuals
372 residual_ += b;
373 }
374
375 /// Find the maximum residual r=b-Ax -- generic version, can be
376 /// overloaded for specific derived classes where the
377 /// max. can be determined "on the fly"
378 virtual double max_residual(const DoubleVector& x, const DoubleVector& rhs)
379 {
381 residual(x, rhs, res);
382 return res.max();
383 }
384
385 /// Multiply the matrix by the vector x: soln=Ax.
386 virtual void multiply(const DoubleVector& x, DoubleVector& soln) const = 0;
387
388 /// Multiply the transposed matrix by the vector x: soln=A^T x
389 virtual void multiply_transpose(const DoubleVector& x,
390 DoubleVector& soln) const = 0;
391
392 /// For every row, find the maximum absolute value of the
393 /// entries in this row. Set all values that are less than alpha times
394 /// this maximum to zero and return the resulting matrix in
395 /// reduced_matrix. Note: Diagonal entries are retained regardless
396 /// of their size.
397 // virtual void matrix_reduction(const double &alpha,
398 // DoubleMatrixBase& reduced_matrix)=0;
399 };
400
401
402 ///////////////////////////////////////////////////////////////////////////////
403 ///////////////////////////////////////////////////////////////////////////////
404 ///////////////////////////////////////////////////////////////////////////////
405
406
407 //======================================================================
408 /// Class for dense matrices, storing all the values of the
409 /// matrix as a pointer to a pointer with assorted output functions
410 /// inherited from Matrix<T>. The curious recursive template pattern is
411 /// used here to pass the specific class to the base class so that
412 /// round bracket access can be inlined.
413 //======================================================================
414 template<class T>
415 class DenseMatrix : public Matrix<T, DenseMatrix<T>>
416 {
417 protected:
418 /// Internal representation of matrix as a pointer to data
420
421 /// Number of rows
422 unsigned long N;
423
424 /// Number of columns
425 unsigned long M;
426
427 public:
428 /// Empty constructor, simply assign the lengths N and M to 0
429 DenseMatrix() : Matrixdata(0), N(0), M(0) {}
430
431 /// Copy constructor: Deep copy!
433 {
434 // Set row and column lengths
435 N = source_matrix.nrow();
436 M = source_matrix.ncol();
437 // Assign space for the data
438 Matrixdata = new T[N * M];
439 // Copy the data across from the other matrix
440 for (unsigned long i = 0; i < N; i++)
441 {
442 for (unsigned long j = 0; j < M; j++)
443 {
444 Matrixdata[M * i + j] = source_matrix(i, j);
445 }
446 }
447 }
448
449 /// Copy assignment
451 {
452 // Don't create a new matrix if the assignment is the identity
453 if (this != &source_matrix)
454 {
455 // Check row and column length
456 unsigned long n = source_matrix.nrow();
457 unsigned long m = source_matrix.ncol();
458 if ((N != n) || (M != m))
459 {
460 resize(n, m);
461 }
462 // Copy entries across from the other matrix
463 for (unsigned long i = 0; i < N; i++)
464 {
465 for (unsigned long j = 0; j < M; j++)
466 {
467 (*this)(i, j) = source_matrix(i, j);
468 }
469 }
470 }
471 // Return reference to object itself (i.e. de-reference this pointer)
472 return *this;
473 }
474
475 /// The access function that will be called by the read-write
476 /// round-bracket operator.
477 inline T& entry(const unsigned long& i, const unsigned long& j)
478 {
479#ifdef RANGE_CHECKING
480 this->range_check(i, j);
481#endif
482 return Matrixdata[M * i + j];
483 }
484
485 /// The access function the will be called by the read-only
486 /// (const version) round-bracket operator.
487 inline T get_entry(const unsigned long& i, const unsigned long& j) const
488 {
489#ifdef RANGE_CHECKING
490 this->range_check(i, j);
491#endif
492 return Matrixdata[M * i + j];
493 }
494
495 /// Constructor to build a square n by n matrix
496 DenseMatrix(const unsigned long& n);
497
498 /// Constructor to build a matrix with n rows and m columns
499 DenseMatrix(const unsigned long& n, const unsigned long& m);
500
501 /// Constructor to build a matrix with n rows and m columns,
502 /// with initial value initial_val
503 DenseMatrix(const unsigned long& n,
504 const unsigned long& m,
505 const T& initial_val);
506
507 /// Destructor, clean up the matrix data
508 virtual ~DenseMatrix()
509 {
510 delete[] Matrixdata;
511 Matrixdata = 0;
512 }
513
514 /// Return the number of rows of the matrix
515 inline unsigned long nrow() const
516 {
517 return N;
518 }
519
520 /// Return the number of columns of the matrix
521 inline unsigned long ncol() const
522 {
523 return M;
524 }
525
526 /// Resize to a square nxn matrix;
527 /// any values already present will be transfered
528 void resize(const unsigned long& n)
529 {
530 resize(n, n);
531 }
532
533 /// Resize to a non-square n x m matrix;
534 /// any values already present will be transfered
535 void resize(const unsigned long& n, const unsigned long& m);
536
537 /// Resize to a non-square n x m matrix and initialize the
538 /// new values to initial_value.
539 void resize(const unsigned long& n,
540 const unsigned long& m,
541 const T& initial_value);
542
543 /// Initialize all values in the matrix to val.
544 void initialise(const T& val)
545 {
546 for (unsigned long i = 0; i < (N * M); ++i)
547 {
548 Matrixdata[i] = val;
549 }
550 }
551
552 /// Output function to print a matrix row-by-row to the stream outfile
553 void output(std::ostream& outfile) const;
554
555 /// Output function to print a matrix row-by-row to a file. Specify
556 /// filename.
557 void output(std::string filename) const;
558
559 /// Indexed output function to print a matrix to the
560 /// stream outfile as i,j,a(i,j)
561 void indexed_output(std::ostream& outfile) const;
562
563 /// Indexed output function to print a matrix to a
564 /// file as i,j,a(i,j). Specify filename.
565 void indexed_output(std::string filename) const;
566
567 /// Output the "bottom right" entry regardless of it being
568 /// zero or not (this allows automatic detection of matrix size in
569 /// e.g. matlab, python).
570 void output_bottom_right_zero_helper(std::ostream& outfile) const;
571
572 /// Indexed output function to print a matrix to the
573 /// stream outfile as i,j,a(i,j) for a(i,j)!=0 only. Final optional argument
574 /// specifies max. size of entries which are set to zero on output.
576 const double& cutoff = 0.0) const;
577 };
578
579
580 ///////////////////////////////////////////////////////////////////
581 ///////////////////////////////////////////////////////////////////
582 ///////////////////////////////////////////////////////////////////
583
584
585 //================================================================
586 /// Class for sparse matrices, that store only the non-zero values
587 /// in a linear array in memory. The details of the array indexing
588 /// vary depending on the storage scheme used. The MATRIX_TYPE
589 /// template parameter for use in the curious recursive template
590 /// pattern is included and passed directly to the base Matrix class.
591 //=================================================================
592 template<class T, class MATRIX_TYPE>
593 class SparseMatrix : public Matrix<T, MATRIX_TYPE>
594 {
595 protected:
596 /// Internal representation of the matrix values, a pointer
598
599 /// Number of rows
600 unsigned long N;
601
602 /// Number of columns
603 unsigned long M;
604
605 /// Number of non-zero values (i.e. size of Value array)
606 unsigned long Nnz;
607
608 /// Dummy zero
609 static T Zero;
610
611 public:
612 /// Default constructor
613 SparseMatrix() : Value(0), N(0), M(0), Nnz(0) {}
614
615 /// Copy constructor
617 {
618 // Number of nonzero entries
619 Nnz = source_matrix.nnz();
620
621 // Number of rows
622 N = source_matrix.nrow();
623
624 // Number of columns
625 M = source_matrix.ncol();
626
627 // Values stored in C-style array
628 Value = new T[Nnz];
629
630 // Assign the values
631 for (unsigned long i = 0; i < Nnz; i++)
632 {
633 Value[i] = source_matrix.value()[i];
634 }
635 }
636
637 /// Broken assignment operator
638 void operator=(const SparseMatrix&) = delete;
639
640 /// Destructor, delete the memory associated with the values
642 {
643 delete[] Value;
644 Value = 0;
645 }
646
647 /// Access to C-style value array
648 T* value()
649 {
650 return Value;
651 }
652
653 /// Access to C-style value array (const version)
654 const T* value() const
655 {
656 return Value;
657 }
658
659 /// Return the number of rows of the matrix
660 inline unsigned long nrow() const
661 {
662 return N;
663 }
664
665 /// Return the number of columns of the matrix
666 inline unsigned long ncol() const
667 {
668 return M;
669 }
670
671 /// Return the number of nonzero entries
672 inline unsigned long nnz() const
673 {
674 return Nnz;
675 }
676
677 /// Output the "bottom right" entry regardless of it being
678 /// zero or not (this allows automatic detection of matrix size in
679 /// e.g. matlab, python).
680 virtual void output_bottom_right_zero_helper(std::ostream& outfile) const
681 {
682 std::string error_message = "SparseMatrix::output_bottom_right_zero_"
683 "helper() is a virtual function.\n";
684 error_message +=
685 "It must be overloaded for specific sparse matrix storage formats\n";
686
687 throw OomphLibError(
689 }
690
691 /// Indexed output function to print a matrix to the
692 /// stream outfile as i,j,a(i,j) for a(i,j)!=0 only. Final optional argument
693 /// specifies max. size of entries which are set to zero on output.
694 virtual void sparse_indexed_output_helper(std::ostream& outfile,
695 const double& cutoff = 0.0) const
696 {
697 std::string error_message =
698 "SparseMatrix::sparse_indexed_output_helper() is a virtual function.\n";
699 error_message +=
700 "It must be overloaded for specific sparse matrix storage formats\n";
701
702 throw OomphLibError(
704 }
705 };
706
707
708 //======================================================================
709 /// A class for compressed row matrices, a sparse storage format
710 /// Once again the recursive template trick is used to inform that base
711 /// class that is should use the access functions provided in the
712 /// CRMatrix class.
713 //=====================================================================
714 template<class T>
715 class CRMatrix : public SparseMatrix<T, CRMatrix<T>>
716 {
717 public:
718 /// Default constructor
720 {
721 Column_index = 0;
722 Row_start = 0;
723 }
724
725
726 /// Constructor: Pass vector of values, vector of column indices,
727 /// vector of row starts and number of rows and columns
728 /// Number of nonzero entries is read
729 /// off from value, so make sure the vector has been shrunk
730 /// to its correct length.
733 const Vector<int>& row_start_,
734 const unsigned long& n,
735 const unsigned long& m)
736 : SparseMatrix<T, CRMatrix<T>>()
737 {
738 Column_index = 0;
739 Row_start = 0;
741 }
742
743 /// Copy constructor
746 {
747 // NNz, N and M are set the the copy constructor of the SparseMatrix
748 // called above
749 // Column indices stored in C-style array
750 Column_index = new int[this->Nnz];
751
752 // Assign:
753 for (unsigned long i = 0; i < this->Nnz; i++)
754 {
755 Column_index[i] = source_matrix.column_index()[i];
756 }
757
758 // Row start:
759 Row_start = new int[this->N + 1];
760
761 // Assign:
762 for (unsigned long i = 0; i <= this->N; i++)
763 {
764 Row_start[i] = source_matrix.row_start()[i];
765 }
766 }
767
768 /// Broken assignment operator
769 void operator=(const CRMatrix&) = delete;
770
771 /// Destructor, delete any allocated memory
772 virtual ~CRMatrix()
773 {
774 delete[] Column_index;
775 Column_index = 0;
776 delete[] Row_start;
777 Row_start = 0;
778 }
779
780 /// Access function that will be called by the read-only
781 /// round-bracket operator (const)
782 T get_entry(const unsigned long& i, const unsigned long& j) const
783 {
784#ifdef RANGE_CHECKING
785 this->range_check(i, j);
786#endif
787 for (long k = Row_start[i]; k < Row_start[i + 1]; k++)
788 {
789 if (unsigned(Column_index[k]) == j)
790 {
791 return this->Value[k];
792 }
793 }
794 return this->Zero;
795 }
796
797 /// The read-write access function is deliberately broken
798 T& entry(const unsigned long& i, const unsigned long& j)
799 {
800 std::string error_string =
801 "Non-const access not provided for the CRMatrix<T> class\n";
802 error_string +=
803 "It is not possible to use round-bracket access: M(i,j)\n";
804 error_string += "if M is not declared as const.\n";
805 error_string += "The solution (albeit ugly) is to create const reference "
806 "to the matrix\n";
807 error_string += " const CRMatrix<T>& read_M = M;\n";
808 error_string += "Then read_M(i,j) is permitted\n";
809
810 throw OomphLibError(
812
813 // Dummy return
814 T dummy;
815 return dummy;
816 }
817
818 /// Access to C-style row_start array
820 {
821 return Row_start;
822 }
823
824 /// Access to C-style row_start array (const version)
825 const int* row_start() const
826 {
827 return Row_start;
828 }
829
830 /// Access to C-style column index array
832 {
833 return Column_index;
834 }
835
836 /// Access to C-style column index array (const version)
837 const int* column_index() const
838 {
839 return Column_index;
840 }
841
842 /// Output the "bottom right" entry regardless of it being
843 /// zero or not (this allows automatic detection of matrix size in
844 /// e.g. matlab, python).
845 void output_bottom_right_zero_helper(std::ostream& outfile) const
846 {
847 int last_row_local = this->N - 1;
848 int last_col = this->M - 1;
849
850 // Use this strange thingy because of the CRTP discussed above.
851 T last_value = this->operator()(last_row_local, last_col);
852
853 if (last_value == T(0))
854 {
855 outfile << last_row_local << " " << last_col << " " << T(0)
856 << std::endl;
857 }
858 }
859
860 /// Indexed output function to print a matrix to the
861 /// stream outfile as i,j,a(i,j) for a(i,j)!=0 only. Final optional argument
862 /// specifies max. size of entries which are set to zero on output.
864 const double& cutoff = 0.0) const
865 {
866 for (unsigned long i = 0; i < this->N; i++)
867 {
868 for (long j = Row_start[i]; j < Row_start[i + 1]; j++)
869 {
870 if (std::abs(this->Value[j]) > cutoff)
871 {
872 outfile << i << " " << Column_index[j] << " " << this->Value[j]
873 << std::endl;
874 }
875 }
876 }
877 }
878
879 /// Wipe matrix data and set all values to 0.
881
882 /// Build matrix from compressed representation. Number of nonzero
883 /// entries is read off from value, so make sure the vector has been shrunk
884 /// to its correct length. This matrix forms the storage for
885 /// CRDoubleMatrices which are distributable. The argument n should be the
886 /// number of local rows. The argument m is the number of columns
887 void build(const Vector<T>& value,
889 const Vector<int>& row_start,
890 const unsigned long& n,
891 const unsigned long& m);
892
893
894 /// Function to build matrix from pointers to arrays
895 /// which hold the row starts, column indices and non-zero values.
896 /// The final two arguments are the number of rows and columns.
897 /// Note that, as the name suggests, this function does not
898 /// make a copy of the data pointed to by the first three arguments!
900 int* column_index,
901 int* row_start,
902 const unsigned long& nnz,
903 const unsigned long& n,
904 const unsigned long& m);
905
906
907 protected:
908 /// Column index
910
911 /// Start index for row
913 };
914
915
916 // Forward definition for the superlu solver
917 class SuperLUSolver;
918
919
920 //=============================================================================
921 /// A class for compressed row matrices. This is a distributable
922 /// object.
923 //=============================================================================
924 class CRDoubleMatrix : public Matrix<double, CRDoubleMatrix>,
925 public DoubleMatrixBase,
927 {
928 public:
929 /// Default constructor
931
932 /// Constructor: vector of values, vector of column indices,
933 /// vector of row starts and number of rows and columns.
935 const unsigned& ncol,
936 const Vector<double>& value,
938 const Vector<int>& row_start);
939
940 /// Constructor: just stores the distribution but does not build the
941 /// matrix
943
944 /// Copy constructor
946
947 /// Broken assignment operator
948 void operator=(const CRDoubleMatrix&) = delete;
949
950 /// Destructor
951 virtual ~CRDoubleMatrix();
952
953 /// Access function: returns the vector Index_of_diagonal_entries.
954 /// The i-th entry of the vector contains the index of the last entry
955 /// below or on the diagonal. If there are no entries below or on the
956 /// diagonal then the corresponding entry is -1. If, however, there are
957 /// no entries in the row then the entry is irrelevant and is kept
958 /// as the initialised value; 0.
960 {
961 // Check to see if the vector has been set up
962 if (Index_of_diagonal_entries.size() == 0)
963 {
964 // Make the warning
965 std::string err_strng =
966 "The Index_of_diagonal_entries vector has not been ";
967 err_strng += "set up yet. Run sort_entries() to set this vector up.";
968
969 // Throw the warning
971 "CRDoubleMatrix::get_index_of_diagonal_entries()",
973 }
974
975 // Return the vector
977 } // End of index_of_diagonal_entries
978
979 /// Create a struct to provide a comparison function for std::sort
981 {
982 // Define the comparison operator
983 bool operator()(const std::pair<int, double>& pair_1,
984 const std::pair<int, double>& pair_2)
985 {
986 // If the first argument of pair_1 is less than the first argument of
987 // pair_2 then return TRUE otherwise return FALSE
988 return (pair_1.first < pair_2.first);
989 }
991
992 /// Runs through the column index vector and checks if the entries
993 /// follow the regular lexicographical ordering of matrix entries, i.e.
994 /// it will check (at the i-th row of the matrix) if the entries in the
995 /// column index vector associated with this row are in increasing order
996 bool entries_are_sorted(const bool& doc_unordered_entries = false) const;
997
998 /// Sorts the entries associated with each row of the matrix in the
999 /// column index vector and the value vector into ascending order and sets
1000 /// up the Index_of_diagonal_entries vector
1001 void sort_entries();
1002
1003 /// build method: vector of values, vector of column indices,
1004 /// vector of row starts and number of rows and columns.
1006 const unsigned& ncol,
1007 const Vector<double>& value,
1009 const Vector<int>& row_start);
1010
1011 /// rebuild the matrix - assembles an empty matrix will a defined
1012 /// distribution
1014
1015 /// keeps the existing distribution and just matrix that is stored
1016 void build(const unsigned& ncol,
1017 const Vector<double>& value,
1019 const Vector<int>& row_start);
1020
1021 /// keeps the existing distribution and just matrix that is stored
1022 /// without copying the matrix data
1023 void build_without_copy(const unsigned& ncol,
1024 const unsigned& nnz,
1025 double* value,
1026 int* column_index,
1027 int* row_start);
1028
1029 /// The contents of the matrix are redistributed to match the new
1030 /// distribution. In a non-MPI build this method does nothing.
1031 /// \b NOTE 1: The current distribution and the new distribution must have
1032 /// the same number of global rows.
1033 /// \b NOTE 2: The current distribution and the new distribution must have
1034 /// the same Communicator.
1036
1037 /// clear
1038 void clear();
1039
1040 /// Return the number of rows of the matrix
1041 inline unsigned long nrow() const
1042 {
1044 }
1045
1046 /// Return the number of columns of the matrix
1047 inline unsigned long ncol() const
1048 {
1049 return CR_matrix.ncol();
1050 }
1051
1052 /// Output the "bottom right" entry regardless of it being
1053 /// zero or not (this allows automatic detection of matrix size in
1054 /// e.g. matlab, python).
1059
1060 /// Indexed output function to print a matrix to the
1061 /// stream outfile as i,j,a(i,j) for a(i,j)!=0 only. Final optional argument
1062 /// specifies max. size of entries which are set to zero on output.
1064 const double& cutoff = 0.0) const
1065 {
1067 }
1068
1069 /// Indexed output function to print a matrix to a
1070 /// file as i,j,a(i,j) for a(i,j)!=0 only. Specify filename.
1071 /// This uses acual global row numbers.
1073 {
1074 // Get offset
1075 unsigned first_row = distribution_pt()->first_row();
1076
1077 // Open file
1078 std::ofstream some_file;
1079 some_file.open(filename.c_str());
1080 unsigned n = nrow_local();
1081 for (unsigned long i = 0; i < n; i++)
1082 {
1083 for (long j = row_start()[i]; j < row_start()[i + 1]; j++)
1084 {
1085 some_file << first_row + i << " " << column_index()[j] << " "
1086 << value()[j] << std::endl;
1087 }
1088 }
1089 some_file.close();
1090 }
1091
1092 /// Overload the round-bracket access operator for read-only access. In a
1093 /// distributed matrix i refers to the local row index.
1094 inline double operator()(const unsigned long& i,
1095 const unsigned long& j) const
1096 {
1097 return CR_matrix.get_entry(i, j);
1098 }
1099
1100 /// Access to C-style row_start array
1102 {
1103 return CR_matrix.row_start();
1104 }
1105
1106 /// Access to C-style row_start array (const version)
1107 const int* row_start() const
1108 {
1109 return CR_matrix.row_start();
1110 }
1111
1112 /// Access to C-style column index array
1114 {
1115 return CR_matrix.column_index();
1116 }
1117
1118 /// Access to C-style column index array (const version)
1119 const int* column_index() const
1120 {
1121 return CR_matrix.column_index();
1122 }
1123
1124 /// Access to C-style value array
1125 double* value()
1126 {
1127 return CR_matrix.value();
1128 }
1129
1130 /// Access to C-style value array (const version)
1131 const double* value() const
1132 {
1133 return CR_matrix.value();
1134 }
1135
1136 /// Return the number of nonzero entries (the local nnz)
1137 inline unsigned long nnz() const
1138 {
1139 return CR_matrix.nnz();
1140 }
1141
1142 /// LU decomposition using SuperLU if matrix is not distributed or
1143 /// distributed onto a single processor.
1144 virtual void ludecompose();
1145
1146 /// LU back solve for given RHS
1147 virtual void lubksub(DoubleVector& rhs);
1148
1149 /// Multiply the matrix by the vector x: soln=Ax
1150 void multiply(const DoubleVector& x, DoubleVector& soln) const;
1151
1152 /// Multiply the transposed matrix by the vector x: soln=A^T x
1153 void multiply_transpose(const DoubleVector& x, DoubleVector& soln) const;
1154
1155 /// Function to multiply this matrix by the CRDoubleMatrix matrix_in.
1156 /// In a serial matrix, there are 4 methods available:
1157 /// Method 1: First runs through this matrix and matrix_in to find the
1158 /// storage
1159 /// requirements for result - arrays of the correct size are
1160 /// then allocated before performing the calculation.
1161 /// Minimises memory requirements but more costly.
1162 /// Method 2: Grows storage for values and column indices of result 'on the
1163 /// fly' using an array of maps. Faster but more memory
1164 /// intensive.
1165 /// Method 3: Grows storage for values and column indices of result 'on the
1166 /// fly' using a vector of vectors. Not particularly impressive
1167 /// on the platforms we tried...
1168 /// Method 4: Trilinos Epetra Matrix Matrix multiply.
1169 /// Method 5: Trilinox Epetra Matrix Matrix Mulitply (ml based)
1170 /// If Trilinos is installed then Method 4 is employed by default, otherwise
1171 /// Method 2 is employed by default.
1172 /// In a distributed matrix, only Trilinos Epetra Matrix Matrix multiply
1173 /// is available.
1174 void multiply(const CRDoubleMatrix& matrix_in,
1175 CRDoubleMatrix& result) const;
1176
1177 /// For every row, find the maximum absolute value of the
1178 /// entries in this row. Set all values that are less than alpha times
1179 /// this maximum to zero and return the resulting matrix in
1180 /// reduced_matrix. Note: Diagonal entries are retained regardless
1181 /// of their size.
1182 void matrix_reduction(const double& alpha, CRDoubleMatrix& reduced_matrix);
1183
1184 /// Access function to Serial_matrix_matrix_multiply_method, the flag
1185 /// which determines the matrix matrix multiplication method used for serial
1186 /// matrices.
1187 /// Method 1: First runs through this matrix and matrix_in to find the
1188 /// storage
1189 /// requirements for result - arrays of the correct size are
1190 /// then allocated before performing the calculation.
1191 /// Minimises memory requirements but more costly.
1192 /// Method 2: Grows storage for values and column indices of result 'on the
1193 /// fly' using an array of maps. Faster but more memory
1194 /// intensive.
1195 /// Method 3: Grows storage for values and column indices of result 'on the
1196 /// fly' using a vector of vectors. Not particularly impressive
1197 /// on the platforms we tried...
1198 /// Method 4: Trilinos Epetra Matrix Matrix multiply.
1199 /// Method 5: Trilinos Epetra Matrix Matrix multiply (ML based).
1204
1205 /// Read only access function (const version) to
1206 /// Serial_matrix_matrix_multiply_method, the flag
1207 /// which determines the matrix matrix multiplication method used for serial
1208 /// matrices.
1209 /// Method 1: First runs through this matrix and matrix_in to find the
1210 /// storage
1211 /// requirements for result - arrays of the correct size are
1212 /// then allocated before performing the calculation.
1213 /// Minimises memory requirements but more costly.
1214 /// Method 2: Grows storage for values and column indices of result 'on the
1215 /// fly' using an array of maps. Faster but more memory
1216 /// intensive.
1217 /// Method 3: Grows storage for values and column indices of result 'on the
1218 /// fly' using a vector of vectors. Not particularly impressive
1219 /// on the platforms we tried...
1220 /// Method 4: Trilinos Epetra Matrix Matrix multiply.
1221 /// Method 5: Trilinos Epetra Matrix Matrix multiply (ML based).
1223 {
1225 }
1226
1227 /// Access function to Distributed_matrix_matrix_multiply_method, the
1228 /// flag which determines the matrix matrix multiplication method used for
1229 /// distributed matrices.
1230 /// Method 1: Trilinos Epetra Matrix Matrix multiply.
1231 /// Method 2: Trilinos Epetra Matrix Matrix multiply (ML based).
1236
1237 /// Read only access function (const version) to
1238 /// Distributed_matrix_matrix_multiply_method, the
1239 /// flag which determines the matrix matrix multiplication method used for
1240 /// distributed matrices.
1241 /// Method 1: Trilinos Epetra Matrix Matrix multiply.
1242 /// Method 2: Trilinos Epetra Matrix Matrix multiply (ML based).
1247
1248 /// access function to the Built flag - indicates whether the matrix
1249 /// has been build - i.e. the distribution has been defined and the matrix
1250 /// assembled.
1251 bool built() const
1252 {
1253 return Built;
1254 }
1255
1256 /// if this matrix is distributed then a the equivalent global matrix
1257 /// is built using new and returned. The calling method is responsible for
1258 /// the destruction of the new matrix.
1260
1261 /// Returns the transpose of this matrix
1263
1264 /// returns the inf-norm of this matrix
1265 double inf_norm() const;
1266
1267 /// returns a Vector of diagonal entries of this matrix.
1268 /// This only works with square matrices. This condition may be relaxed
1269 /// in the future if need be.
1271
1272 /// element-wise addition of this matrix with matrix_in.
1273 void add(const CRDoubleMatrix& matrix_in,
1275
1276 private:
1277 /// Vector whose i'th entry contains the index of the last entry
1278 /// below or on the diagonal of the i'th row of the matrix
1280
1281 /// Flag to determine which matrix-matrix multiplication method is
1282 /// used (for serial (or global) matrices)
1284
1285 /// Flag to determine which matrix-matrix multiplication method is
1286 /// used (for distributed matrices)
1288
1289 /// Storage for the Matrix in CR Format
1291
1292 /// Flag to indicate whether the matrix has been built - i.e. the
1293 /// distribution has been setup AND the matrix has been assembled.
1294 bool Built;
1295 };
1296
1297
1298 ///////////////////////////////////////////////////////////////////////////////
1299 ///////////////////////////////////////////////////////////////////////////////
1300 ///////////////////////////////////////////////////////////////////////////////
1301
1302
1303 // Forward definition of the DenseLU class
1304 class DenseLU;
1305
1306 //=================================================================
1307 /// Class of matrices containing doubles, and stored as a
1308 /// DenseMatrix<double>, but with solving functionality inherited
1309 /// from the abstract DoubleMatrix class.
1310 //=================================================================
1311 class DenseDoubleMatrix : public DoubleMatrixBase, public DenseMatrix<double>
1312 {
1313 public:
1314 /// Constructor, set the default linear solver
1316
1317 /// Constructor to build a square n by n matrix.
1318 DenseDoubleMatrix(const unsigned long& n);
1319
1320 /// Constructor to build a matrix with n rows and m columns.
1321 DenseDoubleMatrix(const unsigned long& n, const unsigned long& m);
1322
1323 /// Constructor to build a matrix with n rows and m columns,
1324 /// with initial value initial_val
1325 DenseDoubleMatrix(const unsigned long& n,
1326 const unsigned long& m,
1327 const double& initial_val);
1328
1329 /// Broken copy constructor
1331
1332 /// Broken assignment operator
1333 void operator=(const DenseDoubleMatrix&) = delete;
1334
1335 /// Return the number of rows of the matrix
1336 inline unsigned long nrow() const
1337 {
1339 }
1340
1341 /// Return the number of columns of the matrix
1342 inline unsigned long ncol() const
1343 {
1345 }
1346
1347 /// Overload the const version of the round-bracket access operator
1348 /// for read-only access.
1349 inline double operator()(const unsigned long& i,
1350 const unsigned long& j) const
1351 {
1353 }
1354
1355 /// Overload the non-const version of the round-bracket access
1356 /// operator for read-write access
1357 inline double& operator()(const unsigned long& i, const unsigned long& j)
1358 {
1360 }
1361
1362 /// Destructor
1363 virtual ~DenseDoubleMatrix();
1364
1365 /// LU decomposition using DenseLU (default linea solver)
1366 virtual void ludecompose();
1367
1368 /// LU backsubstitution
1369 virtual void lubksub(DoubleVector& rhs);
1370
1371 /// LU backsubstitution
1372 virtual void lubksub(Vector<double>& rhs);
1373
1374 /// Determine eigenvalues and eigenvectors, using
1375 /// Jacobi rotations. Only for symmetric matrices. Nothing gets overwritten!
1376 /// - \c eigen_vect(i,j) = j-th component of i-th eigenvector.
1377 /// - \c eigen_val(i) is the i-th eigenvalue; same ordering as in
1378 /// eigenvectors
1381
1382 /// Multiply the matrix by the vector x: soln=Ax
1383 void multiply(const DoubleVector& x, DoubleVector& soln) const;
1384
1385 /// Multiply the transposed matrix by the vector x: soln=A^T x
1386 void multiply_transpose(const DoubleVector& x, DoubleVector& soln) const;
1387
1388 /// For every row, find the maximum absolute value of the
1389 /// entries in this row. Set all values that are less than alpha times
1390 /// this maximum to zero and return the resulting matrix in
1391 /// reduced_matrix. Note: Diagonal entries are retained regardless
1392 /// of their size.
1393 void matrix_reduction(const double& alpha,
1395
1396 /// Function to multiply this matrix by a DenseDoubleMatrix matrix_in
1399 };
1400
1401 /////////////////////////////////////////////////////////////////////
1402 /////////////////////////////////////////////////////////////////////
1403 /////////////////////////////////////////////////////////////////////
1404
1405
1406 //=================================================================
1407 /// A Rank 3 Tensor class
1408 //=================================================================
1409 template<class T>
1411 {
1412 private:
1413 /// Private internal representation as pointer to data
1415
1416 /// 1st Tensor dimension
1417 unsigned N;
1418
1419 /// 2nd Tensor dimension
1420 unsigned M;
1421
1422 /// 3rd Tensor dimension
1423 unsigned P;
1424
1425 /// Range check to catch when an index is out of bounds, if so, it
1426 /// issues a warning message and dies by throwing an \c OomphLibError
1427 void range_check(const unsigned long& i,
1428 const unsigned long& j,
1429 const unsigned long& k) const
1430 {
1431 if (i >= N)
1432 {
1433 std::ostringstream error_message;
1434 error_message << "Range Error: i=" << i << " is not in the range (0,"
1435 << N - 1 << ")." << std::endl;
1436
1437 throw OomphLibError(error_message.str(),
1440 }
1441 else if (j >= M)
1442 {
1443 std::ostringstream error_message;
1444 error_message << "Range Error: j=" << j << " is not in the range (0,"
1445 << M - 1 << ")." << std::endl;
1446
1447 throw OomphLibError(error_message.str(),
1450 }
1451 else if (k >= P)
1452 {
1453 std::ostringstream error_message;
1454 error_message << "Range Error: k=" << k << " is not in the range (0,"
1455 << P - 1 << ")." << std::endl;
1456
1457 throw OomphLibError(error_message.str(),
1460 }
1461 }
1462
1463
1464 public:
1465 /// Empty constructor
1466 RankThreeTensor() : Tensordata(0), N(0), M(0), P(0) {}
1467
1468 /// Copy constructor: Deep copy
1470 {
1471 // Set row and column lengths
1472 N = source_tensor.nindex1();
1473 M = source_tensor.nindex2();
1474 P = source_tensor.nindex3();
1475 // Assign space for the data
1476 Tensordata = new T[N * M * P];
1477 // Copy the data across from the other matrix
1478 for (unsigned i = 0; i < N; i++)
1479 {
1480 for (unsigned j = 0; j < M; j++)
1481 {
1482 for (unsigned k = 0; k < P; k++)
1483 {
1484 Tensordata[P * (M * i + j) + k] = source_tensor(i, j, k);
1485 }
1486 }
1487 }
1488 }
1489
1490 /// Copy assignement
1492 {
1493 // Don't create a new matrix if the assignement is the identity
1494 if (this != &source_tensor)
1495 {
1496 // Check row and column length
1497 unsigned long n = source_tensor.nindex1();
1498 unsigned long m = source_tensor.nindex2();
1499 unsigned long p = source_tensor.nindex3();
1500 // Resie the tensor to be the same size as the old tensor
1501 if ((N != n) || (M != m) || (P != p))
1502 {
1503 resize(n, m, p);
1504 }
1505
1506 // Copy entries across from the other matrix
1507 for (unsigned long i = 0; i < N; i++)
1508 {
1509 for (unsigned long j = 0; j < M; j++)
1510 {
1511 for (unsigned long k = 0; k < P; k++)
1512 {
1513 (*this)(i, j, k) = source_tensor(i, j, k);
1514 }
1515 }
1516 }
1517 }
1518 // Return reference to object itself (i.e. de-reference this pointer)
1519 return *this;
1520 }
1521
1522
1523 /// One parameter constructor produces a cubic nxnxn tensor
1524 RankThreeTensor(const unsigned long& n)
1525 {
1526 // Set row and column lengths
1527 N = n;
1528 M = n;
1529 P = n;
1530 // Assign space for the n rows
1531 Tensordata = new T[N * M * P];
1532 // Initialise to zero if required
1533#ifdef OOMPH_INITIALISE_DENSE_MATRICES
1534 initialise(T(0));
1535#endif
1536 }
1537
1538 /// Three parameter constructor, general non-square tensor
1539 RankThreeTensor(const unsigned long& n_index1,
1540 const unsigned long& n_index2,
1541 const unsigned long& n_index3)
1542 {
1543 // Set row and column lengths
1544 N = n_index1;
1545 M = n_index2;
1546 P = n_index3;
1547 // Assign space for the n rows
1548 Tensordata = new T[N * M * P];
1549 // Initialise to zero if required
1550#ifdef OOMPH_INITIALISE_DENSE_MATRICES
1551 initialise(T(0));
1552#endif
1553 }
1554
1555
1556 /// Three parameter constructor, general non-square tensor
1557 RankThreeTensor(const unsigned long& n_index1,
1558 const unsigned long& n_index2,
1559 const unsigned long& n_index3,
1560 const T& initial_val)
1561 {
1562 // Set row and column lengths
1563 N = n_index1;
1564 M = n_index2;
1565 P = n_index3;
1566 // Assign space for the n rows
1567 Tensordata = new T[N * M * P];
1568 // Initialise to the initial value
1570 }
1571
1572 /// Destructor: delete the pointers
1574 {
1575 delete[] Tensordata;
1576 Tensordata = 0;
1577 }
1578
1579 /// Resize to a square nxnxn tensor
1580 void resize(const unsigned long& n)
1581 {
1582 resize(n, n, n);
1583 }
1584
1585 /// Resize to a general tensor
1586 void resize(const unsigned long& n_index1,
1587 const unsigned long& n_index2,
1588 const unsigned long& n_index3)
1589 {
1590 // If the sizes have not changed do nothing
1591 if ((n_index1 == N) && (n_index2 == M) && (n_index3 == P))
1592 {
1593 return;
1594 }
1595 // Store old sizes
1596 unsigned long n_old = N, m_old = M, p_old = P;
1597 // Reassign the sizes
1598 N = n_index1;
1599 M = n_index2;
1600 P = n_index3;
1601 // Store triple pointer to old matrix data
1603 // Re-create Tensordata in new size
1604 Tensordata = new T[N * M * P];
1605#ifdef OOMPH_INITIALISE_DENSE_MATRICES
1606 initialise(T(0));
1607#endif
1608 // Transfer values
1609 unsigned long n_copy, m_copy, p_copy;
1610 n_copy = std::min(n_old, n_index1);
1611 m_copy = std::min(m_old, n_index2);
1612 p_copy = std::min(p_old, n_index3);
1613 // If matrix has values, transfer them to new matrix
1614 // Loop over rows
1615 for (unsigned long i = 0; i < n_copy; i++)
1616 {
1617 // Loop over columns
1618 for (unsigned long j = 0; j < m_copy; j++)
1619 {
1620 // Loop over columns
1621 for (unsigned long k = 0; k < p_copy; k++)
1622 {
1623 // Transfer values from temp_tensor
1624 Tensordata[M * P * i + P * j + k] =
1625 temp_tensor[m_old * p_old * i + p_old * j + k];
1626 }
1627 }
1628 }
1629 // Now kill storage for old tensor
1630 delete[] temp_tensor;
1631 }
1632
1633 /// Resize to a general tensor
1634 void resize(const unsigned long& n_index1,
1635 const unsigned long& n_index2,
1636 const unsigned long& n_index3,
1637 const T& initial_value)
1638 {
1639 // If the sizes have not changed do nothing
1640 if ((n_index1 == N) && (n_index2 == M) && (n_index3 == P))
1641 {
1642 return;
1643 }
1644 // Store old sizes
1645 unsigned long n_old = N, m_old = M, p_old = P;
1646 // Reassign the sizes
1647 N = n_index1;
1648 M = n_index2;
1649 P = n_index3;
1650 // Store triple pointer to old matrix data
1652 // Re-create Tensordata in new size
1653 Tensordata = new T[N * M * P];
1654 // Initialise the newly allocated storage
1656
1657 // Transfer values
1658 unsigned long n_copy, m_copy, p_copy;
1659 n_copy = std::min(n_old, n_index1);
1660 m_copy = std::min(m_old, n_index2);
1661 p_copy = std::min(p_old, n_index3);
1662 // If matrix has values, transfer them to new matrix
1663 // Loop over rows
1664 for (unsigned long i = 0; i < n_copy; i++)
1665 {
1666 // Loop over columns
1667 for (unsigned long j = 0; j < m_copy; j++)
1668 {
1669 // Loop over columns
1670 for (unsigned long k = 0; k < p_copy; k++)
1671 {
1672 // Transfer values from temp_tensor
1673 Tensordata[M * P * i + P * j + k] =
1674 temp_tensor[m_old * p_old * i + p_old * j + k];
1675 }
1676 }
1677 }
1678 // Now kill storage for old tensor
1679 delete[] temp_tensor;
1680 }
1681
1682 /// Initialise all values in the tensor to val
1683 void initialise(const T& val)
1684 {
1685 for (unsigned long i = 0; i < (N * M * P); ++i)
1686 {
1687 Tensordata[i] = val;
1688 }
1689 }
1690
1691 /// Return the range of index 1 of the tensor
1692 unsigned long nindex1() const
1693 {
1694 return N;
1695 }
1696
1697 /// Return the range of index 2 of the tensor
1698 unsigned long nindex2() const
1699 {
1700 return M;
1701 }
1702
1703 /// Return the range of index 3 of the tensor
1704 unsigned long nindex3() const
1705 {
1706 return P;
1707 }
1708
1709 /// Overload the round brackets to give access as a(i,j,k)
1710 inline T& operator()(const unsigned long& i,
1711 const unsigned long& j,
1712 const unsigned long& k)
1713 {
1714#ifdef RANGE_CHECKING
1715 this->range_check(i, j, k);
1716#endif
1717 return Tensordata[P * (M * i + j) + k];
1718 }
1719
1720 /// Overload a const version for read-only access as a(i,j,k)
1721 inline T operator()(const unsigned long& i,
1722 const unsigned long& j,
1723 const unsigned long& k) const
1724 {
1725#ifdef RANGE_CHECKING
1726 this->range_check(i, j, k);
1727#endif
1728 return Tensordata[P * (M * i + j) + k];
1729 }
1730 };
1731
1732 /////////////////////////////////////////////////////////////////////
1733 /////////////////////////////////////////////////////////////////////
1734 /////////////////////////////////////////////////////////////////////
1735
1736
1737 //=================================================================
1738 /// A Rank 4 Tensor class
1739 //=================================================================
1740 template<class T>
1742 {
1743 private:
1744 /// Private internal representation as pointer to data
1746
1747 /// 1st Tensor dimension
1748 unsigned N;
1749
1750 /// 2nd Tensor dimension
1751 unsigned M;
1752
1753 /// 3rd Tensor dimension
1754 unsigned P;
1755
1756 /// 4th Tensor dimension
1757 unsigned Q;
1758
1759 /// Boolean to indicate whether data is a copy
1761
1762 /// Range check to catch when an index is out of bounds, if so, it
1763 /// issues a warning message and dies by throwing an \c OomphLibError
1764 void range_check(const unsigned long& i,
1765 const unsigned long& j,
1766 const unsigned long& k,
1767 const unsigned long& l) const
1768 {
1769 if (i >= N)
1770 {
1771 std::ostringstream error_message;
1772 error_message << "Range Error: i=" << i << " is not in the range (0,"
1773 << N - 1 << ")." << std::endl;
1774
1775 throw OomphLibError(error_message.str(),
1778 }
1779 else if (j >= M)
1780 {
1781 std::ostringstream error_message;
1782 error_message << "Range Error: j=" << j << " is not in the range (0,"
1783 << M - 1 << ")." << std::endl;
1784
1785 throw OomphLibError(error_message.str(),
1788 }
1789 else if (k >= P)
1790 {
1791 std::ostringstream error_message;
1792 error_message << "Range Error: k=" << k << " is not in the range (0,"
1793 << P - 1 << ")." << std::endl;
1794
1795 throw OomphLibError(error_message.str(),
1798 }
1799 else if (l >= Q)
1800 {
1801 std::ostringstream error_message;
1802 error_message << "Range Error: l=" << l << " is not in the range (0,"
1803 << Q - 1 << ")." << std::endl;
1804
1805 throw OomphLibError(error_message.str(),
1808 }
1809 }
1810
1811 public:
1812 /// Empty constructor
1814 : Tensordata(0), N(0), M(0), P(0), Q(0), Is_tensordata_a_copy(false)
1815 {
1816 }
1817
1818 /// Copy constructor: Deep copy
1820 {
1821 // Set row and column lengths
1822 N = source_tensor.nindex1();
1823 M = source_tensor.nindex2();
1824 P = source_tensor.nindex3();
1825 Q = source_tensor.nindex4();
1826 Is_tensordata_a_copy = false;
1827
1828 // Assign space for the data
1829 Tensordata = new T[N * M * P * Q];
1830
1831 // Copy the data across from the other matrix
1832 for (unsigned i = 0; i < N; i++)
1833 {
1834 for (unsigned j = 0; j < M; j++)
1835 {
1836 for (unsigned k = 0; k < P; k++)
1837 {
1838 for (unsigned l = 0; l < Q; l++)
1839 {
1840 Tensordata[Q * (P * (M * i + j) + k) + l] =
1841 source_tensor(i, j, k, l);
1842 }
1843 }
1844 }
1845 }
1846 }
1847
1848 /// Copy assignement
1850 {
1851 // Don't create a new matrix if the assignement is the identity
1852 if (this != &source_tensor)
1853 {
1854 // Check row and column length
1855 unsigned long n = source_tensor.nindex1();
1856 unsigned long m = source_tensor.nindex2();
1857 unsigned long p = source_tensor.nindex3();
1858 unsigned long q = source_tensor.nindex4();
1859 // Resize the tensor to be the same size as the old tensor
1860 if ((N != n) || (M != m) || (P != p) || (Q != q))
1861 {
1862 resize(n, m, p, q);
1863 }
1864
1865 // Copy entries across from the other matrix
1866 for (unsigned long i = 0; i < N; i++)
1867 {
1868 for (unsigned long j = 0; j < M; j++)
1869 {
1870 for (unsigned long k = 0; k < P; k++)
1871 {
1872 for (unsigned long l = 0; l < Q; l++)
1873 {
1874 (*this)(i, j, k, l) = source_tensor(i, j, k, l);
1875 }
1876 }
1877 }
1878 }
1879 }
1880 // Return reference to object itself (i.e. de-reference this pointer)
1881 return *this;
1882 }
1883
1884
1885 /// Shallow copy of data from source_tensor
1887 {
1888 // Set row and column length
1889 N = source_tensor.nindex1();
1890 M = source_tensor.nindex2();
1891 P = source_tensor.nindex3();
1892 Q = source_tensor.nindex4();
1893 // Delete existing data, if no already a copy
1894 if (Is_tensordata_a_copy == false)
1895 {
1896 delete[] Tensordata;
1897 }
1898 // Set the pointer
1899 Tensordata = source_tensor.Tensordata;
1900 Is_tensordata_a_copy = true;
1901 }
1902
1903 /// One parameter constructor produces a nxnxnxn tensor
1904 RankFourTensor(const unsigned long& n)
1905 {
1906 // Set row and column lengths
1907 N = n;
1908 M = n;
1909 P = n;
1910 Q = n;
1911 Is_tensordata_a_copy = false;
1912 // Assign space for the n rows
1913 Tensordata = new T[N * M * P * Q];
1914 // Initialise to zero if required
1915#ifdef OOMPH_INITIALISE_DENSE_MATRICES
1916 initialise(T(0));
1917#endif
1918 }
1919
1920 /// Four parameter constructor, general non-square tensor
1921 RankFourTensor(const unsigned long& n_index1,
1922 const unsigned long& n_index2,
1923 const unsigned long& n_index3,
1924 const unsigned long& n_index4)
1925 {
1926 // Set row and column lengths
1927 N = n_index1;
1928 M = n_index2;
1929 P = n_index3;
1930 Q = n_index4;
1931 Is_tensordata_a_copy = false;
1932 // Assign space for the n rows
1933 Tensordata = new T[N * M * P * Q];
1934 // Initialise to zero if required
1935#ifdef OOMPH_INITIALISE_DENSE_MATRICES
1936 initialise(T(0));
1937#endif
1938 }
1939
1940
1941 /// Four parameter constructor, general non-square tensor
1942 RankFourTensor(const unsigned long& n_index1,
1943 const unsigned long& n_index2,
1944 const unsigned long& n_index3,
1945 const unsigned long& n_index4,
1946 const T& initial_val)
1947 {
1948 // Set row and column lengths
1949 N = n_index1;
1950 M = n_index2;
1951 P = n_index3;
1952 Q = n_index4;
1953 Is_tensordata_a_copy = false;
1954 // Assign space for the n rows
1955 Tensordata = new T[N * M * P * Q];
1956 // Initialise to the initial value
1958 }
1959
1960 /// Destructor: delete the pointers
1962 {
1963 if (Is_tensordata_a_copy == false)
1964 {
1965 delete[] Tensordata;
1966 }
1967 Tensordata = 0;
1968 }
1969
1970 /// Resize to a square nxnxnxn tensor
1971 void resize(const unsigned long& n)
1972 {
1973 resize(n, n, n, n);
1974 }
1975
1976 /// Resize to a general tensor
1977 void resize(const unsigned long& n_index1,
1978 const unsigned long& n_index2,
1979 const unsigned long& n_index3,
1980 const unsigned long& n_index4)
1981 {
1982 // If the sizes have not changed do nothing
1983 if ((n_index1 == N) && (n_index2 == M) && (n_index3 == P) &&
1984 (n_index4 == Q))
1985 {
1986 return;
1987 }
1988 // Store old sizes
1989 unsigned long n_old = N, m_old = M, p_old = P, q_old = Q;
1990 // Reassign the sizes
1991 N = n_index1;
1992 M = n_index2;
1993 P = n_index3;
1994 Q = n_index4;
1995 // Store pointer to old matrix data
1997 // Re-create Tensordata in new size
1998 Tensordata = new T[N * M * P * Q];
1999#ifdef OOMPH_INITIALISE_DENSE_MATRICES
2000 initialise(T(0));
2001#endif
2002 // Transfer values
2003 unsigned long n_copy, m_copy, p_copy, q_copy;
2004 n_copy = std::min(n_old, n_index1);
2005 m_copy = std::min(m_old, n_index2);
2006 p_copy = std::min(p_old, n_index3);
2007 q_copy = std::min(q_old, n_index4);
2008 // If matrix has values, transfer them to new matrix
2009 // Loop over rows
2010 for (unsigned long i = 0; i < n_copy; i++)
2011 {
2012 // Loop over columns
2013 for (unsigned long j = 0; j < m_copy; j++)
2014 {
2015 // Loop over columns
2016 for (unsigned long k = 0; k < p_copy; k++)
2017 {
2018 // Loop over columns
2019 for (unsigned long l = 0; l < q_copy; l++)
2020 {
2021 // Transfer values from temp_tensor
2022 Tensordata[Q * (M * P * i + P * j + k) + l] =
2023 temp_tensor[q_old * (m_old * p_old * i + p_old * j + k) + l];
2024 }
2025 }
2026 }
2027 }
2028 // Now kill storage for old tensor
2029 if (Is_tensordata_a_copy == false)
2030 {
2031 delete[] temp_tensor;
2032 }
2033 else
2034 {
2035 Is_tensordata_a_copy = false;
2036 }
2037 }
2038
2039 /// Resize to a general tensor
2040 void resize(const unsigned long& n_index1,
2041 const unsigned long& n_index2,
2042 const unsigned long& n_index3,
2043 const unsigned long& n_index4,
2044 const T& initial_value)
2045 {
2046 // If the sizes have not changed do nothing
2047 if ((n_index1 == N) && (n_index2 == M) && (n_index3 == P) &&
2048 (n_index4 == Q))
2049 {
2050 return;
2051 }
2052 // Store old sizes
2053 unsigned long n_old = N, m_old = M, p_old = P, q_old = Q;
2054 // Reassign the sizes
2055 N = n_index1;
2056 M = n_index2;
2057 P = n_index3;
2058 Q = n_index4;
2059 // Store triple pointer to old matrix data
2061 // Re-create Tensordata in new size
2062 Tensordata = new T[N * M * P * Q];
2063 // Initialise the newly allocated storage
2065
2066 // Transfer values
2067 unsigned long n_copy, m_copy, p_copy, q_copy;
2068 n_copy = std::min(n_old, n_index1);
2069 m_copy = std::min(m_old, n_index2);
2070 p_copy = std::min(p_old, n_index3);
2071 q_copy = std::min(q_old, n_index4);
2072 // If matrix has values, transfer them to new matrix
2073 // Loop over rows
2074 for (unsigned long i = 0; i < n_copy; i++)
2075 {
2076 // Loop over columns
2077 for (unsigned long j = 0; j < m_copy; j++)
2078 {
2079 // Loop over columns
2080 for (unsigned long k = 0; k < p_copy; k++)
2081 {
2082 // Loop over columns
2083 for (unsigned long l = 0; l < q_copy; l++)
2084 {
2085 // Transfer values from temp_tensor
2086 Tensordata[Q * (M * P * i + P * j + k) + l] =
2087 temp_tensor[q_old * (m_old * p_old * i + p_old * j + k) + l];
2088 }
2089 }
2090 }
2091 }
2092 // Now kill storage for old tensor
2093 if (Is_tensordata_a_copy == false)
2094 {
2095 delete[] temp_tensor;
2096 }
2097 else
2098 {
2099 Is_tensordata_a_copy = false;
2100 }
2101 }
2102
2103 /// Initialise all values in the tensor to val
2104 void initialise(const T& val)
2105 {
2106 for (unsigned long i = 0; i < (N * M * P * Q); ++i)
2107 {
2108 Tensordata[i] = val;
2109 }
2110 }
2111
2112 /// Return the range of index 1 of the tensor
2113 unsigned long nindex1() const
2114 {
2115 return N;
2116 }
2117
2118 /// Return the range of index 2 of the tensor
2119 unsigned long nindex2() const
2120 {
2121 return M;
2122 }
2123
2124 /// Return the range of index 3 of the tensor
2125 unsigned long nindex3() const
2126 {
2127 return P;
2128 }
2129
2130 /// Return the range of index 4 of the tensor
2131 unsigned long nindex4() const
2132 {
2133 return Q;
2134 }
2135
2136 /// Overload the round brackets to give access as a(i,j,k,l)
2137 inline T& operator()(const unsigned long& i,
2138 const unsigned long& j,
2139 const unsigned long& k,
2140 const unsigned long& l)
2141 {
2142#ifdef RANGE_CHECKING
2143 this->range_check(i, j, k, l);
2144#endif
2145
2146 return Tensordata[Q * (P * (M * i + j) + k) + l];
2147 }
2148
2149 /// Overload a const version for read-only access as a(i,j,k,l)
2150 inline T operator()(const unsigned long& i,
2151 const unsigned long& j,
2152 const unsigned long& k,
2153 const unsigned long& l) const
2154 {
2155#ifdef RANGE_CHECKING
2156 this->range_check(i, j, k, l);
2157#endif
2158 return Tensordata[Q * (P * (M * i + j) + k) + l];
2159 }
2160
2161 /// Direct access to internal storage of data in flat-packed C-style
2162 /// column-major format. WARNING: Only for experienced users. Only
2163 /// use this if raw speed is of the essence, as in the solid mechanics
2164 /// problems.
2165 inline T& raw_direct_access(const unsigned long& i)
2166 {
2167 return Tensordata[i];
2168 }
2169
2170 /// Direct access to internal storage of data in flat-packed C-style
2171 /// column-major format. WARNING: Only for experienced users. Only
2172 /// use this if raw speed is of the essence, as in the solid mechanics
2173 /// problems.
2174 inline const T& raw_direct_access(const unsigned long& i) const
2175 {
2176 return Tensordata[i];
2177 }
2178
2179 /// Caculate the offset in flat-packed C-style, column-major format,
2180 /// required for a given i,j. WARNING: Only for experienced users. Only
2181 /// use this if raw speed is of the essence, as in the solid mechanics
2182 /// problems.
2183 unsigned offset(const unsigned long& i, const unsigned long& j) const
2184 {
2185 return (Q * (P * (M * i + j) + 0) + 0);
2186 }
2187 };
2188
2189
2190 //////////////////////////////////////////////////////////////////
2191 //////////////////////////////////////////////////////////////////
2192 //////////////////////////////////////////////////////////////////
2193
2194
2195 //=================================================================
2196 /// A Rank 5 Tensor class
2197 //=================================================================
2198 template<class T>
2200 {
2201 private:
2202 /// Private internal representation as pointer to data
2204
2205 /// 1st Tensor dimension
2206 unsigned N;
2207
2208 /// 2nd Tensor dimension
2209 unsigned M;
2210
2211 /// 3rd Tensor dimension
2212 unsigned P;
2213
2214 /// 4th Tensor dimension
2215 unsigned Q;
2216
2217 /// 5th Tensor dimension
2218 unsigned R;
2219
2220 /// Range check to catch when an index is out of bounds, if so, it
2221 /// issues a warning message and dies by throwing an \c OomphLibError
2222 void range_check(const unsigned long& i,
2223 const unsigned long& j,
2224 const unsigned long& k,
2225 const unsigned long& l,
2226 const unsigned long& m) const
2227 {
2228 if (i >= N)
2229 {
2230 std::ostringstream error_message;
2231 error_message << "Range Error: i=" << i << " is not in the range (0,"
2232 << N - 1 << ")." << std::endl;
2233
2234 throw OomphLibError(error_message.str(),
2237 }
2238 else if (j >= M)
2239 {
2240 std::ostringstream error_message;
2241 error_message << "Range Error: j=" << j << " is not in the range (0,"
2242 << M - 1 << ")." << std::endl;
2243
2244 throw OomphLibError(error_message.str(),
2247 }
2248 else if (k >= P)
2249 {
2250 std::ostringstream error_message;
2251 error_message << "Range Error: k=" << k << " is not in the range (0,"
2252 << P - 1 << ")." << std::endl;
2253
2254 throw OomphLibError(error_message.str(),
2257 }
2258 else if (l >= Q)
2259 {
2260 std::ostringstream error_message;
2261 error_message << "Range Error: l=" << l << " is not in the range (0,"
2262 << Q - 1 << ")." << std::endl;
2263
2264 throw OomphLibError(error_message.str(),
2267 }
2268 else if (m >= R)
2269 {
2270 std::ostringstream error_message;
2271 error_message << "Range Error: m=" << m << " is not in the range (0,"
2272 << R - 1 << ")." << std::endl;
2273
2274 throw OomphLibError(error_message.str(),
2277 }
2278 }
2279
2280 public:
2281 /// Empty constructor
2282 RankFiveTensor() : Tensordata(0), N(0), M(0), P(0), Q(0), R(0) {}
2283
2284 /// Copy constructor: Deep copy
2286 {
2287 // Set row and column lengths
2288 N = source_tensor.nindex1();
2289 M = source_tensor.nindex2();
2290 P = source_tensor.nindex3();
2291 Q = source_tensor.nindex4();
2292 R = source_tensor.nindex5();
2293
2294 // Assign space for the data
2295 Tensordata = new T[N * M * P * Q * R];
2296
2297 // Copy the data across from the other matrix
2298 for (unsigned i = 0; i < N; i++)
2299 {
2300 for (unsigned j = 0; j < M; j++)
2301 {
2302 for (unsigned k = 0; k < P; k++)
2303 {
2304 for (unsigned l = 0; l < Q; l++)
2305 {
2306 for (unsigned m = 0; m < R; m++)
2307 {
2308 Tensordata[R * (Q * (P * (M * i + j) + k) + l) + m] =
2309 source_tensor(i, j, k, l, m);
2310 }
2311 }
2312 }
2313 }
2314 }
2315 }
2316
2317 /// Copy assignement
2319 {
2320 // Don't create a new matrix if the assignement is the identity
2321 if (this != &source_tensor)
2322 {
2323 // Check row and column length
2324 unsigned long n = source_tensor.nindex1();
2325 unsigned long m = source_tensor.nindex2();
2326 unsigned long p = source_tensor.nindex3();
2327 unsigned long q = source_tensor.nindex4();
2328 unsigned long r = source_tensor.nindex5();
2329 // Resize the tensor to be the same size as the old tensor
2330 if ((N != n) || (M != m) || (P != p) || (Q != q) || (R != r))
2331 {
2332 resize(n, m, p, q, r);
2333 }
2334
2335 // Copy entries across from the other matrix
2336 for (unsigned long i = 0; i < N; i++)
2337 {
2338 for (unsigned long j = 0; j < M; j++)
2339 {
2340 for (unsigned long k = 0; k < P; k++)
2341 {
2342 for (unsigned long l = 0; l < Q; l++)
2343 {
2344 for (unsigned long m = 0; m < R; m++)
2345 {
2346 (*this)(i, j, k, l, m) = source_tensor(i, j, k, l, m);
2347 }
2348 }
2349 }
2350 }
2351 }
2352 }
2353 // Return reference to object itself (i.e. de-reference this pointer)
2354 return *this;
2355 }
2356
2357
2358 /// One parameter constructor produces a nxnxnxnxn tensor
2359 RankFiveTensor(const unsigned long& n)
2360 {
2361 // Set row and column lengths
2362 N = n;
2363 M = n;
2364 P = n;
2365 Q = n;
2366 R = n;
2367 // Assign space for the n rows
2368 Tensordata = new T[N * M * P * Q * R];
2369 // Initialise to zero if required
2370#ifdef OOMPH_INITIALISE_DENSE_MATRICES
2371 initialise(T(0));
2372#endif
2373 }
2374
2375 /// Four parameter constructor, general non-square tensor
2376 RankFiveTensor(const unsigned long& n_index1,
2377 const unsigned long& n_index2,
2378 const unsigned long& n_index3,
2379 const unsigned long& n_index4,
2380 const unsigned long& n_index5)
2381 {
2382 // Set row and column lengths
2383 N = n_index1;
2384 M = n_index2;
2385 P = n_index3;
2386 Q = n_index4;
2387 R = n_index5;
2388 // Assign space for the n rows
2389 Tensordata = new T[N * M * P * Q * R];
2390 // Initialise to zero if required
2391#ifdef OOMPH_INITIALISE_DENSE_MATRICES
2392 initialise(T(0));
2393#endif
2394 }
2395
2396
2397 /// Four parameter constructor, general non-square tensor
2398 RankFiveTensor(const unsigned long& n_index1,
2399 const unsigned long& n_index2,
2400 const unsigned long& n_index3,
2401 const unsigned long& n_index4,
2402 const unsigned long& n_index5,
2403 const T& initial_val)
2404 {
2405 // Set row and column lengths
2406 N = n_index1;
2407 M = n_index2;
2408 P = n_index3;
2409 Q = n_index4;
2410 R = n_index5;
2411 // Assign space for the n rows
2412 Tensordata = new T[N * M * P * Q * R];
2413 // Initialise to the initial value
2415 }
2416
2417 /// Destructor: delete the pointers
2419 {
2420 delete[] Tensordata;
2421 Tensordata = 0;
2422 }
2423
2424 /// Resize to a square nxnxnxn tensor
2425 void resize(const unsigned long& n)
2426 {
2427 resize(n, n, n, n, n);
2428 }
2429
2430 /// Resize to a general tensor
2431 void resize(const unsigned long& n_index1,
2432 const unsigned long& n_index2,
2433 const unsigned long& n_index3,
2434 const unsigned long& n_index4,
2435 const unsigned long& n_index5)
2436 {
2437 // If the sizes have not changed do nothing
2438 if ((n_index1 == N) && (n_index2 == M) && (n_index3 == P) &&
2439 (n_index4 == Q) && (n_index5 == R))
2440 {
2441 return;
2442 }
2443 // Store old sizes
2444 unsigned long n_old = N, m_old = M, p_old = P, q_old = Q, r_old = R;
2445 // Reassign the sizes
2446 N = n_index1;
2447 M = n_index2;
2448 P = n_index3;
2449 Q = n_index4;
2450 R = n_index5;
2451 // Store pointer to old matrix data
2453 // Re-create Tensordata in new size
2454 Tensordata = new T[N * M * P * Q * R];
2455#ifdef OOMPH_INITIALISE_DENSE_MATRICES
2456 initialise(T(0));
2457#endif
2458 // Transfer values
2459 unsigned long n_copy, m_copy, p_copy, q_copy, r_copy;
2460 n_copy = std::min(n_old, n_index1);
2461 m_copy = std::min(m_old, n_index2);
2462 p_copy = std::min(p_old, n_index3);
2463 q_copy = std::min(q_old, n_index4);
2464 r_copy = std::min(r_old, n_index5);
2465 // If matrix has values, transfer them to new matrix
2466 // Loop over rows
2467 for (unsigned long i = 0; i < n_copy; i++)
2468 {
2469 // Loop over columns
2470 for (unsigned long j = 0; j < m_copy; j++)
2471 {
2472 // Loop over columns
2473 for (unsigned long k = 0; k < p_copy; k++)
2474 {
2475 // Loop over columns
2476 for (unsigned long l = 0; l < q_copy; l++)
2477 {
2478 // Loop over columns
2479 for (unsigned long m = 0; m < r_copy; m++)
2480 {
2481 // Transfer values from temp_tensor
2482 Tensordata[R * (Q * (M * P * i + P * j + k) + l) + m] =
2484 (q_old * (m_old * p_old * i + p_old * j + k) +
2485 l) +
2486 m];
2487 }
2488 }
2489 }
2490 }
2491 }
2492 // Now kill storage for old tensor
2493 delete[] temp_tensor;
2494 }
2495
2496 /// Resize to a general tensor
2497 void resize(const unsigned long& n_index1,
2498 const unsigned long& n_index2,
2499 const unsigned long& n_index3,
2500 const unsigned long& n_index4,
2501 const unsigned long& n_index5,
2502 const T& initial_value)
2503 {
2504 // If the sizes have not changed do nothing
2505 if ((n_index1 == N) && (n_index2 == M) && (n_index3 == P) &&
2506 (n_index4 == Q) && (n_index5 == R))
2507 {
2508 return;
2509 }
2510 // Store old sizes
2511 unsigned long n_old = N, m_old = M, p_old = P, q_old = Q, r_old = R;
2512 // Reassign the sizes
2513 N = n_index1;
2514 M = n_index2;
2515 P = n_index3;
2516 Q = n_index4;
2517 R = n_index5;
2518 // Store triple pointer to old matrix data
2520 // Re-create Tensordata in new size
2521 Tensordata = new T[N * M * P * Q * R];
2522 // Initialise the newly allocated storage
2524
2525 // Transfer values
2526 unsigned long n_copy, m_copy, p_copy, q_copy, r_copy;
2527 n_copy = std::min(n_old, n_index1);
2528 m_copy = std::min(m_old, n_index2);
2529 p_copy = std::min(p_old, n_index3);
2530 q_copy = std::min(q_old, n_index4);
2531 r_copy = std::min(r_old, n_index5);
2532 // If matrix has values, transfer them to new matrix
2533 // Loop over rows
2534 for (unsigned long i = 0; i < n_copy; i++)
2535 {
2536 // Loop over columns
2537 for (unsigned long j = 0; j < m_copy; j++)
2538 {
2539 // Loop over columns
2540 for (unsigned long k = 0; k < p_copy; k++)
2541 {
2542 // Loop over columns
2543 for (unsigned long l = 0; l < q_copy; l++)
2544 {
2545 // Loop over columns
2546 for (unsigned long m = 0; m < r_copy; m++)
2547 {
2548 // Transfer values from temp_tensor
2549 Tensordata[R * (Q * (M * P * i + P * j + k) + l) + m] =
2551 (q_old * (m_old * p_old * i + p_old * j + k) +
2552 l) +
2553 m];
2554 }
2555 }
2556 }
2557 }
2558 }
2559 // Now kill storage for old tensor
2560 delete[] temp_tensor;
2561 }
2562
2563 /// Initialise all values in the tensor to val
2564 void initialise(const T& val)
2565 {
2566 for (unsigned long i = 0; i < (N * M * P * Q * R); ++i)
2567 {
2568 Tensordata[i] = val;
2569 }
2570 }
2571
2572 /// Return the range of index 1 of the tensor
2573 unsigned long nindex1() const
2574 {
2575 return N;
2576 }
2577
2578 /// Return the range of index 2 of the tensor
2579 unsigned long nindex2() const
2580 {
2581 return M;
2582 }
2583
2584 /// Return the range of index 3 of the tensor
2585 unsigned long nindex3() const
2586 {
2587 return P;
2588 }
2589
2590 /// Return the range of index 4 of the tensor
2591 unsigned long nindex4() const
2592 {
2593 return Q;
2594 }
2595
2596 /// Return the range of index 5 of the tensor
2597 unsigned long nindex5() const
2598 {
2599 return R;
2600 }
2601
2602 /// Overload the round brackets to give access as a(i,j,k,l,m)
2603 inline T& operator()(const unsigned long& i,
2604 const unsigned long& j,
2605 const unsigned long& k,
2606 const unsigned long& l,
2607 const unsigned long& m)
2608 {
2609#ifdef RANGE_CHECKING
2610 this->range_check(i, j, k, l, m);
2611#endif
2612 return Tensordata[R * (Q * (P * (M * i + j) + k) + l) + m];
2613 }
2614
2615 /// Overload a const version for read-only access as a(i,j,k,l,m)
2616 inline T operator()(const unsigned long& i,
2617 const unsigned long& j,
2618 const unsigned long& k,
2619 const unsigned long& l,
2620 const unsigned long& m) const
2621 {
2622#ifdef RANGE_CHECKING
2623 this->range_check(i, j, k, l, m);
2624#endif
2625 return Tensordata[R * (Q * (P * (M * i + j) + k) + l) + m];
2626 }
2627
2628 /// Direct access to internal storage of data in flat-packed C-style
2629 /// column-major format. WARNING: Only for experienced users. Only
2630 /// use this if raw speed is of the essence, as in the solid mechanics
2631 /// problems.
2632 inline T& raw_direct_access(const unsigned long& i)
2633 {
2634 return Tensordata[i];
2635 }
2636
2637
2638 /// Direct access to internal storage of data in flat-packed C-style
2639 /// column-major format. WARNING: Only for experienced users. Only
2640 /// use this if raw speed is of the essence, as in the solid mechanics
2641 /// problems.
2642 inline const T& raw_direct_access(const unsigned long& i) const
2643 {
2644 return Tensordata[i];
2645 }
2646
2647 /// Caculate the offset in flat-packed Cy-style, column-major format,
2648 /// required for a given i,j,k. WARNING: Only for experienced users. Only
2649 /// use this if raw speed is of the essence, as in the solid mechanics
2650 /// problems.
2651 unsigned offset(const unsigned long& i,
2652 const unsigned long& j,
2653 const unsigned long& k) const
2654 {
2655 return (R * (Q * (P * (M * i + j) + k) + 0) + 0);
2656 }
2657 };
2658
2659
2660 //////////////////////////////////////////////////////////////////
2661 //////////////////////////////////////////////////////////////////
2662 //////////////////////////////////////////////////////////////////
2663
2664 //=======================================================================
2665 /// A class for compressed column matrices: a sparse matrix format
2666 /// The class is passed as the MATRIX_TYPE paramater so that the base
2667 /// class can use the specific access functions in the round-bracket
2668 /// operator.
2669 //=======================================================================
2670 template<class T>
2671 class CCMatrix : public SparseMatrix<T, CCMatrix<T>>
2672 {
2673 public:
2674 /// Default constructor
2676 {
2677 Row_index = 0;
2678 Column_start = 0;
2679 }
2680
2681
2682 /// Constructor: Pass vector of values, vector of row indices,
2683 /// vector of column starts and number of rows (can be suppressed
2684 /// for square matrices). Number of nonzero entries is read
2685 /// off from value, so make sure the vector has been shrunk
2686 /// to its correct length.
2688 const Vector<int>& row_index_,
2690 const unsigned long& n,
2691 const unsigned long& m)
2692 : SparseMatrix<T, CCMatrix<T>>()
2693 {
2694 Row_index = 0;
2695 Column_start = 0;
2697 }
2698
2699
2700 /// Copy constructor
2703 {
2704 // NNz, N and M are set the the copy constructor of the SparseMatrix
2705 // called above
2706
2707 // Row indices stored in C-style array
2708 Row_index = new int[this->Nnz];
2709
2710 // Assign:
2711 for (unsigned long i = 0; i < this->Nnz; i++)
2712 {
2713 Row_index[i] = source_matrix.row_index()[i];
2714 }
2715
2716 // Column start:
2717 Column_start = new int[this->M + 1];
2718
2719 // Assign:
2720 for (unsigned long i = 0; i <= this->M; i++)
2721 {
2722 Column_start[i] = source_matrix.column_start()[i];
2723 }
2724 }
2725
2726 /// Broken assignment operator
2727 void operator=(const CCMatrix&) = delete;
2728
2729
2730 /// Destructor, delete any allocated memory
2731 virtual ~CCMatrix()
2732 {
2733 delete[] Row_index;
2734 Row_index = 0;
2735 delete[] Column_start;
2736 Column_start = 0;
2737 }
2738
2739 /// Access function that will be called by the read-only
2740 /// round-bracket operator (const)
2741 T get_entry(const unsigned long& i, const unsigned long& j) const
2742 {
2743#ifdef RANGE_CHECKING
2744 this->range_check(i, j);
2745#endif
2746 for (long k = Column_start[j]; k < Column_start[j + 1]; k++)
2747 {
2748 if (unsigned(Row_index[k]) == i)
2749 {
2750 return this->Value[k];
2751 }
2752 }
2753 return this->Zero;
2754 }
2755
2756 /// Read-write access is not permitted for these matrices and is
2757 /// deliberately broken.
2758 T& entry(const unsigned long& i, const unsigned long& j)
2759 {
2760 std::string error_string =
2761 "Non-const access not provided for the CCMatrix<T> class\n";
2762 error_string +=
2763 "It is not possible to use round-bracket access: M(i,j)\n";
2764 error_string += "if M is not declared as const.\n";
2765 error_string += "The solution (albeit ugly) is to create const reference "
2766 "to the matrix\n";
2767 error_string += " const CCMatrix<T>& read_M = M;\n";
2768 error_string += "Then read_M(i,j) is permitted\n";
2769
2770 throw OomphLibError(
2772
2773 // Dummy return
2774 T dummy;
2775 return dummy;
2776 }
2777
2778 /// Access to C-style column_start array
2780 {
2781 return Column_start;
2782 }
2783
2784 /// Access to C-style column_start array (const version)
2785 const int* column_start() const
2786 {
2787 return Column_start;
2788 }
2789
2790 /// Access to C-style row index array
2792 {
2793 return Row_index;
2794 }
2795
2796 /// Access to C-style row index array (const version)
2797 const int* row_index() const
2798 {
2799 return Row_index;
2800 }
2801
2802 /// Output the "bottom right" entry regardless of it being
2803 /// zero or not (this allows automatic detection of matrix size in
2804 /// e.g. matlab, python).
2806 {
2807 int last_row = this->N - 1;
2808 int last_col_local = this->M - 1;
2809
2810 // Use this strange thingy because of the CRTP discussed above.
2811 T last_value = this->operator()(last_row, last_col_local);
2812
2813 if (last_value == T(0))
2814 {
2815 outfile << last_row << " " << last_col_local << " " << T(0)
2816 << std::endl;
2817 }
2818 }
2819
2820 /// Indexed output function to print a matrix to the
2821 /// stream outfile as i,j,a(i,j) for a(i,j)!=0 only. Final optional argument
2822 /// specifies max. size of entries which are set to zero on output.
2824 const double& cutoff) const
2825 {
2826 for (unsigned long j = 0; j < this->N; j++)
2827 {
2828 for (long k = Column_start[j]; k < Column_start[j + 1]; k++)
2829 {
2830 if (std::abs(this->Value[k]) > cutoff)
2831 {
2832 outfile << Row_index[k] << " " << j << " " << this->Value[k]
2833 << std::endl;
2834 }
2835 }
2836 }
2837 }
2838
2839 /// Wipe matrix data and set all values to 0.
2841
2842
2843 /// Build matrix from compressed representation.
2844 /// Number of nonzero entries is read
2845 /// off from value, so make sure the vector has been shrunk
2846 /// to its correct length.
2847 void build(const Vector<T>& value,
2848 const Vector<int>& row_index,
2850 const unsigned long& n,
2851 const unsigned long& m);
2852
2853 /// Function to build matrix from pointers to arrays
2854 /// which hold the column starts, row indices and non-zero values.
2855 /// The final parameters specifies the number of rows and columns.
2856 /// Note that, as the name suggests, this function does not
2857 /// make a copy of the data pointed to by the first three arguments!
2859 int* row_index,
2860 int* column_start,
2861 const unsigned long& nnz,
2862 const unsigned long& n,
2863 const unsigned long& m);
2864
2865
2866 protected:
2867 /// Row index
2869
2870 /// Start index for column
2872 };
2873
2874 ///////////////////////////////////////////////////////////////////
2875 ///////////////////////////////////////////////////////////////////
2876 ///////////////////////////////////////////////////////////////////
2877
2878
2879 //=================================================================
2880 /// A class for compressed column matrices that store doubles
2881 //=================================================================
2882 class CCDoubleMatrix : public DoubleMatrixBase, public CCMatrix<double>
2883 {
2884 public:
2885 /// Default constructor
2887
2888 /// Constructor: Pass vector of values, vector of row indices,
2889 /// vector of column starts and number of rows (can be suppressed
2890 /// for square matrices). Number of nonzero entries is read
2891 /// off from value, so make sure the vector has been shrunk
2892 /// to its correct length.
2894 const Vector<int>& row_index_,
2896 const unsigned long& n,
2897 const unsigned long& m);
2898
2899 /// Broken copy constructor
2901
2902 /// Broken assignment operator
2903 void operator=(const CCDoubleMatrix&) = delete;
2904
2905 /// Destructor: Kill the LU factors if they have been setup.
2906 virtual ~CCDoubleMatrix();
2907
2908 /// Return the number of rows of the matrix
2909 inline unsigned long nrow() const
2910 {
2911 return CCMatrix<double>::nrow();
2912 }
2913
2914 /// Return the number of columns of the matrix
2915 inline unsigned long ncol() const
2916 {
2917 return CCMatrix<double>::ncol();
2918 }
2919
2920 /// Overload the round-bracket access operator to provide
2921 /// read-only (const) access to the data
2922 inline double operator()(const unsigned long& i,
2923 const unsigned long& j) const
2924 {
2926 }
2927
2928 /// LU decomposition using SuperLU
2929 virtual void ludecompose();
2930
2931 /// LU back solve for given RHS
2932 virtual void lubksub(DoubleVector& rhs);
2933
2934 /// Multiply the matrix by the vector x: soln=Ax
2935 void multiply(const DoubleVector& x, DoubleVector& soln) const;
2936
2937 /// Multiply the transposed matrix by the vector x: soln=A^T x
2938 void multiply_transpose(const DoubleVector& x, DoubleVector& soln) const;
2939
2940
2941 /// Function to multiply this matrix by the CCDoubleMatrix matrix_in
2942 /// The multiplication method used can be selected using the flag
2943 /// Matrix_matrix_multiply_method. By default Method 2 is used.
2944 /// Method 1: First runs through this matrix and matrix_in to find the
2945 /// storage
2946 /// requirements for result - arrays of the correct size are
2947 /// then allocated before performing the calculation.
2948 /// Minimises memory requirements but more costly.
2949 /// Method 2: Grows storage for values and column indices of result 'on the
2950 /// fly' using an array of maps. Faster but more memory
2951 /// intensive.
2952 /// Method 3: Grows storage for values and column indices of result 'on the
2953 /// fly' using a vector of vectors. Not particularly impressive
2954 /// on the platforms we tried...
2956
2957
2958 /// For every row, find the maximum absolute value of the
2959 /// entries in this row. Set all values that are less than alpha times
2960 /// this maximum to zero and return the resulting matrix in
2961 /// reduced_matrix. Note: Diagonal entries are retained regardless
2962 /// of their size.
2963 void matrix_reduction(const double& alpha, CCDoubleMatrix& reduced_matrix);
2964
2965 /// Access function to Matrix_matrix_multiply_method, the flag
2966 /// which determines the matrix matrix multiplication method used.
2967 /// Method 1: First runs through this matrix and matrix_in to find the
2968 /// storage
2969 /// requirements for result - arrays of the correct size are
2970 /// then allocated before performing the calculation.
2971 /// Minimises memory requirements but more costly.
2972 /// Method 2: Grows storage for values and column indices of result 'on the
2973 /// fly' using an array of maps. Faster but more memory
2974 /// intensive.
2975 /// Method 3: Grows storage for values and column indices of result 'on the
2976 /// fly' using a vector of vectors. Not particularly impressive
2977 /// on the platforms we tried...
2979 {
2981 }
2982
2983 private:
2984 /// Flag to determine which matrix-matrix multiplication method is used.
2986 };
2987
2988
2989 /////////////////////////////////////////////////////////////////////////
2990 /////////////////////////////////////////////////////////////////////////
2991 /////////////////////////////////////////////////////////////////////////
2992
2993
2994 //============================================================================
2995 /// Constructor to build a square n by n matrix
2996 //============================================================================
2997 template<class T>
2998 DenseMatrix<T>::DenseMatrix(const unsigned long& n)
2999 {
3000 // Set row and column lengths
3001 N = n;
3002 M = n;
3003 // Assign space for the n rows
3004 Matrixdata = new T[n * n];
3005 // Initialise to zero if required
3006#ifdef OOMPH_INITIALISE_DENSE_MATRICES
3007 initialise(T(0));
3008#endif
3009 }
3010
3011
3012 //============================================================================
3013 /// Constructor to build a matrix with n rows and m columns
3014 //============================================================================
3015 template<class T>
3016 DenseMatrix<T>::DenseMatrix(const unsigned long& n, const unsigned long& m)
3017 {
3018 // Set row and column lengths
3019 N = n;
3020 M = m;
3021 // Assign space for the n rows
3022 Matrixdata = new T[n * m];
3023#ifdef OOMPH_INITIALISE_DENSE_MATRICES
3024 initialise(T(0));
3025#endif
3026 }
3027
3028 //============================================================================
3029 /// Constructor to build a matrix with n rows and m columns,
3030 /// with initial value initial_val
3031 //============================================================================
3032 template<class T>
3033 DenseMatrix<T>::DenseMatrix(const unsigned long& n,
3034 const unsigned long& m,
3035 const T& initial_val)
3036 {
3037 // Set row and column lengths
3038 N = n;
3039 M = m;
3040 // Assign space for the n rows
3041 Matrixdata = new T[n * m];
3042 initialise(initial_val);
3043 }
3044
3045
3046 //============================================================================
3047 /// Resize to a non-square n_row x m_col matrix,
3048 /// where any values already present will be transfered.
3049 //============================================================================
3050 template<class T>
3051 void DenseMatrix<T>::resize(const unsigned long& n, const unsigned long& m)
3052 {
3053 // If the sizes are the same, do nothing
3054 if ((n == N) && (m == M))
3055 {
3056 return;
3057 }
3058 // Store old sizes
3059 unsigned long n_old = N, m_old = M;
3060 // Reassign the sizes
3061 N = n;
3062 M = m;
3063 // Store double pointer to old matrix data
3064 T* temp_matrix = Matrixdata;
3065
3066 // Re-create Matrixdata in new size
3067 Matrixdata = new T[n * m];
3068 // Initialise to zero
3069#ifdef OOMPH_INITIALISE_DENSE_MATRICES
3070 initialise(T(0));
3071#endif
3072
3073 // Transfer previously existing values
3074 unsigned long n_copy, m_copy;
3075 n_copy = std::min(n_old, n);
3076 m_copy = std::min(m_old, m);
3077
3078 // If matrix has values, transfer them to new matrix
3079 // Loop over rows
3080 for (unsigned long i = 0; i < n_copy; i++)
3081 {
3082 // Loop over columns
3083 for (unsigned long j = 0; j < m_copy; j++)
3084 {
3085 // Transfer values from temp_matrix
3086 Matrixdata[m * i + j] = temp_matrix[m_old * i + j];
3087 }
3088 }
3089
3090 // Now kill storage for old matrix
3091 delete[] temp_matrix;
3092 }
3093
3094
3095 //============================================================================
3096 /// Resize to a non-square n_row x m_col matrix and initialize the
3097 /// new entries to specified value.
3098 //============================================================================
3099 template<class T>
3100 void DenseMatrix<T>::resize(const unsigned long& n,
3101 const unsigned long& m,
3102 const T& initial_value)
3103 {
3104 // If the size is not changed, just return
3105 if ((n == N) && (m == M))
3106 {
3107 return;
3108 }
3109 // Store old sizes
3110 unsigned long n_old = N, m_old = M;
3111 // Reassign the sizes
3112 N = n;
3113 M = m;
3114 // Store double pointer to old matrix data
3115 T* temp_matrix = Matrixdata;
3116 // Re-create Matrixdata in new size
3117 Matrixdata = new T[n * m];
3118 // Assign initial value (will use the newly allocated data)
3119 initialise(initial_value);
3120
3121 // Transfering values
3122 unsigned long n_copy, m_copy;
3123 n_copy = std::min(n_old, n);
3124 m_copy = std::min(m_old, m);
3125 // If matrix has values, transfer them to temp_matrix
3126 // Loop over rows
3127 for (unsigned long i = 0; i < n_copy; i++)
3128 {
3129 // Loop over columns
3130 for (unsigned long j = 0; j < m_copy; j++)
3131 {
3132 // Transfer values to temp_matrix
3133 Matrixdata[m * i + j] = temp_matrix[m_old * i + j];
3134 }
3135 }
3136
3137 // Now kill storage for old matrix
3138 delete[] temp_matrix;
3139 }
3140
3141
3142 //============================================================================
3143 /// Output function to print a matrix row-by-row to the stream outfile
3144 //============================================================================
3145 template<class T>
3146 void DenseMatrix<T>::output(std::ostream& outfile) const
3147 {
3148 // Loop over the rows
3149 for (unsigned i = 0; i < N; i++)
3150 {
3151 // Loop over the columne
3152 for (unsigned j = 0; j < M; j++)
3153 {
3154 outfile << (*this)(i, j) << " ";
3155 }
3156 // Put in a newline
3157 outfile << std::endl;
3158 }
3159 }
3160
3161
3162 //============================================================================
3163 /// Output function to print a matrix row-by-row to a file. Specify filename.
3164 //============================================================================
3165 template<class T>
3166 void DenseMatrix<T>::output(std::string filename) const
3167 {
3168 // Open file
3169 std::ofstream some_file;
3170 some_file.open(filename.c_str());
3171
3173 some_file.close();
3174 }
3175
3176
3177 //============================================================================
3178 /// Indexed output as i,j,a(i,j)
3179 //============================================================================
3180 template<class T>
3181 void DenseMatrix<T>::indexed_output(std::ostream& outfile) const
3182 {
3183 // Loop over the rows
3184 for (unsigned i = 0; i < N; i++)
3185 {
3186 // Loop over the columns
3187 for (unsigned j = 0; j < M; j++)
3188 {
3189 outfile << i << " " << j << " " << (*this)(i, j) << std::endl;
3190 }
3191 }
3192 }
3193
3194
3195 //============================================================================
3196 /// Indexed output function to print a matrix to a
3197 /// file as i,j,a(i,j). Specify filename.
3198 //============================================================================
3199 template<class T>
3201 {
3202 // Open file
3203 std::ofstream some_file;
3204 some_file.open(filename.c_str());
3205 indexed_output(some_file);
3206 some_file.close();
3207 }
3208
3209
3210 //============================================================================
3211 /// Output the "bottom right" entry regardless of it being
3212 /// zero or not (this allows automatic detection of matrix size in
3213 /// e.g. matlab, python).
3214 //============================================================================
3215 template<class T>
3217 std::ostream& outfile) const
3218 {
3219 int last_row = this->N - 1;
3220 int last_col = this->M - 1;
3221
3222 // Use this strange thingy because of the CRTP discussed above.
3223 T last_value = this->operator()(last_row, last_col);
3224
3225 if (last_value == T(0))
3226 {
3227 outfile << last_row << " " << last_col << " " << T(0) << std::endl;
3228 }
3229 }
3230
3231 //============================================================================
3232 /// Sparse indexed output as i,j,a(i,j) for a(i,j)!=0 only. Final optional
3233 /// argument specifies max. size of entries which are set to zero on output.
3234 //============================================================================
3235 template<class T>
3237 const double& cutoff) const
3238 {
3239 // Loop over the rows
3240 for (unsigned i = 0; i < N; i++)
3241 {
3242 // Loop over the column
3243 for (unsigned j = 0; j < M; j++)
3244 {
3245 if ((*this)(i, j) != T(0))
3246 {
3247 // Only do check if the template type an sensibly evaluated
3248 // the abs function which returns something that can be converted
3249 // to a double
3250 if constexpr (HasMagnitude<T>::value)
3251 {
3252 if (std::abs((*this)(i, j)) > cutoff)
3253 {
3254 outfile << i << " " << j << " " << (*this)(i, j) << std::endl;
3255 }
3256 }
3257 // otherwise just output it -- at least it's not null!
3258 else
3259 {
3260 outfile << i << " " << j << " " << (*this)(i, j) << std::endl;
3261 }
3262 }
3263 }
3264 }
3265 }
3266
3267
3268 ////////////////////////////////////////////////////////////////////////
3269 ////////////////////////////////////////////////////////////////////////
3270 ////////////////////////////////////////////////////////////////////////
3271
3272
3273 //=============================================================================
3274 /// Wipe matrix data and set all values to 0.
3275 //=============================================================================
3276 template<class T>
3278 {
3279 // delete any previously allocated storage
3280 if (this->Value != 0)
3281 {
3282 delete[] this->Value;
3283 this->Value = 0;
3284 }
3285 if (this->Row_index != 0)
3286 {
3287 delete[] this->Row_index;
3288 this->Row_index = 0;
3289 }
3290 if (this->Column_start != 0)
3291 {
3292 delete[] this->Column_start;
3293 this->Column_start = 0;
3294 }
3295 this->Nnz = 0;
3296 this->N = 0;
3297 this->M = 0;
3298 }
3299
3300
3301 //=============================================================================
3302 /// Build matrix from compressed representation.
3303 /// Note that, as the name suggests, this function does not
3304 /// make a copy of the data pointed to by the first three arguments!
3305 //=============================================================================
3306 template<class T>
3308 int* row_index,
3309 int* column_start,
3310 const unsigned long& nnz,
3311 const unsigned long& n,
3312 const unsigned long& m)
3313 {
3314 // Number of nonzero entries
3315 this->Nnz = nnz;
3316
3317 // Number of rows
3318 this->N = n;
3319
3320 // Number of columns
3321 this->M = m;
3322
3323 // delete any previously allocated storage
3324 if (this->Value != 0)
3325 {
3326 delete[] this->Value;
3327 }
3328 if (this->Row_index != 0)
3329 {
3330 delete[] this->Row_index;
3331 }
3332 if (this->Column_start != 0)
3333 {
3334 delete[] this->Column_start;
3335 }
3336
3337 // set Value
3338 this->Value = value;
3339
3340 // set Row_index
3341 this->Row_index = row_index;
3342
3343 // set Column_start
3344 this->Column_start = column_start;
3345 }
3346
3347
3348 //===================================================================
3349 /// Build matrix from compressed representation.
3350 /// Number of nonzero entries is read
3351 /// off from value, so make sure the vector has been shrunk
3352 /// to its correct length.
3353 //===================================================================
3354 template<class T>
3356 const Vector<int>& row_index_,
3358 const unsigned long& n,
3359 const unsigned long& m)
3360 {
3361#ifdef PARANOID
3362 if (value.size() != row_index_.size())
3363 {
3364 std::ostringstream error_message;
3365 error_message << "length of value " << value.size()
3366 << " and row_index vectors " << row_index_.size()
3367 << " should match " << std::endl;
3368
3369 throw OomphLibError(
3370 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
3371 }
3372#endif
3373
3374 // Number of nonzero entries
3375 this->Nnz = value.size();
3376
3377 // Number of rows
3378 this->N = n;
3379
3380 // Number of columns
3381 this->M = m;
3382
3383 // We need to delete any previously allocated storage
3384 if (this->Value != 0)
3385 {
3386 delete[] this->Value;
3387 }
3388 if (this->Row_index != 0)
3389 {
3390 delete[] this->Row_index;
3391 }
3392 if (this->Column_start != 0)
3393 {
3394 delete[] this->Column_start;
3395 }
3396
3397 // Values stored in C-style array
3398 this->Value = new T[this->Nnz];
3399
3400 // Row indices stored in C-style array
3401 this->Row_index = new int[this->Nnz];
3402
3403 // Assign:
3404 for (unsigned long i = 0; i < this->Nnz; i++)
3405 {
3406 this->Value[i] = value[i];
3407 this->Row_index[i] = row_index_[i];
3408 }
3409
3410 // Column start:
3411 // Find the size and aollcate
3412 unsigned long n_column_start = column_start_.size();
3413 this->Column_start = new int[n_column_start];
3414
3415 // Assign:
3416 for (unsigned long i = 0; i < n_column_start; i++)
3417 {
3418 this->Column_start[i] = column_start_[i];
3419 }
3420 }
3421
3422 /////////////////////////////////////////////////////////////////////
3423 /////////////////////////////////////////////////////////////////////
3424 /////////////////////////////////////////////////////////////////////
3425
3426
3427 //=============================================================================
3428 /// Wipe matrix data and set all values to 0.
3429 //=============================================================================
3430 template<class T>
3432 {
3433 // delete any previously allocated storage
3434 if (this->Value != 0)
3435 {
3436 delete[] this->Value;
3437 this->Value = 0;
3438 }
3439 if (this->Column_index != 0)
3440 {
3441 delete[] this->Column_index;
3442 this->Column_index = 0;
3443 }
3444 if (this->Row_start != 0)
3445 {
3446 delete[] this->Row_start;
3447 this->Row_start = 0;
3448 }
3449 this->Nnz = 0;
3450 this->N = 0;
3451 this->M = 0;
3452 }
3453
3454
3455 //=============================================================================
3456 /// Function to build a CRMatrix from pointers to arrays which hold the
3457 /// row starts, column indices and non-zero values
3458 /// Note that, as the name suggests, this function does not
3459 /// make a copy of the data pointed to by the first three arguments!
3460 //=============================================================================
3461 template<class T>
3463 int* column_index_,
3464 int* row_start_,
3465 const unsigned long& nnz,
3466 const unsigned long& n,
3467 const unsigned long& m)
3468 {
3469 // Number of nonzero entries
3470 this->Nnz = nnz;
3471
3472 // Number of rows
3473 this->N = n;
3474
3475 // Number of columns
3476 this->M = m;
3477
3478 // delete any previously allocated storage
3479 if (this->Value != 0)
3480 {
3481 delete[] this->Value;
3482 }
3483 if (this->Column_index != 0)
3484 {
3485 delete[] this->Column_index;
3486 }
3487 if (this->Row_start != 0)
3488 {
3489 delete[] this->Row_start;
3490 }
3491
3492 // set Value
3493 this->Value = value;
3494
3495 // set Column_index
3496 this->Column_index = column_index_;
3497
3498 // set Row_start
3499 this->Row_start = row_start_;
3500 }
3501
3502
3503 //=================================================================
3504 /// Build matrix from compressed representation.
3505 /// Number of nonzero entries is read
3506 /// off from value, so make sure the vector has been shrunk
3507 /// to its correct length. The optional final
3508 /// parameter specifies the number of columns. If it is not specified
3509 /// the matrix is assumed to be quadratic.
3510 //=================================================================
3511 template<class T>
3514 const Vector<int>& row_start_,
3515 const unsigned long& n,
3516 const unsigned long& m)
3517 {
3518#ifdef PARANOID
3519 if (value.size() != column_index_.size())
3520 {
3521 std::ostringstream error_message;
3522 error_message << "Must have the same number of values and column indices,"
3523 << "we have " << value.size() << " values and "
3524 << column_index_.size() << " column inidicies."
3525 << std::endl;
3526 throw OomphLibError(
3527 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
3528 }
3529#endif
3530 // Number of nonzero entries
3531 this->Nnz = value.size();
3532
3533 // Number of rows
3534 this->N = n;
3535
3536 // Number of columns
3537 this->M = m;
3538
3539 // We need to delete any previously allocated storage
3540 if (this->Value != 0)
3541 {
3542 delete[] this->Value;
3543 }
3544 if (this->Column_index != 0)
3545 {
3546 delete[] this->Column_index;
3547 }
3548 if (this->Row_start != 0)
3549 {
3550 delete[] this->Row_start;
3551 }
3552
3553 // Values stored in C-style array
3554 this->Value = new T[this->Nnz];
3555
3556 // Column indices stored in C-style array
3557 this->Column_index = new int[this->Nnz];
3558
3559 // Assign:
3560 for (unsigned long i = 0; i < this->Nnz; i++)
3561 {
3562 this->Value[i] = value[i];
3563 this->Column_index[i] = column_index_[i];
3564 }
3565
3566 // Row start:
3567 // Find the size and allocate
3568 unsigned long n_row_start = row_start_.size();
3569 this->Row_start = new int[n_row_start];
3570
3571 // Assign:
3572 for (unsigned long i = 0; i < n_row_start; i++)
3573 {
3574 this->Row_start[i] = row_start_[i];
3575 }
3576 }
3577
3578
3579 //=================================================================
3580 /// Dummy zero
3581 //=================================================================
3582 template<class T, class MATRIX_TYPE>
3584
3585
3586 namespace RRR
3587 {
3588 extern std::string RayStr;
3589 extern bool RayBool;
3590 } // namespace RRR
3591
3592 //=================================================================
3593 /// Namespace for helper functions for CRDoubleMatrices
3594 //=================================================================
3595 namespace CRDoubleMatrixHelpers
3596 {
3597 /// Create a deep copy of the matrix pointed to by in_matrix_pt
3598 inline void deep_copy(const CRDoubleMatrix* const in_matrix_pt,
3600 {
3601#ifdef PARANOID
3602 // Is the out matrix built? We need an empty out matrix!
3603 if (out_matrix.built())
3604 {
3605 std::ostringstream err_msg;
3606 err_msg << "The result matrix has been built.\n"
3607 << "Please clear the matrix.\n";
3608 throw OomphLibError(
3610 }
3611
3612 // Check that the in matrix pointer is not null.
3613 if (in_matrix_pt == 0)
3614 {
3615 std::ostringstream err_msg;
3616 err_msg << "The in_matrix_pt is null.\n";
3617 throw OomphLibError(
3619 }
3620
3621 // Check that the in matrix is built.
3622 if (!in_matrix_pt->built())
3623 {
3624 std::ostringstream err_msg;
3625 err_msg << "The in_matrix_pt is null.\n";
3626 throw OomphLibError(
3628 }
3629#endif
3630
3631 // First set the matrix matrix multiply methods (for both serial and
3632 // distributed)
3633 out_matrix.serial_matrix_matrix_multiply_method() =
3634 in_matrix_pt->serial_matrix_matrix_multiply_method();
3635
3636 out_matrix.distributed_matrix_matrix_multiply_method() =
3637 in_matrix_pt->distributed_matrix_matrix_multiply_method();
3638
3639
3640 // The local nrow and nnz of the in matrix
3641 const unsigned in_nrow_local = in_matrix_pt->nrow_local();
3642 const unsigned long in_nnz = in_matrix_pt->nnz();
3643
3644 // Storage for the values, column indices and row start
3645 double* out_values = new double[in_nnz];
3646 int* out_column_indices = new int[in_nnz];
3647 int* out_row_start = new int[in_nrow_local + 1];
3648
3649 // The data to copy over
3650 const double* const in_values = in_matrix_pt->value();
3651 const int* const in_column_indices = in_matrix_pt->column_index();
3652 const int* const in_row_start = in_matrix_pt->row_start();
3653
3654 // Copy the data
3655 std::copy(in_values, in_values + in_nnz, out_values);
3656
3657 std::copy(
3659
3660 std::copy(
3662
3663 // Build the matrix
3664 out_matrix.build(in_matrix_pt->distribution_pt());
3665
3666 out_matrix.build_without_copy(in_matrix_pt->ncol(),
3667 in_nnz,
3668 out_values,
3671
3672 // The only thing we haven't copied over is the default linear solver
3673 // pointer, but I cannot figure out how to copy over a solver since
3674 // I do not know what it is.
3675 } // EoFunc deep_copy
3676
3677 /// Builds a uniformly distributed matrix.
3678 /// A locally replicated matrix is constructed then redistributed using
3679 /// OOMPH-LIB's default uniform row distribution.
3680 /// This is memory intensive thus should be used for
3681 /// testing or small problems only.
3682 /// The resulting matrix (mat_out) must not have been built.
3684 const unsigned& nrow,
3685 const unsigned& ncol,
3686 const OomphCommunicator* const comm_pt,
3687 const Vector<double>& values,
3689 const Vector<int>& row_start,
3691
3692
3693 /// Calculates the infinity (maximum) norm of a DenseMartrix of
3694 /// CRDoubleMatrices as if it was one large matrix.
3695 /// This avoids creating a concatenation of the sub-blocks just to calculate
3696 /// the infinity norm.
3697 double inf_norm(const DenseMatrix<CRDoubleMatrix*>& matrix_pt);
3698
3699 /// Calculates the largest Gershgorin disc whilst preserving the sign. Let
3700 /// A be an n by n matrix, with entries aij. For \f$ i \in \{ 1,...,n \} \f$
3701 /// let \f$ R_i = \sum_{i\neq j} |a_{ij}| \f$ be the sum of the absolute
3702 /// values of the non-diagonal entries in the i-th row. Let \f$ D(a_{ii},R_i) \f$
3703 /// be the closed disc centered at \f$ a_{ii} \f$ with radius \f$ R_i \f$,
3704 /// such a disc is called a Gershgorin disc.
3705 ///
3706 /// \n
3707 ///
3708 /// We calculate \f$ |D(a_{ii},R_i)|_{max} \f$and multiply by the sign of
3709 /// the diagonal entry.
3710 ///
3711 /// \n
3712 ///
3713 /// The DenseMatrix of CRDoubleMatrices are treated as if they are one
3714 /// large matrix. Therefore the dimensions of the sub matrices has to
3715 /// "make sense", there is a paranoid check for this.
3717 const DenseMatrix<CRDoubleMatrix*>& matrix_pt);
3718
3719 /// Concatenate CRDoubleMatrix matrices.
3720 /// The in matrices are concatenated such that the block structure of the
3721 /// in matrices are preserved in the result matrix. Communication between
3722 /// processors is required. If the block structure of the sub matrices does
3723 /// not need to be preserved, consider using
3724 /// CRDoubleMatrixHelpers::concatenate_without_communication(...).
3725 ///
3726 /// The matrix manipulation functions
3727 /// CRDoubleMatrixHelpers::concatenate(...) and
3728 /// CRDoubleMatrixHelpers::concatenate_without_communication(...)
3729 /// are analogous to the Vector manipulation functions
3730 /// DoubleVectorHelpers::concatenate(...) and
3731 /// DoubleVectorHelpers::concatenate_without_communication(...).
3732 /// Please look at the DoubleVector functions for an illustration of the
3733 /// differences between concatenate(...) and
3734 /// concatenate_without_communication(...).
3735 ///
3736 /// Distribution of the result matrix:
3737 /// If the result matrix does not have a distribution built, then it will be
3738 /// given a uniform row distribution. Otherwise we use the existing
3739 /// distribution. This gives the user the ability to define their own
3740 /// distribution, or save computing power if a distribution has
3741 /// been pre-built.
3742 ///
3743 /// NOTE: ALL the matrices pointed to by matrix_pt has to be built. This is
3744 /// not the case with concatenate_without_communication(...)
3745 void concatenate(const DenseMatrix<CRDoubleMatrix*>& matrix_pt,
3747
3748 /// Concatenate CRDoubleMatrix matrices.
3749 ///
3750 /// The Vector row_distribution_pt contains the LinearAlgebraDistribution
3751 /// of each block row.
3752 /// The Vector col_distribution_pt contains the LinearAlgebraDistribution
3753 /// of each block column.
3754 /// The DenseMatrix matrix_pt contains pointers to the CRDoubleMatrices
3755 /// to concatenate.
3756 /// The CRDoubleMatrix result_matrix is the result matrix.
3757 ///
3758 /// The result matrix is a permutation of the sub matrices such that the
3759 /// data stays on the same processor when the result matrix is built, there
3760 /// is no communication between processors. Thus the block structure of the
3761 /// sub matrices are NOT preserved in the result matrix. The rows are
3762 /// block-permuted, defined by the concatenation of the distributions in
3763 /// row_distribution_pt. Similarly, the columns are block-permuted, defined
3764 /// by the concatenation of the distributions in col_distribution_pt. For
3765 /// more details on the block-permutation, see
3766 /// LinearAlgebraDistributionHelpers::concatenate(...).
3767 ///
3768 /// If one wishes to preserve the block structure of the sub matrices in the
3769 /// result matrix, consider using CRDoubleMatrixHelpers::concatenate(...),
3770 /// which uses communication between processors to ensure that the block
3771 /// structure of the sub matrices are preserved.
3772 ///
3773 /// The matrix manipulation functions
3774 /// CRDoubleMatrixHelpers::concatenate(...) and
3775 /// CRDoubleMatrixHelpers::concatenate_without_communication(...)
3776 /// are analogous to the Vector manipulation functions
3777 /// DoubleVectorHelpers::concatenate(...) and
3778 /// DoubleVectorHelpers::concatenate_without_communication(...).
3779 /// Please look at the DoubleVector functions for an illustration of the
3780 /// differences between concatenate(...) and
3781 /// concatenate_without_communication(...).
3782 ///
3783 /// Distribution of the result matrix:
3784 /// If the result matrix does not have a distribution built, then it will be
3785 /// given a distribution built from the concatenation of the distributions
3786 /// from row_distribution_pt, see
3787 /// LinearAlgebraDistributionHelpers::concatenate(...) for more detail.
3788 /// Otherwise we use the existing distribution.
3789 /// If there is an existing distribution then it must be the same as the
3790 /// distribution from the concatenation of row distributions as described
3791 /// above.
3792 /// Why don't we always compute the distribution "on the fly"?
3793 /// Because a non-uniform distribution requires communication.
3794 /// All block preconditioner distributions are concatenations of the
3795 /// distributions of the individual blocks.
3799 const DenseMatrix<CRDoubleMatrix*>& matrix_pt,
3801
3802 /// Concatenate CRDoubleMatrix matrices.
3803 /// This calls the other concatenate_without_communication(...) function,
3804 /// passing block_distribution_pt as both the row_distribution_pt and
3805 /// col_distribution_pt. This should only be called for block square
3806 /// matrices.
3808 const Vector<LinearAlgebraDistribution*>& block_distribution_pt,
3809 const DenseMatrix<CRDoubleMatrix*>& matrix_pt,
3811
3812 } // namespace CRDoubleMatrixHelpers
3813
3814} // namespace oomph
3815#endif
cstr elem_len * i
Definition cfortran.h:603
A class for compressed column matrices that store doubles.
Definition matrices.h:2883
double operator()(const unsigned long &i, const unsigned long &j) const
Overload the round-bracket access operator to provide read-only (const) access to the data.
Definition matrices.h:2922
void operator=(const CCDoubleMatrix &)=delete
Broken assignment operator.
void multiply_transpose(const DoubleVector &x, DoubleVector &soln) const
Multiply the transposed matrix by the vector x: soln=A^T x.
Definition matrices.cc:715
virtual void lubksub(DoubleVector &rhs)
LU back solve for given RHS.
Definition matrices.cc:614
void matrix_reduction(const double &alpha, CCDoubleMatrix &reduced_matrix)
For every row, find the maximum absolute value of the entries in this row. Set all values that are le...
Definition matrices.cc:1149
unsigned & matrix_matrix_multiply_method()
Access function to Matrix_matrix_multiply_method, the flag which determines the matrix matrix multipl...
Definition matrices.h:2978
virtual ~CCDoubleMatrix()
Destructor: Kill the LU factors if they have been setup.
Definition matrices.cc:597
CCDoubleMatrix(const CCDoubleMatrix &matrix)=delete
Broken copy constructor.
unsigned long ncol() const
Return the number of columns of the matrix.
Definition matrices.h:2915
unsigned long nrow() const
Return the number of rows of the matrix.
Definition matrices.h:2909
CCDoubleMatrix()
Default constructor.
Definition matrices.cc:572
virtual void ludecompose()
LU decomposition using SuperLU.
Definition matrices.cc:606
void multiply(const DoubleVector &x, DoubleVector &soln) const
Multiply the matrix by the vector x: soln=Ax.
Definition matrices.cc:622
unsigned Matrix_matrix_multiply_method
Flag to determine which matrix-matrix multiplication method is used.
Definition matrices.h:2985
A class for compressed column matrices: a sparse matrix format The class is passed as the MATRIX_TYPE...
Definition matrices.h:2672
CCMatrix()
Default constructor.
Definition matrices.h:2675
T & entry(const unsigned long &i, const unsigned long &j)
Read-write access is not permitted for these matrices and is deliberately broken.
Definition matrices.h:2758
CCMatrix(const Vector< T > &value, const Vector< int > &row_index_, const Vector< int > &column_start_, const unsigned long &n, const unsigned long &m)
Constructor: Pass vector of values, vector of row indices, vector of column starts and number of rows...
Definition matrices.h:2687
void build_without_copy(T *value, int *row_index, int *column_start, const unsigned long &nnz, const unsigned long &n, const unsigned long &m)
Function to build matrix from pointers to arrays which hold the column starts, row indices and non-ze...
Definition matrices.h:3307
virtual ~CCMatrix()
Destructor, delete any allocated memory.
Definition matrices.h:2731
int * Column_start
Start index for column.
Definition matrices.h:2871
int * Row_index
Row index.
Definition matrices.h:2868
CCMatrix(const CCMatrix &source_matrix)
Copy constructor.
Definition matrices.h:2701
void sparse_indexed_output_helper(std::ostream &outfile, const double &cutoff) const
Indexed output function to print a matrix to the stream outfile as i,j,a(i,j) for a(i,...
Definition matrices.h:2823
T get_entry(const unsigned long &i, const unsigned long &j) const
Access function that will be called by the read-only round-bracket operator (const)
Definition matrices.h:2741
int * column_start()
Access to C-style column_start array.
Definition matrices.h:2779
void build(const Vector< T > &value, const Vector< int > &row_index, const Vector< int > &column_start, const unsigned long &n, const unsigned long &m)
Build matrix from compressed representation. Number of nonzero entries is read off from value,...
Definition matrices.h:3355
void operator=(const CCMatrix &)=delete
Broken assignment operator.
void output_bottom_right_zero_helper(std::ostream &outfile) const
Output the "bottom right" entry regardless of it being zero or not (this allows automatic detection o...
Definition matrices.h:2805
const int * row_index() const
Access to C-style row index array (const version)
Definition matrices.h:2797
int * row_index()
Access to C-style row index array.
Definition matrices.h:2791
const int * column_start() const
Access to C-style column_start array (const version)
Definition matrices.h:2785
void clean_up_memory()
Wipe matrix data and set all values to 0.
Definition matrices.h:3277
A class for compressed row matrices. This is a distributable object.
Definition matrices.h:927
unsigned & serial_matrix_matrix_multiply_method()
Access function to Serial_matrix_matrix_multiply_method, the flag which determines the matrix matrix ...
Definition matrices.h:1200
void sort_entries()
Sorts the entries associated with each row of the matrix in the column index vector and the value vec...
Definition matrices.cc:1449
virtual ~CRDoubleMatrix()
Destructor.
Definition matrices.cc:1343
void sparse_indexed_output_with_offset(std::string filename)
Indexed output function to print a matrix to a file as i,j,a(i,j) for a(i,j)!=0 only....
Definition matrices.h:1072
int * row_start()
Access to C-style row_start array.
Definition matrices.h:1101
struct oomph::CRDoubleMatrix::CRDoubleMatrixComparisonHelper Comparison_struct
void matrix_reduction(const double &alpha, CRDoubleMatrix &reduced_matrix)
For every row, find the maximum absolute value of the entries in this row. Set all values that are le...
Definition matrices.cc:2365
void operator=(const CRDoubleMatrix &)=delete
Broken assignment operator.
void multiply_transpose(const DoubleVector &x, DoubleVector &soln) const
Multiply the transposed matrix by the vector x: soln=A^T x.
Definition matrices.cc:1882
const double * value() const
Access to C-style value array (const version)
Definition matrices.h:1131
unsigned Distributed_matrix_matrix_multiply_method
Flag to determine which matrix-matrix multiplication method is used (for distributed matrices)
Definition matrices.h:1287
virtual void ludecompose()
LU decomposition using SuperLU if matrix is not distributed or distributed onto a single processor.
Definition matrices.cc:1728
unsigned long ncol() const
Return the number of columns of the matrix.
Definition matrices.h:1047
const Vector< int > get_index_of_diagonal_entries() const
Access function: returns the vector Index_of_diagonal_entries. The i-th entry of the vector contains ...
Definition matrices.h:959
void multiply(const DoubleVector &x, DoubleVector &soln) const
Multiply the matrix by the vector x: soln=Ax.
Definition matrices.cc:1782
void add(const CRDoubleMatrix &matrix_in, CRDoubleMatrix &result_matrix) const
element-wise addition of this matrix with matrix_in.
Definition matrices.cc:3515
unsigned & distributed_matrix_matrix_multiply_method()
Access function to Distributed_matrix_matrix_multiply_method, the flag which determines the matrix ma...
Definition matrices.h:1232
bool Built
Flag to indicate whether the matrix has been built - i.e. the distribution has been setup AND the mat...
Definition matrices.h:1294
Vector< int > Index_of_diagonal_entries
Vector whose i'th entry contains the index of the last entry below or on the diagonal of the i'th row...
Definition matrices.h:1279
double inf_norm() const
returns the inf-norm of this matrix
Definition matrices.cc:3412
void get_matrix_transpose(CRDoubleMatrix *result) const
Returns the transpose of this matrix.
Definition matrices.cc:3271
const unsigned & serial_matrix_matrix_multiply_method() const
Read only access function (const version) to Serial_matrix_matrix_multiply_method,...
Definition matrices.h:1222
int * column_index()
Access to C-style column index array.
Definition matrices.h:1113
unsigned long nnz() const
Return the number of nonzero entries (the local nnz)
Definition matrices.h:1137
CRDoubleMatrix * global_matrix() const
if this matrix is distributed then a the equivalent global matrix is built using new and returned....
Definition matrices.cc:2431
void redistribute(const LinearAlgebraDistribution *const &dist_pt)
The contents of the matrix are redistributed to match the new distribution. In a non-MPI build this m...
Definition matrices.cc:2575
bool built() const
access function to the Built flag - indicates whether the matrix has been build - i....
Definition matrices.h:1251
const unsigned & distributed_matrix_matrix_multiply_method() const
Read only access function (const version) to Distributed_matrix_matrix_multiply_method,...
Definition matrices.h:1243
void build_without_copy(const unsigned &ncol, const unsigned &nnz, double *value, int *column_index, int *row_start)
keeps the existing distribution and just matrix that is stored without copying the matrix data
Definition matrices.cc:1710
double * value()
Access to C-style value array.
Definition matrices.h:1125
void output_bottom_right_zero_helper(std::ostream &outfile) const
Output the "bottom right" entry regardless of it being zero or not (this allows automatic detection o...
Definition matrices.h:1055
const int * row_start() const
Access to C-style row_start array (const version)
Definition matrices.h:1107
unsigned long nrow() const
Return the number of rows of the matrix.
Definition matrices.h:1041
unsigned Serial_matrix_matrix_multiply_method
Flag to determine which matrix-matrix multiplication method is used (for serial (or global) matrices)
Definition matrices.h:1283
Vector< double > diagonal_entries() const
returns a Vector of diagonal entries of this matrix. This only works with square matrices....
Definition matrices.cc:3465
CRDoubleMatrix()
Default constructor.
Definition matrices.cc:1214
bool entries_are_sorted(const bool &doc_unordered_entries=false) const
Runs through the column index vector and checks if the entries follow the regular lexicographical ord...
Definition matrices.cc:1366
void sparse_indexed_output_helper(std::ostream &outfile, const double &cutoff=0.0) const
Indexed output function to print a matrix to the stream outfile as i,j,a(i,j) for a(i,...
Definition matrices.h:1063
const int * column_index() const
Access to C-style column index array (const version)
Definition matrices.h:1119
CRMatrix< double > CR_matrix
Storage for the Matrix in CR Format.
Definition matrices.h:1290
virtual void lubksub(DoubleVector &rhs)
LU back solve for given RHS.
Definition matrices.cc:1749
void build(const LinearAlgebraDistribution *distribution_pt, const unsigned &ncol, const Vector< double > &value, const Vector< int > &column_index, const Vector< int > &row_start)
build method: vector of values, vector of column indices, vector of row starts and number of rows and...
Definition matrices.cc:1672
double operator()(const unsigned long &i, const unsigned long &j) const
Overload the round-bracket access operator for read-only access. In a distributed matrix i refers to ...
Definition matrices.h:1094
A class for compressed row matrices, a sparse storage format Once again the recursive template trick ...
Definition matrices.h:716
CRMatrix()
Default constructor.
Definition matrices.h:719
void clean_up_memory()
Wipe matrix data and set all values to 0.
Definition matrices.h:3431
CRMatrix(const CRMatrix &source_matrix)
Copy constructor.
Definition matrices.h:744
T & entry(const unsigned long &i, const unsigned long &j)
The read-write access function is deliberately broken.
Definition matrices.h:798
void sparse_indexed_output_helper(std::ostream &outfile, const double &cutoff=0.0) const
Indexed output function to print a matrix to the stream outfile as i,j,a(i,j) for a(i,...
Definition matrices.h:863
int * column_index()
Access to C-style column index array.
Definition matrices.h:831
int * Row_start
Start index for row.
Definition matrices.h:912
int * Column_index
Column index.
Definition matrices.h:909
void build(const Vector< T > &value, const Vector< int > &column_index, const Vector< int > &row_start, const unsigned long &n, const unsigned long &m)
Build matrix from compressed representation. Number of nonzero entries is read off from value,...
Definition matrices.h:3512
int * row_start()
Access to C-style row_start array.
Definition matrices.h:819
void operator=(const CRMatrix &)=delete
Broken assignment operator.
void output_bottom_right_zero_helper(std::ostream &outfile) const
Output the "bottom right" entry regardless of it being zero or not (this allows automatic detection o...
Definition matrices.h:845
const int * row_start() const
Access to C-style row_start array (const version)
Definition matrices.h:825
virtual ~CRMatrix()
Destructor, delete any allocated memory.
Definition matrices.h:772
void build_without_copy(T *value, int *column_index, int *row_start, const unsigned long &nnz, const unsigned long &n, const unsigned long &m)
Function to build matrix from pointers to arrays which hold the row starts, column indices and non-ze...
Definition matrices.h:3462
const int * column_index() const
Access to C-style column index array (const version)
Definition matrices.h:837
T get_entry(const unsigned long &i, const unsigned long &j) const
Access function that will be called by the read-only round-bracket operator (const)
Definition matrices.h:782
CRMatrix(const Vector< T > &value, const Vector< int > &column_index_, const Vector< int > &row_start_, const unsigned long &n, const unsigned long &m)
Constructor: Pass vector of values, vector of column indices, vector of row starts and number of rows...
Definition matrices.h:731
Class of matrices containing doubles, and stored as a DenseMatrix<double>, but with solving functiona...
Definition matrices.h:1312
double & operator()(const unsigned long &i, const unsigned long &j)
Overload the non-const version of the round-bracket access operator for read-write access.
Definition matrices.h:1357
DenseDoubleMatrix()
Constructor, set the default linear solver.
Definition matrices.cc:139
DenseDoubleMatrix(const DenseDoubleMatrix &matrix)=delete
Broken copy constructor.
virtual void lubksub(DoubleVector &rhs)
LU backsubstitution.
Definition matrices.cc:202
virtual ~DenseDoubleMatrix()
Destructor.
Definition matrices.cc:182
void matrix_reduction(const double &alpha, DenseDoubleMatrix &reduced_matrix)
For every row, find the maximum absolute value of the entries in this row. Set all values that are le...
Definition matrices.cc:481
virtual void ludecompose()
LU decomposition using DenseLU (default linea solver)
Definition matrices.cc:192
void multiply_transpose(const DoubleVector &x, DoubleVector &soln) const
Multiply the transposed matrix by the vector x: soln=A^T x.
Definition matrices.cc:385
void multiply(const DoubleVector &x, DoubleVector &soln) const
Multiply the matrix by the vector x: soln=Ax.
Definition matrices.cc:294
unsigned long nrow() const
Return the number of rows of the matrix.
Definition matrices.h:1336
double operator()(const unsigned long &i, const unsigned long &j) const
Overload the const version of the round-bracket access operator for read-only access.
Definition matrices.h:1349
unsigned long ncol() const
Return the number of columns of the matrix.
Definition matrices.h:1342
void eigenvalues_by_jacobi(Vector< double > &eigen_val, DenseMatrix< double > &eigen_vect) const
Determine eigenvalues and eigenvectors, using Jacobi rotations. Only for symmetric matrices....
Definition matrices.cc:224
void operator=(const DenseDoubleMatrix &)=delete
Broken assignment operator.
Dense LU decomposition-based solve of full assembled linear system. VERY inefficient but useful to il...
Class for dense matrices, storing all the values of the matrix as a pointer to a pointer with assorte...
Definition matrices.h:416
DenseMatrix & operator=(const DenseMatrix &source_matrix)
Copy assignment.
Definition matrices.h:450
void output(std::ostream &outfile) const
Output function to print a matrix row-by-row to the stream outfile.
Definition matrices.h:3146
T get_entry(const unsigned long &i, const unsigned long &j) const
The access function the will be called by the read-only (const version) round-bracket operator.
Definition matrices.h:487
void resize(const unsigned long &n, const unsigned long &m)
Resize to a non-square n x m matrix; any values already present will be transfered.
Definition matrices.h:3051
unsigned long nrow() const
Return the number of rows of the matrix.
Definition matrices.h:515
DenseMatrix(const DenseMatrix &source_matrix)
Copy constructor: Deep copy!
Definition matrices.h:432
DenseMatrix(const unsigned long &n)
Constructor to build a square n by n matrix.
Definition matrices.h:2998
unsigned long N
Number of rows.
Definition matrices.h:422
void indexed_output(std::ostream &outfile) const
Indexed output function to print a matrix to the stream outfile as i,j,a(i,j)
Definition matrices.h:3181
void output(std::string filename) const
Output function to print a matrix row-by-row to a file. Specify filename.
Definition matrices.h:3166
void indexed_output(std::string filename) const
Indexed output function to print a matrix to a file as i,j,a(i,j). Specify filename.
Definition matrices.h:3200
DenseMatrix(const unsigned long &n, const unsigned long &m)
Constructor to build a matrix with n rows and m columns.
Definition matrices.h:3016
virtual ~DenseMatrix()
Destructor, clean up the matrix data.
Definition matrices.h:508
T & entry(const unsigned long &i, const unsigned long &j)
The access function that will be called by the read-write round-bracket operator.
Definition matrices.h:477
DenseMatrix(const unsigned long &n, const unsigned long &m, const T &initial_val)
Constructor to build a matrix with n rows and m columns, with initial value initial_val.
Definition matrices.h:3033
T * Matrixdata
Internal representation of matrix as a pointer to data.
Definition matrices.h:419
unsigned long ncol() const
Return the number of columns of the matrix.
Definition matrices.h:521
void sparse_indexed_output_helper(std::ostream &outfile, const double &cutoff=0.0) const
Indexed output function to print a matrix to the stream outfile as i,j,a(i,j) for a(i,...
Definition matrices.h:3236
void output_bottom_right_zero_helper(std::ostream &outfile) const
Output the "bottom right" entry regardless of it being zero or not (this allows automatic detection o...
Definition matrices.h:3216
unsigned long M
Number of columns.
Definition matrices.h:425
void initialise(const T &val)
Initialize all values in the matrix to val.
Definition matrices.h:544
void resize(const unsigned long &n)
Resize to a square nxn matrix; any values already present will be transfered.
Definition matrices.h:528
void resize(const unsigned long &n, const unsigned long &m, const T &initial_value)
Resize to a non-square n x m matrix and initialize the new values to initial_value.
Definition matrices.h:3100
DenseMatrix()
Empty constructor, simply assign the lengths N and M to 0.
Definition matrices.h:429
Base class for any linear algebra object that is distributable. Just contains storage for the LinearA...
unsigned nrow() const
access function to the number of global rows.
unsigned nrow_local() const
access function for the num of local rows on this processor.
unsigned first_row() const
access function for the first row on this processor
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
Abstract base class for matrices of doubles – adds abstract interfaces for solving,...
Definition matrices.h:291
virtual double operator()(const unsigned long &i, const unsigned long &j) const =0
Round brackets to give access as a(i,j) for read only (we're not providing a general interface for co...
virtual unsigned long ncol() const =0
Return the number of columns of the matrix.
DoubleMatrixBase(const DoubleMatrixBase &matrix)=delete
Broken copy constructor.
LinearSolver *const & linear_solver_pt() const
Return a pointer to the linear solver object (const version)
Definition matrices.h:332
void solve(DoubleVector &rhs)
Complete LU solve (replaces matrix by its LU decomposition and overwrites RHS with solution)....
Definition matrices.cc:50
virtual double max_residual(const DoubleVector &x, const DoubleVector &rhs)
Find the maximum residual r=b-Ax – generic version, can be overloaded for specific derived classes wh...
Definition matrices.h:378
LinearSolver * Default_linear_solver_pt
Definition matrices.h:297
virtual void multiply(const DoubleVector &x, DoubleVector &soln) const =0
Multiply the matrix by the vector x: soln=Ax.
virtual ~DoubleMatrixBase()
virtual (empty) destructor
Definition matrices.h:316
virtual void multiply_transpose(const DoubleVector &x, DoubleVector &soln) const =0
Multiply the transposed matrix by the vector x: soln=A^T x.
LinearSolver * Linear_solver_pt
Definition matrices.h:294
virtual void residual(const DoubleVector &x, const DoubleVector &b, DoubleVector &residual_)
Find the residual, i.e. r=b-Ax the residual.
Definition matrices.h:356
DoubleMatrixBase()
(Empty) constructor.
Definition matrices.h:301
LinearSolver *& linear_solver_pt()
Return a pointer to the linear solver object.
Definition matrices.h:326
void operator=(const DoubleMatrixBase &)=delete
Broken assignment operator.
virtual unsigned long nrow() const =0
Return the number of rows of the matrix.
A vector in the mathematical sense, initially developed for linear algebra type applications....
double size() const
Calculate the size of the element (length, area, volume,...) in Eulerian computational coordinates....
Definition elements.cc:4320
Describes the distribution of a distributable linear algebra type object. Typically this is a contain...
unsigned first_row() const
access function for the first row on this processor. If not distributed then this is just zero.
Base class for all linear solvers. This merely defines standard interfaces for linear solvers,...
Abstract base class for matrices, templated by the type of object that is stored in them and the type...
Definition matrices.h:75
T & operator()(const unsigned long &i, const unsigned long &j)
Round brackets to give access as a(i,j) for read-write access. The function uses the MATRIX_TYPE temp...
Definition matrices.h:141
virtual void output_bottom_right_zero_helper(std::ostream &outfile) const =0
Output the "bottom right" entry regardless of it being zero or not (this allows automatic detection o...
void sparse_indexed_output_with_cutoff(std::ostream &outfile, const double &cutoff=0.0) const
Indexed output function to print a matrix to the stream outfile as i,j,a(i,j) for a(i,...
Definition matrices.h:254
T operator()(const unsigned long &i, const unsigned long &j) const
Round brackets to give access as a(i,j) for read only (we're not providing a general interface for co...
Definition matrices.h:129
void range_check(const unsigned long &i, const unsigned long &j) const
Range check to catch when an index is out of bounds, if so, it issues a warning message and dies by t...
Definition matrices.h:79
void sparse_indexed_output_with_cutoff(std::string filename, const double &cutoff=0.0) const
Indexed output function to print a matrix to the stream outfile as i,j,a(i,j) for a(i,...
Definition matrices.h:266
virtual ~Matrix()
Virtual (empty) destructor.
Definition matrices.h:115
virtual void sparse_indexed_output_helper(std::ostream &outfile, const double &cutoff=0.0) const =0
Indexed output function to print a matrix to the stream outfile as i,j,a(i,j) for a(i,...
void sparse_indexed_output(std::ostream &outfile, const unsigned &precision=0, const bool &output_bottom_right_zero=false, const double &cutoff=0.0) const
Indexed output function to print a matrix to the stream outfile as i,j,a(i,j) for a(i,...
Definition matrices.h:185
void operator=(const Matrix &)=delete
Broken assignment operator.
Matrix()
(Empty) constructor
Definition matrices.h:106
virtual unsigned long nrow() const =0
Return the number of rows of the matrix.
Matrix(const Matrix &matrix)=delete
Broken copy constructor.
virtual void output(std::ostream &outfile) const
Output function to print a matrix row-by-row, in the form a(0,0) a(0,1) ... a(1,0) a(1,...
Definition matrices.h:153
virtual unsigned long ncol() const =0
Return the number of columns of the matrix.
void sparse_indexed_output(std::string filename, const unsigned &precision=0, const bool &output_bottom_right_zero=false, const double &cutoff=0.0) const
Indexed output function to print a matrix to the file named filename as i,j,a(i,j) for a(i,...
Definition matrices.h:231
An oomph-lib wrapper to the MPI_Comm communicator object. Just contains an MPI_Comm object (which is ...
An OomphLibError object which should be thrown when an run-time error is encountered....
An OomphLibWarning object which should be created as a temporary object to issue a warning....
A Rank 5 Tensor class.
Definition matrices.h:2200
unsigned R
5th Tensor dimension
Definition matrices.h:2218
T operator()(const unsigned long &i, const unsigned long &j, const unsigned long &k, const unsigned long &l, const unsigned long &m) const
Overload a const version for read-only access as a(i,j,k,l,m)
Definition matrices.h:2616
RankFiveTensor(const RankFiveTensor &source_tensor)
Copy constructor: Deep copy.
Definition matrices.h:2285
RankFiveTensor & operator=(const RankFiveTensor &source_tensor)
Copy assignement.
Definition matrices.h:2318
unsigned M
2nd Tensor dimension
Definition matrices.h:2209
unsigned long nindex4() const
Return the range of index 4 of the tensor.
Definition matrices.h:2591
RankFiveTensor(const unsigned long &n)
One parameter constructor produces a nxnxnxnxn tensor.
Definition matrices.h:2359
RankFiveTensor()
Empty constructor.
Definition matrices.h:2282
unsigned Q
4th Tensor dimension
Definition matrices.h:2215
unsigned long nindex3() const
Return the range of index 3 of the tensor.
Definition matrices.h:2585
T & raw_direct_access(const unsigned long &i)
Direct access to internal storage of data in flat-packed C-style column-major format....
Definition matrices.h:2632
RankFiveTensor(const unsigned long &n_index1, const unsigned long &n_index2, const unsigned long &n_index3, const unsigned long &n_index4, const unsigned long &n_index5, const T &initial_val)
Four parameter constructor, general non-square tensor.
Definition matrices.h:2398
const T & raw_direct_access(const unsigned long &i) const
Direct access to internal storage of data in flat-packed C-style column-major format....
Definition matrices.h:2642
void resize(const unsigned long &n_index1, const unsigned long &n_index2, const unsigned long &n_index3, const unsigned long &n_index4, const unsigned long &n_index5, const T &initial_value)
Resize to a general tensor.
Definition matrices.h:2497
void resize(const unsigned long &n)
Resize to a square nxnxnxn tensor.
Definition matrices.h:2425
void range_check(const unsigned long &i, const unsigned long &j, const unsigned long &k, const unsigned long &l, const unsigned long &m) const
Range check to catch when an index is out of bounds, if so, it issues a warning message and dies by t...
Definition matrices.h:2222
unsigned long nindex2() const
Return the range of index 2 of the tensor.
Definition matrices.h:2579
T & operator()(const unsigned long &i, const unsigned long &j, const unsigned long &k, const unsigned long &l, const unsigned long &m)
Overload the round brackets to give access as a(i,j,k,l,m)
Definition matrices.h:2603
unsigned long nindex5() const
Return the range of index 5 of the tensor.
Definition matrices.h:2597
unsigned P
3rd Tensor dimension
Definition matrices.h:2212
unsigned offset(const unsigned long &i, const unsigned long &j, const unsigned long &k) const
Caculate the offset in flat-packed Cy-style, column-major format, required for a given i,...
Definition matrices.h:2651
void initialise(const T &val)
Initialise all values in the tensor to val.
Definition matrices.h:2564
unsigned long nindex1() const
Return the range of index 1 of the tensor.
Definition matrices.h:2573
T * Tensordata
Private internal representation as pointer to data.
Definition matrices.h:2203
virtual ~RankFiveTensor()
Destructor: delete the pointers.
Definition matrices.h:2418
unsigned N
1st Tensor dimension
Definition matrices.h:2206
RankFiveTensor(const unsigned long &n_index1, const unsigned long &n_index2, const unsigned long &n_index3, const unsigned long &n_index4, const unsigned long &n_index5)
Four parameter constructor, general non-square tensor.
Definition matrices.h:2376
void resize(const unsigned long &n_index1, const unsigned long &n_index2, const unsigned long &n_index3, const unsigned long &n_index4, const unsigned long &n_index5)
Resize to a general tensor.
Definition matrices.h:2431
A Rank 4 Tensor class.
Definition matrices.h:1742
unsigned M
2nd Tensor dimension
Definition matrices.h:1751
unsigned N
1st Tensor dimension
Definition matrices.h:1748
RankFourTensor()
Empty constructor.
Definition matrices.h:1813
T & raw_direct_access(const unsigned long &i)
Direct access to internal storage of data in flat-packed C-style column-major format....
Definition matrices.h:2165
RankFourTensor(const unsigned long &n_index1, const unsigned long &n_index2, const unsigned long &n_index3, const unsigned long &n_index4)
Four parameter constructor, general non-square tensor.
Definition matrices.h:1921
void resize(const unsigned long &n_index1, const unsigned long &n_index2, const unsigned long &n_index3, const unsigned long &n_index4, const T &initial_value)
Resize to a general tensor.
Definition matrices.h:2040
virtual ~RankFourTensor()
Destructor: delete the pointers.
Definition matrices.h:1961
unsigned offset(const unsigned long &i, const unsigned long &j) const
Caculate the offset in flat-packed C-style, column-major format, required for a given i,...
Definition matrices.h:2183
T * Tensordata
Private internal representation as pointer to data.
Definition matrices.h:1745
void resize(const unsigned long &n_index1, const unsigned long &n_index2, const unsigned long &n_index3, const unsigned long &n_index4)
Resize to a general tensor.
Definition matrices.h:1977
unsigned long nindex4() const
Return the range of index 4 of the tensor.
Definition matrices.h:2131
RankFourTensor & operator=(const RankFourTensor &source_tensor)
Copy assignement.
Definition matrices.h:1849
void shallow_copy_from(const RankFourTensor &source_tensor)
Shallow copy of data from source_tensor.
Definition matrices.h:1886
unsigned long nindex2() const
Return the range of index 2 of the tensor.
Definition matrices.h:2119
const T & raw_direct_access(const unsigned long &i) const
Direct access to internal storage of data in flat-packed C-style column-major format....
Definition matrices.h:2174
unsigned long nindex1() const
Return the range of index 1 of the tensor.
Definition matrices.h:2113
bool Is_tensordata_a_copy
Boolean to indicate whether data is a copy.
Definition matrices.h:1760
T operator()(const unsigned long &i, const unsigned long &j, const unsigned long &k, const unsigned long &l) const
Overload a const version for read-only access as a(i,j,k,l)
Definition matrices.h:2150
unsigned long nindex3() const
Return the range of index 3 of the tensor.
Definition matrices.h:2125
RankFourTensor(const unsigned long &n)
One parameter constructor produces a nxnxnxn tensor.
Definition matrices.h:1904
RankFourTensor(const unsigned long &n_index1, const unsigned long &n_index2, const unsigned long &n_index3, const unsigned long &n_index4, const T &initial_val)
Four parameter constructor, general non-square tensor.
Definition matrices.h:1942
unsigned P
3rd Tensor dimension
Definition matrices.h:1754
void range_check(const unsigned long &i, const unsigned long &j, const unsigned long &k, const unsigned long &l) const
Range check to catch when an index is out of bounds, if so, it issues a warning message and dies by t...
Definition matrices.h:1764
T & operator()(const unsigned long &i, const unsigned long &j, const unsigned long &k, const unsigned long &l)
Overload the round brackets to give access as a(i,j,k,l)
Definition matrices.h:2137
RankFourTensor(const RankFourTensor &source_tensor)
Copy constructor: Deep copy.
Definition matrices.h:1819
unsigned Q
4th Tensor dimension
Definition matrices.h:1757
void initialise(const T &val)
Initialise all values in the tensor to val.
Definition matrices.h:2104
void resize(const unsigned long &n)
Resize to a square nxnxnxn tensor.
Definition matrices.h:1971
A Rank 3 Tensor class.
Definition matrices.h:1411
virtual ~RankThreeTensor()
Destructor: delete the pointers.
Definition matrices.h:1573
void resize(const unsigned long &n_index1, const unsigned long &n_index2, const unsigned long &n_index3, const T &initial_value)
Resize to a general tensor.
Definition matrices.h:1634
unsigned N
1st Tensor dimension
Definition matrices.h:1417
RankThreeTensor(const unsigned long &n_index1, const unsigned long &n_index2, const unsigned long &n_index3, const T &initial_val)
Three parameter constructor, general non-square tensor.
Definition matrices.h:1557
RankThreeTensor & operator=(const RankThreeTensor &source_tensor)
Copy assignement.
Definition matrices.h:1491
unsigned long nindex1() const
Return the range of index 1 of the tensor.
Definition matrices.h:1692
unsigned long nindex2() const
Return the range of index 2 of the tensor.
Definition matrices.h:1698
void range_check(const unsigned long &i, const unsigned long &j, const unsigned long &k) const
Range check to catch when an index is out of bounds, if so, it issues a warning message and dies by t...
Definition matrices.h:1427
RankThreeTensor(const RankThreeTensor &source_tensor)
Copy constructor: Deep copy.
Definition matrices.h:1469
RankThreeTensor()
Empty constructor.
Definition matrices.h:1466
unsigned M
2nd Tensor dimension
Definition matrices.h:1420
T & operator()(const unsigned long &i, const unsigned long &j, const unsigned long &k)
Overload the round brackets to give access as a(i,j,k)
Definition matrices.h:1710
T operator()(const unsigned long &i, const unsigned long &j, const unsigned long &k) const
Overload a const version for read-only access as a(i,j,k)
Definition matrices.h:1721
void resize(const unsigned long &n)
Resize to a square nxnxn tensor.
Definition matrices.h:1580
void resize(const unsigned long &n_index1, const unsigned long &n_index2, const unsigned long &n_index3)
Resize to a general tensor.
Definition matrices.h:1586
unsigned long nindex3() const
Return the range of index 3 of the tensor.
Definition matrices.h:1704
void initialise(const T &val)
Initialise all values in the tensor to val.
Definition matrices.h:1683
RankThreeTensor(const unsigned long &n_index1, const unsigned long &n_index2, const unsigned long &n_index3)
Three parameter constructor, general non-square tensor.
Definition matrices.h:1539
unsigned P
3rd Tensor dimension
Definition matrices.h:1423
T * Tensordata
Private internal representation as pointer to data.
Definition matrices.h:1414
RankThreeTensor(const unsigned long &n)
One parameter constructor produces a cubic nxnxn tensor.
Definition matrices.h:1524
Class for sparse matrices, that store only the non-zero values in a linear array in memory....
Definition matrices.h:594
unsigned long Nnz
Number of non-zero values (i.e. size of Value array)
Definition matrices.h:606
unsigned long nrow() const
Return the number of rows of the matrix.
Definition matrices.h:660
virtual void output_bottom_right_zero_helper(std::ostream &outfile) const
Output the "bottom right" entry regardless of it being zero or not (this allows automatic detection o...
Definition matrices.h:680
unsigned long ncol() const
Return the number of columns of the matrix.
Definition matrices.h:666
T * Value
Internal representation of the matrix values, a pointer.
Definition matrices.h:597
static T Zero
Dummy zero.
Definition matrices.h:609
T * value()
Access to C-style value array.
Definition matrices.h:648
void operator=(const SparseMatrix &)=delete
Broken assignment operator.
unsigned long nnz() const
Return the number of nonzero entries.
Definition matrices.h:672
unsigned long N
Number of rows.
Definition matrices.h:600
SparseMatrix()
Default constructor.
Definition matrices.h:613
SparseMatrix(const SparseMatrix &source_matrix)
Copy constructor.
Definition matrices.h:616
virtual ~SparseMatrix()
Destructor, delete the memory associated with the values.
Definition matrices.h:641
unsigned long M
Number of columns.
Definition matrices.h:603
virtual void sparse_indexed_output_helper(std::ostream &outfile, const double &cutoff=0.0) const
Indexed output function to print a matrix to the stream outfile as i,j,a(i,j) for a(i,...
Definition matrices.h:694
const T * value() const
Access to C-style value array (const version)
Definition matrices.h:654
SuperLU Project Solver class. This is a combined wrapper for both SuperLU and SuperLU Dist....
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
void output(std::ostream &outfile)
Output function: x,y,u or x,y,z,u.
TAdvectionDiffusionReactionElement()
Constructor: Call constructors for TElement and AdvectionDiffusionReaction equations.
double gershgorin_eigenvalue_estimate(const DenseMatrix< CRDoubleMatrix * > &matrix_pt)
Calculates the largest Gershgorin disc whilst preserving the sign. Let A be an n by n matrix,...
Definition matrices.cc:4003
void deep_copy(const CRDoubleMatrix *const in_matrix_pt, CRDoubleMatrix &out_matrix)
Create a deep copy of the matrix pointed to by in_matrix_pt.
Definition matrices.h:3598
void concatenate_without_communication(const Vector< LinearAlgebraDistribution * > &row_distribution_pt, const Vector< LinearAlgebraDistribution * > &col_distribution_pt, const DenseMatrix< CRDoubleMatrix * > &matrix_pt, CRDoubleMatrix &result_matrix)
Concatenate CRDoubleMatrix matrices.
Definition matrices.cc:5223
double inf_norm(const DenseMatrix< CRDoubleMatrix * > &matrix_pt)
Compute infinity (maximum) norm of sub blocks as if it was one matrix.
Definition matrices.cc:3731
void concatenate(const DenseMatrix< CRDoubleMatrix * > &matrix_pt, CRDoubleMatrix &result_matrix)
Concatenate CRDoubleMatrix matrices. The in matrices are concatenated such that the block structure o...
Definition matrices.cc:4349
void create_uniformly_distributed_matrix(const unsigned &nrow, const unsigned &ncol, const OomphCommunicator *const comm_pt, const Vector< double > &values, const Vector< int > &column_indices, const Vector< int > &row_start, CRDoubleMatrix &matrix_out)
Builds a uniformly distributed matrix. A locally replicated matrix is constructed then redistributed ...
Definition matrices.cc:3676
std::string RayStr
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Create a struct to provide a comparison function for std::sort.
Definition matrices.h:981
bool operator()(const std::pair< int, double > &pair_1, const std::pair< int, double > &pair_2)
Definition matrices.h:983
Compile-time test to determine if a type T has a notion of "magnitude", i.e. if std::abs(T) is a vali...