Loading...
Searching...
No Matches
SparseTable.hpp
//===========================================================================
//
// File: SparseTable.hpp
//
// Created: Fri Apr 24 09:50:27 2009
//
// Author(s): Atgeirr F Rasmussen <atgeirr@sintef.no>
//
// $Date$
//
// $Revision$
//
//===========================================================================
/*
Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
Copyright 2009, 2010 Statoil ASA.
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPM_SPARSETABLE_HEADER
#define OPM_SPARSETABLE_HEADER
#include <vector>
#include <numeric>
#include <algorithm>
#include <opm/common/ErrorMacros.hpp>
#include <opm/grid/utility/IteratorRange.hpp>
#include <ostream>
namespace Opm
{
template <typename T>
class SparseTable
{
public:
SparseTable()
: row_start_(1, 0)
{
}
template <typename DataIter, typename IntegerIter>
SparseTable(DataIter data_beg, DataIter data_end,
IntegerIter rowsize_beg, IntegerIter rowsize_end)
: data_(data_beg, data_end)
{
setRowStartsFromSizes(rowsize_beg, rowsize_end);
}
template <typename DataIter, typename IntegerIter>
void assign(DataIter data_beg, DataIter data_end,
IntegerIter rowsize_beg, IntegerIter rowsize_end)
{
data_.assign(data_beg, data_end);
setRowStartsFromSizes(rowsize_beg, rowsize_end);
}
template <typename IntegerIter>
void allocate(IntegerIter rowsize_beg, IntegerIter rowsize_end)
{
typedef typename std::vector<T>::size_type sz_t;
sz_t ndata = std::accumulate(rowsize_beg, rowsize_end, sz_t(0));
data_.resize(ndata);
setRowStartsFromSizes(rowsize_beg, rowsize_end);
}
template <typename DataIter>
void appendRow(DataIter row_beg, DataIter row_end)
{
data_.insert(data_.end(), row_beg, row_end);
row_start_.push_back(data_.size());
}
bool empty() const
{
return row_start_.size()==1;
}
int size() const
{
return row_start_.size() - 1;
}
void reserve(int exptd_nrows, int exptd_ndata)
{
row_start_.reserve(exptd_nrows + 1);
data_.reserve(exptd_ndata);
}
void swap(SparseTable<T>& other)
{
row_start_.swap(other.row_start_);
data_.swap(other.data_);
}
int dataSize() const
{
return data_.size();
}
int rowSize(int row) const
{
#ifndef NDEBUG
OPM_ERROR_IF(row < 0 || row >= size(),
"Row index " + std::to_string(row) + " is out of range");
#endif
return row_start_[row + 1] - row_start_[row];
}
void clear()
{
data_.clear();
row_start_.resize(1);
}
using row_type = iterator_range<typename std::vector<T>::const_iterator>;
using mutable_row_type = mutable_iterator_range<typename std::vector<T>::iterator>;
row_type operator[](int row) const
{
assert(row >= 0 && row < size());
return row_type{data_.begin()+ row_start_[row],
data_.begin() + row_start_[row + 1]};
}
mutable_row_type operator[](int row)
{
assert(row >= 0 && row < size());
return mutable_row_type{data_.begin() + row_start_[row],
data_.begin() + row_start_[row + 1]};
}
class Iterator
{
public:
Iterator(const SparseTable& table, const int begin_row_index)
: table_(table)
, row_index_(begin_row_index)
{
}
Iterator& operator++()
{
++row_index_;
return *this;
}
row_type operator*() const
{
return table_[row_index_];
}
bool operator==(const Iterator& other)
{
assert(&table_ == &other.table_);
return row_index_ == other.row_index_;
}
bool operator!=(const Iterator& other)
{
return !(*this == other);
}
private:
const SparseTable& table_;
int row_index_;
};
Iterator begin() const
{
return Iterator(*this, 0);
}
Iterator end() const
{
return Iterator(*this, size());
}
bool operator==(const SparseTable& other) const
{
return data_ == other.data_ && row_start_ == other.row_start_;
}
template<class charT, class traits>
void print(std::basic_ostream<charT, traits>& os) const
{
os << "Number of rows: " << size() << '\n';
os << "Row starts = [";
std::copy(row_start_.begin(), row_start_.end(),
std::ostream_iterator<int>(os, " "));
os << "\b]\n";
os << "Data values = [";
std::copy(data_.begin(), data_.end(),
std::ostream_iterator<T>(os, " "));
os << "\b]\n";
}
const T data(int i)const {
return data_[i];
}
// Get pointer to start of databuffer
// This is useful for getting access to the buffer itself so we can copy to GPU easily
const T* dataPtr() const
{
return data_.data();
}
private:
std::vector<T> data_;
// Like in the compressed row sparse matrix format,
// row_start_.size() is equal to the number of rows + 1.
std::vector<int> row_start_;
template <class IntegerIter>
void setRowStartsFromSizes(IntegerIter rowsize_beg, IntegerIter rowsize_end)
{
#ifndef NDEBUG
// Check that all row sizes given are nonnegative.
for (auto it = rowsize_beg; it != rowsize_end; ++it) {
if (*it < 0) {
OPM_THROW(std::runtime_error, "Negative row size given.");
}
}
#endif
// Since we do not store the row sizes, but cumulative row sizes,
// we have to create the cumulative ones.
int num_rows = rowsize_end - rowsize_beg;
row_start_.resize(num_rows + 1);
row_start_[0] = 0;
std::partial_sum(rowsize_beg, rowsize_end, row_start_.begin() + 1);
// Check that data_ and row_start_ match.
if (int(data_.size()) != row_start_.back()) {
OPM_THROW(std::runtime_error, "End of row start indices different from data size.");
}
}
};
} // namespace Opm
#endif // OPM_SPARSETABLE_HEADER
Opm::SparseTable::reserve
void reserve(int exptd_nrows, int exptd_ndata)
Allocate storage for table of expected size.
Definition SparseTable.hpp:127
Opm::SparseTable::assign
void assign(DataIter data_beg, DataIter data_end, IntegerIter rowsize_beg, IntegerIter rowsize_end)
Sets the table to contain the given data, organized into rows as indicated by the given row sizes.
Definition SparseTable.hpp:84
Opm::SparseTable::empty
bool empty() const
True if the table contains no rows.
Definition SparseTable.hpp:115
Opm::SparseTable::appendRow
void appendRow(DataIter row_beg, DataIter row_end)
Appends a row to the table.
Definition SparseTable.hpp:108
Opm::SparseTable::swap
void swap(SparseTable< T > &other)
Swap contents for other SparseTable<T>.
Definition SparseTable.hpp:134
Opm::SparseTable::size
int size() const
Returns the number of rows in the table.
Definition SparseTable.hpp:121
Opm::SparseTable::operator[]
row_type operator[](int row) const
Returns a row of the table.
Definition SparseTable.hpp:168
Opm::SparseTable::begin
Iterator begin() const
Iterator access.
Definition SparseTable.hpp:217
Opm::row_type::row_type
iterator_range< typename std::vector< ToType >::const_iterator > row_type
Definition SparseTable.hpp:164
Opm::SparseTable::operator[]
mutable_row_type operator[](int row)
Returns a mutable row of the table.
Definition SparseTable.hpp:176
Opm::SparseTable::rowSize
int rowSize(int row) const
Returns the size of a table row.
Definition SparseTable.hpp:147
Opm::SparseTable::dataSize
int dataSize() const
Returns the number of data elements.
Definition SparseTable.hpp:141
Opm::SparseTable::SparseTable
SparseTable(DataIter data_beg, DataIter data_end, IntegerIter rowsize_beg, IntegerIter rowsize_end)
A constructor taking all the data for the table and row sizes.
Definition SparseTable.hpp:69
Opm::SparseTable::allocate
void allocate(IntegerIter rowsize_beg, IntegerIter rowsize_end)
Request storage for table of given size.
Definition SparseTable.hpp:96
Opm::SparseTable::SparseTable
SparseTable()
Default constructor. Yields an empty SparseTable.
Definition SparseTable.hpp:58
Opm::SparseTable::clear
void clear()
Makes the table empty().
Definition SparseTable.hpp:157
Opm::SparseTable::operator==
bool operator==(const SparseTable &other) const
Equality.
Definition SparseTable.hpp:227
Opm
Holds the implementation of the CpGrid as a pimple.
Definition CellQuadrature.cpp:68
Opm::iterator_range
Definition IteratorRange.hpp:50
Opm::mutable_iterator_range
Definition IteratorRange.hpp:70