12 #include "../general/array.hpp"
13 #include "../general/globals.hpp"
25 nRowBlocks(offsets.Size()-1),
26 nColBlocks(offsets.Size()-1),
27 row_offsets(const_cast<
Array<int>& >(offsets).GetData(), offsets.Size()),
28 col_offsets(const_cast<
Array<int>& >(offsets).GetData(), offsets.Size()),
29 Aij(nRowBlocks, nColBlocks)
38 nRowBlocks(row_offsets_.Size()-1),
39 nColBlocks(col_offsets_.Size()-1),
40 row_offsets(const_cast<
Array<int>& >(row_offsets_).GetData(),
42 col_offsets(const_cast<
Array<int>& >(col_offsets_).GetData(),
44 Aij(nRowBlocks, nColBlocks)
54 it != Aij.GetRow(0)+(Aij.NumRows()*Aij.NumCols()); ++it)
63 if (nRowBlocks <= i || nColBlocks <= j)
68 if (mat->
Height() != row_offsets[i+1] - row_offsets[i])
73 if (mat->
Width() != col_offsets[j+1] - col_offsets[j])
84 if (nRowBlocks <= i || nColBlocks <= j)
100 if (nRowBlocks <= i || nColBlocks <= j)
118 for (
int jcol = 0; jcol != nColBlocks; ++jcol)
119 for (
int irow = 0; irow != nRowBlocks; ++irow)
123 nnz_elem+= Aij(irow,jcol)->NumNonZeroElems();
135 findGlobalRow(i, iblock, iloc);
136 findGlobalCol(j, jblock, jloc);
143 return Aij(iblock, jblock)->Elem(iloc, jloc);
151 findGlobalRow(i, iblock, iloc);
152 findGlobalCol(j, jblock, jloc);
159 return Aij(iblock, jblock)->Elem(iloc, jloc);
167 findGlobalRow(i, iblock, iloc);
169 for (
int jblock = 0; jblock < nColBlocks; ++jblock)
170 if (Aij(iblock,jblock) != NULL)
172 rowsize += Aij(iblock,jblock)->RowSize(iloc);
180 int iblock, iloc, rowsize;
181 findGlobalRow(row, iblock, iloc);
189 int * it_cols = cols.
GetData();
190 double *it_srow = srow.
GetData();
192 for (
int jblock = 0; jblock < nColBlocks; ++jblock)
193 if (Aij(iblock,jblock) != NULL)
195 Aij(iblock,jblock)->GetRow(iloc, bcols, bsrow);
196 for (
int i = 0; i < bcols.
Size(); ++i)
198 *(it_cols++) = bcols[i] + col_offsets[jblock];
199 *(it_srow++) = bsrow(i);
209 if (nRowBlocks != nColBlocks)
211 mfem_error(
"BlockMatrix::EliminateRowCol: nRowBlocks != nColBlocks");
214 for (
int iiblock = 0; iiblock < nRowBlocks; ++iiblock)
215 if (row_offsets[iiblock] != col_offsets[iiblock])
217 mfem::out <<
"BlockMatrix::EliminateRowCol: row_offests["
218 << iiblock <<
"] != col_offsets["<<iiblock<<
"]\n";
224 Vector block_sol, block_rhs;
226 for (
int iiblock = 0; iiblock < nRowBlocks; ++iiblock)
228 int dsize = row_offsets[iiblock+1] - row_offsets[iiblock];
229 block_dofs.
MakeRef(ess_bc_dofs.
GetData()+row_offsets[iiblock], dsize);
233 if (Aij(iiblock, iiblock))
235 for (
int i = 0; i < block_dofs.
Size(); ++i)
238 Aij(iiblock, iiblock)->EliminateRowCol(i,block_sol(i), block_rhs);
243 for (
int i = 0; i < block_dofs.
Size(); ++i)
246 mfem_error(
"BlockMatrix::EliminateRowCol: Null diagonal block \n");
250 for (
int jjblock = 0; jjblock < nRowBlocks; ++jjblock)
252 if (jjblock != iiblock && Aij(iiblock, jjblock))
254 for (
int i = 0; i < block_dofs.
Size(); ++i)
257 Aij(iiblock, jjblock)->EliminateRow(i);
260 if (jjblock != iiblock && Aij(jjblock, iiblock))
263 row_offsets[jjblock+1] - row_offsets[jjblock]);
264 Aij(jjblock, iiblock)->EliminateCols(block_dofs, &block_sol, &block_rhs);
272 if (nRowBlocks != nColBlocks)
274 mfem_error(
"BlockMatrix::EliminateZeroRows() #1");
277 for (
int iblock = 0; iblock < nRowBlocks; ++iblock)
279 if (Aij(iblock,iblock))
282 for (
int i = 0; i < Aij(iblock, iblock)->NumRows(); ++i)
285 for (
int jblock = 0; jblock < nColBlocks; ++jblock)
286 if (Aij(iblock,jblock))
288 norm += Aij(iblock,jblock)->GetRowNorml1(i);
293 for (
int jblock = 0; jblock < nColBlocks; ++jblock)
294 if (Aij(iblock,jblock))
296 Aij(iblock,jblock)->EliminateRow(i, iblock==jblock);
304 for (
int i = 0; i < row_offsets[iblock+1] - row_offsets[iblock]; ++i)
307 for (
int jblock = 0; jblock < nColBlocks; ++jblock)
308 if (Aij(iblock,jblock))
310 norm += Aij(iblock,jblock)->GetRowNorml1(i);
317 mfem_error(
"BlockMatrix::EliminateZeroRows() #2");
328 mfem_error(
"Error: x and y can't point to the same datas \n");
339 mfem_error(
"Error: x and y can't point to the same datas \n");
342 Vector xblockview, yblockview;
344 for (
int iblock = 0; iblock != nRowBlocks; ++iblock)
347 row_offsets[iblock+1] - row_offsets[iblock]);
349 for (
int jblock = 0; jblock != nColBlocks; ++jblock)
351 if (Aij(iblock, jblock) != NULL)
354 x.
GetData() + col_offsets[jblock],
355 col_offsets[jblock+1] - col_offsets[jblock]);
357 Aij(iblock, jblock)->AddMult(xblockview, yblockview, val);
367 mfem_error(
"Error: x and y can't point to the same datas \n");
375 const double val)
const
379 mfem_error(
"Error: x and y can't point to the same datas \n");
382 Vector xblockview, yblockview;
384 for (
int iblock = 0; iblock != nColBlocks; ++iblock)
387 col_offsets[iblock+1] - col_offsets[iblock]);
389 for (
int jblock = 0; jblock != nRowBlocks; ++jblock)
391 if (Aij(jblock, iblock) != NULL)
394 x.
GetData() + row_offsets[jblock],
395 row_offsets[jblock+1] - row_offsets[jblock]);
397 Aij(jblock, iblock)->AddMultTranspose(xblockview, yblockview, val);
407 int * i_amono =
new int[ row_offsets[nRowBlocks]+2 ];
408 int * j_amono =
new int[ nnz ];
409 double * data =
new double[ nnz ];
411 for (
int i = 0; i < row_offsets[nRowBlocks]+2; i++)
416 int * i_amono_construction = i_amono+1;
418 int * i_it(i_amono_construction);
420 for (
int iblock = 0; iblock != nRowBlocks; ++iblock)
422 for (
int irow(row_offsets[iblock]); irow < row_offsets[iblock+1]; ++irow)
424 int local_row = irow - row_offsets[iblock];
425 int ind = i_amono_construction[irow];
426 for (
int jblock = 0; jblock < nColBlocks; ++jblock)
428 if (Aij(iblock,jblock) != NULL)
429 ind += Aij(iblock, jblock)->GetI()[local_row+1]
430 - Aij(iblock, jblock)->GetI()[local_row];
432 i_amono_construction[irow+1] = ind;
437 for (
int iblock = 0; iblock != nRowBlocks; ++iblock)
439 for (
int jblock = 0; jblock != nColBlocks; ++jblock)
441 if (Aij(iblock,jblock) != NULL)
443 int nrow = row_offsets[iblock+1]-row_offsets[iblock];
444 int * i_aij = Aij(iblock, jblock)->GetI();
445 int * j_aij = Aij(iblock, jblock)->GetJ();
446 double * data_aij = Aij(iblock, jblock)->GetData();
447 i_it = i_amono_construction+row_offsets[iblock];
449 int loc_start_index = 0;
450 int loc_end_index = 0;
451 int glob_start_index = 0;
453 int shift(col_offsets[jblock]);
454 for (
int * i_it_aij(i_aij+1); i_it_aij != i_aij+nrow+1; ++i_it_aij)
456 glob_start_index = *i_it;
459 if (glob_start_index > nnz)
461 mfem::out<<
"glob_start_index = " << glob_start_index <<
"\n";
462 mfem::out<<
"Block:" << iblock <<
" " << jblock <<
"\n";
466 loc_end_index = *(i_it_aij);
467 for (
int cnt = 0; cnt < loc_end_index-loc_start_index; cnt++)
469 data[glob_start_index+cnt] = data_aij[loc_start_index+cnt];
470 j_amono[glob_start_index+cnt] = j_aij[loc_start_index+cnt] + shift;
473 *i_it += loc_end_index-loc_start_index;
475 loc_start_index = loc_end_index;
481 return new SparseMatrix(i_amono, j_amono, data, row_offsets[nRowBlocks],
482 col_offsets[nColBlocks]);
491 os<<
"% size " << row_offsets.
Last() <<
" " << col_offsets.
Last() <<
"\n";
492 os<<
"% Non Zeros " << nnz_elem <<
"\n";
494 std::ios::fmtflags old_fmt = os.flags();
495 os.setf(std::ios::scientific);
496 std::streamsize old_prec = os.precision(14);
497 for (i = 0; i < row_offsets.
Last(); i++)
499 GetRow(i, row_ind, row_data);
500 for (j = 0; j < row_ind.
Size(); j++)
502 os << i+1 <<
" " << row_ind[j]+1 <<
" " << row_data[j] << std::endl;
506 os.precision(old_prec);
515 for (
int irowAt = 0; irowAt < At->
NumRowBlocks(); ++irowAt)
516 for (
int jcolAt = 0; jcolAt < At->
NumColBlocks(); ++jcolAt)
533 CijPieces.
SetSize(0, static_cast<SparseMatrix *>(NULL));
540 if (CijPieces.Size() > 1)
544 it != CijPieces.GetData()+CijPieces.Size(); ++it)
549 else if (CijPieces.Size() == 1)
551 C->
SetBlock(irowC, jcolC, CijPieces[0]);
int Size() const
Logical size of the array.
SparseMatrix * CreateMonolithic() const
Returns a monolithic CSR matrix that represents this operator.
int owns_blocks
if owns_blocks the SparseMatrix objects Aij will be deallocated.
void SetSize(int s)
Resize the vector to size s.
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Abstract data type for sparse matrices.
T * GetData()
Returns the data.
BlockMatrix(const Array< int > &offsets)
Constructor for square block matrices.
virtual void AddMultTranspose(const Vector &x, Vector &y, const double val=1.) const
MatrixTranspose-Vector Multiplication y = y + val*A'*x.
virtual int GetRow(const int row, Array< int > &cols, Vector &srow) const
void Add(const DenseMatrix &A, const DenseMatrix &B, double alpha, DenseMatrix &C)
C = A + alpha*B.
void SetBlock(int i, int j, SparseMatrix *mat)
Set A(i,j) = mat.
virtual double & Elem(int i, int j)
Returns reference to a_{ij}.
virtual void EliminateZeroRows()
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
int IsZeroBlock(int i, int j) const
Check if block (i,j) is a zero block.
int NumRowBlocks() const
Return the number of row blocks.
Array< int > & ColOffsets()
Return the columns offsets for block starts.
void Transpose(const Table &A, Table &At, int _ncols_A)
Transpose a Table.
void PrintMatlab(std::ostream &os=mfem::out) const
Export the monolithic matrix to file.
Array< int > & RowOffsets()
Return the row offsets for block starts.
void EliminateRowCol(Array< int > &ess_bc_dofs, Vector &sol, Vector &rhs)
Symmetric elimination of the marked degree of freedom.
virtual int NumNonZeroElems() const
Returns the total number of non zeros in the matrix.
virtual ~BlockMatrix()
Destructor.
double * GetData() const
Return element data, i.e. array A.
virtual void MultTranspose(const Vector &x, Vector &y) const
MatrixTranspose-Vector Multiplication y = A'*x.
virtual void Mult(const Vector &x, Vector &y) const
Matrix-Vector Multiplication y = A*x.
void mfem_error(const char *msg)
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
int NumColBlocks() const
Return the number of column blocks.
void SetDataAndSize(double *d, int s)
Set the Vector data and size.
virtual void AddMult(const Vector &x, Vector &y, const double val=1.) const
Matrix-Vector Multiplication y = y + val*A*x.
SparseMatrix & GetBlock(int i, int j)
Return a reference to block (i,j). Reference may be invalid if Aij(i,j) == NULL.
T & Last()
Return the last element in the array.
void MakeRef(T *, int)
Make this Array a reference to a pointer.
int RowSize(const int i) const
Return the number of non zeros in row i.
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...