MFEM v2.0
|
00001 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at 00002 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights 00003 // reserved. See file COPYRIGHT for details. 00004 // 00005 // This file is part of the MFEM library. For more information and source code 00006 // availability see http://mfem.googlecode.com. 00007 // 00008 // MFEM is free software; you can redistribute it and/or modify it under the 00009 // terms of the GNU Lesser General Public License (as published by the Free 00010 // Software Foundation) version 2.1 dated February 1999. 00011 00012 // Implementation of data types Table. 00013 00014 #include <iostream> 00015 #include <iomanip> 00016 00017 #include "array.hpp" 00018 #include "table.hpp" 00019 00020 00021 Table::Table (int dim, int connections_per_row) 00022 { 00023 int i, j, sum = dim * connections_per_row; 00024 00025 size = dim; 00026 I = new int[size+1]; 00027 J = new int[sum]; 00028 00029 I[0] = 0; 00030 for (i = 1; i <= size; i++) 00031 { 00032 I[i] = I[i-1] + connections_per_row; 00033 for (j = I[i-1]; j < I[i]; j++) { J[j] = -1; } 00034 } 00035 } 00036 00037 Table::Table (int nrows, int *partitioning) 00038 { 00039 size = nrows; 00040 00041 I = new int[size+1]; 00042 J = new int[size]; 00043 00044 for (int i = 0; i < size; i++) 00045 { 00046 I[i] = i; 00047 J[i] = partitioning[i]; 00048 } 00049 I[size] = size; 00050 } 00051 00052 void Table::MakeI (int nrows) 00053 { 00054 SetDims (nrows, 0); 00055 00056 for (int i = 0; i <= nrows; i++) 00057 I[i] = 0; 00058 } 00059 00060 void Table::MakeJ() 00061 { 00062 int i, j, k; 00063 00064 for (k = i = 0; i < size; i++) 00065 j = I[i], I[i] = k, k += j; 00066 00067 J = new int[I[size]=k]; 00068 } 00069 00070 void Table::AddConnections (int r, int *c, int nc) 00071 { 00072 int *jp = J+I[r]; 00073 00074 for (int i = 0; i < nc; i++) 00075 jp[i] = c[i]; 00076 I[r] += nc; 00077 } 00078 00079 void Table::ShiftUpI() 00080 { 00081 for (int i = size; i > 0; i--) 00082 I[i] = I[i-1]; 00083 I[0] = 0; 00084 } 00085 00086 void Table::SetSize(int dim, int connections_per_row) 00087 { 00088 SetDims (dim, dim * connections_per_row); 00089 00090 if (size > 0) 00091 { 00092 I[0] = 0; 00093 for (int i = 0, j = 0; i < size; i++) 00094 { 00095 int end = I[i] + connections_per_row; 00096 I[i+1] = end; 00097 for ( ; j < end; j++) J[j] = -1; 00098 } 00099 } 00100 } 00101 00102 void Table::SetDims(int rows, int nnz) 00103 { 00104 int j; 00105 00106 j = (I) ? (I[size]) : (0); 00107 if (size != rows) 00108 { 00109 size = rows; 00110 if (I) delete [] I; 00111 I = (rows >= 0) ? (new int[rows+1]) : (NULL); 00112 } 00113 00114 if (j != nnz) 00115 { 00116 if (J) delete [] J; 00117 J = (nnz > 0) ? (new int[nnz]) : (NULL); 00118 } 00119 00120 if (size >= 0) 00121 { 00122 I[0] = 0; 00123 I[size] = nnz; 00124 } 00125 } 00126 00127 int Table::operator() (int i, int j) const 00128 { 00129 if ( i>=size || i<0 ) 00130 return -1; 00131 00132 int k, end = I[i+1]; 00133 00134 for(k=I[i]; k<end; k++) 00135 if (J[k]==j) 00136 return k; 00137 else if (J[k]==-1) 00138 return -1; 00139 00140 return -1; 00141 } 00142 00143 void Table::GetRow(int i, Array<int> &row) const 00144 { 00145 const int *jp = GetRow(i), n = RowSize(i); 00146 00147 row.SetSize(n); 00148 for(int i = 0; i < n; i++) 00149 row[i] = jp[i]; 00150 } 00151 00152 void Table::SetIJ(int *newI, int *newJ, int newsize) 00153 { 00154 delete [] I; 00155 delete [] J; 00156 I = newI; 00157 J = newJ; 00158 if (newsize >= 0) 00159 size = newsize; 00160 } 00161 00162 int Table::Push(int i, int j) 00163 { 00164 #ifdef MFEM_DEBUG 00165 if (i >= size || i < 0) 00166 { 00167 cerr << "Table::Push() i = " << i << endl; 00168 mfem_error(); 00169 } 00170 #endif 00171 00172 for(int k = I[i], end = I[i+1]; k < end; k++) 00173 if (J[k] == j) 00174 return k; 00175 else if (J[k] == -1) 00176 { 00177 J[k] = j; 00178 return k; 00179 } 00180 cerr << "Table::Push() : (i,j) = (" << i << ", " << j << ")" << endl; 00181 mfem_error(); 00182 00183 return -1; 00184 } 00185 00186 void Table::Finalize() 00187 { 00188 int i, j, end, sum = 0, n = 0, newI = 0; 00189 00190 for(i=0; i<I[size]; i++) 00191 if (J[i] != -1) 00192 sum++; 00193 00194 if (sum != I[size]){ 00195 int *NewJ = new int[sum]; 00196 00197 for(i=0; i<size; i++){ 00198 end = I[i+1]; 00199 for(j=I[i]; j<end; j++){ 00200 if (J[j] == -1) break; 00201 NewJ[ n++ ] = J[j]; 00202 } 00203 I[i] = newI; 00204 newI = n; 00205 } 00206 I[size] = sum; 00207 00208 delete [] J; 00209 00210 J = NewJ; 00211 00212 #ifdef MFEM_DEBUG 00213 if (sum != n) 00214 mfem_error ("Table::Finalize"); 00215 #endif 00216 } 00217 } 00218 00219 int Table::Width() const 00220 { 00221 int width = -1, nnz = I[size]; 00222 for (int k = 0; k < nnz; k++) 00223 if (J[k] > width) width = J[k]; 00224 return width + 1; 00225 } 00226 00227 void Table::Print(ostream & out, int width) const 00228 { 00229 int i, j; 00230 00231 for (i = 0; i < size; i++) 00232 { 00233 out << "[row " << i << "]\n"; 00234 for (j = I[i]; j < I[i+1]; j++) 00235 { 00236 out << setw(5) << J[j]; 00237 if ( !((j+1-I[i]) % width) ) 00238 out << '\n'; 00239 } 00240 if ((j-I[i]) % width) 00241 out << '\n'; 00242 } 00243 } 00244 00245 void Table::Save(ostream & out) const 00246 { 00247 int i; 00248 00249 out << size << '\n'; 00250 00251 for (i = 0; i <= size; i++) 00252 out << I[i] << '\n'; 00253 for (i = 0; i < I[size]; i++) 00254 out << J[i] << '\n'; 00255 } 00256 00257 Table::~Table () 00258 { 00259 if (I) delete [] I; 00260 if (J) delete [] J; 00261 } 00262 00263 void Transpose (const Table &A, Table &At, int _ncols_A) 00264 { 00265 const int *i_A = A.GetI(); 00266 const int *j_A = A.GetJ(); 00267 const int nrows_A = A.Size(); 00268 const int ncols_A = (_ncols_A < 0) ? A.Width() : _ncols_A; 00269 const int nnz_A = i_A[nrows_A]; 00270 00271 At.SetDims (ncols_A, nnz_A); 00272 00273 int *i_At = At.GetI(); 00274 int *j_At = At.GetJ(); 00275 00276 for (int i = 0; i <= ncols_A; i++) 00277 i_At[i] = 0; 00278 for (int i = 0; i < nnz_A; i++) 00279 i_At[j_A[i]+1]++; 00280 for (int i = 1; i < ncols_A; i++) 00281 i_At[i+1] += i_At[i]; 00282 00283 for (int i = 0; i < nrows_A; i++) 00284 for (int j = i_A[i]; j < i_A[i+1]; j++) 00285 j_At[i_At[j_A[j]]++] = i; 00286 for (int i = ncols_A; i > 0; i--) 00287 i_At[i] = i_At[i-1]; 00288 i_At[0] = 0; 00289 } 00290 00291 void Transpose(const Array<int> &A, Table &At, int _ncols_A) 00292 { 00293 At.MakeI((_ncols_A < 0) ? (A.Max() + 1) : _ncols_A); 00294 for (int i = 0; i < A.Size(); i++) 00295 At.AddAColumnInRow(A[i]); 00296 At.MakeJ(); 00297 for (int i = 0; i < A.Size(); i++) 00298 At.AddConnection(A[i], i); 00299 At.ShiftUpI(); 00300 } 00301 00302 void Mult (const Table &A, const Table &B, Table &C) 00303 { 00304 int i, j, k, l, m; 00305 const int *i_A = A.GetI(); 00306 const int *j_A = A.GetJ(); 00307 const int *i_B = B.GetI(); 00308 const int *j_B = B.GetJ(); 00309 const int nrows_A = A.Size(); 00310 const int nrows_B = B.Size(); 00311 const int ncols_A = A.Width(); 00312 const int ncols_B = B.Width(); 00313 00314 if (ncols_A > nrows_B) 00315 mfem_error ("Mult (Table &A, Table &B, Table &C)"); 00316 00317 Array<int> B_marker (ncols_B); 00318 00319 for (i = 0; i < ncols_B; i++) 00320 B_marker[i] = -1; 00321 00322 int counter = 0; 00323 for (i = 0; i < nrows_A; i++) 00324 { 00325 for (j = i_A[i]; j < i_A[i+1]; j++) 00326 { 00327 k = j_A[j]; 00328 for (l = i_B[k]; l < i_B[k+1]; l++) 00329 { 00330 m = j_B[l]; 00331 if (B_marker[m] != i) 00332 { 00333 B_marker[m] = i; 00334 counter++; 00335 } 00336 } 00337 } 00338 } 00339 00340 C.SetDims (nrows_A, counter); 00341 00342 for (i = 0; i < ncols_B; i++) 00343 B_marker[i] = -1; 00344 00345 int *i_C = C.GetI(); 00346 int *j_C = C.GetJ(); 00347 counter = 0; 00348 for (i = 0; i < nrows_A; i++) 00349 { 00350 i_C[i] = counter; 00351 for (j = i_A[i]; j < i_A[i+1]; j++) 00352 { 00353 k = j_A[j]; 00354 for (l = i_B[k]; l < i_B[k+1]; l++) 00355 { 00356 m = j_B[l]; 00357 if (B_marker[m] != i) 00358 { 00359 B_marker[m] = i; 00360 j_C[counter] = m; 00361 counter++; 00362 } 00363 } 00364 } 00365 } 00366 } 00367 00368 00369 STable::STable (int dim, int connections_per_row) : 00370 Table(dim, connections_per_row) 00371 {} 00372 00373 int STable::operator() (int i, int j) const 00374 { 00375 if (i < j) 00376 return Table::operator()(i,j); 00377 else 00378 return Table::operator()(j,i); 00379 } 00380 00381 int STable::Push( int i, int j ){ 00382 if (i < j) 00383 return Table::Push(i, j); 00384 else 00385 return Table::Push(j, i); 00386 } 00387 00388 00389 DSTable::DSTable(int nrows) 00390 { 00391 Rows = new Node*[nrows]; 00392 for (int i = 0; i < nrows; i++) 00393 { 00394 Rows[i] = NULL; 00395 } 00396 NumRows = nrows; 00397 NumEntries = 0; 00398 } 00399 00400 int DSTable::Push_(int r, int c) 00401 { 00402 #ifdef MFEM_DEBUG 00403 if (r < 0 || r >= NumRows) 00404 mfem_error("DSTable::Push_()"); 00405 #endif 00406 Node *n; 00407 for (n = Rows[r]; n != NULL; n = n->Prev) 00408 { 00409 if (n->Column == c) 00410 { 00411 return(n->Index); 00412 } 00413 } 00414 #ifdef MFEM_USE_MEMALLOC 00415 n = NodesMem.Alloc (); 00416 #else 00417 n = new Node; 00418 #endif 00419 n->Column = c; 00420 n->Index = NumEntries; 00421 n->Prev = Rows[r]; 00422 Rows[r] = n; 00423 return(NumEntries++); 00424 } 00425 00426 int DSTable::Index(int r, int c) const 00427 { 00428 #ifdef MFEM_DEBUG 00429 if (r < 0) 00430 mfem_error("DSTable::Index()"); 00431 #endif 00432 if (r >= NumRows) 00433 return(-1); 00434 for (Node *n = Rows[r]; n != NULL; n = n->Prev) 00435 { 00436 if (n->Column == c) 00437 { 00438 return(n->Index); 00439 } 00440 } 00441 return(-1); 00442 } 00443 00444 DSTable::~DSTable() 00445 { 00446 #ifdef MFEM_USE_MEMALLOC 00447 // NodesMem.Clear(); // this is done implicitly 00448 #else 00449 for (int i = 0; i < NumRows; i++) 00450 { 00451 Node *na, *nb = Rows[i]; 00452 while (nb != NULL) 00453 { 00454 na = nb; 00455 nb = nb->Prev; 00456 delete na; 00457 } 00458 } 00459 #endif 00460 delete [] Rows; 00461 }