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// Copyright (C) 2006-2022 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 #ifndef OOMPH_SUM_OF_MATRICES_H
27 #define OOMPH_SUM_OF_MATRICES_H
28 
29 
30 #include "mesh.h"
31 #include "matrices.h"
32 #include "Vector.h"
33 #include "oomph_utilities.h"
34 
35 #include <map>
36 
37 
38 namespace oomph
39 {
40  using namespace StringConversion;
41 
42  // =================================================================
45  // =================================================================
47  {
48  public:
51 
56  AddedMainNumberingLookup(const Mesh* mesh_pt, const unsigned& dof_index)
57  {
58  this->build(mesh_pt, dof_index);
59  }
60 
63  AddedMainNumberingLookup(const int* lookup_array, const unsigned& length)
64  {
65  this->build(lookup_array, length);
66  }
67 
70 
73  unsigned main_to_added(const int& main) const
74  {
75  int result = unsafe_main_to_added(main);
76 #ifdef PARANOID
77  // If it's -1 then we failed to find it:
78  if (result == -1)
79  {
80  std::string err = "Main matrix row/col number " + to_string(main) +
81  " not found in lookup.";
82  throw OomphLibError(
84  }
85 
86  if (result < 0)
87  {
88  std::string err = "Something crazy went wrong here.";
89  throw OomphLibError(
91  }
92 #endif
93 
94  return unsigned(result);
95  }
96 
99  int unsafe_main_to_added(const int& main) const
100  {
101  // Find the entry
102  std::map<unsigned, unsigned>::const_iterator it =
103  Main_to_added_mapping.find(unsigned(main));
104 
105  // Check the entry existed, it not then return -1.
106  if (it == main_to_added_mapping_pt()->end())
107  {
108  return -1;
109  }
110  else
111  {
112  return it->second;
113  }
114  }
115 
118  unsigned added_to_main(const unsigned& added) const
119  {
120  return Added_to_main_mapping[added];
121  }
122 
125  void build(const Mesh* mesh_pt, const unsigned& dof_index)
126  {
127  construct_added_to_main_mapping(mesh_pt, dof_index);
128  construct_reverse_mapping();
129  }
130 
133  void build(const int* lookup_array, const unsigned& length)
134  {
135 #ifdef PARANOID
136  // Check for negative entries just in case (since it's an integer
137  // array).
138  for (unsigned j = 0; j < length; j++)
139  {
140  if (lookup_array[j] < 0)
141  {
142  std::string err = "negative entry in lookup array!";
143  throw OomphLibError(
145  }
146  }
147 #endif
148 
149  // Copy array into mapping and generate the inverse lookup
150  Added_to_main_mapping.assign(lookup_array, lookup_array + length);
151  construct_reverse_mapping();
152  }
153 
155  void build(const Vector<const Node*>& bem_lookup, const unsigned& dof_index)
156  {
157  const unsigned ni = bem_lookup.size();
158  Added_to_main_mapping.assign(ni, -1);
159 
160  for (unsigned i = 0; i < ni; i++)
161  {
162  Added_to_main_mapping[i] = bem_lookup[i]->eqn_number(dof_index);
163  }
164 
165  construct_reverse_mapping();
166  }
167 
169  void build_identity_map(const unsigned& n)
170  {
171  Added_to_main_mapping.assign(n, 0);
172  for (unsigned j = 0; j < n; j++)
173  {
174  Added_to_main_mapping[j] = j;
175  }
176  construct_reverse_mapping();
177  }
178 
179 
180  // Access functions
181  // ============================================================
182 
185  {
186  return &Added_to_main_mapping;
187  }
188 
190  const std::map<unsigned, unsigned>* main_to_added_mapping_pt() const
191  {
192  return &Main_to_added_mapping;
193  }
194 
195  private:
198  const unsigned& dof_index)
199  {
200  // Basically just copy from the node data.
201  Added_to_main_mapping.resize(mesh_pt->nnode());
202  for (unsigned nd = 0, nnode = mesh_pt->nnode(); nd < nnode; nd++)
203  {
204  Added_to_main_mapping[nd] = mesh_pt->node_pt(nd)->eqn_number(dof_index);
205  }
206  }
207 
210  {
211 #ifdef PARANOID
212  if (Added_to_main_mapping.size() == 0)
213  {
214  std::ostringstream error_msg;
215  error_msg << "Must set up Added_to_main_mapping first.";
216  throw OomphLibError(
218  }
219 #endif
220 
221  // Clear old data
222  Main_to_added_mapping.clear();
223 
224  // Copy from Added_to_main_mapping with order reversed.
225  for (unsigned j = 0; j < Added_to_main_mapping.size(); j++)
226  {
227  Main_to_added_mapping.insert(
228  std::make_pair(Added_to_main_mapping[j], j));
229  }
230  }
231 
235 
241  std::map<unsigned, unsigned> Main_to_added_mapping;
242 
245 
247  void operator=(const AddedMainNumberingLookup& dummy) = delete;
248  };
249 
250 
251  //======================================================================
256 
259  //======================================================================
261  public Matrix<double, SumOfMatrices>
262  {
263  private:
266 
269 
273 
277 
280 
284 
285  public:
288  : Main_matrix_pt(0),
289  Added_matrix_pt(0),
290  Row_map_pt(0),
291  Col_map_pt(0),
292  Should_delete_added_matrix(0),
293  Should_delete_main_matrix(0)
294  {
295  }
296 
299  : Main_matrix_pt(main_matrix_pt),
300  Added_matrix_pt(0),
301  Row_map_pt(0),
302  Col_map_pt(0),
303  Should_delete_added_matrix(0),
304  Should_delete_main_matrix(0)
305  {
306  }
307 
310 
312  void operator=(const SumOfMatrices&) = delete;
313 
317  {
318  for (unsigned i_matrix = 0; i_matrix < Added_matrix_pt.size(); i_matrix++)
319  {
320  if (Should_delete_added_matrix[i_matrix] == 1)
321  {
322  delete Added_matrix_pt[i_matrix];
323  }
324  }
325 
326  if (Should_delete_main_matrix)
327  {
328  delete Main_matrix_pt;
329  }
330  }
331 
334  {
335  return Main_matrix_pt;
336  }
338  {
339  return Main_matrix_pt;
340  }
341 
345  {
346  Should_delete_main_matrix = true;
347  }
348 
349 
353  void output_bottom_right_zero_helper(std::ostream& outfile) const
354  {
355  int last_row = this->nrow() - 1;
356  int last_col = this->ncol() - 1;
357 
358  double last_value = operator()(last_row, last_col);
359 
360  if (last_value == 0.0)
361  {
362  outfile << last_row << " " << last_col << " " << 0.0 << std::endl;
363  }
364  }
365 
366 
369  void sparse_indexed_output_helper(std::ostream& outfile) const
370  {
371  for (unsigned long i = 0; i < nrow(); i++)
372  {
373  for (unsigned long j = 0; j < ncol(); j++)
374  {
375  double entry = operator()(i, j);
376  // Output if non-zero entry
377  if (entry != 0.0)
378  {
379  outfile << i << " " << j << " " << entry << std::endl;
380  }
381  }
382  }
383  }
384 
385 
390  Vector<int>& col,
391  Vector<double>& values)
392  {
393  row.clear();
394  col.clear();
395  values.clear();
396 
397  for (int i = 0; i < int(nrow()); i++)
398  {
399  for (int j = 0; j < int(ncol()); j++)
400  {
401  double entry = operator()(i, j);
402  // Output if non-zero entry
403  if (entry != 0.0)
404  {
405  row.push_back(i);
406  col.push_back(j);
407  values.push_back(entry);
408  }
409  }
410  }
411  }
412 
415  void add_matrix(DoubleMatrixBase* added_matrix_pt_in,
416  const AddedMainNumberingLookup* main_to_added_rows_pt,
417  const AddedMainNumberingLookup* main_to_added_cols_pt,
418  bool should_delete_matrix = false)
419  {
420 #ifdef PARANOID
421  // Check that row mapping has correct size
422  if (main_to_added_rows_pt->main_to_added_mapping_pt()->size() >
423  added_matrix_pt_in->nrow())
424  {
425  throw OomphLibError(
426  "Row mapping size should be less than or equal to nrow (less than if "
427  "it is a sparse matrix and there are some empty rows).",
430  }
431 
432  // Check that col mapping has correct size
433  if (main_to_added_cols_pt->main_to_added_mapping_pt()->size() >
434  added_matrix_pt_in->ncol())
435  {
436  throw OomphLibError(
437  "Col mapping size should be less than or equal to ncol (less than if "
438  "it is a sparse matrix and there are some empty cols).",
441  }
442 #endif
443 #ifdef RANGE_CHECKING
444  // Check that all entries in the row mapping are "in range" for the
445  // main matrix.
446  const Vector<unsigned>* rowmap_pt =
447  main_to_added_rows_pt->added_to_main_mapping_pt();
448  unsigned max_row =
449  *std::max_element(rowmap_pt->begin(), rowmap_pt->end());
450  if (max_row > main_matrix_pt()->nrow())
451  {
452  std::string err =
453  "Trying to add a matrix with a mapping which specifices";
454  err += " a max row of " + to_string(max_row) + " but the main matrix ";
455  err += "only has " + to_string(main_matrix_pt()->nrow()) + " rows!";
456  throw OomphLibError(
458  }
459 
460  // Check that all entries in the row mapping are "in range" for the
461  // main matrix.
462  const Vector<unsigned>* colmap_pt =
463  main_to_added_cols_pt->added_to_main_mapping_pt();
464  unsigned max_col =
465  *std::max_element(colmap_pt->begin(), colmap_pt->end());
466  if (max_col > main_matrix_pt()->ncol())
467  {
468  std::string err =
469  "Trying to add a matrix with a mapping which specifices";
470  err += " a max col of " + to_string(max_col) + " but the main matrix ";
471  err += "only has " + to_string(main_matrix_pt()->ncol()) + " cols!";
472  throw OomphLibError(
474  }
475 #endif
476 
477  Added_matrix_pt.push_back(added_matrix_pt_in);
478  Row_map_pt.push_back(main_to_added_rows_pt);
479  Col_map_pt.push_back(main_to_added_cols_pt);
480  Should_delete_added_matrix.push_back(unsigned(should_delete_matrix));
481  }
482 
485  inline DoubleMatrixBase* added_matrix_pt(const unsigned& i) const
486  {
487  return Added_matrix_pt[i];
488  }
489 
491  const AddedMainNumberingLookup* row_map_pt(const unsigned& i) const
492  {
493  return Row_map_pt[i];
494  }
495  const AddedMainNumberingLookup* col_map_pt(const unsigned& i) const
496  {
497  return Col_map_pt[i];
498  }
499 
501  inline unsigned long nrow() const
502  {
503 #ifdef PARANOID
504  if (Main_matrix_pt == 0)
505  {
506  throw OomphLibError("Main_matrix_pt not set",
509  }
510 #endif
511  return Main_matrix_pt->nrow();
512  }
513 
515  inline unsigned long ncol() const
516  {
517 #ifdef PARANOID
518  if (Main_matrix_pt == 0)
519  {
520  throw OomphLibError("Main_matrix_pt not set",
523  }
524 #endif
525  return Main_matrix_pt->ncol();
526  }
527 
529  inline unsigned n_added_matrix() const
530  {
531  return Added_matrix_pt.size();
532  }
533 
536  void multiply(const DoubleVector& x, DoubleVector& soln) const;
537 
540  double& entry(const unsigned long& i, const unsigned long& j) const
541  {
542  throw OomphLibError(
543  "Broken write to entry: it does not make sense to write to a sum, you "
544  "must write to one of the component matrices.",
547  }
548 
552  double operator()(const unsigned long& i, const unsigned long& j) const
553  {
554  // Get contributions from all matrices
555  double sum = main_matrix_pt()->operator()(i, j);
556  for (unsigned i_matrix = 0; i_matrix < n_added_matrix(); i_matrix++)
557  {
558  int li = Row_map_pt[i_matrix]->unsafe_main_to_added(i);
559  int lj = Col_map_pt[i_matrix]->unsafe_main_to_added(j);
560 
561  // If the added matrix contributes to this entry then add it
562  if ((li != -1) && (lj != -1))
563  {
564  sum += added_matrix_pt(i_matrix)->operator()(li, lj);
565  }
566  }
567 
568  return sum;
569  }
570 
573  virtual void multiply_transpose(const DoubleVector& x,
574  DoubleVector& soln) const
575  {
576  std::ostringstream error_msg;
577  error_msg << "Function not yet implemented.";
578  throw OomphLibError(
580 
581  // Possible implementations (not really thought through):
582  // - just call multiply transpose on submatrices?
583  // - do something funny with switching row and column maps?
584  }
585  };
586 
587 
588 } // namespace oomph
589 #endif
int i
Definition: BiCGSTAB_step_by_step.cpp:9
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
m col(1)
m row(1)
int main(int argc, char *argv[])
Definition: T_protectiveWall.cpp:194
Definition: sum_of_matrices.h:47
AddedMainNumberingLookup(const Mesh *mesh_pt, const unsigned &dof_index)
Definition: sum_of_matrices.h:56
const Vector< unsigned > * added_to_main_mapping_pt() const
Const access function for mapping.
Definition: sum_of_matrices.h:184
unsigned main_to_added(const int &main) const
Definition: sum_of_matrices.h:73
AddedMainNumberingLookup()
Default constructor.
Definition: sum_of_matrices.h:50
void construct_reverse_mapping()
Set up the main to added mapping using the added to main mapping.
Definition: sum_of_matrices.h:209
AddedMainNumberingLookup(const int *lookup_array, const unsigned &length)
Definition: sum_of_matrices.h:63
unsigned added_to_main(const unsigned &added) const
Definition: sum_of_matrices.h:118
Vector< unsigned > Added_to_main_mapping
Definition: sum_of_matrices.h:234
AddedMainNumberingLookup(const AddedMainNumberingLookup &dummy)=delete
Inaccessible copy constructor.
int unsafe_main_to_added(const int &main) const
Definition: sum_of_matrices.h:99
void build(const Mesh *mesh_pt, const unsigned &dof_index)
Definition: sum_of_matrices.h:125
void operator=(const AddedMainNumberingLookup &dummy)=delete
Inaccessible assignment operator.
void build_identity_map(const unsigned &n)
Construct an identity map (mostly for testing).
Definition: sum_of_matrices.h:169
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.
Definition: sum_of_matrices.h:197
const std::map< unsigned, unsigned > * main_to_added_mapping_pt() const
Const access function for mapping.
Definition: sum_of_matrices.h:190
void build(const Vector< const Node * > &bem_lookup, const unsigned &dof_index)
Construct lookup using node vector.
Definition: sum_of_matrices.h:155
std::map< unsigned, unsigned > Main_to_added_mapping
Definition: sum_of_matrices.h:241
~AddedMainNumberingLookup()
Destructor.
Definition: sum_of_matrices.h:69
void build(const int *lookup_array, const unsigned &length)
Definition: sum_of_matrices.h:133
long & eqn_number(const unsigned &i)
Return the equation number of the i-th stored variable.
Definition: nodes.h:367
Definition: matrices.h:261
virtual unsigned long ncol() const =0
Return the number of columns of the matrix.
virtual unsigned long nrow() const =0
Return the number of rows of the matrix.
Definition: double_vector.h:58
Definition: matrices.h:74
Definition: mesh.h:67
unsigned long nnode() const
Return number of nodes in the mesh.
Definition: mesh.h:596
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
Definition: mesh.h:436
Definition: oomph_definitions.h:222
Definition: sum_of_matrices.h:262
virtual void multiply_transpose(const DoubleVector &x, DoubleVector &soln) const
Definition: sum_of_matrices.h:573
SumOfMatrices(const SumOfMatrices &matrix)=delete
Broken copy constructor.
void output_bottom_right_zero_helper(std::ostream &outfile) const
Definition: sum_of_matrices.h:353
SumOfMatrices(DoubleMatrixBase *main_matrix_pt)
Constructor taking a pointer to the main matrix as input.
Definition: sum_of_matrices.h:298
unsigned n_added_matrix() const
Return the number of added matrices in the sum.
Definition: sum_of_matrices.h:529
DoubleMatrixBase * added_matrix_pt(const unsigned &i) const
Definition: sum_of_matrices.h:485
const AddedMainNumberingLookup * row_map_pt(const unsigned &i) const
Access to the maps.
Definition: sum_of_matrices.h:491
unsigned long nrow() const
Return the number of rows of the main matrix.
Definition: sum_of_matrices.h:501
SumOfMatrices()
Default constructor.
Definition: sum_of_matrices.h:287
Vector< DoubleMatrixBase * > Added_matrix_pt
List of pointers to the matrices that are added to the main matrix.
Definition: sum_of_matrices.h:268
Vector< const AddedMainNumberingLookup * > Col_map_pt
Definition: sum_of_matrices.h:276
double & entry(const unsigned long &i, const unsigned long &j) const
Definition: sum_of_matrices.h:540
void set_delete_main_matrix()
Definition: sum_of_matrices.h:344
const DoubleMatrixBase * main_matrix_pt() const
Access to the main matrix.
Definition: sum_of_matrices.h:333
double operator()(const unsigned long &i, const unsigned long &j) const
Definition: sum_of_matrices.h:552
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)
Definition: sum_of_matrices.h:415
void operator=(const SumOfMatrices &)=delete
Broken assignment operator.
Vector< const AddedMainNumberingLookup * > Row_map_pt
Definition: sum_of_matrices.h:272
Vector< unsigned > Should_delete_added_matrix
Should we delete the sub matrices when destructor is called?
Definition: sum_of_matrices.h:279
void get_as_indices(Vector< int > &row, Vector< int > &col, Vector< double > &values)
Definition: sum_of_matrices.h:389
const AddedMainNumberingLookup * col_map_pt(const unsigned &i) const
Definition: sum_of_matrices.h:495
unsigned long ncol() const
Return the number of columns of the main matrix.
Definition: sum_of_matrices.h:515
bool Should_delete_main_matrix
Definition: sum_of_matrices.h:283
~SumOfMatrices()
Definition: sum_of_matrices.h:316
void sparse_indexed_output_helper(std::ostream &outfile) const
Definition: sum_of_matrices.h:369
DoubleMatrixBase * Main_matrix_pt
Pointer to the matrix which we are adding the others to.
Definition: sum_of_matrices.h:265
DoubleMatrixBase *& main_matrix_pt()
Definition: sum_of_matrices.h:337
Definition: oomph-lib/src/generic/Vector.h:58
Eigen::Map< Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor >, 0, Eigen::OuterStride<> > matrix(T *data, int rows, int cols, int stride)
Definition: common.h:85
static constexpr lastp1_t end
Definition: IndexedViewHelper.h:79
return int(ret)+1
std::string string(const unsigned &i)
Definition: oomph_definitions.cc:286
std::string to_string(T object, unsigned float_precision=8)
Definition: oomph_utilities.h:189
void multiply(const CRDoubleMatrix *matrix, const DoubleVector &x, DoubleVector &soln)
Definition: trilinos_helpers.cc:657
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition: AnisotropicHookean.h:10
list x
Definition: plotDoE.py:28
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2