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