MFEM  v4.5.2
Finite element discretization library
table.hpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2023, Lawrence Livermore National Security, LLC. Produced
2 // at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3 // LICENSE and NOTICE for details. LLNL-CODE-806117.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability visit https://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the BSD-3 license. We welcome feedback and contributions, see file
10 // CONTRIBUTING.md for details.
11 
12 #ifndef MFEM_TABLE
13 #define MFEM_TABLE
14 
15 // Data types for Table.
16 
17 #include "mem_alloc.hpp"
18 #include "array.hpp"
19 #include "globals.hpp"
20 #include <ostream>
21 #include <istream>
22 
23 namespace mfem
24 {
25 
26 /// Helper struct for defining a connectivity table, see Table::MakeFromList.
27 struct Connection
28 {
29  int from, to;
30  Connection() = default;
31  Connection(int from, int to) : from(from), to(to) {}
32 
33  bool operator== (const Connection &rhs) const
34  { return (from == rhs.from) && (to == rhs.to); }
35  bool operator< (const Connection &rhs) const
36  { return (from == rhs.from) ? (to < rhs.to) : (from < rhs.from); }
37 };
38 
39 
40 /** Data type Table. Table stores the connectivity of elements of TYPE I
41  to elements of TYPE II, for example, it may be Element-To-Face
42  connectivity table, etc. */
43 class Table
44 {
45 protected:
46  /// size is the number of TYPE I elements.
47  int size;
48 
49  /** Arrays for the connectivity information in the CSR storage.
50  I is of size "size+1", J is of size the number of connections
51  between TYPE I to TYPE II elements (actually stored I[size]). */
53 
54 public:
55  /// Creates an empty table
56  Table() { size = -1; }
57 
58  /// Copy constructor
59  Table(const Table &);
60 
61  /// Assignment operator: deep copy
62  Table& operator=(const Table &rhs);
63 
64  /// Create a table with an upper limit for the number of connections.
65  explicit Table (int dim, int connections_per_row = 3);
66 
67  /** Create a table from a list of connections, see MakeFromList(). */
68  Table(int nrows, Array<Connection> &list) : size(-1)
69  { MakeFromList(nrows, list); }
70 
71  /** Create a table with one entry per row with column indices given
72  by 'partitioning'. */
73  Table (int nrows, int *partitioning);
74 
75  /// Next 7 methods are used together with the default constructor
76  void MakeI (int nrows);
77  void AddAColumnInRow (int r) { I[r]++; }
78  void AddColumnsInRow (int r, int ncol) { I[r] += ncol; }
79  void MakeJ();
80  void AddConnection (int r, int c) { J[I[r]++] = c; }
81  void AddConnections (int r, const int *c, int nc);
82  void ShiftUpI();
83 
84  /// Set the size and the number of connections for the table.
85  void SetSize(int dim, int connections_per_row);
86 
87  /** Set the rows and the number of all connections for the table.
88  Does NOT initialize the whole array I ! (I[0]=0 and I[rows]=nnz only) */
89  void SetDims(int rows, int nnz);
90 
91  /// Returns the number of TYPE I elements.
92  inline int Size() const { return size; }
93 
94  /** Returns the number of connections in the table. If Finalize() is
95  not called, it returns the number of possible connections established
96  by the used constructor. Otherwise, it is exactly the number of
97  established connections before calling Finalize(). */
98  inline int Size_of_connections() const { return I[size]; }
99 
100  /** Returns index of the connection between element i of TYPE I and
101  element j of TYPE II. If there is no connection between element i
102  and element j established in the table, then the return value is -1. */
103  int operator() (int i, int j) const;
104 
105  /// Return row i in array row (the Table must be finalized)
106  void GetRow(int i, Array<int> &row) const;
107 
108  int RowSize(int i) const { return I[i+1]-I[i]; }
109 
110  const int *GetRow(int i) const { return J+I[i]; }
111  int *GetRow(int i) { return J+I[i]; }
112 
113  int *GetI() { return I; }
114  int *GetJ() { return J; }
115  const int *GetI() const { return I; }
116  const int *GetJ() const { return J; }
117 
118  Memory<int> &GetIMemory() { return I; }
119  Memory<int> &GetJMemory() { return J; }
120  const Memory<int> &GetIMemory() const { return I; }
121  const Memory<int> &GetJMemory() const { return J; }
122 
123  const int *ReadI(bool on_dev = true) const
124  { return mfem::Read(I, I.Capacity(), on_dev); }
125  int *WriteI(bool on_dev = true)
126  { return mfem::Write(I, I.Capacity(), on_dev); }
127  int *ReadWriteI(bool on_dev = true)
128  { return mfem::ReadWrite(I, I.Capacity(), on_dev); }
129  const int *HostReadI() const
130  { return mfem::Read(I, I.Capacity(), false); }
131  int *HostWriteI()
132  { return mfem::Write(I, I.Capacity(), false); }
134  { return mfem::ReadWrite(I, I.Capacity(), false); }
135 
136  const int *ReadJ(bool on_dev = true) const
137  { return mfem::Read(J, J.Capacity(), on_dev); }
138  int *WriteJ(bool on_dev = true)
139  { return mfem::Write(J, J.Capacity(), on_dev); }
140  int *ReadWriteJ(bool on_dev = true)
141  { return mfem::ReadWrite(J, J.Capacity(), on_dev); }
142  const int *HostReadJ() const
143  { return mfem::Read(J, J.Capacity(), false); }
144  int *HostWriteJ()
145  { return mfem::Write(J, J.Capacity(), false); }
147  { return mfem::ReadWrite(J, J.Capacity(), false); }
148 
149  /// @brief Sort the column (TYPE II) indices in each row.
150  void SortRows();
151 
152  /// Replace the #I and #J arrays with the given @a newI and @a newJ arrays.
153  /** If @a newsize < 0, then the size of the Table is not modified. */
154  void SetIJ(int *newI, int *newJ, int newsize = -1);
155 
156  /** Establish connection between element i and element j in the table.
157  The return value is the index of the connection. It returns -1 if it
158  fails to establish the connection. Possibilities are there is not
159  enough memory on row i to establish connection to j, an attempt to
160  establish new connection after calling Finalize(). */
161  int Push( int i, int j );
162 
163  /** Finalize the table initialization. The function may be called
164  only once, after the table has been initialized, in order to compress
165  array J (by getting rid of -1's in array J). Calling this function
166  will "freeze" the table and function Push will work no more.
167  Note: The table is functional even without calling Finalize(). */
168  void Finalize();
169 
170  /** Create the table from a list of connections {(from, to)}, where 'from'
171  is a TYPE I index and 'to' is a TYPE II index. The list is assumed to be
172  sorted and free of duplicities, i.e., you need to call Array::Sort and
173  Array::Unique before calling this method. */
174  void MakeFromList(int nrows, const Array<Connection> &list);
175 
176  /// Returns the number of TYPE II elements (after Finalize() is called).
177  int Width() const;
178 
179  /// Call this if data has been stolen.
180  void LoseData() { size = -1; I.Reset(); J.Reset(); }
181 
182  /// Prints the table to stream out.
183  void Print(std::ostream & out = mfem::out, int width = 4) const;
184  void PrintMatlab(std::ostream & out) const;
185 
186  void Save(std::ostream &out) const;
187  void Load(std::istream &in);
188 
189  void Copy(Table & copy) const;
190  void Swap(Table & other);
191 
192  void Clear();
193 
194  std::size_t MemoryUsage() const;
195 
196  /// Destroys Table.
197  ~Table();
198 };
199 
200 /// Specialization of the template function Swap<> for class Table
201 template <> inline void Swap<Table>(Table &a, Table &b)
202 {
203  a.Swap(b);
204 }
205 
206 /// Transpose a Table
207 void Transpose (const Table &A, Table &At, int ncols_A_ = -1);
208 Table * Transpose (const Table &A);
209 
210 /// Transpose an Array<int>
211 void Transpose(const Array<int> &A, Table &At, int ncols_A_ = -1);
212 
213 /// C = A * B (as boolean matrices)
214 void Mult (const Table &A, const Table &B, Table &C);
215 Table * Mult (const Table &A, const Table &B);
216 
217 
218 /** Data type STable. STable is similar to Table, but it's for symmetric
219  connectivity, i.e. TYPE I is equivalent to TYPE II. In the first
220  dimension we put the elements with smaller index. */
221 class STable : public Table
222 {
223 public:
224  /// Creates table with fixed number of connections.
225  STable (int dim, int connections_per_row = 3);
226 
227  /** Returns index of the connection between element i of TYPE I and
228  element j of TYPE II. If there is no connection between element i
229  and element j established in the table, then the return value is -1. */
230  int operator() (int i, int j) const;
231 
232  /** Establish connection between element i and element j in the table.
233  The return value is the index of the connection. It returns -1 if it
234  fails to establish the connection. Possibilities are there is not
235  enough memory on row i to establish connection to j, an attempt to
236  establish new connection after calling Finalize(). */
237  int Push( int i, int j );
238 
239  /// Destroys STable.
240  ~STable() {}
241 };
242 
243 
244 class DSTable
245 {
246 private:
247  class Node
248  {
249  public:
250  Node *Prev;
251  int Column, Index;
252  };
253 
254  int NumRows, NumEntries;
255  Node **Rows;
256 #ifdef MFEM_USE_MEMALLOC
257  MemAlloc <Node, 1024> NodesMem;
258 #endif
259 
260  int Push_(int r, int c);
261  int Index(int r, int c) const;
262 
263 public:
264  DSTable(int nrows);
265  int NumberOfRows() const { return (NumRows); }
266  int NumberOfEntries() const { return (NumEntries); }
267  int Push(int a, int b)
268  { return ((a <= b) ? Push_(a, b) : Push_(b, a)); }
269  int operator()(int a, int b) const
270  { return ((a <= b) ? Index(a, b) : Index(b, a)); }
271  ~DSTable();
272 
274  {
275  private:
276  Node *n;
277  public:
278  RowIterator (const DSTable &t, int r) { n = t.Rows[r]; }
279  int operator!() { return (n != NULL); }
280  void operator++() { n = n->Prev; }
281  int Column() { return (n->Column); }
282  int Index() { return (n->Index); }
283  void SetIndex(int new_idx) { n->Index = new_idx; }
284  };
285 };
286 
287 }
288 
289 #endif
int * ReadWriteJ(bool on_dev=true)
Definition: table.hpp:140
Table(int nrows, Array< Connection > &list)
Definition: table.hpp:68
int Push(int i, int j)
Definition: table.cpp:219
int * GetJ()
Definition: table.hpp:114
void Print(std::ostream &out=mfem::out, int width=4) const
Prints the table to stream out.
Definition: table.cpp:310
int * HostReadWriteI()
Definition: table.hpp:133
Memory< int > I
Definition: table.hpp:52
void SetSize(int dim, int connections_per_row)
Set the size and the number of connections for the table.
Definition: table.cpp:124
void AddColumnsInRow(int r, int ncol)
Definition: table.hpp:78
void MakeI(int nrows)
Next 7 methods are used together with the default constructor.
Definition: table.cpp:81
void Swap< Table >(Table &a, Table &b)
Specialization of the template function Swap<> for class Table.
Definition: table.hpp:201
void SortRows()
Sort the column (TYPE II) indices in each row.
Definition: table.cpp:199
void Swap(Table &other)
Definition: table.cpp:394
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
Definition: table.cpp:475
void SetDims(int rows, int nnz)
Definition: table.cpp:140
int Push(int a, int b)
Definition: table.hpp:267
int * WriteI(bool on_dev=true)
Definition: table.hpp:125
T * Write(Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for write access to mem with the mfem::Device&#39;s DeviceMemoryClass, if on_dev = true...
Definition: device.hpp:336
const int * HostReadI() const
Definition: table.hpp:129
int Push(int i, int j)
Definition: table.cpp:569
void Save(std::ostream &out) const
Definition: table.cpp:347
int * HostWriteJ()
Definition: table.hpp:144
void LoseData()
Call this if data has been stolen.
Definition: table.hpp:180
Connection()=default
const int * HostReadJ() const
Definition: table.hpp:142
const int * GetRow(int i) const
Definition: table.hpp:110
int * WriteJ(bool on_dev=true)
Definition: table.hpp:138
int RowSize(int i) const
Definition: table.hpp:108
RowIterator(const DSTable &t, int r)
Definition: table.hpp:278
void PrintMatlab(std::ostream &out) const
Definition: table.cpp:332
void AddConnections(int r, const int *c, int nc)
Definition: table.cpp:104
bool operator==(const Connection &rhs) const
Definition: table.hpp:33
void MakeFromList(int nrows, const Array< Connection > &list)
Definition: table.cpp:279
Table & operator=(const Table &rhs)
Assignment operator: deep copy.
Definition: table.cpp:40
Memory< int > & GetJMemory()
Definition: table.hpp:119
void Clear()
Definition: table.cpp:380
double b
Definition: lissajous.cpp:42
std::size_t MemoryUsage() const
Definition: table.cpp:401
void AddConnection(int r, int c)
Definition: table.hpp:80
const int * ReadJ(bool on_dev=true) const
Definition: table.hpp:136
int Capacity() const
Return the size of the allocated memory.
int operator()(int i, int j) const
Definition: table.cpp:165
const T * Read(const Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for read access to mem with the mfem::Device&#39;s DeviceMemoryClass, if on_dev = true...
Definition: device.hpp:319
Connection(int from, int to)
Definition: table.hpp:31
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
Definition: table.cpp:187
void Reset()
Reset the memory to be empty, ensuring that Delete() will be a no-op.
const Memory< int > & GetIMemory() const
Definition: table.hpp:120
STable(int dim, int connections_per_row=3)
Creates table with fixed number of connections.
Definition: table.cpp:553
void SetIndex(int new_idx)
Definition: table.hpp:283
Memory< int > & GetIMemory()
Definition: table.hpp:118
int Width() const
Returns the number of TYPE II elements (after Finalize() is called).
Definition: table.cpp:300
Memory< int > J
Definition: table.hpp:52
void Finalize()
Definition: table.cpp:242
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition: globals.hpp:66
int size
size is the number of TYPE I elements.
Definition: table.hpp:47
void AddAColumnInRow(int r)
Definition: table.hpp:77
int * GetRow(int i)
Definition: table.hpp:111
const Memory< int > & GetJMemory() const
Definition: table.hpp:121
void Transpose(const Table &A, Table &At, int ncols_A_)
Transpose a Table.
Definition: table.cpp:413
Helper struct for defining a connectivity table, see Table::MakeFromList.
Definition: table.hpp:27
int operator()(int a, int b) const
Definition: table.hpp:269
void ShiftUpI()
Definition: table.cpp:115
int * HostReadWriteJ()
Definition: table.hpp:146
double a
Definition: lissajous.cpp:41
const int * GetJ() const
Definition: table.hpp:116
T * ReadWrite(Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for read+write access to mem with the mfem::Device&#39;s DeviceMemoryClass, if on_dev = true, or the mfem::Device&#39;s HostMemoryClass, otherwise.
Definition: device.hpp:353
void Load(std::istream &in)
Definition: table.cpp:361
int Size() const
Returns the number of TYPE I elements.
Definition: table.hpp:92
~Table()
Destroys Table.
Definition: table.cpp:407
void SetIJ(int *newI, int *newJ, int newsize=-1)
Replace the I and J arrays with the given newI and newJ arrays.
Definition: table.cpp:207
void MakeJ()
Definition: table.cpp:91
int dim
Definition: ex24.cpp:53
int NumberOfEntries() const
Definition: table.hpp:266
int Size_of_connections() const
Definition: table.hpp:98
int * ReadWriteI(bool on_dev=true)
Definition: table.hpp:127
RefCoord t[3]
void Copy(Table &copy) const
Definition: table.cpp:389
~STable()
Destroys STable.
Definition: table.hpp:240
int * GetI()
Definition: table.hpp:113
const int * ReadI(bool on_dev=true) const
Definition: table.hpp:123
int operator()(int i, int j) const
Definition: table.cpp:557
const int * GetI() const
Definition: table.hpp:115
int * HostWriteI()
Definition: table.hpp:131
bool operator<(const Connection &rhs) const
Definition: table.hpp:35
int NumberOfRows() const
Definition: table.hpp:265
DSTable(int nrows)
Definition: table.cpp:582
Table()
Creates an empty table.
Definition: table.hpp:56