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