MFEM  v3.4
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
table.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
3 // reserved. See file COPYRIGHT for details.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability see http://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the GNU Lesser General Public License (as published by the Free
10 // Software Foundation) version 2.1 dated February 1999.
11 
12 // Implementation of data types Table.
13 
14 #include "array.hpp"
15 #include "table.hpp"
16 #include "error.hpp"
17 
18 #include <iostream>
19 #include <iomanip>
20 
21 namespace mfem
22 {
23 
24 using namespace std;
25 
26 Table::Table(const Table &table)
27 {
28  size = table.size;
29  if (size >= 0)
30  {
31  const int nnz = table.I[size];
32  I = new int[size+1];
33  J = new int[nnz];
34  memcpy(I, table.I, sizeof(int)*(size+1));
35  memcpy(J, table.J, sizeof(int)*nnz);
36  }
37  else
38  {
39  I = J = NULL;
40  }
41 }
42 
44 {
45  Clear();
46 
47  Table copy(rhs);
48  Swap(copy);
49 
50  return *this;
51 }
52 
53 Table::Table (int dim, int connections_per_row)
54 {
55  int i, j, sum = dim * connections_per_row;
56 
57  size = dim;
58  I = new int[size+1];
59  J = new int[sum];
60 
61  I[0] = 0;
62  for (i = 1; i <= size; i++)
63  {
64  I[i] = I[i-1] + connections_per_row;
65  for (j = I[i-1]; j < I[i]; j++) { J[j] = -1; }
66  }
67 }
68 
69 Table::Table (int nrows, int *partitioning)
70 {
71  size = nrows;
72 
73  I = new int[size+1];
74  J = new int[size];
75 
76  for (int i = 0; i < size; i++)
77  {
78  I[i] = i;
79  J[i] = partitioning[i];
80  }
81  I[size] = size;
82 }
83 
84 void Table::MakeI (int nrows)
85 {
86  SetDims (nrows, 0);
87 
88  for (int i = 0; i <= nrows; i++)
89  {
90  I[i] = 0;
91  }
92 }
93 
95 {
96  int i, j, k;
97 
98  for (k = i = 0; i < size; i++)
99  {
100  j = I[i], I[i] = k, k += j;
101  }
102 
103  J = new int[I[size]=k];
104 }
105 
106 void Table::AddConnections (int r, const int *c, int nc)
107 {
108  int *jp = J+I[r];
109 
110  for (int i = 0; i < nc; i++)
111  {
112  jp[i] = c[i];
113  }
114  I[r] += nc;
115 }
116 
118 {
119  for (int i = size; i > 0; i--)
120  {
121  I[i] = I[i-1];
122  }
123  I[0] = 0;
124 }
125 
126 void Table::SetSize(int dim, int connections_per_row)
127 {
128  SetDims (dim, dim * connections_per_row);
129 
130  if (size > 0)
131  {
132  I[0] = 0;
133  for (int i = 0, j = 0; i < size; i++)
134  {
135  int end = I[i] + connections_per_row;
136  I[i+1] = end;
137  for ( ; j < end; j++) { J[j] = -1; }
138  }
139  }
140 }
141 
142 void Table::SetDims(int rows, int nnz)
143 {
144  int j;
145 
146  j = (I) ? (I[size]) : (0);
147  if (size != rows)
148  {
149  size = rows;
150  if (I) { delete [] I; }
151  I = (rows >= 0) ? (new int[rows+1]) : (NULL);
152  }
153 
154  if (j != nnz)
155  {
156  if (J) { delete [] J; }
157  J = (nnz > 0) ? (new int[nnz]) : (NULL);
158  }
159 
160  if (size >= 0)
161  {
162  I[0] = 0;
163  I[size] = nnz;
164  }
165 }
166 
167 int Table::operator() (int i, int j) const
168 {
169  if ( i>=size || i<0 )
170  {
171  return -1;
172  }
173 
174  int k, end = I[i+1];
175  for (k = I[i]; k < end; k++)
176  {
177  if (J[k] == j)
178  {
179  return k;
180  }
181  else if (J[k] == -1)
182  {
183  return -1;
184  }
185  }
186  return -1;
187 }
188 
189 void Table::GetRow(int i, Array<int> &row) const
190 {
191  MFEM_ASSERT(i >= 0 && i < size, "Row index " << i << " is out of range [0,"
192  << size << ')');
193 
194  row.SetSize(RowSize(i));
195  row.Assign(GetRow(i));
196 }
197 
199 {
200  for (int r = 0; r < size; r++)
201  {
202  std::sort(J + I[r], J + I[r+1]);
203  }
204 }
205 
206 void Table::SetIJ(int *newI, int *newJ, int newsize)
207 {
208  delete [] I;
209  delete [] J;
210  I = newI;
211  J = newJ;
212  if (newsize >= 0)
213  {
214  size = newsize;
215  }
216 }
217 
218 int Table::Push(int i, int j)
219 {
220  MFEM_ASSERT( i >=0 && i<size, "Index out of bounds. i = "<<i);
221 
222  for (int k = I[i], end = I[i+1]; k < end; k++)
223  if (J[k] == j)
224  {
225  return k;
226  }
227  else if (J[k] == -1)
228  {
229  J[k] = j;
230  return k;
231  }
232 
233  MFEM_ABORT("Reached end of loop unexpectedly: (i,j) = (" << i << ", " << j
234  << ")");
235 
236  return -1;
237 }
238 
240 {
241  int i, j, end, sum = 0, n = 0, newI = 0;
242 
243  for (i=0; i<I[size]; i++)
244  if (J[i] != -1)
245  {
246  sum++;
247  }
248 
249  if (sum != I[size])
250  {
251  int *NewJ = new int[sum];
252 
253  for (i=0; i<size; i++)
254  {
255  end = I[i+1];
256  for (j=I[i]; j<end; j++)
257  {
258  if (J[j] == -1) { break; }
259  NewJ[ n++ ] = J[j];
260  }
261  I[i] = newI;
262  newI = n;
263  }
264  I[size] = sum;
265 
266  delete [] J;
267 
268  J = NewJ;
269 
270  MFEM_ASSERT(sum == n, "sum = " << sum << ", n = " << n);
271  }
272 }
273 
274 void Table::MakeFromList(int nrows, const Array<Connection> &list)
275 {
276  Clear();
277 
278  size = nrows;
279  int nnz = list.Size();
280 
281  I = new int[size+1];
282  J = new int[nnz];
283 
284  for (int i = 0, k = 0; i <= size; i++)
285  {
286  I[i] = k;
287  while (k < nnz && list[k].from == i)
288  {
289  J[k] = list[k].to;
290  k++;
291  }
292  }
293 }
294 
295 int Table::Width() const
296 {
297  int width = -1, nnz = (size >= 0) ? I[size] : 0;
298  for (int k = 0; k < nnz; k++)
299  {
300  if (J[k] > width) { width = J[k]; }
301  }
302  return width + 1;
303 }
304 
305 void Table::Print(std::ostream & out, int width) const
306 {
307  int i, j;
308 
309  for (i = 0; i < size; i++)
310  {
311  out << "[row " << i << "]\n";
312  for (j = I[i]; j < I[i+1]; j++)
313  {
314  out << setw(5) << J[j];
315  if ( !((j+1-I[i]) % width) )
316  {
317  out << '\n';
318  }
319  }
320  if ((j-I[i]) % width)
321  {
322  out << '\n';
323  }
324  }
325 }
326 
327 void Table::PrintMatlab(std::ostream & out) const
328 {
329  int i, j;
330 
331  for (i = 0; i < size; i++)
332  for (j = I[i]; j < I[i+1]; j++)
333  {
334  out << i << " " << J[j] << " 1. \n";
335  }
336 
337  out << flush;
338 }
339 
340 void Table::Save(std::ostream &out) const
341 {
342  out << size << '\n';
343 
344  for (int i = 0; i <= size; i++)
345  {
346  out << I[i] << '\n';
347  }
348  for (int i = 0, nnz = I[size]; i < nnz; i++)
349  {
350  out << J[i] << '\n';
351  }
352 }
353 
354 void Table::Load(std::istream &in)
355 {
356  delete [] I;
357  delete [] J;
358 
359  in >> size;
360  I = new int[size+1];
361  for (int i = 0; i <= size; i++)
362  {
363  in >> I[i];
364  }
365  int nnz = I[size];
366  J = new int[nnz];
367  for (int j = 0; j < nnz; j++)
368  {
369  in >> J[j];
370  }
371 }
372 
374 {
375  delete [] I;
376  delete [] J;
377  size = -1;
378  I = J = NULL;
379 }
380 
381 void Table::Copy(Table & copy) const
382 {
383  if (size >= 0)
384  {
385  int * i_copy = new int[size+1];
386  int * j_copy = new int[I[size]];
387 
388  memcpy(i_copy, I, sizeof(int)*(size+1));
389  memcpy(j_copy, J, sizeof(int)*I[size]);
390 
391  copy.SetIJ(i_copy, j_copy, size);
392  }
393  else
394  {
395  copy.Clear();
396  }
397 }
398 
399 void Table::Swap(Table & other)
400 {
401  mfem::Swap(size, other.size);
402  mfem::Swap(I, other.I);
403  mfem::Swap(J, other.J);
404 }
405 
406 long Table::MemoryUsage() const
407 {
408  if (size < 0 || I == NULL) { return 0; }
409  return (size+1 + I[size]) * sizeof(int);
410 }
411 
413 {
414  if (I) { delete [] I; }
415  if (J) { delete [] J; }
416 }
417 
418 void Transpose (const Table &A, Table &At, int _ncols_A)
419 {
420  const int *i_A = A.GetI();
421  const int *j_A = A.GetJ();
422  const int nrows_A = A.Size();
423  const int ncols_A = (_ncols_A < 0) ? A.Width() : _ncols_A;
424  const int nnz_A = i_A[nrows_A];
425 
426  At.SetDims (ncols_A, nnz_A);
427 
428  int *i_At = At.GetI();
429  int *j_At = At.GetJ();
430 
431  for (int i = 0; i <= ncols_A; i++)
432  {
433  i_At[i] = 0;
434  }
435  for (int i = 0; i < nnz_A; i++)
436  {
437  i_At[j_A[i]+1]++;
438  }
439  for (int i = 1; i < ncols_A; i++)
440  {
441  i_At[i+1] += i_At[i];
442  }
443 
444  for (int i = 0; i < nrows_A; i++)
445  for (int j = i_A[i]; j < i_A[i+1]; j++)
446  {
447  j_At[i_At[j_A[j]]++] = i;
448  }
449  for (int i = ncols_A; i > 0; i--)
450  {
451  i_At[i] = i_At[i-1];
452  }
453  i_At[0] = 0;
454 }
455 
456 Table * Transpose(const Table &A)
457 {
458  Table * At = new Table;
459  Transpose(A, *At);
460  return At;
461 }
462 
463 void Transpose(const Array<int> &A, Table &At, int _ncols_A)
464 {
465  At.MakeI((_ncols_A < 0) ? (A.Max() + 1) : _ncols_A);
466  for (int i = 0; i < A.Size(); i++)
467  {
468  At.AddAColumnInRow(A[i]);
469  }
470  At.MakeJ();
471  for (int i = 0; i < A.Size(); i++)
472  {
473  At.AddConnection(A[i], i);
474  }
475  At.ShiftUpI();
476 }
477 
478 void Mult (const Table &A, const Table &B, Table &C)
479 {
480  int i, j, k, l, m;
481  const int *i_A = A.GetI();
482  const int *j_A = A.GetJ();
483  const int *i_B = B.GetI();
484  const int *j_B = B.GetJ();
485  const int nrows_A = A.Size();
486  const int nrows_B = B.Size();
487  const int ncols_A = A.Width();
488  const int ncols_B = B.Width();
489 
490  MFEM_VERIFY( ncols_A <= nrows_B, "Table size mismatch: ncols_A = " << ncols_A
491  << ", nrows_B = " << nrows_B);
492 
493  Array<int> B_marker (ncols_B);
494 
495  for (i = 0; i < ncols_B; i++)
496  {
497  B_marker[i] = -1;
498  }
499 
500  int counter = 0;
501  for (i = 0; i < nrows_A; i++)
502  {
503  for (j = i_A[i]; j < i_A[i+1]; j++)
504  {
505  k = j_A[j];
506  for (l = i_B[k]; l < i_B[k+1]; l++)
507  {
508  m = j_B[l];
509  if (B_marker[m] != i)
510  {
511  B_marker[m] = i;
512  counter++;
513  }
514  }
515  }
516  }
517 
518  C.SetDims (nrows_A, counter);
519 
520  for (i = 0; i < ncols_B; i++)
521  {
522  B_marker[i] = -1;
523  }
524 
525  int *i_C = C.GetI();
526  int *j_C = C.GetJ();
527  counter = 0;
528  for (i = 0; i < nrows_A; i++)
529  {
530  i_C[i] = counter;
531  for (j = i_A[i]; j < i_A[i+1]; j++)
532  {
533  k = j_A[j];
534  for (l = i_B[k]; l < i_B[k+1]; l++)
535  {
536  m = j_B[l];
537  if (B_marker[m] != i)
538  {
539  B_marker[m] = i;
540  j_C[counter] = m;
541  counter++;
542  }
543  }
544  }
545  }
546 }
547 
548 
549 Table * Mult (const Table &A, const Table &B)
550 {
551  Table * C = new Table;
552  Mult(A,B,*C);
553  return C;
554 }
555 
556 STable::STable (int dim, int connections_per_row) :
557  Table(dim, connections_per_row)
558 {}
559 
560 int STable::operator() (int i, int j) const
561 {
562  if (i < j)
563  {
564  return Table::operator()(i,j);
565  }
566  else
567  {
568  return Table::operator()(j,i);
569  }
570 }
571 
572 int STable::Push( int i, int j )
573 {
574  if (i < j)
575  {
576  return Table::Push(i, j);
577  }
578  else
579  {
580  return Table::Push(j, i);
581  }
582 }
583 
584 
586 {
587  Rows = new Node*[nrows];
588  for (int i = 0; i < nrows; i++)
589  {
590  Rows[i] = NULL;
591  }
592  NumRows = nrows;
593  NumEntries = 0;
594 }
595 
596 int DSTable::Push_(int r, int c)
597 {
598  MFEM_ASSERT(r >= 0 && r < NumRows,
599  "Row out of bounds: r = " << r << ", NumRows = " << NumRows);
600  Node *n;
601  for (n = Rows[r]; n != NULL; n = n->Prev)
602  {
603  if (n->Column == c)
604  {
605  return (n->Index);
606  }
607  }
608 #ifdef MFEM_USE_MEMALLOC
609  n = NodesMem.Alloc ();
610 #else
611  n = new Node;
612 #endif
613  n->Column = c;
614  n->Index = NumEntries;
615  n->Prev = Rows[r];
616  Rows[r] = n;
617  return (NumEntries++);
618 }
619 
620 int DSTable::Index(int r, int c) const
621 {
622  MFEM_ASSERT( r>=0, "Row index must be non-negative, not "<<r);
623  if (r >= NumRows)
624  {
625  return (-1);
626  }
627  for (Node *n = Rows[r]; n != NULL; n = n->Prev)
628  {
629  if (n->Column == c)
630  {
631  return (n->Index);
632  }
633  }
634  return (-1);
635 }
636 
638 {
639 #ifdef MFEM_USE_MEMALLOC
640  // NodesMem.Clear(); // this is done implicitly
641 #else
642  for (int i = 0; i < NumRows; i++)
643  {
644  Node *na, *nb = Rows[i];
645  while (nb != NULL)
646  {
647  na = nb;
648  nb = nb->Prev;
649  delete na;
650  }
651  }
652 #endif
653  delete [] Rows;
654 }
655 
656 }
Elem * Alloc()
Definition: mem_alloc.hpp:146
int Size() const
Logical size of the array.
Definition: array.hpp:133
int Push(int i, int j)
Definition: table.cpp:218
int * GetJ()
Definition: table.hpp:114
void SetSize(int dim, int connections_per_row)
Set the size and the number of connections for the table.
Definition: table.cpp:126
int operator()(int i, int j) const
Definition: table.cpp:167
void MakeI(int nrows)
Next 7 methods are used together with the default constructor.
Definition: table.cpp:84
void SortRows()
Sort the column (TYPE II) indices in each row.
Definition: table.cpp:198
void Swap(Table &other)
Definition: table.cpp:399
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
Definition: table.cpp:478
void SetDims(int rows, int nnz)
Definition: table.cpp:142
int * J
Definition: table.hpp:52
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
Definition: table.cpp:189
int Push(int i, int j)
Definition: table.cpp:572
void Save(std::ostream &out) const
Definition: table.cpp:340
void AddConnections(int r, const int *c, int nc)
Definition: table.cpp:106
int Width() const
Returns the number of TYPE II elements (after Finalize() is called).
Definition: table.cpp:295
int operator()(int i, int j) const
Definition: table.cpp:560
void Print(std::ostream &out=mfem::out, int width=4) const
Prints the table to stream out.
Definition: table.cpp:305
int dim
Definition: ex3.cpp:47
void MakeFromList(int nrows, const Array< Connection > &list)
Definition: table.cpp:274
Table & operator=(const Table &rhs)
Assignment operator: deep copy.
Definition: table.cpp:43
void Clear()
Definition: table.cpp:373
void AddConnection(int r, int c)
Definition: table.hpp:80
int * I
Definition: table.hpp:52
T Max() const
Find the maximal element in the array, using the comparison operator &lt; for class T.
Definition: array.cpp:109
long MemoryUsage() const
Definition: table.cpp:406
void Transpose(const Table &A, Table &At, int _ncols_A)
Transpose a Table.
Definition: table.cpp:418
void Assign(const T *)
Copy data from a pointer. Size() elements are copied.
Definition: array.hpp:764
int Size() const
Returns the number of TYPE I elements.
Definition: table.hpp:92
void PrintMatlab(std::ostream &out) const
Definition: table.cpp:327
STable(int dim, int connections_per_row=3)
Creates table with fixed number of connections.
Definition: table.cpp:556
void Swap(Array< T > &, Array< T > &)
Definition: array.hpp:560
void Finalize()
Definition: table.cpp:239
int size
size is the number of TYPE I elements.
Definition: table.hpp:47
void AddAColumnInRow(int r)
Definition: table.hpp:77
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
Definition: array.hpp:569
void ShiftUpI()
Definition: table.cpp:117
void Load(std::istream &in)
Definition: table.cpp:354
~Table()
Destroys Table.
Definition: table.cpp:412
void SetIJ(int *newI, int *newJ, int newsize=-1)
Definition: table.cpp:206
void MakeJ()
Definition: table.cpp:94
int * GetI()
Definition: table.hpp:113
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:64
void Copy(Table &copy) const
Definition: table.cpp:381
DSTable(int nrows)
Definition: table.cpp:585
Table()
Creates an empty table.
Definition: table.hpp:56