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