sum_of_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// Version 1.0; svn revision $LastChangedRevision$
7 //LIC//
8 //LIC// $LastChangedDate$
9 //LIC//
10 //LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11 //LIC//
12 //LIC// This library is free software; you can redistribute it and/or
13 //LIC// modify it under the terms of the GNU Lesser General Public
14 //LIC// License as published by the Free Software Foundation; either
15 //LIC// version 2.1 of the License, or (at your option) any later version.
16 //LIC//
17 //LIC// This library is distributed in the hope that it will be useful,
18 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 //LIC// Lesser General Public License for more details.
21 //LIC//
22 //LIC// You should have received a copy of the GNU Lesser General Public
23 //LIC// License along with this library; if not, write to the Free Software
24 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 //LIC// 02110-1301 USA.
26 //LIC//
27 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28 //LIC//
29 //LIC//====================================================================
30 #ifndef OOMPH_SUM_OF_MATRICES_H
31 #define OOMPH_SUM_OF_MATRICES_H
32 
33 
34 #include "mesh.h"
35 #include "matrices.h"
36 #include "Vector.h"
37 #include "oomph_utilities.h"
38 
39 #include <map>
40 
41 
42 namespace oomph
43 {
44 
45  using namespace StringConversion;
46 
47  // =================================================================
48  /// Class to store bi-directional lookup between added matrix row/col
49  /// numbers to main matrix (SumOfMatrix) row/col numbers.
50  // =================================================================
52  {
53 
54  public:
55 
56  /// Default constructor
58 
59  /// Real constructor: construct lookup from node numbers in mesh and
60  /// global equation numbers. Useful for the case when the main matrix is
61  /// a Jacobian and the added matrix is a contribution only on a certain
62  /// mesh.
63  AddedMainNumberingLookup(const Mesh* mesh_pt, const unsigned& dof_index)
64  {
65  this->build(mesh_pt, dof_index);
66  }
67 
68  /// Construct lookup schemes from int array (HLib's format for this
69  /// data).
70  AddedMainNumberingLookup(const int* lookup_array, const unsigned& length)
71  {
72  this->build(lookup_array, length);
73  }
74 
75  /// Destructor
77 
78  /// \short Given a main matrix row/col number get the equivalent row/col
79  /// in the added matrix. Throw an error if not found.
80  unsigned main_to_added(const int& main) const
81  {
82  int result = unsafe_main_to_added(main);
83 #ifdef PARANOID
84  // If it's -1 then we failed to find it:
85  if(result == -1)
86  {
87  std::string err = "Main matrix row/col number " + to_string(main)
88  + " not found in lookup.";
89  throw OomphLibError(err, OOMPH_EXCEPTION_LOCATION,
90  OOMPH_CURRENT_FUNCTION);
91  }
92 
93  if(result < 0)
94  {
95  std::string err = "Something crazy went wrong here.";
96  throw OomphLibError(err, OOMPH_EXCEPTION_LOCATION,
97  OOMPH_CURRENT_FUNCTION);
98  }
99 #endif
100 
101  return unsigned(result);
102  }
103 
104  /// \short Given a main matrix row/col number get the equivalent row/col
105  /// in the added matrix. Return -1 if not found.
106  int unsafe_main_to_added(const int& main) const
107  {
108  // Find the entry
109  std::map<unsigned, unsigned>::const_iterator
110  it = Main_to_added_mapping.find(unsigned(main));
111 
112  // Check the entry existed, it not then return -1.
113  if(it == main_to_added_mapping_pt()->end())
114  {
115  return -1;
116  }
117  else
118  {
119  return it->second;
120  }
121  }
122 
123  /// Given a row/col number in the added matrix return the equivalent
124  /// row/col number in the main matrix.
125  unsigned added_to_main(const unsigned& added) const
126  {return Added_to_main_mapping[added];}
127 
128  /// Construct the lookup schemes given a mesh and the degree of freedom
129  /// to lookup main equation numbers for.
130  void build(const Mesh* mesh_pt, const unsigned& dof_index)
131  {
132  construct_added_to_main_mapping(mesh_pt, dof_index);
133  construct_reverse_mapping();
134  }
135 
136  /// Construct lookup schemes from int array (HLib's format for this
137  /// data).
138  void build(const int* lookup_array, const unsigned& length)
139  {
140 #ifdef PARANOID
141  // Check for negative entries just in case (since it's an integer
142  // array).
143  for(unsigned j=0; j<length; j++)
144  {
145  if(lookup_array[j] < 0)
146  {
147  std::string err = "negative entry in lookup array!";
148  throw OomphLibError(err, OOMPH_EXCEPTION_LOCATION,
149  OOMPH_CURRENT_FUNCTION);
150  }
151  }
152 #endif
153 
154  // Copy array into mapping and generate the inverse lookup
155  Added_to_main_mapping.assign(lookup_array, lookup_array+length);
156  construct_reverse_mapping();
157  }
158 
159  /// Construct lookup using node vector
160  void build(const Vector<const Node*>& bem_lookup,
161  const unsigned& dof_index)
162  {
163  const unsigned ni = bem_lookup.size();
164  Added_to_main_mapping.assign(ni, -1);
165 
166  for(unsigned i=0; i<ni; i++)
167  {
168  Added_to_main_mapping[i] = bem_lookup[i]->eqn_number(dof_index);
169  }
170 
171  construct_reverse_mapping();
172  }
173 
174  /// Construct an identity map (mostly for testing).
175  void build_identity_map(const unsigned& n)
176  {
177  Added_to_main_mapping.assign(n, 0);
178  for(unsigned j=0; j<n; j++)
179  {
180  Added_to_main_mapping[j] = j;
181  }
182  construct_reverse_mapping();
183  }
184 
185 
186  // Access functions
187  // ============================================================
188 
189  /// \short Const access function for mapping.
191  {return &Added_to_main_mapping;}
192 
193  /// \short Const access function for mapping.
194  const std::map<unsigned, unsigned>* main_to_added_mapping_pt() const
195  {return &Main_to_added_mapping;}
196 
197  private:
198 
199  /// Set up the lookup from added matrix row/col to main matrix.
201  const unsigned& dof_index)
202  {
203  // Basically just copy from the node data.
204  Added_to_main_mapping.resize(mesh_pt->nnode());
205  for(unsigned nd=0, nnode=mesh_pt->nnode(); nd<nnode; nd++)
206  {
207  Added_to_main_mapping[nd] = mesh_pt->node_pt(nd)->eqn_number(dof_index);
208  }
209  }
210 
211  /// Set up the main to added mapping using the added to main mapping.
213  {
214 #ifdef PARANOID
215  if(Added_to_main_mapping.size() == 0)
216  {
217  std::ostringstream error_msg;
218  error_msg << "Must set up Added_to_main_mapping first.";
219  throw OomphLibError(error_msg.str(),
220  OOMPH_CURRENT_FUNCTION,
221  OOMPH_EXCEPTION_LOCATION);
222  }
223 #endif
224 
225  // Clear old data
226  Main_to_added_mapping.clear();
227 
228  // Copy from Added_to_main_mapping with order reversed.
229  for(unsigned j=0; j<Added_to_main_mapping.size(); j++)
230  {
231  Main_to_added_mapping.insert(std::make_pair(Added_to_main_mapping[j],
232  j));
233  }
234  }
235 
236  /// Mapping from added matrix row/col numbers to main matrix row/col numbers.
238 
239  /// Mapping from main matrix row/col numbers to added matrix row/col
240  /// numbers. Note that we cannot use a vector here because the main
241  /// matrix rows/cols mapped onto are probably not contiguous. Access
242  /// times are O(log N) so if you need to iterate over all elements then
243  /// use the pointer access functions and use stl iterators properly.
244  std::map<unsigned, unsigned> Main_to_added_mapping;
245 
246  /// Inaccessible copy constructor
248  {BrokenCopy::broken_copy("AddedMainNumberingLookup");}
249 
250  /// Inaccessible assignment operator
252  {BrokenCopy::broken_assign("AddedMainNumberingLookup");}
253 
254  };
255 
256 
257 //======================================================================
258 /// Class for a matrix of the form M = S + G + H + ... where S is the main
259 /// matrix and G,H etc. are matrices of size S or smaller. This may be useful
260 /// if, for example, G,H etc. are subblocks of M that must be stored in a
261 /// different format to S.
262 
263 /// Maps mut be provided which gives a map from the rows/cols of the main
264 /// matrix to the rows/cols of each of the added matrices.
265 //======================================================================
267  public Matrix<double,SumOfMatrices>
268  {
269 
270  private:
271 
272  /// Pointer to the matrix which we are adding the others to
274 
275  /// List of pointers to the matrices that are added to the main matrix
277 
278  /// \short List of maps between row numbers of the main matrix and the
279  /// added matrices.
281 
282  /// \short List of maps between col numbers of the main matrix and the
283  /// added matrices.
285 
286  /// Should we delete the sub matrices when destructor is called?
288 
289  /// \short Should we delete the main matrix when destructor is called?
290  /// Default is no.
292 
293  public:
294 
295  /// Default constructor
297  : Main_matrix_pt(0), Added_matrix_pt(0),
298  Row_map_pt(0), Col_map_pt(0),
299  Should_delete_added_matrix(0), Should_delete_main_matrix(0) {}
300 
301  /// Constructor taking a pointer to the main matrix as input.
303  : Main_matrix_pt(main_matrix_pt), Added_matrix_pt(0),
304  Row_map_pt(0), Col_map_pt(0),
305  Should_delete_added_matrix(0), Should_delete_main_matrix(0) {}
306 
307  /// Broken copy constructor
309  {BrokenCopy::broken_copy("SumOfMatrices");}
310 
311  /// Broken assignment operator
313  {BrokenCopy::broken_assign("SumOfMatrices");}
314 
315  /// Destructor: delete matrices as instructed by
316  /// Should_delete_added_matrix vector and Should_delete_main_matrix.
318  {
319  for(unsigned i_matrix=0; i_matrix<Added_matrix_pt.size(); i_matrix++)
320  {
321  if(Should_delete_added_matrix[i_matrix] == 1)
322  {
323  delete Added_matrix_pt[i_matrix];
324  }
325  }
326 
327  if(Should_delete_main_matrix) {delete Main_matrix_pt;}
328  }
329 
330  /// Access to the main matrix
331  const DoubleMatrixBase* main_matrix_pt() const {return Main_matrix_pt;}
332  DoubleMatrixBase*& main_matrix_pt() {return Main_matrix_pt;}
333 
334  /// \short Set the main matrix to be deleted by the destructor of the
335  /// SumOfMatrices (default is to not delete it).
337  {Should_delete_main_matrix = true;}
338 
339 
340  /// \short Output the "bottom right" entry regardless of it being
341  /// zero or not (this allows automatic detection of matrix size in
342  /// e.g. matlab, python).
343  void output_bottom_right_zero_helper(std::ostream &outfile) const
344  {
345  int last_row = this->nrow()-1;
346  int last_col = this->ncol()-1;
347 
348  double last_value = operator()(last_row, last_col);
349 
350  if(last_value == 0.0)
351  {
352  outfile << last_row << " " << last_col << " " << 0.0
353  << std::endl;
354  }
355  }
356 
357 
358  /// \short Output the matrix in sparse format. Note that this is going to be
359  /// slow because we have to check every entry of every matrix for non-zeros.
360  void sparse_indexed_output_helper(std::ostream &outfile) const
361  {
362  for (unsigned long i=0; i<nrow(); i++)
363  {
364  for (unsigned long j=0; j<ncol(); j++)
365  {
366  double entry = operator()(i,j);
367  // Output if non-zero entry
368  if(entry != 0.0)
369  {
370  outfile << i << " " << j << " " << entry
371  << std::endl;
372  }
373  }
374  }
375  }
376 
377 
378  /// \short Get a list of row/col indices and total entry for non-zeros in the
379  /// matrix. e.g. for use as input to other matrix classes. Warning this is
380  /// SLOW! for sparse matrices.
382  Vector<double>& values)
383  {
384  row.clear(); col.clear(); values.clear();
385 
386  for (int i=0; i<int(nrow()); i++)
387  {
388  for (int j=0; j<int(ncol()); j++)
389  {
390  double entry = operator()(i,j);
391  // Output if non-zero entry
392  if(entry != 0.0)
393  {
394  row.push_back(i);
395  col.push_back(j);
396  values.push_back(entry);
397  }
398  }
399  }
400  }
401 
402  /// \short Add a new matrix to the sum by giving a matrix pointer and a
403  /// mapping from the main matrix numbering to the added matrix's numbering.
404  void add_matrix(DoubleMatrixBase* added_matrix_pt_in,
405  const AddedMainNumberingLookup* main_to_added_rows_pt,
406  const AddedMainNumberingLookup* main_to_added_cols_pt,
407  bool should_delete_matrix=false)
408  {
409 #ifdef PARANOID
410  // Check that row mapping has correct size
411  if (main_to_added_rows_pt->main_to_added_mapping_pt()->size()
412  > added_matrix_pt_in->nrow())
413  {
414  throw OomphLibError("Row mapping size should be less than or equal to nrow (less than if it is a sparse matrix and there are some empty rows).",
415  OOMPH_CURRENT_FUNCTION,
416  OOMPH_EXCEPTION_LOCATION);
417  }
418 
419  // Check that col mapping has correct size
420  if (main_to_added_cols_pt->main_to_added_mapping_pt()->size()
421  > added_matrix_pt_in->ncol())
422  {
423  throw OomphLibError("Col mapping size should be less than or equal to ncol (less than if it is a sparse matrix and there are some empty cols).",
424  OOMPH_CURRENT_FUNCTION,
425  OOMPH_EXCEPTION_LOCATION);
426  }
427 #endif
428 #ifdef RANGE_CHECKING
429  // Check that all entries in the row mapping are "in range" for the
430  // main matrix.
431  const Vector<unsigned>* rowmap_pt = main_to_added_rows_pt->added_to_main_mapping_pt();
432  unsigned max_row = *std::max_element(rowmap_pt->begin(), rowmap_pt->end());
433  if(max_row > main_matrix_pt()->nrow())
434  {
435  std::string err = "Trying to add a matrix with a mapping which specifices";
436  err += " a max row of "+to_string(max_row)+" but the main matrix ";
437  err += "only has "+to_string(main_matrix_pt()->nrow()) +" rows!";
438  throw OomphLibError(err, OOMPH_EXCEPTION_LOCATION,
439  OOMPH_CURRENT_FUNCTION);
440  }
441 
442  // Check that all entries in the row mapping are "in range" for the
443  // main matrix.
444  const Vector<unsigned>* colmap_pt = main_to_added_cols_pt->added_to_main_mapping_pt();
445  unsigned max_col = *std::max_element(colmap_pt->begin(), colmap_pt->end());
446  if(max_col > main_matrix_pt()->ncol())
447  {
448  std::string err = "Trying to add a matrix with a mapping which specifices";
449  err += " a max col of "+to_string(max_col)+" but the main matrix ";
450  err += "only has "+to_string(main_matrix_pt()->ncol()) +" cols!";
451  throw OomphLibError(err, OOMPH_EXCEPTION_LOCATION,
452  OOMPH_CURRENT_FUNCTION);
453  }
454 #endif
455 
456  Added_matrix_pt.push_back(added_matrix_pt_in);
457  Row_map_pt.push_back(main_to_added_rows_pt);
458  Col_map_pt.push_back(main_to_added_cols_pt);
459  Should_delete_added_matrix.push_back(unsigned(should_delete_matrix));
460  }
461 
462  /// Access function for ith added matrix (main matrix not included in
463  /// numbering).
464  inline DoubleMatrixBase* added_matrix_pt(const unsigned& i) const
465  {return Added_matrix_pt[i];}
466 
467  /// Access to the maps
468  const AddedMainNumberingLookup* row_map_pt(const unsigned& i) const
469  {return Row_map_pt[i];}
470  const AddedMainNumberingLookup* col_map_pt(const unsigned& i) const
471  {return Col_map_pt[i];}
472 
473  /// Return the number of rows of the main matrix.
474  inline unsigned long nrow() const
475  {
476 #ifdef PARANOID
477  if(Main_matrix_pt==0)
478  {
479  throw OomphLibError("Main_matrix_pt not set",
480  OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
481  }
482 #endif
483  return Main_matrix_pt->nrow();
484  }
485 
486  /// \short Return the number of columns of the main matrix.
487  inline unsigned long ncol() const
488  {
489 #ifdef PARANOID
490  if(Main_matrix_pt==0)
491  {
492  throw OomphLibError("Main_matrix_pt not set",
493  OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
494  }
495 #endif
496  return Main_matrix_pt->ncol();
497  }
498 
499  /// Return the number of added matrices in the sum
500  inline unsigned n_added_matrix() const {return Added_matrix_pt.size();}
501 
502  /// \short Multiply: just call multiply on each of the matrices and add up the
503  /// results (with appropriate bookeeping of the relative positions).
504  void multiply(const DoubleVector &x, DoubleVector &soln) const;
505 
506  /// \short Broken operator() because it does not make sense to return
507  /// anything by reference.
508  double& entry(const unsigned long& i, const unsigned long& j) const
509  {
510  throw OomphLibError("Broken write to entry: it does not make sense to write to a sum, you must write to one of the component matrices.",
511  OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
512  }
513 
514  /// Access function to get the total value of entries in position
515  /// (i,j). Warning: this way of getting entries is far too slow to use
516  /// inside of loops.
517  double operator()(const unsigned long &i,
518  const unsigned long &j) const
519  {
520  // Get contributions from all matrices
521  double sum = main_matrix_pt()->operator()(i,j);
522  for(unsigned i_matrix=0; i_matrix<n_added_matrix(); i_matrix++)
523  {
524  int li = Row_map_pt[i_matrix]->unsafe_main_to_added(i);
525  int lj = Col_map_pt[i_matrix]->unsafe_main_to_added(j);
526 
527  // If the added matrix contributes to this entry then add it
528  if(( li != -1) && (lj != -1))
529  {
530  sum += added_matrix_pt(i_matrix)->operator()(li,lj);
531  }
532  }
533 
534  return sum;
535  }
536 
537  /// \short Dummy overload of a pure virtual function. I'm not sure how best to
538  /// implement this and I don't think I need it.
539  virtual void multiply_transpose(const DoubleVector &x,
540  DoubleVector &soln)const
541  {
542  std::ostringstream error_msg;
543  error_msg << "Function not yet implemented.";
544  throw OomphLibError(error_msg.str(),
545  OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
546 
547  // Possible implementations (not really thought through):
548  // - just call multiply transpose on submatrices?
549  // - do something funny with switching row and column maps?
550  }
551 
552  };
553 
554 
555 }
556 #endif
void add_matrix(DoubleMatrixBase *added_matrix_pt_in, const AddedMainNumberingLookup *main_to_added_rows_pt, const AddedMainNumberingLookup *main_to_added_cols_pt, bool should_delete_matrix=false)
Add a new matrix to the sum by giving a matrix pointer and a mapping from the main matrix numbering t...
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
AddedMainNumberingLookup()
Default constructor.
unsigned main_to_added(const int &main) const
Given a main matrix row/col number get the equivalent row/col in the added matrix. Throw an error if not found.
unsigned n_added_matrix() const
Return the number of added matrices in the sum.
void get_as_indices(Vector< int > &row, Vector< int > &col, Vector< double > &values)
Get a list of row/col indices and total entry for non-zeros in the matrix. e.g. for use as input to o...
SumOfMatrices(DoubleMatrixBase *main_matrix_pt)
Constructor taking a pointer to the main matrix as input.
SumOfMatrices(const SumOfMatrices &matrix)
Broken copy constructor.
SumOfMatrices()
Default constructor.
void operator=(const AddedMainNumberingLookup &dummy)
Inaccessible assignment operator.
Vector< DoubleMatrixBase * > Added_matrix_pt
List of pointers to the matrices that are added to the main matrix.
cstr elem_len * i
Definition: cfortran.h:607
Vector< unsigned > Should_delete_added_matrix
Should we delete the sub matrices when destructor is called?
const AddedMainNumberingLookup * col_map_pt(const unsigned &i) const
void multiply(const CRDoubleMatrix *matrix, const DoubleVector &x, DoubleVector &soln)
Function to perform a matrix-vector multiplication on a oomph-lib matrix and vector using Trilinos fu...
Vector< unsigned > Added_to_main_mapping
Mapping from added matrix row/col numbers to main matrix row/col numbers.
long & eqn_number(const unsigned &i)
Return the equation number of the i-th stored variable.
Definition: nodes.h:365
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...
std::map< unsigned, unsigned > Main_to_added_mapping
void set_delete_main_matrix()
Set the main matrix to be deleted by the destructor of the SumOfMatrices (default is to not delete it...
void construct_reverse_mapping()
Set up the main to added mapping using the added to main mapping.
unsigned long nrow() const
Return the number of rows of the main matrix.
AddedMainNumberingLookup(const Mesh *mesh_pt, const unsigned &dof_index)
double & entry(const unsigned long &i, const unsigned long &j) const
Broken operator() because it does not make sense to return anything by reference. ...
void build(const int *lookup_array, const unsigned &length)
void build(const Vector< const Node *> &bem_lookup, const unsigned &dof_index)
Construct lookup using node vector.
const DoubleMatrixBase * main_matrix_pt() const
Access to the main matrix.
const Vector< unsigned > * added_to_main_mapping_pt() const
Const access function for mapping.
void operator=(const SumOfMatrices &)
Broken assignment operator.
const std::map< unsigned, unsigned > * main_to_added_mapping_pt() const
Const access function for mapping.
DoubleMatrixBase * added_matrix_pt(const unsigned &i) const
const AddedMainNumberingLookup * row_map_pt(const unsigned &i) const
Access to the maps.
void build_identity_map(const unsigned &n)
Construct an identity map (mostly for testing).
DoubleMatrixBase *& main_matrix_pt()
Vector< const AddedMainNumberingLookup *> Row_map_pt
List of maps between row numbers of the main matrix and the added matrices.
virtual void multiply_transpose(const DoubleVector &x, DoubleVector &soln) const
Dummy overload of a pure virtual function. I&#39;m not sure how best to implement this and I don&#39;t think ...
AddedMainNumberingLookup(const AddedMainNumberingLookup &dummy)
Inaccessible copy constructor.
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
Definition: mesh.h:456
unsigned long nnode() const
Return number of nodes in the mesh.
Definition: mesh.h:590
bool Should_delete_main_matrix
Should we delete the main matrix when destructor is called? Default is no.
double operator()(const unsigned long &i, const unsigned long &j) const
DoubleMatrixBase * Main_matrix_pt
Pointer to the matrix which we are adding the others to.
Vector< const AddedMainNumberingLookup *> Col_map_pt
List of maps between col numbers of the main matrix and the added matrices.
void broken_assign(const std::string &class_name)
Issue error message and terminate execution.
Abstract base class for matrices, templated by the type of object that is stored in them and the type...
Definition: matrices.h:78
virtual unsigned long nrow() const =0
Return the number of rows of the matrix.
AddedMainNumberingLookup(const int *lookup_array, const unsigned &length)
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn&#39;t been defined.
A vector in the mathematical sense, initially developed for linear algebra type applications. If MPI then this vector can be distributed - its distribution is described by the LinearAlgebraDistribution object at Distribution_pt. Data is stored in a C-style pointer vector (double*)
Definition: double_vector.h:61
void sparse_indexed_output_helper(std::ostream &outfile) const
Output the matrix in sparse format. Note that this is going to be slow because we have to check every...
unsigned long ncol() const
Return the number of columns of the main matrix.
Abstract base class for matrices of doubles – adds abstract interfaces for solving, LU decomposition and multiplication by vectors.
Definition: matrices.h:275
virtual unsigned long ncol() const =0
Return the number of columns of the matrix.
void build(const Mesh *mesh_pt, const unsigned &dof_index)
A general mesh class.
Definition: mesh.h:74
int unsafe_main_to_added(const int &main) const
Given a main matrix row/col number get the equivalent row/col in the added matrix. Return -1 if not found.
unsigned added_to_main(const unsigned &added) const
std::string to_string(T object, unsigned float_precision=8)
Conversion function that should work for anything with operator<< defined (at least all basic types)...
void construct_added_to_main_mapping(const Mesh *mesh_pt, const unsigned &dof_index)
Set up the lookup from added matrix row/col to main matrix.