map_matrix.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_MAP_MATRIX_HEADER
31 #define OOMPH_MAP_MATRIX_HEADER
32 
33 
34 // Config header generated by autoconfig
35 #ifdef HAVE_CONFIG_H
36  #include <oomph-lib-config.h>
37 #endif
38 
39 
40 #ifdef OOMPH_HAS_MPI
41 #include "mpi.h"
42 #endif
43 
44 #include<map>
45 
46 //oomph-lib headers
47 #include "Vector.h"
48 #include "oomph_utilities.h"
49 
50 namespace oomph
51 {
52 
53 
54 //================================================================
55 /// MapMatrixMixed is a generalised, STL-map-based, sparse(ish) matrix
56 /// class with mixed indices
57 ///
58 /// The matrix is indexed by indices of type KEY_TYPE_ROW and KEY_TYPE_COL
59 /// and has entries of type VALUE_TYPE.
60 ///
61 /// Careful: If a zero entry is referenced then it is created in
62 /// memory. Therefore this isn't really a practical sparse matrix scheme.
63 /// Do not loop over `all' possible indices as even looking
64 /// at them will inflate the matrix until it occupies as much
65 /// space as a full one -- use (modification of) output routine
66 /// to retrieve all nonzero entries.
67 ///
68 /// However, this is not a serious restriction, as the main purpose
69 /// of this class is to allow non-integer indices.
70 ///
71 /// Example of usage:
72 /// \code
73 ///
74 ///
75 /// // Assume we have a Vector of pointers to objects:
76 /// Vector<Rubbish*> object_pt;
77 ///
78 /// [...]
79 ///
80 /// // Number of objects
81 /// int nentry=object_pt.size();
82 ///
83 /// // Use the pointers to the objects and associated integers as indices
84 /// // in a MapMatrixMixed whose entries are of type int
85 /// MapMatrixMixed<Rubbish*,int,int> like_a_matrix;
86 ///
87 /// for (int i=1;i<nentry;i++)
88 /// {
89 /// for (int j=1;j<nentry;j++)
90 /// {
91 /// int number=100*i+j;
92 /// like_a_matrix(object_pt[i],j)=number;
93 /// }
94 /// }
95 ///
96 /// oomph_info << "Matrix has nnz() " << like_a_matrix.nnz() <<
97 /// " and size() " << like_a_matrix.size() << std::endl;
98 ///
99 /// oomph_info << "\n\n\n Here are the nonzero entries: i, j, a(i,j)\n";
100 ///
101 /// like_a_matrix.output(oomph_info);
102 ///
103 /// // Can be used like a normal matrix:
104 /// like_a_matrix(object_pt[1],20)+=13;
105 /// like_a_matrix(object_pt[1],1)+=13;
106 ///
107 /// oomph_info << "\n\n\n Here are the nonzero entries: i, j, a(i,j)\n";
108 /// like_a_matrix.output(oomph_info);
109 ///
110 /// \endcode
111 ///
112 //================================================================
113 template<class KEY_TYPE_ROW, class KEY_TYPE_COL, class VALUE_TYPE>
115 {
116 
117 public:
118 
119  /// Default (empty) constructor
121 
122  /// Broken assignment operator
123  void operator=(const MapMatrixMixed&)
124  {
125  BrokenCopy::broken_assign("MapMatrixMixed");
126  }
127 
128  /// Typedef to keep the code more readable
129  typedef std::map<KEY_TYPE_COL,VALUE_TYPE> InnerMapMixed;
130 
131  /// Typedef to keep the code more readable
132  typedef typename InnerMapMixed::iterator InnerMixedIt;
133 
134  /// Typedef to keep the code more readable const version
135  typedef typename InnerMapMixed::const_iterator ConstInnerMixedIt;
136 
137  /// Typedef to keep the code more readable
138  typedef std::map<KEY_TYPE_ROW,std::map<KEY_TYPE_COL,VALUE_TYPE>*>
140 
141  /// Typedef to keep the code more readable
142  typedef typename OuterMapMixed::iterator OuterMixedIt;
143 
144  /// Typedef to keep the code more readable const version
145  typedef typename OuterMapMixed::const_iterator ConstOuterMixedIt;
146 
147 
148  /// Copy constructor
149  MapMatrixMixed(const MapMatrixMixed<KEY_TYPE_ROW,
150  KEY_TYPE_COL,VALUE_TYPE>& map_mat)
151  {
152  // Step through the row pointers
153  for (ConstOuterMixedIt it=map_mat.Row_pt.begin(); it!=map_mat.Row_pt.end();
154  it++)
155  {
156  // Is the row pointer nonzero, i.e. are there any entries in this row?
157  if (it->second!=0)
158  {
159 
160  // Identify the map that holds the entries in this row:
161  InnerMapMixed inner_map=*(it->second);
162 
163  // Loop over entries in the row
164  for (ConstInnerMixedIt it2=inner_map.begin(); it2!=inner_map.end();
165  it2++)
166  {
167 
168  // If the entry is nonzero: Copy
169  if (it2->second!=0)
170  {
171  // key1, key2, value
172  (*this)(it->first,it2->first)=it2->second;
173  }
174  }
175  }
176  }
177 
178  }
179 
180 
181  /// Copy a single column into its own map
182  void copy_column(const KEY_TYPE_COL& j,
183  std::map<KEY_TYPE_ROW,VALUE_TYPE> &copied_map)
184  {
185  // Step through the row pointers
186  for(OuterMixedIt it=Row_pt.begin(); it!=Row_pt.end(); it++)
187  {
188  // Is the row pointer nonzero, i.e. are there any entries in this row?
189  if (it->second!=0)
190  {
191  // Identify the map that holds the entries in this row:
192  InnerMapMixed inner_map=*(it->second);
193  // If the desired column of the inner map is non-zero
194  if(inner_map[j] != 0)
195  {
196  //Set the value of the copied map to be the desired column of the
197  //inner map
198  copied_map[it->first] = inner_map[j];
199  }
200  }
201  }
202  }
203 
204 
205  /// Destructor
206  virtual ~MapMatrixMixed()
207  {
208  // Step through the pointers to row maps
209  for (OuterMixedIt it=Row_pt.begin(); it!=Row_pt.end(); it++)
210  {
211  // Is the row pointer nonzero, i.e. are there any entries in this row?
212  if (it->second!=0)
213  {
214  // it->second is the stored object
215  delete it->second;
216  }
217  }
218  }
219 
220  /// Wipe all entries
221  void clear()
222  {
223  // Step through the pointers to row maps
224  for (OuterMixedIt it=Row_pt.begin(); it!=Row_pt.end(); it++)
225  {
226  // Is the row pointer nonzero, i.e. are there any entries in this row?
227  if (it->second!=0)
228  {
229  // it->second is the stored object: a map which can be cleared!
230  it->second->clear();
231  }
232  }
233  }
234 
235 
236  /// \short Return (reference to) entry.
237  /// Careful: If the entry does not exist then it is created and
238  /// set to zero
239  VALUE_TYPE& operator()(const KEY_TYPE_ROW& i, const KEY_TYPE_COL& j)
240  {
241  return *entry_pt(i,j);
242  }
243 
244  /// \short Get an element corresponding to the key (i,j)
245  /// Searches the container for an element with a key equivalent to
246  /// (i,j) and returns the element if found, otherwise the default 0 value for
247  /// the value type is returned. The container is not modified.
248  VALUE_TYPE get(const KEY_TYPE_ROW& i, const KEY_TYPE_COL& j) const
249  {
250  if(Row_pt.count(i) > 0)
251  {
252  // Get the pointer to the row and check the j key
253  InnerMapMixed* inner_map_mixed_pt = Row_pt.find(i)->second;
254  if(inner_map_mixed_pt->count(j) > 0)
255  {
256  return inner_map_mixed_pt->find(j)->second;
257  }
258  else
259  {
260  return VALUE_TYPE(0);
261  }
262  }
263  else
264  {
265  // The key does not exist, return VALUE_TYPE(0)
266  return VALUE_TYPE(0);
267  }
268  }
269 
270 
271  /// \short Dump all non-`zero' entries to file.
272  /// Output is in the format
273  /// `i', `j', `entry[i][j]'
274  void output(std::ostream &outfile)
275  {
276  // NOTE:
277  //------
278  // map.first = key
279  // map.second = value
280 
281  // Step through the row pointers
282  for (OuterMixedIt it=Row_pt.begin(); it!=Row_pt.end(); it++)
283  {
284  // Is the row pointer nonzero, i.e. are there any entries in this row?
285  if (it->second!=0)
286  {
287  // Identify the map that holds the entries in this row:
288  InnerMapMixed inner_map=*(it->second);
289 
290  // Loop over entries in the row
291  for (InnerMixedIt it2=inner_map.begin(); it2!=inner_map.end(); it2++)
292  {
293  // If the entry is nonzero: Doc
294  if (it2->second!=0)
295  {
296  // Output key1, key2, value
297  outfile << it->first << " " << it2->first << " "
298  << it2->second << std::endl;
299  }
300  }
301  }
302  }
303  }
304 
305  /// \short Work out number of non-`zero' entries
306  unsigned long nnz()
307  {
308  // Initialise counter for # of nonzero entries
309  unsigned long count=0;
310 
311  // Step through the row pointers
312  for (OuterMixedIt it=Row_pt.begin(); it!=Row_pt.end(); it++)
313  {
314  // Is the row pointer nonzero, i.e. are there any entries in this row?
315  if (it->second!=0)
316  {
317  // Identify the map that holds the entries in this row:
318  InnerMapMixed inner_map=*(it->second);
319 
320  // Loop over entries in the row
321  for (InnerMixedIt it2=inner_map.begin(); it2!=inner_map.end(); it2++)
322  {
323  // If the entry is nonzero: Increment counter
324  if (it2->second!=0)
325  {
326  count++;
327  }
328  }
329  }
330  }
331  return count;
332  }
333 
334  /// \short Work out number of non-`zero' entries, const version
335  unsigned long nnz() const
336  {
337  // Initialise counter for # of nonzero entries
338  unsigned long count=0;
339 
340  // Step through the row pointers
341  for (ConstOuterMixedIt it=Row_pt.begin(); it!=Row_pt.end(); it++)
342  {
343  // Is the row pointer nonzero, i.e. are there any entries in this row?
344  if (it->second!=0)
345  {
346  // Identify the map that holds the entries in this row:
347  InnerMapMixed inner_map=*(it->second);
348 
349  // Loop over entries in the row
350  for (ConstInnerMixedIt it2=inner_map.begin(); it2!=inner_map.end(); it2++)
351  {
352  // If the entry is nonzero: Increment counter
353  if (it2->second!=0)
354  {
355  count++;
356  }
357  }
358  }
359  }
360  return count;
361  }
362 
363 
364 
365 
366  /// \short Work out total number of entries
367  unsigned long size()
368  {
369  // Initialise counter for # of nonzero entries
370  unsigned long count=0;
371 
372  // Step through the row pointers
373  for (OuterMixedIt it=Row_pt.begin(); it!=Row_pt.end(); it++)
374  {
375  // Is the row pointer nonzero, i.e. are there any entries in this row?
376  if (it->second!=0)
377  {
378  // Identify the map that holds the entries in this row:
379  InnerMapMixed inner_map=*(it->second);
380 
381  // Loop over all (!) entries in the row (incl. zero ones!)
382  for (InnerMixedIt it2=inner_map.begin(); it2!=inner_map.end(); it2++)
383  {
384  count++;
385  }
386  }
387  }
388  return count;
389  }
390 
391  /// \short Work out total number of entries const version
392  unsigned long size() const
393  {
394  // Initialise counter for # of nonzero entries
395  unsigned long count=0;
396 
397  // Step through the row pointers
398  for (ConstOuterMixedIt it=Row_pt.begin(); it!=Row_pt.end(); it++)
399  {
400  // Is the row pointer nonzero, i.e. are there any entries in this row?
401  if (it->second!=0)
402  {
403  // Identify the map that holds the entries in this row:
404  InnerMapMixed inner_map=*(it->second);
405 
406  // Loop over all (!) entries in the row (incl. zero ones!)
407  for (ConstInnerMixedIt it2=inner_map.begin(); it2!=inner_map.end(); it2++)
408  {
409  count++;
410  }
411  }
412  }
413  return count;
414  }
415 
416 
417 protected:
418 
419  /// \short Return pointer to entry
420  VALUE_TYPE* entry_pt(const KEY_TYPE_ROW& i, const KEY_TYPE_COL& j)
421  {
422  // There's not a single entry in this row: Entry must be zero.
423  if (Row_pt[i]==0)
424  {
425  // Create row and entry in row and set the value to zero
426  Row_pt[i]=new std::map<KEY_TYPE_COL, VALUE_TYPE>;
427  (*Row_pt[i])[j]=VALUE_TYPE(0);
428  return &(*Row_pt[i])[j];
429  }
430  // Simply return pointer to existing entry
431  else
432  {
433  return &(*Row_pt[i])[j];
434  }
435  }
436 
437 
438  /// Here's the generalised matrix structure: A map of pointers to
439  /// the maps that hold the entries in each row.
440  std::map<KEY_TYPE_ROW, std::map<KEY_TYPE_COL, VALUE_TYPE>* > Row_pt;
441 
442 
443 };
444 
445 
446 
447 ///////////////////////////////////////////////////////////////////////
448 ///////////////////////////////////////////////////////////////////////
449 ///////////////////////////////////////////////////////////////////////
450 
451 
452 
453 
454 //================================================================
455 /// MapMatrix is a generalised, STL-map-based, sparse(-ish) matrix
456 /// class.
457 ///
458 /// The matrix is indexed by indices of type KEY_TYPE
459 /// and has entries of type VALUE_TYPE. It is a specialisation of the
460 /// class MapMatrixMixed. Please implement future functions in that class.
461 ///
462 /// Careful: If a zero entry is referenced then it is created in
463 /// memory. Therefore this isn't really a practical sparse matrix scheme.
464 /// Do not loop over `all' possible indices as even looking
465 /// at them will inflate the matrix until it occupies as much
466 /// space as a full one -- use (modification of) output routine
467 /// to retrieve all nonzero entries.
468 ///
469 /// However, this is not a serious restriction, as the main purpose
470 /// of this class is to allow non-integer indices.
471 ///
472 /// Example of usage:
473 /// \code
474 ///
475 ///
476 /// // Assume we have a Vector of pointers to objects:
477 /// Vector<Rubbish*> object_pt;
478 ///
479 /// [...]
480 ///
481 /// // Number of objects
482 /// int nentry=object_pt.size();
483 ///
484 /// // Use the pointers to the objects as indices
485 /// // in a MapMatrix whose entries are of type int
486 /// MapMatrix<Rubbish*,int> like_a_matrix;
487 ///
488 /// for (int i=1;i<nentry;i++)
489 /// {
490 /// for (int j=1;j<nentry;j++)
491 /// {
492 /// int number=100*i+j;
493 /// like_a_matrix(object_pt[i],object_pt[j])=number;
494 /// }
495 /// }
496 ///
497 /// oomph_info << "Matrix has nnz() " << like_a_matrix.nnz() <<
498 /// " and size() " << like_a_matrix.size() << std::endl;
499 ///
500 /// oomph_info << "\n\n\n Here are the nonzero entries: i, j, a(i,j)\n";
501 ///
502 /// like_a_matrix.output(oomph_info);
503 ///
504 /// // Can be used like a normal matrix:
505 ///
506 /// //Add to existing entry
507 /// like_a_matrix(object_pt[1],object_pt[2])+=13;
508 ///
509 /// // Add to non-existing entry
510 /// Rubbish* temp_pt=new Rubbish(20);
511 /// like_a_matrix(object_pt[1],temp_pt)+=13;
512 ///
513 /// oomph_info << "\n\n\n Here are the nonzero entries: i, j, a(i,j)\n";
514 /// like_a_matrix.output(oomph_info);
515 ///
516 /// \endcode
517 ///
518 //================================================================
519 template<class KEY_TYPE, class VALUE_TYPE>
520 class MapMatrix : public MapMatrixMixed<KEY_TYPE,KEY_TYPE,VALUE_TYPE>
521 {
522 
523 public:
524 
525  /// Default (empty) constructor
527 
528  /// Typedef to keep the code more readable
529  typedef std::map<KEY_TYPE,VALUE_TYPE> InnerMap;
530 
531  /// Typedef to keep the code more readable
532  typedef typename InnerMap::iterator InnerIt;
533 
534  /// Typedef to keep the code more readable
535  typedef typename InnerMap::const_iterator ConstInnerIt;
536 
537  /// Typedef to keep the code more readable
538  typedef std::map<KEY_TYPE,std::map<KEY_TYPE,VALUE_TYPE>*> OuterMap;
539 
540  /// Typedef to keep the code more readable
541  typedef typename OuterMap::iterator OuterIt;
542 
543  /// Typedef to keep the code more readable
544  typedef typename OuterMap::const_iterator ConstOuterIt;
545 
546  /// Copy constructor
548  {
549  // Step through the row pointers
550  for (ConstOuterIt it=map_mat.Row_pt.begin(); it!=map_mat.Row_pt.end(); it++)
551  {
552  // Is the row pointer nonzero, i.e. are there any entries in this row?
553  if (it->second!=0)
554  {
555  // Identify the map that holds the entries in this row:
556  InnerMap inner_map=*(it->second);
557 
558  // Loop over entries in the row
559  for (ConstInnerIt it2=inner_map.begin(); it2!=inner_map.end(); it2++)
560  {
561  // If the entry is nonzero: Copy
562  if (it2->second!=0)
563  {
564  (*this)(it->first,it2->first)=it2->second;
565  }
566  }
567  }
568  }
569  }
570 
571  /// Broken assignment operator
572  void operator=(const MapMatrix&)
573  {
574  BrokenCopy::broken_assign("MapMatrix");
575  }
576 
577 
578 };
579 
580 }
581 
582 #endif
VALUE_TYPE & operator()(const KEY_TYPE_ROW &i, const KEY_TYPE_COL &j)
Return (reference to) entry. Careful: If the entry does not exist then it is created and set to zero...
Definition: map_matrix.h:239
virtual ~MapMatrixMixed()
Destructor.
Definition: map_matrix.h:206
InnerMap::const_iterator ConstInnerIt
Typedef to keep the code more readable.
Definition: map_matrix.h:535
unsigned long nnz()
Work out number of non-`zero&#39; entries.
Definition: map_matrix.h:306
InnerMapMixed::const_iterator ConstInnerMixedIt
Typedef to keep the code more readable const version.
Definition: map_matrix.h:135
OuterMap::iterator OuterIt
Typedef to keep the code more readable.
Definition: map_matrix.h:541
InnerMap::iterator InnerIt
Typedef to keep the code more readable.
Definition: map_matrix.h:532
void clear()
Wipe all entries.
Definition: map_matrix.h:221
void operator=(const MapMatrixMixed &)
Broken assignment operator.
Definition: map_matrix.h:123
void operator=(const MapMatrix &)
Broken assignment operator.
Definition: map_matrix.h:572
std::map< KEY_TYPE, std::map< KEY_TYPE, VALUE_TYPE > * > OuterMap
Typedef to keep the code more readable.
Definition: map_matrix.h:538
MapMatrix(const MapMatrix< KEY_TYPE, VALUE_TYPE > &map_mat)
Copy constructor.
Definition: map_matrix.h:547
cstr elem_len * i
Definition: cfortran.h:607
std::map< unsigned, oomph::CRDoubleMatrix * > InnerMap
Typedef to keep the code more readable.
Definition: map_matrix.h:526
OuterMapMixed::const_iterator ConstOuterMixedIt
Typedef to keep the code more readable const version.
Definition: map_matrix.h:145
OuterMap::const_iterator ConstOuterIt
Typedef to keep the code more readable.
Definition: map_matrix.h:544
InnerMapMixed::iterator InnerMixedIt
Typedef to keep the code more readable.
Definition: map_matrix.h:132
std::map< KEY_TYPE_ROW, std::map< KEY_TYPE_COL, VALUE_TYPE > *> Row_pt
Definition: map_matrix.h:440
MapMatrixMixed()
Default (empty) constructor.
Definition: map_matrix.h:120
void copy_column(const KEY_TYPE_COL &j, std::map< KEY_TYPE_ROW, VALUE_TYPE > &copied_map)
Copy a single column into its own map.
Definition: map_matrix.h:182
MapMatrix()
Default (empty) constructor.
Definition: map_matrix.h:526
VALUE_TYPE * entry_pt(const KEY_TYPE_ROW &i, const KEY_TYPE_COL &j)
Return pointer to entry.
Definition: map_matrix.h:420
unsigned long size() const
Work out total number of entries const version.
Definition: map_matrix.h:392
std::map< KEY_TYPE_COL, VALUE_TYPE > InnerMapMixed
Typedef to keep the code more readable.
Definition: map_matrix.h:129
unsigned long size()
Work out total number of entries.
Definition: map_matrix.h:367
std::map< KEY_TYPE_ROW, std::map< KEY_TYPE_COL, VALUE_TYPE > * > OuterMapMixed
Typedef to keep the code more readable.
Definition: map_matrix.h:139
void broken_assign(const std::string &class_name)
Issue error message and terminate execution.
unsigned long nnz() const
Work out number of non-`zero&#39; entries, const version.
Definition: map_matrix.h:335
OuterMapMixed::iterator OuterMixedIt
Typedef to keep the code more readable.
Definition: map_matrix.h:142
MapMatrixMixed(const MapMatrixMixed< KEY_TYPE_ROW, KEY_TYPE_COL, VALUE_TYPE > &map_mat)
Copy constructor.
Definition: map_matrix.h:149
void output(std::ostream &outfile)
Dump all non-`zero&#39; entries to file. Output is in the format `i&#39;, `j&#39;, `entry[i][j]&#39;.
Definition: map_matrix.h:274