103
103
// Get local range
104
const std::pair<uint, uint> range = tensor_layout.local_range(0);
105
const uint num_local_rows = range.second - range.first;
106
const uint n0 = range.first;
104
const std::pair<std::size_t, std::size_t> range = tensor_layout.local_range(0);
105
const std::size_t num_local_rows = range.second - range.first;
106
const std::size_t n0 = range.first;
108
108
dolfin_assert(tensor_layout.sparsity_pattern());
109
const SparsityPattern& _pattern = dynamic_cast<const SparsityPattern&>(*tensor_layout.sparsity_pattern());
110
const std::vector<std::vector<dolfin::uint> > d_pattern = _pattern.diagonal_pattern(SparsityPattern::unsorted);
111
const std::vector<std::vector<dolfin::uint> > o_pattern = _pattern.off_diagonal_pattern(SparsityPattern::unsorted);
109
const SparsityPattern& _pattern
110
= dynamic_cast<const SparsityPattern&>(*tensor_layout.sparsity_pattern());
111
const std::vector<std::vector<std::size_t> > d_pattern
112
= _pattern.diagonal_pattern(SparsityPattern::unsorted);
113
const std::vector<std::vector<std::size_t> > o_pattern
114
= _pattern.off_diagonal_pattern(SparsityPattern::unsorted);
113
116
// Get number of non-zeroes per row
114
std::vector<uint> num_nonzeros;
117
std::vector<std::size_t> num_nonzeros;
115
118
_pattern.num_local_nonzeros(num_nonzeros);
117
120
// Create row map
118
121
EpetraFactory& f = EpetraFactory::instance();
119
122
Epetra_MpiComm comm = f.get_mpi_comm();
120
Epetra_Map row_map((int) tensor_layout.size(0), (int) num_local_rows, 0, comm);
123
Epetra_Map row_map((DolfinIndex) tensor_layout.size(0), (DolfinIndex) num_local_rows, 0, comm);
122
125
// For rectangular matrices with more columns than rows, the columns which are
123
126
// larger than those in row_map are marked as nonlocal (and assembly fails).
124
127
// The domain_map fixes that problem, at least in the serial case.
125
128
// FIXME: Needs attention in the parallel case. Maybe range_map is also req'd.
126
const std::pair<uint, uint> colrange = tensor_layout.local_range(1);
129
const std::pair<std::size_t, std::size_t> colrange = tensor_layout.local_range(1);
127
130
const int num_local_cols = colrange.second - colrange.first;
128
Epetra_Map domain_map((int) tensor_layout.size(1), (int) num_local_cols, 0, comm);
131
Epetra_Map domain_map((DolfinIndex) tensor_layout.size(1), num_local_cols, 0, comm);
130
133
// Create Epetra_FECrsGraph
131
Epetra_CrsGraph matrix_map(Copy, row_map, reinterpret_cast<int*>(&num_nonzeros[0]));
134
const std::vector<int> _num_nonzeros(num_nonzeros.begin(), num_nonzeros.end());
135
Epetra_CrsGraph matrix_map(Copy, row_map, _num_nonzeros.data());
133
137
// Add diagonal block indices
134
for (uint local_row = 0; local_row < d_pattern.size(); local_row++)
138
for (std::size_t local_row = 0; local_row < d_pattern.size(); local_row++)
136
const uint global_row = local_row + n0;
137
std::vector<uint>& entries = const_cast<std::vector<uint>&>(d_pattern[local_row]);
138
matrix_map.InsertGlobalIndices(global_row, entries.size(),
139
reinterpret_cast<int*>(&entries[0]));
140
const DolfinIndex global_row = local_row + n0;
141
std::vector<DolfinIndex> entries(d_pattern[local_row].begin(), d_pattern[local_row].end());
142
matrix_map.InsertGlobalIndices(global_row, (DolfinIndex) entries.size(), entries.data());
142
145
// Add off-diagonal block indices (parallel only)
143
for (uint local_row = 0; local_row < o_pattern.size(); local_row++)
146
for (std::size_t local_row = 0; local_row < o_pattern.size(); local_row++)
145
const uint global_row = local_row + n0;
146
std::vector<uint>& entries = const_cast<std::vector<uint>&>(o_pattern[local_row]);
147
matrix_map.InsertGlobalIndices(global_row, entries.size(),
148
reinterpret_cast<int*>(&entries[0]));
148
const std::size_t global_row = local_row + n0;
149
std::vector<DolfinIndex> entries(o_pattern[local_row].begin(),o_pattern[local_row].end());
150
matrix_map.InsertGlobalIndices(global_row, entries.size(), entries.data());
287
289
//-----------------------------------------------------------------------------
288
290
void EpetraMatrix::set(const double* block,
289
uint m, const uint* rows,
290
uint n, const uint* cols)
291
std::size_t m, const DolfinIndex* rows,
292
std::size_t n, const DolfinIndex* cols)
292
294
// This function is awkward and somewhat restrictive because of the
293
295
// poor support for setting off-process values in Epetra
295
297
dolfin_assert(A);
297
// Check that all rows are local to this process
299
for (uint i = 0; i < m; ++i)
301
if (!A->MyGRID(rows[i]))
303
dolfin_error("EpetraMatrix.cpp",
304
"set block of values for Epetra matrix",
305
"Only values in row belonging to process can be set");
310
const int err = A->ReplaceGlobalValues(m,
311
reinterpret_cast<const int*>(rows), n,
312
reinterpret_cast<const int*>(cols), block, Epetra_FECrsMatrix::ROW_MAJOR);
299
const int err = A->ReplaceGlobalValues(m, rows, n, cols, block,
300
Epetra_FECrsMatrix::ROW_MAJOR);
315
303
dolfin_error("EpetraMatrix.cpp",
320
308
//-----------------------------------------------------------------------------
321
309
void EpetraMatrix::add(const double* block,
322
uint m, const uint* rows,
323
uint n, const uint* cols)
310
std::size_t m, const DolfinIndex* rows,
311
std::size_t n, const DolfinIndex* cols)
325
313
dolfin_assert(A);
326
const std::pair<uint, uint> local_row_range = local_range(0);
327
for (uint i = 0; i < m; ++i)
329
const uint row = rows[i];
330
if (row >= local_row_range.first && row < local_row_range.second)
332
A->Epetra_CrsMatrix::SumIntoGlobalValues((int) row, n, block + i*n,
333
reinterpret_cast<const int*>(cols));
337
A->SumIntoGlobalValues(1, reinterpret_cast<const int*>(rows + i),
338
n, reinterpret_cast<const int*>(cols), block + i*n,
339
Epetra_FECrsMatrix::ROW_MAJOR);
344
const int err = A->SumIntoGlobalValues(m, reinterpret_cast<const int*>(rows),
345
n, reinterpret_cast<const int*>(cols), block,
314
const int err = A->SumIntoGlobalValues(m, rows, n, cols, block,
346
315
Epetra_FECrsMatrix::ROW_MAJOR);
459
428
// but is due to the sparsity pattern computation). This function only
460
429
// work for locally owned rows (the PETSc version works for any row).
462
typedef boost::unordered_set<uint> MySet;
431
typedef boost::unordered_set<std::size_t> MySet;
464
433
// Build lists of local and nonlocal rows
465
434
MySet local_rows;
466
std::vector<uint> non_local_rows;
467
for (uint i = 0; i < m; ++i)
435
std::vector<std::size_t> non_local_rows;
436
for (std::size_t i = 0; i < m; ++i)
469
if (A->MyGlobalRow(static_cast<int>(rows[i])))
438
if (A->MyGlobalRow(rows[i]))
470
439
local_rows.insert(rows[i]);
472
441
non_local_rows.push_back(rows[i]);
682
653
//-----------------------------------------------------------------------------
683
void EpetraMatrix::setrow(uint row, const std::vector<uint>& columns,
654
void EpetraMatrix::setrow(std::size_t row,
655
const std::vector<std::size_t>& columns,
684
656
const std::vector<double>& values)
686
static bool print_msg_once=true;
658
static bool print_msg_once = true;
687
659
if (print_msg_once)
689
661
info("EpetraMatrix::setrow is implemented inefficiently");
690
662
print_msg_once = false;
693
for (uint i=0; i < columns.size(); i++)
694
set(&values[i], 1, &row, 1, &columns[i]);
665
for (std::size_t i = 0; i < columns.size(); i++)
667
DolfinIndex _row = row;
668
DolfinIndex _col = columns[i];
669
set(&values[i], 1, &_row, 1, &_col);
696
672
//-----------------------------------------------------------------------------
697
673
GenericLinearAlgebraFactory& EpetraMatrix::factory() const