//----------------------------------------------------------------------------- void STLMatrix::init(const TensorLayout& tensor_layout) { // Check that sparsity pattern has correct storage (row vs column storage) if (_primary_dim != tensor_layout.primary_dim) { dolfin_error("STLMatrix.cpp", "initialization of STL matrix", "Primary storage dim of matrix and tensot layout must be the same"); } //primary_dim = sparsity_pattern.primary_dim(); std::size_t primary_codim = 1; if (_primary_dim == 1) primary_codim = 0; _local_range = tensor_layout.local_range(_primary_dim); num_codim_entities = tensor_layout.size(primary_codim); const std::size_t num_primary_entiries = _local_range.second - _local_range.first; _values.resize(num_primary_entiries); // FIXME: Add function to sparsity pattern to get nnz per row to // to reserve space for vectors //if (tensor_layout.sparsity_pattern() //{ // Reserve space here //} }
//---------------------------------------------------------------------------- void EigenMatrix::init(const TensorLayout& tensor_layout) { resize(tensor_layout.size(0), tensor_layout.size(1)); // Get sparsity pattern dolfin_assert(tensor_layout.sparsity_pattern()); auto sparsity_pattern = tensor_layout.sparsity_pattern(); dolfin_assert(sparsity_pattern); // Reserve space for non-zeroes and get non-zero pattern std::vector<std::size_t> num_nonzeros_per_row; sparsity_pattern->num_nonzeros_diagonal(num_nonzeros_per_row); _matA.reserve(num_nonzeros_per_row); const std::vector<std::vector<std::size_t>> pattern = sparsity_pattern->diagonal_pattern(SparsityPattern::Type::sorted); if (!eigen_matrix_type::IsRowMajor) warning ("Entering sparsity for RowMajor matrix - performance may be affected"); // Add entries for RowMajor matrix for (std::size_t i = 0; i != pattern.size(); ++i) { for (auto j : pattern[i]) _matA.insert(i, j) = 0.0; } }
//----------------------------------------------------------------------------- GraphOrdering::GraphOrdering(const TensorLayout& tensor_layout) : _tensor_layout(tensor_layout) { if (tensor_layout.rank() != 2) { dolfin_error("GraphOrdering.cpp", "create matrix re-ordering", "Zoltan object for sparsity pattern re-ordering can only be used for rank 2 tensors"); } if (!tensor_layout.sparsity_pattern()) { dolfin_error("GraphOrdering.cpp", "create matrix re-ordering", "TensorLayout object must a have sparsity pattern"); } if (tensor_layout.size(0) != tensor_layout.size(1)) { dolfin_error("GraphOrdering.cpp", "create matrix re-ordering", "Zoltan object for sparsity pattern re-ordering can only be used for square matrices"); } }
//----------------------------------------------------------------------------- void TpetraMatrix::init(const TensorLayout& tensor_layout) { if (!_matA.is_null()) error("TpetraMatrix may not be initialized more than once."); // Get global dimensions and local range dolfin_assert(tensor_layout.rank() == 2); const std::size_t M = tensor_layout.size(0); const std::size_t N = tensor_layout.size(1); const std::pair<std::size_t, std::size_t> row_range = tensor_layout.local_range(0); const std::size_t m = row_range.second - row_range.first; // Get sparsity pattern dolfin_assert(tensor_layout.sparsity_pattern()); std::shared_ptr<const GenericSparsityPattern> sparsity_pattern = tensor_layout.sparsity_pattern(); // Initialize matrix // Insist on square Matrix for now dolfin_assert(M == N); // Set up MPI Comm Teuchos::RCP<const Teuchos::Comm<int>> _comm(new Teuchos::MpiComm<int>(sparsity_pattern->mpi_comm())); // Save the local row and column mapping, so we can use add_local // and set_local later with off-process entries std::vector<dolfin::la_index> global_indices0 (tensor_layout.local_to_global_map[0].begin(), tensor_layout.local_to_global_map[0].end()); Teuchos::ArrayView<dolfin::la_index> _global_indices0(global_indices0); _row_map = Teuchos::rcp (new map_type(Teuchos::OrdinalTraits<dolfin::la_index>::invalid(), _global_indices0, 0, _comm)); std::vector<dolfin::la_index> global_indices1 (tensor_layout.local_to_global_map[1].begin(), tensor_layout.local_to_global_map[1].end()); Teuchos::ArrayView<dolfin::la_index> _global_indices1(global_indices1); _col_map = Teuchos::rcp (new map_type(Teuchos::OrdinalTraits<dolfin::la_index>::invalid(), _global_indices1, 0, _comm)); // Make a Tpetra::CrsGraph of the sparsity_pattern typedef Tpetra::CrsGraph<> graph_type; std::vector<std::vector<std::size_t>> pattern_diag = sparsity_pattern->diagonal_pattern(GenericSparsityPattern::unsorted); std::vector<std::vector<std::size_t>> pattern_off = sparsity_pattern->off_diagonal_pattern(GenericSparsityPattern::unsorted); dolfin_assert(pattern_diag.size() == pattern_off.size()); dolfin_assert(m == pattern_diag.size()); // Get number of non-zeros per row to allocate storage std::vector<std::size_t> entries_per_row(m); sparsity_pattern->num_local_nonzeros(entries_per_row); Teuchos::ArrayRCP<std::size_t> _nnz(entries_per_row.data(), 0, entries_per_row.size(), false); // Create a non-overlapping "row" map for the graph // The column map will be auto-generated from the entries. Teuchos::ArrayView<dolfin::la_index> _global_indices_subset(global_indices0.data(), m); Teuchos::RCP<const map_type> graph_row_map (new map_type(Teuchos::OrdinalTraits<dolfin::la_index>::invalid(), _global_indices_subset, 0, _comm)); Teuchos::RCP<graph_type> crs_graph (new graph_type(graph_row_map, _nnz, Tpetra::StaticProfile)); for (std::size_t i = 0; i != m; ++i) { std::vector<dolfin::la_index> indices(pattern_diag[i].begin(), pattern_diag[i].end()); indices.insert(indices.end(), pattern_off[i].begin(), pattern_off[i].end()); Teuchos::ArrayView<dolfin::la_index> _indices(indices); crs_graph->insertGlobalIndices(tensor_layout.local_to_global_map[0][i], _indices); } crs_graph->fillComplete(); _matA = Teuchos::rcp(new matrix_type(crs_graph)); }
//----------------------------------------------------------------------------- void TpetraMatrix::init(const TensorLayout& tensor_layout) { if (!_matA.is_null()) { dolfin_error("TpetraMatrix.h", "initialize matrix", "Matrix cannot be initialised more than once"); } // Get global dimensions and local range dolfin_assert(tensor_layout.rank() == 2); const std::pair<std::size_t, std::size_t> row_range = tensor_layout.local_range(0); const std::size_t m = row_range.second - row_range.first; const std::pair<std::size_t, std::size_t> col_range = tensor_layout.local_range(1); const std::size_t n = col_range.second - col_range.first; // Get sparsity pattern auto sparsity_pattern = tensor_layout.sparsity_pattern(); dolfin_assert(sparsity_pattern); // Initialize matrix // Set up MPI Comm Teuchos::RCP<const Teuchos::Comm<int>> _comm(new Teuchos::MpiComm<int>(sparsity_pattern->mpi_comm())); // Save the local row and column mapping, so we can use add_local // later with off-process entries // Overlapping RowMap index_map[0] = tensor_layout.index_map(0); std::vector<dolfin::la_index> global_indices0(m); for (std::size_t i = 0; i < m; ++i) { global_indices0[i] = tensor_layout.index_map(0)->local_to_global(i); } // Non-overlapping RangeMap Teuchos::ArrayView<dolfin::la_index> _global_indices0(global_indices0.data(), m); Teuchos::RCP<const map_type> range_map (new map_type(Teuchos::OrdinalTraits<dolfin::la_index>::invalid(), _global_indices0, 0, _comm)); // Overlapping ColMap index_map[1] = tensor_layout.index_map(1); std::vector<dolfin::la_index> global_indices1(n); { for (std::size_t i = 0; i < n; ++i) global_indices1[i] = tensor_layout.index_map(1)->local_to_global(i); } // Non-overlapping DomainMap Teuchos::ArrayView<dolfin::la_index> _global_indices1(global_indices1.data(), n); Teuchos::RCP<const map_type> domain_map (new map_type(Teuchos::OrdinalTraits<dolfin::la_index>::invalid(), _global_indices1, 0, _comm)); std::vector<std::vector<std::size_t>> pattern_diag = sparsity_pattern->diagonal_pattern(SparsityPattern::unsorted); std::vector<std::vector<std::size_t>> pattern_off = sparsity_pattern->off_diagonal_pattern(SparsityPattern::unsorted); const bool has_off_diag = pattern_off.size() > 0; dolfin_assert(pattern_diag.size() == pattern_off.size() || !has_off_diag); dolfin_assert(m == pattern_diag.size()); // Get number of non-zeros per row to allocate storage std::vector<std::size_t> entries_per_row(m); sparsity_pattern->num_local_nonzeros(entries_per_row); Teuchos::ArrayRCP<std::size_t> _nnz(entries_per_row.data(), 0, entries_per_row.size(), false); // Create a non-overlapping "row" map for the graph // The column map will be auto-generated from the entries. Teuchos::RCP<graph_type> crs_graph (new graph_type(range_map, _nnz, Tpetra::StaticProfile)); for (std::size_t i = 0; i != m; ++i) { std::vector<dolfin::la_index> indices(pattern_diag[i].begin(), pattern_diag[i].end()); if (has_off_diag) { indices.insert(indices.end(), pattern_off[i].begin(), pattern_off[i].end()); } Teuchos::ArrayView<dolfin::la_index> _indices(indices); crs_graph->insertGlobalIndices ((dolfin::la_index)tensor_layout.index_map(0)->local_to_global(i), _indices); } crs_graph->fillComplete(domain_map, range_map); _matA = Teuchos::rcp(new matrix_type(crs_graph)); }