Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
179aa07b8b | ||
|
|
7d736ebf6d | ||
|
|
870f6bb0d4 | ||
|
|
2109794db6 | ||
|
|
e9429c73b6 | ||
|
|
f74e713616 |
@@ -62,6 +62,11 @@ constexpr real_t operator""_r(unsigned long long v)
|
||||
return static_cast<real_t>(v);
|
||||
}
|
||||
|
||||
// MFEM bigint type
|
||||
|
||||
/// MFEM's "big" integer type.
|
||||
typedef long long int bigint;
|
||||
|
||||
} // namespace mfem
|
||||
|
||||
// Return value for main function in examples that should be skipped by testing
|
||||
|
||||
+11
-12
@@ -23,7 +23,7 @@ namespace mfem
|
||||
template <class T>
|
||||
void Array<T>::Print(std::ostream &os, int width) const
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
for (bigint i = 0; i < size; i++)
|
||||
{
|
||||
os << data[i];
|
||||
if ( !((i+1) % width) || i+1 == size )
|
||||
@@ -44,7 +44,7 @@ void Array<T>::Save(std::ostream &os, int fmt) const
|
||||
{
|
||||
os << size << '\n';
|
||||
}
|
||||
for (int i = 0; i < size; i++)
|
||||
for (bigint i = 0; i < size; i++)
|
||||
{
|
||||
os << operator[](i) << '\n';
|
||||
}
|
||||
@@ -55,11 +55,11 @@ void Array<T>::Load(std::istream &in, int fmt)
|
||||
{
|
||||
if (fmt == 0)
|
||||
{
|
||||
int new_size;
|
||||
bigint new_size;
|
||||
in >> new_size;
|
||||
SetSize(new_size);
|
||||
}
|
||||
for (int i = 0; i < size; i++)
|
||||
for (bigint i = 0; i < size; i++)
|
||||
{
|
||||
in >> operator[](i);
|
||||
}
|
||||
@@ -71,7 +71,7 @@ T Array<T>::Max() const
|
||||
MFEM_ASSERT(size > 0, "Array is empty with size " << size);
|
||||
|
||||
T max = operator[](0);
|
||||
for (int i = 1; i < size; i++)
|
||||
for (bigint i = 1; i < size; i++)
|
||||
{
|
||||
if (max < operator[](i))
|
||||
{
|
||||
@@ -88,7 +88,7 @@ T Array<T>::Min() const
|
||||
MFEM_ASSERT(size > 0, "Array is empty with size " << size);
|
||||
|
||||
T min = operator[](0);
|
||||
for (int i = 1; i < size; i++)
|
||||
for (bigint i = 1; i < size; i++)
|
||||
{
|
||||
if (operator[](i) < min)
|
||||
{
|
||||
@@ -104,7 +104,7 @@ template <class T>
|
||||
void Array<T>::PartialSum()
|
||||
{
|
||||
T sum = static_cast<T>(0);
|
||||
for (int i = 0; i < size; i++)
|
||||
for (bigint i = 0; i < size; i++)
|
||||
{
|
||||
sum+=operator[](i);
|
||||
operator[](i) = sum;
|
||||
@@ -116,9 +116,8 @@ void Array<T>::Abs()
|
||||
{
|
||||
static_assert(std::is_arithmetic<T>::value, "Use with arithmetic types!");
|
||||
const bool useDevice = UseDevice();
|
||||
const int N = size;
|
||||
auto y = ReadWrite(useDevice);
|
||||
mfem::forall_switch(useDevice, N, [=] MFEM_HOST_DEVICE (int i)
|
||||
mfem::forall_switch(useDevice, size, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
y[i] = std::abs(y[i]);
|
||||
});
|
||||
@@ -129,7 +128,7 @@ template <class T>
|
||||
T Array<T>::Sum() const
|
||||
{
|
||||
T sum = static_cast<T>(0);
|
||||
for (int i = 0; i < size; i++)
|
||||
for (bigint i = 0; i < size; i++)
|
||||
{
|
||||
sum+=operator[](i);
|
||||
}
|
||||
@@ -141,7 +140,7 @@ template <class T>
|
||||
int Array<T>::IsSorted() const
|
||||
{
|
||||
T val_prev = operator[](0), val;
|
||||
for (int i = 1; i < size; i++)
|
||||
for (bigint i = 1; i < size; i++)
|
||||
{
|
||||
val=operator[](i);
|
||||
if (val < val_prev)
|
||||
@@ -159,7 +158,7 @@ bool Array<T>::IsConstant() const
|
||||
{
|
||||
if (size < 2) { return true; }
|
||||
const T v0 = data[0];
|
||||
for (int i = 1; i < size; i++)
|
||||
for (bigint i = 1; i < size; i++)
|
||||
{
|
||||
if (data[i] != v0)
|
||||
{
|
||||
|
||||
+71
-69
@@ -50,9 +50,9 @@ protected:
|
||||
/// Pointer to data
|
||||
Memory<T> data;
|
||||
/// Size of the array
|
||||
int size;
|
||||
bigint size;
|
||||
|
||||
inline void GrowSize(int minsize);
|
||||
inline void GrowSize(bigint minsize);
|
||||
|
||||
static_assert(std::is_trivial<T>::value, "type T must be trivial");
|
||||
|
||||
@@ -68,11 +68,11 @@ public:
|
||||
inline Array(MemoryType mt) : data(mt), size(0) { }
|
||||
|
||||
/// Creates array of @a asize elements
|
||||
explicit inline Array(int asize)
|
||||
explicit inline Array(bigint asize)
|
||||
: size(asize) { if (asize > 0) { data.New(asize); } }
|
||||
|
||||
/// Creates array of @a asize elements with a given MemoryType
|
||||
inline Array(int asize, MemoryType mt)
|
||||
inline Array(bigint asize, MemoryType mt)
|
||||
: data(mt), size(asize) { if (asize > 0) { data.New(asize, mt); } }
|
||||
|
||||
/** @brief Creates array using an externally allocated host pointer @a data_
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
|
||||
When @a own_data is true, the pointer @a data_ must be allocated with
|
||||
MemoryType given by MemoryManager::GetHostMemoryType(). */
|
||||
inline Array(T *data_, int asize, bool own_data = false)
|
||||
inline Array(T *data_, bigint asize, bool own_data = false)
|
||||
{ data.Wrap(data_, asize, own_data); size = asize; }
|
||||
|
||||
/// Copy constructor: deep copy from @a src
|
||||
@@ -93,7 +93,7 @@ public:
|
||||
inline Array(const Array<CT> &src);
|
||||
|
||||
/// Construct an Array from a C-style array of static length
|
||||
template <typename CT, int N>
|
||||
template <typename CT, bigint N>
|
||||
explicit inline Array(const CT (&values)[N]);
|
||||
|
||||
/// Construct an Array from a braced initializer list of convertible type
|
||||
@@ -175,47 +175,47 @@ public:
|
||||
void MakeDataOwner() const { data.SetHostPtrOwner(true); }
|
||||
|
||||
/// Return the logical size of the array.
|
||||
inline int Size() const { return size; }
|
||||
inline bigint Size() const { return size; }
|
||||
|
||||
/// Change the logical size of the array, keep existing entries.
|
||||
inline void SetSize(int nsize);
|
||||
inline void SetSize(bigint nsize);
|
||||
|
||||
/// Same as SetSize(int) plus initialize new entries with 'initval'.
|
||||
inline void SetSize(int nsize, const T &initval);
|
||||
/// Same as SetSize(bigint) plus initialize new entries with 'initval'.
|
||||
inline void SetSize(bigint nsize, const T &initval);
|
||||
|
||||
/** @brief Resize the array to size @a nsize using MemoryType @a mt. Note
|
||||
that unlike the other versions of SetSize(), the current content of the
|
||||
array is not preserved. */
|
||||
inline void SetSize(int nsize, MemoryType mt);
|
||||
inline void SetSize(bigint nsize, MemoryType mt);
|
||||
|
||||
/** Maximum number of entries the array can store without allocating more
|
||||
memory. */
|
||||
inline int Capacity() const { return data.Capacity(); }
|
||||
inline bigint Capacity() const { return data.Capacity(); }
|
||||
|
||||
/// Ensures that the allocated size is at least the given size.
|
||||
inline void Reserve(int capacity)
|
||||
inline void Reserve(bigint capacity)
|
||||
{ if (capacity > Capacity()) { GrowSize(capacity); } }
|
||||
|
||||
/// Reference access to the ith element.
|
||||
inline T & operator[](int i);
|
||||
inline T & operator[](bigint i);
|
||||
|
||||
/// Const reference access to the ith element.
|
||||
inline const T &operator[](int i) const;
|
||||
inline const T &operator[](bigint i) const;
|
||||
|
||||
/// Append element 'el' to array, resize if necessary.
|
||||
inline int Append(const T & el);
|
||||
inline bigint Append(const T & el);
|
||||
|
||||
/// STL-like push_back. Append element 'el' to array, resize if necessary.
|
||||
void push_back(const T &el) { Append(el); }
|
||||
|
||||
/// Append another array to this array, resize if necessary.
|
||||
inline int Append(const T *els, int nels);
|
||||
inline bigint Append(const T *els, bigint nels);
|
||||
|
||||
/// Append another array to this array, resize if necessary.
|
||||
inline int Append(const Array<T> &els) { return Append(els, els.Size()); }
|
||||
inline bigint Append(const Array<T> &els) { return Append(els, els.Size()); }
|
||||
|
||||
/// Prepend an 'el' to the array, resize if necessary.
|
||||
inline int Prepend(const T &el);
|
||||
inline bigint Prepend(const T &el);
|
||||
|
||||
/// Return the last element in the array.
|
||||
inline T &Last();
|
||||
@@ -224,13 +224,13 @@ public:
|
||||
inline const T &Last() const;
|
||||
|
||||
/// Append element when it is not yet in the array, return index.
|
||||
inline int Union(const T & el);
|
||||
inline bigint Union(const T & el);
|
||||
|
||||
/// Return the first index where 'el' is found; return -1 if not found.
|
||||
inline int Find(const T &el) const;
|
||||
inline bigint Find(const T &el) const;
|
||||
|
||||
/// Do bisection search for 'el' in a sorted array; return -1 if not found.
|
||||
inline int FindSorted(const T &el) const;
|
||||
inline bigint FindSorted(const T &el) const;
|
||||
|
||||
/// Delete the last entry of the array.
|
||||
inline void DeleteLast() { if (size > 0) { size--; } }
|
||||
@@ -253,18 +253,18 @@ public:
|
||||
/// Make this Array a reference to a pointer.
|
||||
/** When @a own_data is true, the pointer @a data_ must be allocated with
|
||||
MemoryType given by MemoryManager::GetHostMemoryType(). */
|
||||
inline void MakeRef(T *data_, int size_, bool own_data = false);
|
||||
inline void MakeRef(T *data_, bigint size_, bool own_data = false);
|
||||
|
||||
/// Make this Array a reference to a pointer.
|
||||
/** When @a own_data is true, the pointer @a data_ must be allocated with
|
||||
MemoryType given by @a mt. */
|
||||
inline void MakeRef(T *data_, int size, MemoryType mt, bool own_data);
|
||||
inline void MakeRef(T *data_, bigint size, MemoryType mt, bool own_data);
|
||||
|
||||
/// Make this Array a reference to 'master'.
|
||||
inline void MakeRef(const Array &master);
|
||||
|
||||
/// Make this Array a reference to the given sub-Memory of @a base.
|
||||
inline void MakeRef(Memory<T> &base, int offset, int size_);
|
||||
inline void MakeRef(Memory<T> &base, bigint offset, bigint size_);
|
||||
|
||||
/// Reset the Array to use the given external Memory @a mem and size @a s.
|
||||
/** If @a own_mem is false, the Array will not own any of the pointers of
|
||||
@@ -273,7 +273,7 @@ public:
|
||||
Note that when @a own_mem is true, the @a mem object can be destroyed
|
||||
immediately by the caller but `mem.Delete()` should NOT be called since
|
||||
the Array object takes ownership of all pointers owned by @a mem. */
|
||||
inline void NewMemoryAndSize(const Memory<T> &mem, int s, bool own_mem);
|
||||
inline void NewMemoryAndSize(const Memory<T> &mem, bigint s, bool own_mem);
|
||||
|
||||
/**
|
||||
* @brief Permute the array using the provided indices. Sorts the indices
|
||||
@@ -289,7 +289,7 @@ public:
|
||||
inline void Permute(const I &indices) { Permute(I(indices)); }
|
||||
|
||||
/// Copy sub array starting from @a offset out to the provided @a sa.
|
||||
inline void GetSubArray(int offset, int sa_size, Array<T> &sa) const;
|
||||
inline void GetSubArray(bigint offset, bigint sa_size, Array<T> &sa) const;
|
||||
|
||||
/// Prints array to stream with width elements per row.
|
||||
void Print(std::ostream &out = mfem::out, int width = 4) const;
|
||||
@@ -312,7 +312,7 @@ public:
|
||||
|
||||
/** @brief Set the Array size to @a new_size and read that many entries from
|
||||
the stream @a in. */
|
||||
void Load(int new_size, std::istream &in)
|
||||
void Load(bigint new_size, std::istream &in)
|
||||
{ SetSize(new_size); Load(in, 1); }
|
||||
|
||||
/** @brief Find the maximal element in the array, using the comparison
|
||||
@@ -335,7 +335,7 @@ public:
|
||||
void Unique()
|
||||
{
|
||||
T* end = std::unique((T*)data, data + size);
|
||||
SetSize((int)(end - data));
|
||||
SetSize((bigint)(end - data));
|
||||
}
|
||||
|
||||
/// Return 1 if the array is sorted from lowest to highest. Otherwise return 0.
|
||||
@@ -421,7 +421,7 @@ template <class T>
|
||||
inline bool operator==(const Array<T> &LHS, const Array<T> &RHS)
|
||||
{
|
||||
if ( LHS.Size() != RHS.Size() ) { return false; }
|
||||
for (int i=0; i<LHS.Size(); i++)
|
||||
for (bigint i=0; i<LHS.Size(); i++)
|
||||
{
|
||||
if ( LHS[i] != RHS[i] ) { return false; }
|
||||
}
|
||||
@@ -451,13 +451,13 @@ public:
|
||||
Array2D() { M = N = 0; }
|
||||
|
||||
/// Construct an m x n 2D array.
|
||||
Array2D(int m, int n) : array1d(m*n) { M = m; N = n; }
|
||||
Array2D(int m, int n) : array1d(bigint(m)*n) { M = m; N = n; }
|
||||
|
||||
Array2D(const Array2D &) = default;
|
||||
Array2D(Array2D &&) = default;
|
||||
|
||||
/// Set the 2D array size to m x n.
|
||||
void SetSize(int m, int n) { array1d.SetSize(m*n); M = m; N = n; }
|
||||
void SetSize(int m, int n) { array1d.SetSize(bigint(m)*n); M = m; N = n; }
|
||||
|
||||
int NumRows() const { return M; }
|
||||
int NumCols() const { return N; }
|
||||
@@ -562,16 +562,16 @@ public:
|
||||
|
||||
/// Construct a 3D array of size n1 x n2 x n3.
|
||||
Array3D(int n1, int n2, int n3)
|
||||
: array1d(n1*n2*n3) { N2 = n2; N3 = n3; }
|
||||
: array1d(bigint(n1)*n2*n3) { N2 = n2; N3 = n3; }
|
||||
|
||||
/// Set the 3D array size to n1 x n2 x n3.
|
||||
void SetSize(int n1, int n2, int n3)
|
||||
{ array1d.SetSize(n1*n2*n3); N2 = n2; N3 = n3; }
|
||||
{ array1d.SetSize(bigint(n1)*n2*n3); N2 = n2; N3 = n3; }
|
||||
|
||||
/// Get the 3D array size in the first dimension.
|
||||
int GetSize1() const
|
||||
{
|
||||
const int size = array1d.Size();
|
||||
const bigint size = array1d.Size();
|
||||
return size == 0 ? 0 : size / (N2 * N3);
|
||||
}
|
||||
|
||||
@@ -779,7 +779,7 @@ inline Array<T>::Array(const Array<CT> &src)
|
||||
: size(src.Size())
|
||||
{
|
||||
size > 0 ? data.New(size) : data.Reset();
|
||||
for (int i = 0; i < size; i++) { (*this)[i] = T(src[i]); }
|
||||
for (bigint i = 0; i < size; i++) { (*this)[i] = T(src[i]); }
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -790,7 +790,7 @@ inline Array<T>::Array(std::initializer_list<CT> values) : Array(values.size())
|
||||
std::copy(values.begin(), values.end(), begin());
|
||||
}
|
||||
|
||||
template <typename T> template <typename CT, int N>
|
||||
template <typename T> template <typename CT, bigint N>
|
||||
inline Array<T>::Array(const CT (&values)[N]) : Array(N)
|
||||
{
|
||||
std::copy(values, values + N, begin());
|
||||
@@ -804,9 +804,9 @@ inline void Array<T>::Swap(Array &other)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void Array<T>::GrowSize(int minsize)
|
||||
inline void Array<T>::GrowSize(bigint minsize)
|
||||
{
|
||||
const int nsize = std::max(minsize, 2 * data.Capacity());
|
||||
const bigint nsize = std::max(minsize, 2 * data.Capacity());
|
||||
Memory<T> p(nsize, data.GetMemoryType());
|
||||
p.CopyFrom(data, size);
|
||||
p.UseDevice(data.UseDevice());
|
||||
@@ -829,7 +829,7 @@ template <typename T>
|
||||
template <typename I>
|
||||
inline void Array<T>::Permute(I &&indices)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
for (bigint i = 0; i < size; i++)
|
||||
{
|
||||
auto current = i;
|
||||
while (i != indices[current])
|
||||
@@ -847,12 +847,12 @@ template <typename T> template <typename CT>
|
||||
inline Array<T> &Array<T>::operator=(const Array<CT> &src)
|
||||
{
|
||||
SetSize(src.Size());
|
||||
for (int i = 0; i < size; i++) { (*this)[i] = T(src[i]); }
|
||||
for (bigint i = 0; i < size; i++) { (*this)[i] = T(src[i]); }
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void Array<T>::SetSize(int nsize)
|
||||
inline void Array<T>::SetSize(bigint nsize)
|
||||
{
|
||||
MFEM_ASSERT( nsize>=0, "Size must be non-negative. It is " << nsize );
|
||||
if (nsize > Capacity())
|
||||
@@ -863,7 +863,7 @@ inline void Array<T>::SetSize(int nsize)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void Array<T>::SetSize(int nsize, const T &initval)
|
||||
inline void Array<T>::SetSize(bigint nsize, const T &initval)
|
||||
{
|
||||
MFEM_ASSERT( nsize>=0, "Size must be non-negative. It is " << nsize );
|
||||
if (nsize > size)
|
||||
@@ -872,7 +872,7 @@ inline void Array<T>::SetSize(int nsize, const T &initval)
|
||||
{
|
||||
GrowSize(nsize);
|
||||
}
|
||||
for (int i = size; i < nsize; i++)
|
||||
for (bigint i = size; i < nsize; i++)
|
||||
{
|
||||
data[i] = initval;
|
||||
}
|
||||
@@ -881,7 +881,7 @@ inline void Array<T>::SetSize(int nsize, const T &initval)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void Array<T>::SetSize(int nsize, MemoryType mt)
|
||||
inline void Array<T>::SetSize(bigint nsize, MemoryType mt)
|
||||
{
|
||||
MFEM_ASSERT(nsize >= 0, "invalid new size: " << nsize);
|
||||
if (mt == data.GetMemoryType())
|
||||
@@ -908,7 +908,7 @@ inline void Array<T>::SetSize(int nsize, MemoryType mt)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T &Array<T>::operator[](int i)
|
||||
inline T &Array<T>::operator[](bigint i)
|
||||
{
|
||||
MFEM_ASSERT( i>=0 && i<size,
|
||||
"Access element " << i << " of array, size = " << size );
|
||||
@@ -916,7 +916,7 @@ inline T &Array<T>::operator[](int i)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline const T &Array<T>::operator[](int i) const
|
||||
inline const T &Array<T>::operator[](bigint i) const
|
||||
{
|
||||
MFEM_ASSERT( i>=0 && i<size,
|
||||
"Access element " << i << " of array, size = " << size );
|
||||
@@ -924,7 +924,7 @@ inline const T &Array<T>::operator[](int i) const
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline int Array<T>::Append(const T &el)
|
||||
inline bigint Array<T>::Append(const T &el)
|
||||
{
|
||||
SetSize(size+1);
|
||||
data[size-1] = el;
|
||||
@@ -932,12 +932,12 @@ inline int Array<T>::Append(const T &el)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline int Array<T>::Append(const T *els, int nels)
|
||||
inline bigint Array<T>::Append(const T *els, bigint nels)
|
||||
{
|
||||
const int old_size = size;
|
||||
const bigint old_size = size;
|
||||
|
||||
SetSize(size + nels);
|
||||
for (int i = 0; i < nels; i++)
|
||||
for (bigint i = 0; i < nels; i++)
|
||||
{
|
||||
data[old_size+i] = els[i];
|
||||
}
|
||||
@@ -945,10 +945,10 @@ inline int Array<T>::Append(const T *els, int nels)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline int Array<T>::Prepend(const T &el)
|
||||
inline bigint Array<T>::Prepend(const T &el)
|
||||
{
|
||||
SetSize(size+1);
|
||||
for (int i = size-1; i > 0; i--)
|
||||
for (bigint i = size-1; i > 0; i--)
|
||||
{
|
||||
data[i] = data[i-1];
|
||||
}
|
||||
@@ -971,9 +971,9 @@ inline const T &Array<T>::Last() const
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline int Array<T>::Union(const T &el)
|
||||
inline bigint Array<T>::Union(const T &el)
|
||||
{
|
||||
int i = 0;
|
||||
bigint i = 0;
|
||||
while ((i < size) && (data[i] != el)) { i++; }
|
||||
if (i == size)
|
||||
{
|
||||
@@ -983,9 +983,9 @@ inline int Array<T>::Union(const T &el)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline int Array<T>::Find(const T &el) const
|
||||
inline bigint Array<T>::Find(const T &el) const
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
for (bigint i = 0; i < size; i++)
|
||||
{
|
||||
if (data[i] == el) { return i; }
|
||||
}
|
||||
@@ -993,18 +993,18 @@ inline int Array<T>::Find(const T &el) const
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline int Array<T>::FindSorted(const T &el) const
|
||||
inline bigint Array<T>::FindSorted(const T &el) const
|
||||
{
|
||||
const T *begin = data, *end = begin + size;
|
||||
const T* first = std::lower_bound(begin, end, el);
|
||||
if (first == end || !(*first == el)) { return -1; }
|
||||
return (int)(first - begin);
|
||||
return (bigint)(first - begin);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void Array<T>::DeleteFirst(const T &el)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
for (bigint i = 0; i < size; i++)
|
||||
{
|
||||
if (data[i] == el)
|
||||
{
|
||||
@@ -1027,8 +1027,8 @@ inline void Array<T>::DeleteAt(const Array<int> &indices)
|
||||
Array<int> sorted_indices(indices);
|
||||
sorted_indices.Sort();
|
||||
|
||||
int rm_count = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
bigint rm_count = 0;
|
||||
for (bigint i = 0; i < size; i++)
|
||||
{
|
||||
if (rm_count < sorted_indices.Size() && i == sorted_indices[rm_count])
|
||||
{
|
||||
@@ -1065,7 +1065,7 @@ inline void Array<T>::Copy(Array ©) const
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void Array<T>::MakeRef(T *data_, int size_, bool own_data)
|
||||
inline void Array<T>::MakeRef(T *data_, bigint size_, bool own_data)
|
||||
{
|
||||
data.Delete();
|
||||
data.Wrap(data_, size_, own_data);
|
||||
@@ -1073,7 +1073,8 @@ inline void Array<T>::MakeRef(T *data_, int size_, bool own_data)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void Array<T>::MakeRef(T *data_, int size_, MemoryType mt, bool own_data)
|
||||
inline void Array<T>::MakeRef(T *data_, bigint size_, MemoryType mt,
|
||||
bool own_data)
|
||||
{
|
||||
data.Delete();
|
||||
data.Wrap(data_, size_, mt, own_data);
|
||||
@@ -1089,7 +1090,7 @@ inline void Array<T>::MakeRef(const Array &master)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void Array<T>::MakeRef(Memory<T> &base, int offset, int size_)
|
||||
inline void Array<T>::MakeRef(Memory<T> &base, bigint offset, bigint size_)
|
||||
{
|
||||
data.Delete();
|
||||
size = size_;
|
||||
@@ -1098,7 +1099,7 @@ inline void Array<T>::MakeRef(Memory<T> &base, int offset, int size_)
|
||||
|
||||
template <class T>
|
||||
inline void Array<T>::NewMemoryAndSize(
|
||||
const Memory<T> &mem, int s, bool own_mem)
|
||||
const Memory<T> &mem, bigint s, bool own_mem)
|
||||
{
|
||||
data.Delete();
|
||||
size = s;
|
||||
@@ -1113,10 +1114,11 @@ inline void Array<T>::NewMemoryAndSize(
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void Array<T>::GetSubArray(int offset, int sa_size, Array<T> &sa) const
|
||||
inline void Array<T>::GetSubArray(bigint offset, bigint sa_size,
|
||||
Array<T> &sa) const
|
||||
{
|
||||
sa.SetSize(sa_size);
|
||||
for (int i = 0; i < sa_size; i++)
|
||||
for (bigint i = 0; i < sa_size; i++)
|
||||
{
|
||||
sa[i] = (*this)[offset+i];
|
||||
}
|
||||
@@ -1125,7 +1127,7 @@ inline void Array<T>::GetSubArray(int offset, int sa_size, Array<T> &sa) const
|
||||
template <class T>
|
||||
inline void Array<T>::operator=(const T &a)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
for (bigint i = 0; i < size; i++)
|
||||
{
|
||||
data[i] = a;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,18 @@
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#if defined(__linux__)
|
||||
#include <sys/resource.h> // getrusage
|
||||
#include <unistd.h> // sysconf
|
||||
#include <cstdio> // fopen, fscanf, fclose
|
||||
#elif defined(__APPLE__)
|
||||
#include <mach/mach_init.h> // mach_task_self
|
||||
#include <mach/task.h> // task_info
|
||||
#elif defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include <psapi.h> // GetProcessMemoryInfo
|
||||
#pragma comment(lib, "psapi.lib")
|
||||
#endif
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
@@ -718,6 +730,52 @@ void Device::DeviceMem(size_t *free, size_t *total)
|
||||
#endif
|
||||
}
|
||||
|
||||
// static method
|
||||
void Device::HostMem(size_t *rss_p, size_t *maxrss_p)
|
||||
{
|
||||
size_t rss = 0, maxrss = 0;
|
||||
|
||||
#if defined(__linux__)
|
||||
struct rusage usage;
|
||||
if (getrusage(RUSAGE_SELF, &usage)) { usage.ru_maxrss = 0; }
|
||||
maxrss = 1024*usage.ru_maxrss;
|
||||
static const long PAGE_SIZE = sysconf(_SC_PAGESIZE);
|
||||
FILE *statm = fopen("/proc/self/statm", "r");
|
||||
if (statm)
|
||||
{
|
||||
// Values are measured in pages, see Table 1-3 at
|
||||
// https://www.kernel.org/doc/Documentation/filesystems/proc.txt
|
||||
long rss_pages;
|
||||
if (fscanf(statm, "%*d %ld", &rss_pages) == EOF) { rss_pages = 0; }
|
||||
fclose(statm);
|
||||
rss = rss_pages * PAGE_SIZE;
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
struct mach_task_basic_info info;
|
||||
mach_msg_type_number_t count = MACH_TASK_BASIC_INFO_COUNT;
|
||||
if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO,
|
||||
(task_info_t)&info, &count) == KERN_SUCCESS)
|
||||
{
|
||||
rss = info.resident_size;
|
||||
maxrss = info.resident_size_max;
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
PROCESS_MEMORY_COUNTERS mem_counters;
|
||||
if (GetProcessMemoryInfo(GetCurrentProcess(),
|
||||
&mem_counters,
|
||||
sizeof(mem_counters)))
|
||||
{
|
||||
// Reference:
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/psapi/ns-psapi-process_memory_counters
|
||||
rss = mem_counters.WorkingSetSize;
|
||||
maxrss = mem_counters.PeakWorkingSetSize;
|
||||
}
|
||||
#endif
|
||||
|
||||
*rss_p = rss;
|
||||
*maxrss_p = maxrss;
|
||||
}
|
||||
|
||||
std::string Device::GetUUID(const int device_id)
|
||||
{
|
||||
std::stringstream res;
|
||||
|
||||
+13
-9
@@ -321,6 +321,10 @@ public:
|
||||
|
||||
/** @brief Gets the @a free and @a total memory on the device. */
|
||||
static void DeviceMem(size_t *free, size_t *total);
|
||||
|
||||
/** @brief Gets the @a rss (resident set size) and @a maxrss (maximum
|
||||
resident set size) memory of the host process, in bytes. */
|
||||
static void HostMem(size_t *rss, size_t *maxrss);
|
||||
};
|
||||
|
||||
|
||||
@@ -349,14 +353,14 @@ inline MemoryClass GetMemoryClass(const Memory<T> &mem, bool on_dev)
|
||||
HostMemoryClass, otherwise. */
|
||||
/** Also, if @a on_dev = true, the device flag of @a mem will be set. */
|
||||
template <typename T>
|
||||
inline const T *Read(const Memory<T> &mem, int size, bool on_dev = true)
|
||||
inline const T *Read(const Memory<T> &mem, bigint size, bool on_dev = true)
|
||||
{
|
||||
return mem.Read(GetMemoryClass(mem, on_dev), size);
|
||||
}
|
||||
|
||||
/** @brief Shortcut to Read(const Memory<T> &mem, int size, false) */
|
||||
/** @brief Shortcut to Read(const Memory<T> &mem, bigint size, false) */
|
||||
template <typename T>
|
||||
inline const T *HostRead(const Memory<T> &mem, int size)
|
||||
inline const T *HostRead(const Memory<T> &mem, bigint size)
|
||||
{
|
||||
return mfem::Read(mem, size, false);
|
||||
}
|
||||
@@ -366,14 +370,14 @@ inline const T *HostRead(const Memory<T> &mem, int size)
|
||||
HostMemoryClass, otherwise. */
|
||||
/** Also, if @a on_dev = true, the device flag of @a mem will be set. */
|
||||
template <typename T>
|
||||
inline T *Write(Memory<T> &mem, int size, bool on_dev = true)
|
||||
inline T *Write(Memory<T> &mem, bigint size, bool on_dev = true)
|
||||
{
|
||||
return mem.Write(GetMemoryClass(mem, on_dev), size);
|
||||
}
|
||||
|
||||
/** @brief Shortcut to Write(const Memory<T> &mem, int size, false) */
|
||||
/** @brief Shortcut to Write(const Memory<T> &mem, bigint size, false) */
|
||||
template <typename T>
|
||||
inline T *HostWrite(Memory<T> &mem, int size)
|
||||
inline T *HostWrite(Memory<T> &mem, bigint size)
|
||||
{
|
||||
return mfem::Write(mem, size, false);
|
||||
}
|
||||
@@ -383,14 +387,14 @@ inline T *HostWrite(Memory<T> &mem, int size)
|
||||
HostMemoryClass, otherwise. */
|
||||
/** Also, if @a on_dev = true, the device flag of @a mem will be set. */
|
||||
template <typename T>
|
||||
inline T *ReadWrite(Memory<T> &mem, int size, bool on_dev = true)
|
||||
inline T *ReadWrite(Memory<T> &mem, bigint size, bool on_dev = true)
|
||||
{
|
||||
return mem.ReadWrite(GetMemoryClass(mem, on_dev), size);
|
||||
}
|
||||
|
||||
/** @brief Shortcut to ReadWrite(Memory<T> &mem, int size, false) */
|
||||
/** @brief Shortcut to ReadWrite(Memory<T> &mem, bigint size, false) */
|
||||
template <typename T>
|
||||
inline T *HostReadWrite(Memory<T> &mem, int size)
|
||||
inline T *HostReadWrite(Memory<T> &mem, bigint size)
|
||||
{
|
||||
return mfem::ReadWrite(mem, size, false);
|
||||
}
|
||||
|
||||
+2
-1
@@ -68,7 +68,8 @@ void mfem_error(const char *msg = NULL);
|
||||
__attribute__((enzyme_inactive))
|
||||
#endif
|
||||
void mfem_warning(const char *msg = NULL);
|
||||
}
|
||||
|
||||
} // namespace mfem
|
||||
|
||||
#ifndef _MFEM_FUNC_NAME
|
||||
#ifndef _MSC_VER
|
||||
|
||||
+33
-33
@@ -176,10 +176,10 @@ private:
|
||||
// with CUDA/HIP language. Otherwise, this macro is a no-op.
|
||||
#if defined(MFEM_USE_CUDA) && defined(__CUDACC__)
|
||||
#define MFEM_GPU_FORALL(i, N,...) CuWrap1D(N, [=] MFEM_DEVICE \
|
||||
(int i) {__VA_ARGS__})
|
||||
(bigint i) {__VA_ARGS__})
|
||||
#elif defined(MFEM_USE_HIP) && defined(__HIP__)
|
||||
#define MFEM_GPU_FORALL(i, N,...) HipWrap1D(N, [=] MFEM_DEVICE \
|
||||
(int i) {__VA_ARGS__})
|
||||
(bigint i) {__VA_ARGS__})
|
||||
#else
|
||||
#define MFEM_GPU_FORALL(i, N,...) do { } while (false)
|
||||
#endif
|
||||
@@ -189,7 +189,7 @@ private:
|
||||
|
||||
// The MFEM_FORALL wrapper
|
||||
#define MFEM_FORALL(i,N,...) \
|
||||
ForallWrap<1>(true,N,[=] MFEM_HOST_DEVICE (int i) {__VA_ARGS__})
|
||||
ForallWrap<1>(true,N,[=] MFEM_HOST_DEVICE (bigint i) {__VA_ARGS__})
|
||||
|
||||
// MFEM_FORALL with a 2D CUDA block
|
||||
#define MFEM_FORALL_2D(i,N,X,Y,BZ,...) \
|
||||
@@ -208,16 +208,16 @@ private:
|
||||
// example the functions in vector.cpp, where we don't want to use the mfem
|
||||
// device for operations on small vectors.
|
||||
#define MFEM_FORALL_SWITCH(use_dev,i,N,...) \
|
||||
ForallWrap<1>(use_dev,N,[=] MFEM_HOST_DEVICE (int i) {__VA_ARGS__})
|
||||
ForallWrap<1>(use_dev,N,[=] MFEM_HOST_DEVICE (bigint i) {__VA_ARGS__})
|
||||
|
||||
|
||||
/// OpenMP backend
|
||||
template <typename HBODY>
|
||||
void OmpWrap(const int N, HBODY &&h_body)
|
||||
void OmpWrap(const bigint N, HBODY &&h_body)
|
||||
{
|
||||
#ifdef MFEM_USE_OPENMP
|
||||
#pragma omp parallel for
|
||||
for (int k = 0; k < N; k++)
|
||||
for (bigint k = 0; k < N; k++)
|
||||
{
|
||||
h_body(k);
|
||||
}
|
||||
@@ -296,7 +296,7 @@ using hip_threads_z =
|
||||
|
||||
#if defined(MFEM_USE_RAJA) && defined(RAJA_ENABLE_CUDA) && defined(__CUDACC__)
|
||||
template <typename DBODY>
|
||||
void RajaCuWrap1D(const int N, DBODY &&d_body)
|
||||
void RajaCuWrap1D(const bigint N, DBODY &&d_body)
|
||||
{
|
||||
//true denotes asynchronous kernel
|
||||
RAJA::forall<RAJA::cuda_exec<MFEM_CUDA_BLOCKS,true>>(RAJA::RangeSegment(0,N),
|
||||
@@ -364,7 +364,7 @@ template <>
|
||||
struct RajaCuWrap<1>
|
||||
{
|
||||
template <typename DBODY>
|
||||
static void run(const int N, DBODY &&d_body,
|
||||
static void run(const bigint N, DBODY &&d_body,
|
||||
const int X, const int Y, const int Z, const int G)
|
||||
{
|
||||
RajaCuWrap1D(N, d_body);
|
||||
@@ -397,7 +397,7 @@ struct RajaCuWrap<3>
|
||||
|
||||
#if defined(MFEM_USE_RAJA) && defined(RAJA_ENABLE_HIP) && defined(__HIP__)
|
||||
template <typename DBODY>
|
||||
void RajaHipWrap1D(const int N, DBODY &&d_body)
|
||||
void RajaHipWrap1D(const bigint N, DBODY &&d_body)
|
||||
{
|
||||
//true denotes asynchronous kernel
|
||||
RAJA::forall<RAJA::hip_exec<MFEM_HIP_BLOCKS,true>>(RAJA::RangeSegment(0,N),
|
||||
@@ -465,7 +465,7 @@ template <>
|
||||
struct RajaHipWrap<1>
|
||||
{
|
||||
template <typename DBODY>
|
||||
static void run(const int N, DBODY &&d_body,
|
||||
static void run(const bigint N, DBODY &&d_body,
|
||||
const int X, const int Y, const int Z, const int G)
|
||||
{
|
||||
RajaHipWrap1D(N, d_body);
|
||||
@@ -500,7 +500,7 @@ struct RajaHipWrap<3>
|
||||
#if defined(MFEM_USE_RAJA) && defined(RAJA_ENABLE_OPENMP)
|
||||
|
||||
template <typename HBODY>
|
||||
void RajaOmpWrap(const int N, HBODY &&h_body)
|
||||
void RajaOmpWrap(const bigint N, HBODY &&h_body)
|
||||
{
|
||||
RAJA::forall<RAJA::omp_parallel_for_exec>(RAJA::RangeSegment(0,N), h_body);
|
||||
}
|
||||
@@ -546,7 +546,7 @@ void RajaOmpWrap3D(const int Nx, const int Ny, const int Nz, HBODY &&h_body)
|
||||
|
||||
/// RAJA sequential loop backend
|
||||
template <typename HBODY>
|
||||
void RajaSeqWrap(const int N, HBODY &&h_body)
|
||||
void RajaSeqWrap(const bigint N, HBODY &&h_body)
|
||||
{
|
||||
#ifdef MFEM_USE_RAJA
|
||||
|
||||
@@ -571,9 +571,9 @@ void RajaSeqWrap(const int N, HBODY &&h_body)
|
||||
#if defined(MFEM_USE_CUDA) && defined(__CUDACC__)
|
||||
|
||||
template <typename BODY> __global__ static
|
||||
void CuKernel1D(const int N, BODY body)
|
||||
void CuKernel1D(const bigint N, BODY body)
|
||||
{
|
||||
const int k = blockDim.x*blockIdx.x + threadIdx.x;
|
||||
const bigint k = bigint(blockDim.x)*blockIdx.x + threadIdx.x;
|
||||
if (k >= N) { return; }
|
||||
body(k);
|
||||
}
|
||||
@@ -612,10 +612,10 @@ static void CuKernel3DLaunchBounds(const int N, BODY body)
|
||||
}
|
||||
|
||||
template <const int BLCK = MFEM_CUDA_BLOCKS, typename DBODY>
|
||||
void CuWrap1D(const int N, DBODY &&d_body)
|
||||
void CuWrap1D(const bigint N, DBODY &&d_body)
|
||||
{
|
||||
if (N==0) { return; }
|
||||
const int GRID = (N+BLCK-1)/BLCK;
|
||||
const unsigned int GRID = (N+BLCK-1)/BLCK;
|
||||
CuKernel1D<<<GRID,BLCK>>>(N, d_body);
|
||||
MFEM_GPU_CHECK(cudaGetLastError());
|
||||
}
|
||||
@@ -676,7 +676,7 @@ template <int MAX_THREADS_PER_BLOCK>
|
||||
struct CuWrap<1, MAX_THREADS_PER_BLOCK>
|
||||
{
|
||||
template <typename DBODY>
|
||||
static void run(const int N, DBODY &&d_body,
|
||||
static void run(const bigint N, DBODY &&d_body,
|
||||
const int X, const int Y, const int Z, const int G)
|
||||
{
|
||||
CuWrap1D<MFEM_CUDA_BLOCKS>(N, d_body);
|
||||
@@ -735,9 +735,9 @@ struct CuWrap<3, MAX_THREADS_PER_BLOCK>
|
||||
#if defined(MFEM_USE_HIP) && defined(__HIP__)
|
||||
|
||||
template <typename BODY> __global__ static
|
||||
void HipKernel1D(const int N, BODY body)
|
||||
void HipKernel1D(const bigint N, BODY body)
|
||||
{
|
||||
const int k = hipBlockDim_x*hipBlockIdx_x + hipThreadIdx_x;
|
||||
const bigint k = bigint(hipBlockDim_x)*hipBlockIdx_x + hipThreadIdx_x;
|
||||
if (k >= N) { return; }
|
||||
body(k);
|
||||
}
|
||||
@@ -775,10 +775,10 @@ static void HipKernel3DLaunchBounds(const int N, BODY body)
|
||||
}
|
||||
|
||||
template <int BLCK = MFEM_HIP_BLOCKS, typename DBODY>
|
||||
void HipWrap1D(const int N, DBODY &&d_body)
|
||||
void HipWrap1D(const bigint N, DBODY &&d_body)
|
||||
{
|
||||
if (N==0) { return; }
|
||||
const int GRID = (N+BLCK-1)/BLCK;
|
||||
const unsigned int GRID = (N+BLCK-1)/BLCK;
|
||||
hipLaunchKernelGGL(HipKernel1D,GRID,BLCK,0,nullptr,N,d_body);
|
||||
MFEM_GPU_CHECK(hipGetLastError());
|
||||
}
|
||||
@@ -839,7 +839,7 @@ template <int MAX_THREADS_PER_BLOCK>
|
||||
struct HipWrap<1, MAX_THREADS_PER_BLOCK>
|
||||
{
|
||||
template <typename DBODY>
|
||||
static void run(const int N, DBODY &&d_body,
|
||||
static void run(const bigint N, DBODY &&d_body,
|
||||
const int X, const int Y, const int Z, const int G)
|
||||
{
|
||||
HipWrap1D<MFEM_HIP_BLOCKS>(N, d_body);
|
||||
@@ -897,7 +897,7 @@ struct HipWrap<3, MAX_THREADS_PER_BLOCK>
|
||||
/// Forall host & device kernel dispatch
|
||||
template <int DIM, int MAX_THREADS_PER_BLOCK = 0,
|
||||
typename d_lambda, typename h_lambda>
|
||||
inline void ForallWrap(const bool use_dev, const int N,
|
||||
inline void ForallWrap(const bool use_dev, const bigint N,
|
||||
d_lambda &&d_body, h_lambda &&h_body,
|
||||
const int X=0, const int Y=0, const int Z=0,
|
||||
const int G=0)
|
||||
@@ -963,13 +963,13 @@ backend_cpu:
|
||||
// Handle Backend::CPU. This is also a fallback for any allowed backends not
|
||||
// handled above, e.g. OCCA_CPU with configuration 'occa-cpu,cpu', or
|
||||
// OCCA_OMP with configuration 'occa-omp,cpu'.
|
||||
for (int k = 0; k < N; k++) { h_body(k); }
|
||||
for (bigint k = 0; k < N; k++) { h_body(k); }
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Forall host & device kernel wrappers
|
||||
template <int DIM, typename lambda>
|
||||
inline void ForallWrap(const bool use_dev, const int N, lambda &&body,
|
||||
inline void ForallWrap(const bool use_dev, const bigint N, lambda &&body,
|
||||
const int X=0, const int Y=0, const int Z=0,
|
||||
const int G=0)
|
||||
{
|
||||
@@ -977,7 +977,7 @@ inline void ForallWrap(const bool use_dev, const int N, lambda &&body,
|
||||
}
|
||||
|
||||
template <int DIM, int MAX_THREADS_PER_BLOCK, typename lambda>
|
||||
inline void ForallWrap(const bool use_dev, const int N, lambda &&body,
|
||||
inline void ForallWrap(const bool use_dev, const bigint N, lambda &&body,
|
||||
const int X=0, const int Y=0, const int Z=0,
|
||||
const int G=0)
|
||||
{
|
||||
@@ -987,14 +987,14 @@ inline void ForallWrap(const bool use_dev, const int N, lambda &&body,
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// forall interfaces
|
||||
template<typename lambda>
|
||||
inline void forall(int N, lambda &&body) { ForallWrap<1>(true, N, body); }
|
||||
inline void forall(bigint N, lambda &&body) { ForallWrap<1>(true, N, body); }
|
||||
|
||||
template<typename lambda>
|
||||
inline void forall(int Nx, int Ny, lambda &&body)
|
||||
{
|
||||
if (Device::Allows(Backend::DEVICE_MASK))
|
||||
{
|
||||
mfem::forall(Nx * Ny, [=] MFEM_HOST_DEVICE(int idx)
|
||||
mfem::forall(bigint(Nx) * Ny, [=] MFEM_HOST_DEVICE(bigint idx)
|
||||
{
|
||||
int j = idx / Nx;
|
||||
int i = idx % Nx;
|
||||
@@ -1030,12 +1030,12 @@ inline void forall(int Nx, int Ny, int Nz, lambda &&body)
|
||||
{
|
||||
if (Device::Allows(Backend::DEVICE_MASK))
|
||||
{
|
||||
mfem::forall(Nx * Ny * Nz, [=] MFEM_HOST_DEVICE(int idx)
|
||||
mfem::forall(bigint(Nx) * Ny * Nz, [=] MFEM_HOST_DEVICE(bigint idx)
|
||||
{
|
||||
int i = idx % Nx;
|
||||
int j = idx / Nx;
|
||||
int k = j / Ny;
|
||||
j = j % Ny;
|
||||
bigint jk = idx / Nx;
|
||||
int k = jk / Ny;
|
||||
int j = jk % Ny;
|
||||
body(i, j, k);
|
||||
});
|
||||
}
|
||||
@@ -1067,7 +1067,7 @@ inline void forall(int Nx, int Ny, int Nz, lambda &&body)
|
||||
}
|
||||
|
||||
template<typename lambda>
|
||||
inline void forall_switch(bool use_dev, int N, lambda &&body)
|
||||
inline void forall_switch(bool use_dev, bigint N, lambda &&body)
|
||||
{
|
||||
ForallWrap<1>(use_dev, N, body);
|
||||
}
|
||||
|
||||
@@ -150,8 +150,8 @@ template void Memory<int>::PrintFlags() const;
|
||||
template void Memory<real_t>::PrintFlags() const;
|
||||
|
||||
// Instantiate Memory<T>::CompareHostAndDevice for T = int and T = real_t.
|
||||
template int Memory<int>::CompareHostAndDevice(int size) const;
|
||||
template int Memory<real_t>::CompareHostAndDevice(int size) const;
|
||||
template int Memory<int>::CompareHostAndDevice(bigint size) const;
|
||||
template int Memory<real_t>::CompareHostAndDevice(bigint size) const;
|
||||
|
||||
|
||||
namespace internal
|
||||
|
||||
+46
-44
@@ -197,7 +197,7 @@ protected:
|
||||
/** The type of the pointer is given by the field #h_mt; it can be any type
|
||||
from MemoryClass::HOST. */
|
||||
T *h_ptr;
|
||||
int capacity; ///< Size of the allocated memory
|
||||
bigint capacity; ///< Size of the allocated memory
|
||||
MemoryType h_mt; ///< Host memory type
|
||||
mutable unsigned flags; ///< Bit flags defined from the #FlagMask enum
|
||||
// 'flags' is mutable so that it can be modified in Set{Host,Device}PtrOwner,
|
||||
@@ -236,7 +236,7 @@ public:
|
||||
/// Allocate host memory for @a size entries.
|
||||
/** The allocation uses the current host memory type returned by
|
||||
MemoryManager::GetHostMemoryType(). */
|
||||
explicit Memory(int size) { New(size); }
|
||||
explicit Memory(bigint size) { New(size); }
|
||||
|
||||
/// Creates a new empty Memory object with host MemoryType @a mt.
|
||||
explicit Memory(MemoryType mt) { Reset(mt); }
|
||||
@@ -245,19 +245,20 @@ public:
|
||||
@a mt. */
|
||||
/** The newly allocated memory is not initialized, however the given
|
||||
MemoryType is still set as valid. */
|
||||
Memory(int size, MemoryType mt) { New(size, mt); }
|
||||
Memory(bigint size, MemoryType mt) { New(size, mt); }
|
||||
|
||||
/** @brief Allocate memory for @a size entries with the given host MemoryType
|
||||
@a h_mt and device MemoryType @a d_mt. */
|
||||
/** The newly allocated memory is not initialized. The host pointer is set as
|
||||
valid. */
|
||||
Memory(int size, MemoryType h_mt, MemoryType d_mt) { New(size, h_mt, d_mt); }
|
||||
Memory(bigint size, MemoryType h_mt, MemoryType d_mt)
|
||||
{ New(size, h_mt, d_mt); }
|
||||
|
||||
/** @brief Wrap an externally allocated host pointer, @a ptr with the current
|
||||
host memory type returned by MemoryManager::GetHostMemoryType(). */
|
||||
/** The parameter @a own determines whether @a ptr will be deleted when the
|
||||
method Delete() is called. */
|
||||
explicit Memory(T *ptr, int size, bool own) { Wrap(ptr, size, own); }
|
||||
explicit Memory(T *ptr, bigint size, bool own) { Wrap(ptr, size, own); }
|
||||
|
||||
/// Wrap an externally allocated pointer, @a ptr, of the given MemoryType.
|
||||
/** The new memory object will have the given MemoryType set as valid.
|
||||
@@ -267,13 +268,13 @@ public:
|
||||
|
||||
The parameter @a own determines whether @a ptr will be deleted when the
|
||||
method Delete() is called. */
|
||||
Memory(T *ptr, int size, MemoryType mt, bool own)
|
||||
Memory(T *ptr, bigint size, MemoryType mt, bool own)
|
||||
{ Wrap(ptr, size, mt, own); }
|
||||
|
||||
/** @brief Alias constructor. Create a Memory object that points inside the
|
||||
Memory object @a base. */
|
||||
/** The new Memory object uses the same MemoryType(s) as @a base. */
|
||||
Memory(const Memory &base, int offset, int size)
|
||||
Memory(const Memory &base, bigint offset, bigint size)
|
||||
{ MakeAlias(base, offset, size); }
|
||||
|
||||
/// Destructor: default.
|
||||
@@ -319,7 +320,7 @@ public:
|
||||
{ flags = use_dev ? (flags | USE_DEVICE) : (flags & ~USE_DEVICE); }
|
||||
|
||||
/// Return the size of the allocated memory.
|
||||
int Capacity() const { return capacity; }
|
||||
bigint Capacity() const { return capacity; }
|
||||
|
||||
/// Reset the memory to be empty, ensuring that Delete() will be a no-op.
|
||||
/** This is the Memory class equivalent to setting a pointer to NULL, see
|
||||
@@ -339,7 +340,7 @@ public:
|
||||
/** @brief Allocate host memory for @a size entries with the current host
|
||||
memory type returned by MemoryManager::GetHostMemoryType(). */
|
||||
/** @note The current memory is NOT deleted by this method. */
|
||||
inline void New(int size);
|
||||
inline void New(bigint size);
|
||||
|
||||
/// Allocate memory for @a size entries with the given MemoryType.
|
||||
/** The newly allocated memory is not initialized, however the given
|
||||
@@ -353,7 +354,7 @@ public:
|
||||
to be the dual of @a mt, see MemoryManager::GetDualMemoryType().
|
||||
|
||||
@note The current memory is NOT deleted by this method. */
|
||||
inline void New(int size, MemoryType mt);
|
||||
inline void New(bigint size, MemoryType mt);
|
||||
|
||||
/** @brief Allocate memory for @a size entries with the given host MemoryType
|
||||
@a h_mt and device MemoryType @a d_mt. */
|
||||
@@ -361,7 +362,7 @@ public:
|
||||
valid.
|
||||
|
||||
@note The current memory is NOT deleted by this method. */
|
||||
inline void New(int size, MemoryType h_mt, MemoryType d_mt);
|
||||
inline void New(bigint size, MemoryType h_mt, MemoryType d_mt);
|
||||
|
||||
/** @brief Wrap an externally allocated host pointer, @a ptr with the current
|
||||
host memory type returned by MemoryManager::GetHostMemoryType(). */
|
||||
@@ -369,7 +370,7 @@ public:
|
||||
method Delete() is called.
|
||||
|
||||
@note The current memory is NOT deleted by this method. */
|
||||
inline void Wrap(T *ptr, int size, bool own);
|
||||
inline void Wrap(T *ptr, bigint size, bool own);
|
||||
|
||||
/// Wrap an externally allocated pointer, @a ptr, of the given MemoryType.
|
||||
/** The new memory object will have the given MemoryType set as valid.
|
||||
@@ -381,7 +382,7 @@ public:
|
||||
method Delete() is called.
|
||||
|
||||
@note The current memory is NOT deleted by this method. */
|
||||
inline void Wrap(T *ptr, int size, MemoryType mt, bool own);
|
||||
inline void Wrap(T *ptr, bigint size, MemoryType mt, bool own);
|
||||
|
||||
/** Wrap an externally pair of allocated pointers, @a h_ptr and @a d_ptr,
|
||||
of the given host MemoryType @a h_mt. */
|
||||
@@ -405,14 +406,14 @@ public:
|
||||
- SetDevicePtrOwner.
|
||||
|
||||
@note The current memory is NOT deleted by this method. */
|
||||
inline void Wrap(T *h_ptr, T *d_ptr, int size, MemoryType h_mt, bool own,
|
||||
inline void Wrap(T *h_ptr, T *d_ptr, bigint size, MemoryType h_mt, bool own,
|
||||
bool valid_host = false, bool valid_device = true);
|
||||
|
||||
/// Create a memory object that points inside the memory object @a base.
|
||||
/** The new Memory object uses the same MemoryType(s) as @a base.
|
||||
|
||||
@note The current memory is NOT deleted by this method. */
|
||||
inline void MakeAlias(const Memory &base, int offset, int size);
|
||||
inline void MakeAlias(const Memory &base, bigint offset, bigint size);
|
||||
|
||||
/// Set the device MemoryType to be used by the Memory object.
|
||||
/** If the specified @a d_mt is not a device MemoryType, i.e. not one of the
|
||||
@@ -437,10 +438,10 @@ public:
|
||||
inline void DeleteDevice(bool copy_to_host = true);
|
||||
|
||||
/// Array subscript operator for host memory.
|
||||
inline T &operator[](int idx);
|
||||
inline T &operator[](bigint idx);
|
||||
|
||||
/// Array subscript operator for host memory, const version.
|
||||
inline const T &operator[](int idx) const;
|
||||
inline const T &operator[](bigint idx) const;
|
||||
|
||||
/// Direct access to the host memory as T* (implicit conversion).
|
||||
/** When the type T is const-qualified, this method can be used only if the
|
||||
@@ -492,11 +493,11 @@ public:
|
||||
Read() or Write() should be used instead of this method.
|
||||
|
||||
The parameter @a size must not exceed the Capacity(). */
|
||||
inline T *ReadWrite(MemoryClass mc, int size);
|
||||
inline T *ReadWrite(MemoryClass mc, bigint size);
|
||||
|
||||
/// Get read-only access to the memory with the given MemoryClass.
|
||||
/** The parameter @a size must not exceed the Capacity(). */
|
||||
inline const T *Read(MemoryClass mc, int size) const;
|
||||
inline const T *Read(MemoryClass mc, bigint size) const;
|
||||
|
||||
/// Get write-only access to the memory with the given MemoryClass.
|
||||
/** The parameter @a size must not exceed the Capacity().
|
||||
@@ -504,7 +505,7 @@ public:
|
||||
The contents of the returned pointer is undefined, unless it was
|
||||
validated by a previous call to Read() or ReadWrite() with
|
||||
the same MemoryClass. */
|
||||
inline T *Write(MemoryClass mc, int size);
|
||||
inline T *Write(MemoryClass mc, bigint size);
|
||||
|
||||
/// Copy the host/device pointer validity flags from @a other to @a *this.
|
||||
/** This method synchronizes the pointer validity flags of two Memory objects
|
||||
@@ -521,7 +522,7 @@ public:
|
||||
of the base incorrect. Calling this method will ensure that @a base is
|
||||
up-to-date. Note that this is achieved by moving/copying @a *this (if
|
||||
necessary), and not @a base. */
|
||||
inline void SyncAlias(const Memory &base, int alias_size) const;
|
||||
inline void SyncAlias(const Memory &base, bigint alias_size) const;
|
||||
|
||||
/** @brief Return a MemoryType that is currently valid. If both the host and
|
||||
the device pointers are currently valid, then the device memory type is
|
||||
@@ -544,20 +545,20 @@ public:
|
||||
/// Copy @a size entries from @a src to @a *this.
|
||||
/** The given @a size should not exceed the Capacity() of the source @a src
|
||||
and the destination, @a *this. */
|
||||
inline void CopyFrom(const Memory &src, int size);
|
||||
inline void CopyFrom(const Memory &src, bigint size);
|
||||
|
||||
/// Copy @a size entries from the host pointer @a src to @a *this.
|
||||
/** The given @a size should not exceed the Capacity() of @a *this. */
|
||||
inline void CopyFromHost(const T *src, int size);
|
||||
inline void CopyFromHost(const T *src, bigint size);
|
||||
|
||||
/// Copy @a size entries from @a *this to @a dest.
|
||||
/** The given @a size should not exceed the Capacity() of @a *this and the
|
||||
destination, @a dest. */
|
||||
inline void CopyTo(Memory &dest, int size) const;
|
||||
inline void CopyTo(Memory &dest, bigint size) const;
|
||||
|
||||
/// Copy @a size entries from @a *this to the host pointer @a dest.
|
||||
/** The given @a size should not exceed the Capacity() of @a *this. */
|
||||
inline void CopyToHost(T *dest, int size) const;
|
||||
inline void CopyToHost(T *dest, bigint size) const;
|
||||
|
||||
/// Print the internal flags.
|
||||
/** This method can be useful for debugging. It is explicitly instantiated
|
||||
@@ -567,7 +568,7 @@ public:
|
||||
/// If both the host and the device data are valid, compare their contents.
|
||||
/** This method can be useful for debugging. It is explicitly instantiated
|
||||
for Memory<T> with T = int and T = real_t. */
|
||||
inline int CompareHostAndDevice(int size) const;
|
||||
inline int CompareHostAndDevice(bigint size) const;
|
||||
|
||||
private:
|
||||
// GCC 4.8 workaround: max_align_t is not in std.
|
||||
@@ -956,7 +957,7 @@ inline void Memory<T>::Reset(MemoryType host_mt)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void Memory<T>::New(int size)
|
||||
inline void Memory<T>::New(bigint size)
|
||||
{
|
||||
capacity = size;
|
||||
flags = OWNS_HOST | VALID_HOST;
|
||||
@@ -966,7 +967,7 @@ inline void Memory<T>::New(int size)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void Memory<T>::New(int size, MemoryType mt)
|
||||
inline void Memory<T>::New(bigint size, MemoryType mt)
|
||||
{
|
||||
capacity = size;
|
||||
const size_t bytes = size*sizeof(T);
|
||||
@@ -978,7 +979,8 @@ inline void Memory<T>::New(int size, MemoryType mt)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void Memory<T>::New(int size, MemoryType host_mt, MemoryType device_mt)
|
||||
inline void Memory<T>::New(bigint size, MemoryType host_mt,
|
||||
MemoryType device_mt)
|
||||
{
|
||||
capacity = size;
|
||||
const size_t bytes = size*sizeof(T);
|
||||
@@ -989,7 +991,7 @@ inline void Memory<T>::New(int size, MemoryType host_mt, MemoryType device_mt)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void Memory<T>::Wrap(T *ptr, int size, bool own)
|
||||
inline void Memory<T>::Wrap(T *ptr, bigint size, bool own)
|
||||
{
|
||||
h_ptr = ptr;
|
||||
capacity = size;
|
||||
@@ -1011,7 +1013,7 @@ inline void Memory<T>::Wrap(T *ptr, int size, bool own)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void Memory<T>::Wrap(T *ptr, int size, MemoryType mt, bool own)
|
||||
inline void Memory<T>::Wrap(T *ptr, bigint size, MemoryType mt, bool own)
|
||||
{
|
||||
capacity = size;
|
||||
if (IsHostMemory(mt))
|
||||
@@ -1036,7 +1038,7 @@ inline void Memory<T>::Wrap(T *ptr, int size, MemoryType mt, bool own)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void Memory<T>::Wrap(T *h_ptr_, T *d_ptr, int size, MemoryType h_mt_,
|
||||
inline void Memory<T>::Wrap(T *h_ptr_, T *d_ptr, bigint size, MemoryType h_mt_,
|
||||
bool own, bool valid_host, bool valid_device)
|
||||
{
|
||||
h_mt = h_mt_;
|
||||
@@ -1053,7 +1055,7 @@ inline void Memory<T>::Wrap(T *h_ptr_, T *d_ptr, int size, MemoryType h_mt_,
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void Memory<T>::MakeAlias(const Memory &base, int offset, int size)
|
||||
inline void Memory<T>::MakeAlias(const Memory &base, bigint offset, bigint size)
|
||||
{
|
||||
MFEM_ASSERT(0 <= offset, "invalid offset = " << offset);
|
||||
MFEM_ASSERT(0 <= size, "invalid size = " << size);
|
||||
@@ -1140,7 +1142,7 @@ inline void Memory<T>::DeleteDevice(bool copy_to_host)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T &Memory<T>::operator[](int idx)
|
||||
inline T &Memory<T>::operator[](bigint idx)
|
||||
{
|
||||
MFEM_ASSERT((flags & VALID_HOST) && !(flags & VALID_DEVICE),
|
||||
"invalid host pointer access");
|
||||
@@ -1148,7 +1150,7 @@ inline T &Memory<T>::operator[](int idx)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline const T &Memory<T>::operator[](int idx) const
|
||||
inline const T &Memory<T>::operator[](bigint idx) const
|
||||
{
|
||||
MFEM_ASSERT((flags & VALID_HOST), "invalid host pointer access");
|
||||
return h_ptr[idx];
|
||||
@@ -1189,7 +1191,7 @@ inline Memory<T>::operator const U*() const
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T *Memory<T>::ReadWrite(MemoryClass mc, int size)
|
||||
inline T *Memory<T>::ReadWrite(MemoryClass mc, bigint size)
|
||||
{
|
||||
const size_t bytes = size * sizeof(T);
|
||||
if (!(flags & Registered))
|
||||
@@ -1202,7 +1204,7 @@ inline T *Memory<T>::ReadWrite(MemoryClass mc, int size)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline const T *Memory<T>::Read(MemoryClass mc, int size) const
|
||||
inline const T *Memory<T>::Read(MemoryClass mc, bigint size) const
|
||||
{
|
||||
const size_t bytes = size * sizeof(T);
|
||||
if (!(flags & Registered))
|
||||
@@ -1215,7 +1217,7 @@ inline const T *Memory<T>::Read(MemoryClass mc, int size) const
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T *Memory<T>::Write(MemoryClass mc, int size)
|
||||
inline T *Memory<T>::Write(MemoryClass mc, bigint size)
|
||||
{
|
||||
const size_t bytes = size * sizeof(T);
|
||||
if (!(flags & Registered))
|
||||
@@ -1242,7 +1244,7 @@ inline void Memory<T>::Sync(const Memory &other) const
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void Memory<T>::SyncAlias(const Memory &base, int alias_size) const
|
||||
inline void Memory<T>::SyncAlias(const Memory &base, bigint alias_size) const
|
||||
{
|
||||
// Assuming that if *this is registered then base is also registered.
|
||||
MFEM_ASSERT(!(flags & Registered) || (base.flags & Registered),
|
||||
@@ -1279,7 +1281,7 @@ inline bool Memory<T>::DeviceIsValid() const
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void Memory<T>::CopyFrom(const Memory &src, int size)
|
||||
inline void Memory<T>::CopyFrom(const Memory &src, bigint size)
|
||||
{
|
||||
MFEM_VERIFY(src.capacity>=size && capacity>=size, "Incorrect size");
|
||||
if (size <= 0) { return; }
|
||||
@@ -1300,7 +1302,7 @@ inline void Memory<T>::CopyFrom(const Memory &src, int size)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void Memory<T>::CopyFromHost(const T *src, int size)
|
||||
inline void Memory<T>::CopyFromHost(const T *src, bigint size)
|
||||
{
|
||||
MFEM_VERIFY(capacity>=size, "Incorrect size");
|
||||
if (size <= 0) { return; }
|
||||
@@ -1321,13 +1323,13 @@ inline void Memory<T>::CopyFromHost(const T *src, int size)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void Memory<T>::CopyTo(Memory &dest, int size) const
|
||||
inline void Memory<T>::CopyTo(Memory &dest, bigint size) const
|
||||
{
|
||||
dest.CopyFrom(*this, size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void Memory<T>::CopyToHost(T *dest, int size) const
|
||||
inline void Memory<T>::CopyToHost(T *dest, bigint size) const
|
||||
{
|
||||
MFEM_VERIFY(capacity>=size, "Incorrect size");
|
||||
if (size <= 0) { return; }
|
||||
@@ -1359,7 +1361,7 @@ inline void Memory<T>::PrintFlags() const
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int Memory<T>::CompareHostAndDevice(int size) const
|
||||
inline int Memory<T>::CompareHostAndDevice(bigint size) const
|
||||
{
|
||||
if (!(flags & VALID_HOST) || !(flags & VALID_DEVICE)) { return 0; }
|
||||
return MemoryManager::CompareHostAndDevice_(h_ptr, size*sizeof(T), flags);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "error.hpp"
|
||||
#include "stable3d.hpp"
|
||||
#include <limits>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -90,6 +91,8 @@ int STable3D::Push (int r, int c, int f)
|
||||
node->Prev = Rows[r];
|
||||
Rows[r] = node;
|
||||
|
||||
MFEM_VERIFY(NElem != std::numeric_limits<int>::max(),
|
||||
"integer overflow error");
|
||||
NElem++;
|
||||
return (NElem-1);
|
||||
}
|
||||
|
||||
+240
-88
@@ -18,6 +18,7 @@
|
||||
#include "../general/mem_manager.hpp"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
@@ -27,6 +28,8 @@ using namespace std;
|
||||
Table::Table(const Table &table1,
|
||||
const Table &table2, int offset)
|
||||
{
|
||||
MFEM_VERIFY(!table1.UsingBigI() && !table2.UsingBigI(), "");
|
||||
|
||||
MFEM_ASSERT(table1.size == table2.size,
|
||||
"Tables have different sizes can not merge.");
|
||||
size = table1.size;
|
||||
@@ -60,6 +63,9 @@ Table::Table(const Table &table1,
|
||||
const Table &table2, int offset2,
|
||||
const Table &table3, int offset3)
|
||||
{
|
||||
MFEM_VERIFY(!table1.UsingBigI() && !table2.UsingBigI() &&
|
||||
!table3.UsingBigI(), "");
|
||||
|
||||
MFEM_ASSERT(table1.size == table2.size,
|
||||
"Tables have different sizes can not merge.");
|
||||
MFEM_ASSERT(table1.size == table3.size,
|
||||
@@ -98,17 +104,30 @@ Table::Table(const Table &table1,
|
||||
|
||||
Table::Table (int dim, int connections_per_row)
|
||||
{
|
||||
int i, j, sum = dim * connections_per_row;
|
||||
bigint sum = bigint(dim) * connections_per_row;
|
||||
|
||||
size = dim;
|
||||
I.SetSize(size+1);
|
||||
J.SetSize(sum);
|
||||
|
||||
I[0] = 0;
|
||||
for (i = 1; i <= size; i++)
|
||||
if (int(sum) == sum)
|
||||
{
|
||||
I[i] = I[i-1] + connections_per_row;
|
||||
for (j = I[i-1]; j < I[i]; j++) { J[j] = -1; }
|
||||
I.SetSize(size+1);
|
||||
J.SetSize(sum);
|
||||
I[0] = 0;
|
||||
for (int i = 1; i <= size; i++)
|
||||
{
|
||||
I[i] = I[i-1] + connections_per_row;
|
||||
for (int j = I[i-1]; j < I[i]; j++) { J[j] = -1; }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bigI.SetSize(size+1);
|
||||
J.SetSize(sum);
|
||||
bigI[0] = 0;
|
||||
for (int i = 1; i <= size; i++)
|
||||
{
|
||||
bigI[i] = bigI[i-1] + connections_per_row;
|
||||
for (bigint j = bigI[i-1]; j < bigI[i]; j++) { J[j] = -1; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,77 +158,153 @@ void Table::MakeI(int nrows)
|
||||
|
||||
void Table::MakeJ()
|
||||
{
|
||||
int i, j, k;
|
||||
bigint nnz;
|
||||
|
||||
for (k = i = 0; i < size; i++)
|
||||
if (!UsingBigI())
|
||||
{
|
||||
j = I[i], I[i] = k, k += j;
|
||||
nnz = 0;
|
||||
int nnz_int = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
const int row_size = I[i];
|
||||
I[i] = nnz_int;
|
||||
nnz_int += row_size;
|
||||
nnz += row_size;
|
||||
if (nnz_int != nnz) // check for overflow
|
||||
{
|
||||
bigI.SetSize(size+1);
|
||||
for (int j = 0; j <= i; j++) { bigI[j] = I[j]; }
|
||||
for (i++ ; i < size; i++)
|
||||
{
|
||||
bigI[i] = nnz;
|
||||
nnz += I[i];
|
||||
}
|
||||
bigI[size] = nnz;
|
||||
I.DeleteAll();
|
||||
goto I_is_updated;
|
||||
}
|
||||
}
|
||||
I[size] = nnz_int;
|
||||
nnz = nnz_int;
|
||||
I_is_updated: ;
|
||||
}
|
||||
else
|
||||
{
|
||||
nnz = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
const bigint row_size = bigI[i];
|
||||
bigI[i] = nnz;
|
||||
nnz += row_size;
|
||||
}
|
||||
bigI[size] = nnz;
|
||||
}
|
||||
|
||||
J.SetSize(I[size]=k);
|
||||
J.SetSize(nnz);
|
||||
}
|
||||
|
||||
void Table::AddConnections(int r, const int *c, int nc)
|
||||
{
|
||||
int *jp = J+I[r];
|
||||
int *jp = GetRow(r);
|
||||
|
||||
for (int i = 0; i < nc; i++)
|
||||
{
|
||||
jp[i] = c[i];
|
||||
}
|
||||
I[r] += nc;
|
||||
UsingBigI() ? bigI[r] += nc : I[r] += nc;
|
||||
}
|
||||
|
||||
void Table::ShiftUpI()
|
||||
{
|
||||
for (int i = size; i > 0; i--)
|
||||
if (!UsingBigI())
|
||||
{
|
||||
I[i] = I[i-1];
|
||||
for (int i = size; i > 0; i--)
|
||||
{
|
||||
I[i] = I[i-1];
|
||||
}
|
||||
I[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = size; i > 0; i--)
|
||||
{
|
||||
bigI[i] = bigI[i-1];
|
||||
}
|
||||
bigI[0] = 0;
|
||||
}
|
||||
I[0] = 0;
|
||||
}
|
||||
|
||||
void Table::SetSize(int dim, int connections_per_row)
|
||||
{
|
||||
SetDims (dim, dim * connections_per_row);
|
||||
SetDims(dim, bigint(dim) * connections_per_row);
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
I[0] = 0;
|
||||
for (int i = 0, j = 0; i < size; i++)
|
||||
if (!UsingBigI())
|
||||
{
|
||||
int end = I[i] + connections_per_row;
|
||||
I[i+1] = end;
|
||||
for ( ; j < end; j++) { J[j] = -1; }
|
||||
I[0] = 0;
|
||||
for (int i = 0, j = 0; i < size; i++)
|
||||
{
|
||||
int end = I[i] + connections_per_row;
|
||||
I[i+1] = end;
|
||||
for ( ; j < end; j++) { J[j] = -1; }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bigint j = 0;
|
||||
bigI[0] = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
bigint end = bigI[i] + connections_per_row;
|
||||
bigI[i+1] = end;
|
||||
for ( ; j < end; j++) { J[j] = -1; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Table::SetDims(int rows, int nnz)
|
||||
void Table::SetDims(int rows, bigint nnz)
|
||||
{
|
||||
int j;
|
||||
|
||||
j = (I) ? (I[size]) : (0);
|
||||
if (size != rows)
|
||||
const bool new_use_big_i = (bigint(int(nnz)) != nnz);
|
||||
if (size != rows || new_use_big_i != UsingBigI())
|
||||
{
|
||||
size = rows;
|
||||
(rows >= 0) ? I.SetSize(rows+1) : I.DeleteAll();
|
||||
if (new_use_big_i != UsingBigI())
|
||||
{
|
||||
UsingBigI() ? bigI.DeleteAll() : I.DeleteAll();
|
||||
}
|
||||
if (size >= 0)
|
||||
{
|
||||
new_use_big_i ? bigI.SetSize(size+1) : I.SetSize(size+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
new_use_big_i ? bigI.DeleteAll() : I.DeleteAll();
|
||||
}
|
||||
}
|
||||
|
||||
if (j != nnz)
|
||||
{
|
||||
(nnz > 0) ? J.SetSize(nnz) : J.DeleteAll();
|
||||
}
|
||||
(nnz > 0) ? J.SetSize(nnz) : J.DeleteAll();
|
||||
|
||||
if (size >= 0)
|
||||
{
|
||||
I[0] = 0;
|
||||
I[size] = nnz;
|
||||
if (!UsingBigI())
|
||||
{
|
||||
I[0] = 0;
|
||||
I[size] = int(nnz);
|
||||
}
|
||||
else
|
||||
{
|
||||
bigI[0] = 0;
|
||||
bigI[size] = nnz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Table::operator()(int i, int j) const
|
||||
{
|
||||
MFEM_VERIFY(!UsingBigI(), "");
|
||||
|
||||
if ( i>=size || i<0 )
|
||||
{
|
||||
return -1;
|
||||
@@ -236,7 +331,8 @@ void Table::GetRow(int i, Array<int> &row) const
|
||||
<< size << ')');
|
||||
|
||||
HostReadJ();
|
||||
HostReadI();
|
||||
if (UsingBigI()) { HostReadBigI(); }
|
||||
else { HostReadI(); }
|
||||
|
||||
row.SetSize(RowSize(i));
|
||||
row.Assign(GetRow(i));
|
||||
@@ -244,14 +340,25 @@ void Table::GetRow(int i, Array<int> &row) const
|
||||
|
||||
void Table::SortRows()
|
||||
{
|
||||
for (int r = 0; r < size; r++)
|
||||
if (!UsingBigI())
|
||||
{
|
||||
std::sort(J + I[r], J + I[r+1]);
|
||||
for (int r = 0; r < size; r++)
|
||||
{
|
||||
std::sort(J.GetData()+I[r], J.GetData()+I[r+1]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int r = 0; r < size; r++)
|
||||
{
|
||||
std::sort(J.GetData()+bigI[r], J.GetData()+bigI[r+1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Table::SetIJ(int *newI, int *newJ, int newsize)
|
||||
{
|
||||
if (UsingBigI()) { bigI.DeleteAll(); }
|
||||
if (newsize >= 0)
|
||||
{
|
||||
size = newsize;
|
||||
@@ -262,6 +369,8 @@ void Table::SetIJ(int *newI, int *newJ, int newsize)
|
||||
|
||||
int Table::Push(int i, int j)
|
||||
{
|
||||
MFEM_VERIFY(!UsingBigI(), "");
|
||||
|
||||
MFEM_ASSERT(i >=0 &&
|
||||
i<size, "Index out of bounds. i = " << i << " size " << size);
|
||||
|
||||
@@ -286,6 +395,8 @@ int Table::Push(int i, int j)
|
||||
|
||||
void Table::Finalize()
|
||||
{
|
||||
MFEM_VERIFY(!UsingBigI(), "");
|
||||
|
||||
int i, j, end, sum = 0, n = 0, newI = 0;
|
||||
|
||||
for (i=0; i<I[size]; i++)
|
||||
@@ -324,14 +435,16 @@ void Table::MakeFromList(int nrows, const Array<Connection> &list)
|
||||
Clear();
|
||||
|
||||
size = nrows;
|
||||
int nnz = list.Size();
|
||||
const bigint nnz = list.Size();
|
||||
const bool use_big_i = (bigint(int(nnz)) != nnz);
|
||||
|
||||
I.SetSize(size+1);
|
||||
use_big_i ? bigI.SetSize(size+1) : I.SetSize(size+1);
|
||||
J.SetSize(nnz);
|
||||
|
||||
for (int i = 0, k = 0; i <= size; i++)
|
||||
bigint k = 0;
|
||||
for (int i = 0; i <= size; i++)
|
||||
{
|
||||
I[i] = k;
|
||||
use_big_i ? bigI[i] = k : I[i] = int(k);
|
||||
while (k < nnz && list[k].from == i)
|
||||
{
|
||||
J[k] = list[k].to;
|
||||
@@ -342,30 +455,25 @@ void Table::MakeFromList(int nrows, const Array<Connection> &list)
|
||||
|
||||
int Table::Width() const
|
||||
{
|
||||
int width = -1, nnz = (size >= 0) ? I[size] : 0;
|
||||
for (int k = 0; k < nnz; k++)
|
||||
{
|
||||
if (J[k] > width) { width = J[k]; }
|
||||
}
|
||||
return width + 1;
|
||||
return (J.Size() > 0) ? J.Max() + 1 : 0;
|
||||
}
|
||||
|
||||
void Table::Print(std::ostream & os, int width) const
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
os << "[row " << i << "]\n";
|
||||
for (j = I[i]; j < I[i+1]; j++)
|
||||
const int row_size = RowSize(i);
|
||||
const int *row = GetRow(i);
|
||||
for (int j = 0; j < row_size; j++)
|
||||
{
|
||||
os << setw(5) << J[j];
|
||||
if ( !((j+1-I[i]) % width) )
|
||||
os << setw(5) << row[j];
|
||||
if ( !((j+1) % width) )
|
||||
{
|
||||
os << '\n';
|
||||
}
|
||||
}
|
||||
if ((j-I[i]) % width)
|
||||
if (row_size % width)
|
||||
{
|
||||
os << '\n';
|
||||
}
|
||||
@@ -378,9 +486,11 @@ void Table::PrintMatlab(std::ostream & os) const
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
for (j = I[i]; j < I[i+1]; j++)
|
||||
const int row_size = RowSize(i);
|
||||
const int *row = GetRow(i);
|
||||
for (j = 0; j < row_size; j++)
|
||||
{
|
||||
os << i << " " << J[j] << " 1. \n";
|
||||
os << i << " " << row[j] << " 1. \n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,35 +501,51 @@ void Table::Save(std::ostream &os) const
|
||||
{
|
||||
os << size << '\n';
|
||||
|
||||
for (int i = 0; i <= size; i++)
|
||||
if (!UsingBigI())
|
||||
{
|
||||
os << I[i] << '\n';
|
||||
I.Save(os, 1);
|
||||
}
|
||||
for (int i = 0, nnz = I[size]; i < nnz; i++)
|
||||
else
|
||||
{
|
||||
os << J[i] << '\n';
|
||||
bigI.Save(os, 1);
|
||||
}
|
||||
J.Save(os, 1);
|
||||
}
|
||||
|
||||
void Table::Load(std::istream &in)
|
||||
{
|
||||
Clear();
|
||||
|
||||
in >> size;
|
||||
I.SetSize(size+1);
|
||||
for (int i = 0; i <= size; i++)
|
||||
{
|
||||
in >> I[i];
|
||||
}
|
||||
int nnz = I[size];
|
||||
J.SetSize(nnz);
|
||||
for (int j = 0; j < nnz; j++)
|
||||
{
|
||||
in >> J[j];
|
||||
bigint big_offset;
|
||||
in >> big_offset;
|
||||
const int offset = int(big_offset);
|
||||
if (bigint(offset) != big_offset)
|
||||
{
|
||||
// switch to using bigI instead of I
|
||||
bigI.SetSize(size+1);
|
||||
for (int j = 0; j < i; j++) { bigI[j] = I[j]; }
|
||||
I.DeleteAll();
|
||||
bigI[i] = big_offset;
|
||||
for (i++; i <= size; i++)
|
||||
{
|
||||
in >> bigI[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
I[i] = offset;
|
||||
}
|
||||
J.SetSize(UsingBigI() ? bigI[size] : I[size]);
|
||||
J.Load(in, 1);
|
||||
}
|
||||
|
||||
void Table::Clear()
|
||||
{
|
||||
I.DeleteAll();
|
||||
bigI.DeleteAll();
|
||||
J.DeleteAll();
|
||||
size = -1;
|
||||
}
|
||||
@@ -436,50 +562,72 @@ void Table::Swap(Table & other)
|
||||
|
||||
std::size_t Table::MemoryUsage() const
|
||||
{
|
||||
if (size < 0 || I == NULL) { return 0; }
|
||||
return (size+1 + I[size]) * sizeof(int);
|
||||
return I.MemoryUsage() + bigI.MemoryUsage() + J.MemoryUsage();
|
||||
}
|
||||
|
||||
void Transpose(const Table &A, Table &At, int ncols_A_)
|
||||
template <typename TI, typename TJ>
|
||||
void TransposeImpl(const TI *i_A, const TJ *j_A, const TJ nrows_A,
|
||||
const TJ ncols_A, const TI nnz_A, TI *i_At, TJ *j_At)
|
||||
{
|
||||
const int *i_A = A.GetI();
|
||||
const int *j_A = A.GetJ();
|
||||
const int nrows_A = A.Size();
|
||||
const int ncols_A = (ncols_A_ < 0) ? A.Width() : ncols_A_;
|
||||
const int nnz_A = i_A[nrows_A];
|
||||
|
||||
At.SetDims (ncols_A, nnz_A);
|
||||
|
||||
int *i_At = At.GetI();
|
||||
int *j_At = At.GetJ();
|
||||
|
||||
for (int i = 0; i <= ncols_A; i++)
|
||||
for (TJ i = 0; i <= ncols_A; i++)
|
||||
{
|
||||
i_At[i] = 0;
|
||||
}
|
||||
for (int i = 0; i < nnz_A; i++)
|
||||
for (TI i = 0; i < nnz_A; i++)
|
||||
{
|
||||
i_At[j_A[i]+1]++;
|
||||
}
|
||||
for (int i = 1; i < ncols_A; i++)
|
||||
for (TJ i = 1; i < ncols_A; i++)
|
||||
{
|
||||
i_At[i+1] += i_At[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < nrows_A; i++)
|
||||
for (TJ i = 0; i < nrows_A; i++)
|
||||
{
|
||||
for (int j = i_A[i]; j < i_A[i+1]; j++)
|
||||
for (TI j = i_A[i]; j < i_A[i+1]; j++)
|
||||
{
|
||||
j_At[i_At[j_A[j]]++] = i;
|
||||
}
|
||||
}
|
||||
for (int i = ncols_A; i > 0; i--)
|
||||
for (TJ i = ncols_A; i > 0; i--)
|
||||
{
|
||||
i_At[i] = i_At[i-1];
|
||||
}
|
||||
i_At[0] = 0;
|
||||
}
|
||||
|
||||
void Transpose(const Table &A, Table &At, int ncols_A_)
|
||||
{
|
||||
const int *j_A = A.HostReadJ();
|
||||
const int nrows_A = A.Size();
|
||||
const int ncols_A = (ncols_A_ < 0) ? A.Width() : ncols_A_;
|
||||
|
||||
if (!A.UsingBigI())
|
||||
{
|
||||
const int *i_A = A.HostReadI();
|
||||
const int nnz_A = i_A[nrows_A];
|
||||
|
||||
At.SetDims(ncols_A, nnz_A);
|
||||
|
||||
int *i_At = At.HostWriteI();
|
||||
int *j_At = At.HostWriteJ();
|
||||
|
||||
TransposeImpl(i_A, j_A, nrows_A, ncols_A, nnz_A, i_At, j_At);
|
||||
}
|
||||
else
|
||||
{
|
||||
const bigint *i_A = A.HostReadBigI();
|
||||
const bigint nnz_A = i_A[nrows_A];
|
||||
|
||||
At.SetDims(ncols_A, nnz_A);
|
||||
|
||||
bigint *i_At = At.HostWriteBigI();
|
||||
int *j_At = At.HostWriteJ();
|
||||
|
||||
TransposeImpl(i_A, j_A, nrows_A, ncols_A, nnz_A, i_At, j_At);
|
||||
}
|
||||
}
|
||||
|
||||
Table * Transpose(const Table &A)
|
||||
{
|
||||
Table * At = new Table;
|
||||
@@ -504,6 +652,8 @@ void Transpose(const Array<int> &A, Table &At, int ncols_A_)
|
||||
|
||||
void Mult(const Table &A, const Table &B, Table &C)
|
||||
{
|
||||
MFEM_VERIFY(!A.UsingBigI() && !B.UsingBigI(), "");
|
||||
|
||||
int i, j, k, l, m;
|
||||
const int *i_A = A.GetI();
|
||||
const int *j_A = A.GetJ();
|
||||
@@ -641,6 +791,8 @@ int DSTable::Push_(int r, int c)
|
||||
n->Index = NumEntries;
|
||||
n->Prev = Rows[r];
|
||||
Rows[r] = n;
|
||||
MFEM_VERIFY(NumEntries != std::numeric_limits<int>::max(),
|
||||
"integer overflow error");
|
||||
return (NumEntries++);
|
||||
}
|
||||
|
||||
|
||||
+95
-19
@@ -42,6 +42,7 @@ struct Connection
|
||||
class Table
|
||||
{
|
||||
protected:
|
||||
// FIXME: this member can mess up the default move ctor ?!!
|
||||
int size; ///< The number of TYPE I elements.
|
||||
|
||||
/// @name Arrays for the connectivity information in the CSR storage.
|
||||
@@ -50,6 +51,10 @@ protected:
|
||||
/// The length of the I array is 'size + 1',
|
||||
Array<int> I;
|
||||
|
||||
/** @brief Alternative to the I array. Used when the number of connections
|
||||
overflows the int type. */
|
||||
Array<bigint> bigI;
|
||||
|
||||
/// @brief The length of the J array is equal to the number of connections
|
||||
/// between TYPE I and TYPE II elements.
|
||||
Array<int> J;
|
||||
@@ -83,21 +88,25 @@ public:
|
||||
/// @name Used together with the default constructor
|
||||
/// @{
|
||||
void MakeI(int nrows);
|
||||
void AddAColumnInRow(int r) { I[r]++; }
|
||||
void AddColumnsInRow(int r, int ncol) { I[r] += ncol; }
|
||||
void AddAColumnInRow(int r) { UsingBigI() ? bigI[r]++ : I[r]++; }
|
||||
void AddColumnsInRow (int r, int ncol)
|
||||
{ UsingBigI() ? bigI[r] += ncol : I[r] += ncol; }
|
||||
void MakeJ();
|
||||
void AddConnection(int r, int c) { J[I[r]++] = c; }
|
||||
void AddConnection (int r, int c)
|
||||
{ UsingBigI() ? J[bigI[r]++] = c : J[I[r]++] = c; }
|
||||
void AddConnections(int r, const int *c, int nc);
|
||||
void ShiftUpI();
|
||||
/// @}
|
||||
|
||||
bool UsingBigI() const { return !bigI.IsEmpty(); }
|
||||
|
||||
/// Set the size and the number of connections for the table.
|
||||
void SetSize(int dim, int connections_per_row);
|
||||
|
||||
/// @brief Set the rows and the number of all connections for the table.
|
||||
///
|
||||
/// Does NOT initialize the whole array I ! (I[0]=0 and I[rows]=nnz only)
|
||||
void SetDims(int rows, int nnz);
|
||||
void SetDims(int rows, bigint nnz);
|
||||
|
||||
/// Returns the number of TYPE I elements.
|
||||
inline int Size() const { return size; }
|
||||
@@ -107,7 +116,7 @@ public:
|
||||
/// If Finalize() is not called, it returns the number of possible
|
||||
/// connections established by the used constructor. Otherwise, it is exactly
|
||||
/// the number of established connections after calling Finalize(). */
|
||||
inline int Size_of_connections() const { return J.Size(); }
|
||||
inline bigint Size_of_connections() const { return J.Size(); }
|
||||
|
||||
/// @brief Returns index of the connection between element i of TYPE I and
|
||||
/// element j of TYPE II.
|
||||
@@ -119,27 +128,94 @@ public:
|
||||
/// Return row i in array row (the Table must be finalized)
|
||||
void GetRow(int i, Array<int> &row) const;
|
||||
|
||||
int RowSize(int i) const { return I[i+1] - I[i]; }
|
||||
int RowSize(int i) const
|
||||
{ return UsingBigI() ? int(bigI[i+1]-bigI[i]): I[i+1]-I[i]; }
|
||||
|
||||
const int *GetRow(int i) const { return J.GetMemory() + I[i]; }
|
||||
int *GetRow(int i) { return J.GetMemory() + I[i]; }
|
||||
const int *GetRow(int i) const
|
||||
{ return UsingBigI() ? J.GetData()+bigI[i] : J.GetData()+I[i]; }
|
||||
|
||||
int *GetRow(int i)
|
||||
{ return UsingBigI() ? J.GetData()+bigI[i] : J.GetData()+I[i]; }
|
||||
|
||||
int *GetI()
|
||||
{
|
||||
MFEM_ASSERT(!UsingBigI(), "");
|
||||
return I.GetData();
|
||||
}
|
||||
|
||||
int *GetI() { return I.GetData(); }
|
||||
int *GetJ() { return J.GetData(); }
|
||||
const int *GetI() const { return I.GetData(); }
|
||||
|
||||
const int *GetI() const
|
||||
{
|
||||
MFEM_ASSERT(!UsingBigI(), "");
|
||||
return I.GetData();
|
||||
}
|
||||
|
||||
const int *GetJ() const { return J.GetData(); }
|
||||
|
||||
Memory<int> &GetIMemory() { return I.GetMemory(); }
|
||||
Memory<int> &GetIMemory()
|
||||
{ MFEM_ASSERT(!UsingBigI(), ""); return I.GetMemory(); }
|
||||
|
||||
Memory<int> &GetJMemory() { return J.GetMemory(); }
|
||||
const Memory<int> &GetIMemory() const { return I.GetMemory(); }
|
||||
|
||||
const Memory<int> &GetIMemory() const
|
||||
{ MFEM_ASSERT(!UsingBigI(), ""); return I.GetMemory(); }
|
||||
|
||||
const Memory<int> &GetJMemory() const { return J.GetMemory(); }
|
||||
|
||||
const int *ReadI(bool on_dev = true) const { return I.Read(on_dev); }
|
||||
int *WriteI(bool on_dev = true) { return I.Write(on_dev); }
|
||||
int *ReadWriteI(bool on_dev = true) { return I.ReadWrite(on_dev); }
|
||||
const int *HostReadI() const { return I.HostRead(); }
|
||||
int *HostWriteI() { return I.HostWrite(); }
|
||||
int *HostReadWriteI() { return I.HostReadWrite(); }
|
||||
const int *ReadI(bool on_dev = true) const
|
||||
{
|
||||
MFEM_ASSERT(!UsingBigI(), "");
|
||||
return I.Read(on_dev);
|
||||
}
|
||||
|
||||
int *WriteI(bool on_dev = true)
|
||||
{
|
||||
MFEM_ASSERT(!UsingBigI(), "");
|
||||
return I.Write(on_dev);
|
||||
}
|
||||
|
||||
int *ReadWriteI(bool on_dev = true)
|
||||
{
|
||||
MFEM_ASSERT(!UsingBigI(), "");
|
||||
return I.ReadWrite(on_dev);
|
||||
}
|
||||
|
||||
const int *HostReadI() const
|
||||
{
|
||||
MFEM_ASSERT(!UsingBigI(), "");
|
||||
return I.HostRead();
|
||||
}
|
||||
|
||||
int *HostWriteI()
|
||||
{
|
||||
MFEM_ASSERT(!UsingBigI(), "");
|
||||
return I.HostWrite();
|
||||
}
|
||||
|
||||
int *HostReadWriteI()
|
||||
{
|
||||
MFEM_ASSERT(!UsingBigI(), "");
|
||||
return I.HostReadWrite();
|
||||
}
|
||||
|
||||
const bigint *HostReadBigI() const
|
||||
{
|
||||
MFEM_ASSERT(UsingBigI(), "");
|
||||
return bigI.HostRead();
|
||||
}
|
||||
|
||||
bigint *HostWriteBigI()
|
||||
{
|
||||
MFEM_ASSERT(UsingBigI(), "");
|
||||
return bigI.HostWrite();
|
||||
}
|
||||
|
||||
bigint *HostReadWriteBigI()
|
||||
{
|
||||
MFEM_ASSERT(UsingBigI(), "");
|
||||
return bigI.HostReadWrite();
|
||||
}
|
||||
|
||||
const int *ReadJ(bool on_dev = true) const { return J.Read(on_dev); }
|
||||
int *WriteJ(bool on_dev = true) { return J.Write(on_dev); }
|
||||
@@ -181,7 +257,7 @@ public:
|
||||
int Width() const;
|
||||
|
||||
/// Releases ownership of and null-ifies the data.
|
||||
void LoseData() { size = -1; I.LoseData(); J.LoseData(); }
|
||||
void LoseData() { size = -1; I.LoseData(); bigI.LoseData(); J.LoseData(); }
|
||||
|
||||
/// Prints the table to the stream @a out.
|
||||
void Print(std::ostream & out = mfem::out, int width = 4) const;
|
||||
|
||||
+12
-12
@@ -24,13 +24,14 @@ class TensorInd
|
||||
{
|
||||
public:
|
||||
MFEM_HOST_DEVICE
|
||||
static inline int result(const int* sizes, T first, Args... args)
|
||||
static inline bigint result(const int* sizes, T first, Args... args)
|
||||
{
|
||||
#if !(defined(MFEM_USE_CUDA) || defined(MFEM_USE_HIP))
|
||||
MFEM_ASSERT(first<sizes[N-1],"Trying to access out of boundary.");
|
||||
#endif
|
||||
return static_cast<int>(first + sizes[N - 1] * TensorInd < N + 1, Dim, Args... >
|
||||
::result(sizes, args...));
|
||||
return static_cast<bigint>(
|
||||
first + sizes[N - 1] * TensorInd < N + 1, Dim, Args... >
|
||||
::result(sizes, args...));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -40,13 +41,13 @@ class TensorInd<Dim, Dim, T, Args...>
|
||||
{
|
||||
public:
|
||||
MFEM_HOST_DEVICE
|
||||
static inline int result(const int* sizes, T first, Args... args)
|
||||
static inline bigint result(const int* sizes, T first, Args... args)
|
||||
{
|
||||
#if !(defined(MFEM_USE_CUDA) || defined(MFEM_USE_HIP))
|
||||
MFEM_ASSERT(first<static_cast<T>(sizes[Dim-1]),
|
||||
"Trying to access out of boundary.");
|
||||
#endif
|
||||
return static_cast<int>(first);
|
||||
return static_cast<bigint>(first);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -57,7 +58,7 @@ class Init
|
||||
{
|
||||
public:
|
||||
MFEM_HOST_DEVICE
|
||||
static inline int result(int* sizes, T first, Args... args)
|
||||
static inline bigint result(int* sizes, T first, Args... args)
|
||||
{
|
||||
sizes[N - 1] = first;
|
||||
return first * Init < N + 1, Dim, Args... >::result(sizes, args...);
|
||||
@@ -70,10 +71,10 @@ class Init<Dim, Dim, T, Args...>
|
||||
{
|
||||
public:
|
||||
MFEM_HOST_DEVICE
|
||||
static inline int result(int* sizes, T first, Args... args)
|
||||
static inline bigint result(int* sizes, T first, Args... args)
|
||||
{
|
||||
sizes[Dim - 1] = first;
|
||||
return first;
|
||||
return static_cast<bigint>(first);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -83,7 +84,7 @@ template<int Dim, typename Scalar = real_t>
|
||||
class DeviceTensor
|
||||
{
|
||||
protected:
|
||||
int capacity;
|
||||
bigint capacity;
|
||||
Scalar *data;
|
||||
int sizes[Dim];
|
||||
|
||||
@@ -99,8 +100,7 @@ public:
|
||||
{
|
||||
static_assert(sizeof...(args) == Dim, "Wrong number of arguments");
|
||||
// Initialize sizes, and compute the number of values
|
||||
const long int nb = Init<1, Dim, Args...>::result(sizes, args...);
|
||||
capacity = nb;
|
||||
capacity = Init<1, Dim, Args...>::result(sizes, args...);
|
||||
data = (capacity > 0) ? data_ : nullptr;
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ public:
|
||||
}
|
||||
|
||||
/// Subscript operator where the tensor is viewed as a 1D array.
|
||||
MFEM_HOST_DEVICE inline Scalar& operator[](int i) const
|
||||
MFEM_HOST_DEVICE inline Scalar& operator[](bigint i) const
|
||||
{
|
||||
return data[i];
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@ namespace mfem
|
||||
|
||||
void ParticleVector::GrowSize(int min_num_vectors, bool keep_data)
|
||||
{
|
||||
const int nsize = std::max(min_num_vectors*vdim, 2 * data.Capacity());
|
||||
const bigint nsize = std::max(bigint(min_num_vectors)*vdim,
|
||||
2 * data.Capacity());
|
||||
Memory<real_t> p(nsize, data.GetMemoryType());
|
||||
if (keep_data) { p.CopyFrom(data, size); }
|
||||
p.UseDevice(data.UseDevice());
|
||||
|
||||
+161
-111
@@ -107,7 +107,7 @@ static Array<DevicePair<real_t, real_t>> &Lpvector_workspace()
|
||||
|
||||
Vector::Vector(const Vector &v)
|
||||
{
|
||||
const int s = v.Size();
|
||||
const bigint s = v.Size();
|
||||
size = s;
|
||||
if (s > 0)
|
||||
{
|
||||
@@ -126,10 +126,8 @@ Vector::Vector(Vector &&v)
|
||||
|
||||
void Vector::Load(std::istream **in, int np, int *dim)
|
||||
{
|
||||
int i, j, s;
|
||||
|
||||
s = 0;
|
||||
for (i = 0; i < np; i++)
|
||||
bigint s = 0;
|
||||
for (int i = 0; i < np; i++)
|
||||
{
|
||||
s += dim[i];
|
||||
}
|
||||
@@ -137,10 +135,10 @@ void Vector::Load(std::istream **in, int np, int *dim)
|
||||
SetSize(s);
|
||||
HostWrite();
|
||||
|
||||
int p = 0;
|
||||
for (i = 0; i < np; i++)
|
||||
bigint p = 0;
|
||||
for (int i = 0; i < np; i++)
|
||||
{
|
||||
for (j = 0; j < dim[i]; j++)
|
||||
for (int j = 0; j < dim[i]; j++)
|
||||
{
|
||||
*in[i] >> data[p++];
|
||||
// Clang's libc++ sets the failbit when (correctly) parsing subnormals,
|
||||
@@ -153,12 +151,12 @@ void Vector::Load(std::istream **in, int np, int *dim)
|
||||
}
|
||||
}
|
||||
|
||||
void Vector::Load(std::istream &in, int Size)
|
||||
void Vector::Load(std::istream &in, bigint Size)
|
||||
{
|
||||
SetSize(Size);
|
||||
HostWrite();
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
for (bigint i = 0; i < size; i++)
|
||||
{
|
||||
in >> data[i];
|
||||
// Clang's libc++ sets the failbit when (correctly) parsing subnormals,
|
||||
@@ -170,12 +168,12 @@ void Vector::Load(std::istream &in, int Size)
|
||||
}
|
||||
}
|
||||
|
||||
real_t &Vector::Elem(int i)
|
||||
real_t &Vector::Elem(bigint i)
|
||||
{
|
||||
return operator()(i);
|
||||
}
|
||||
|
||||
const real_t &Vector::Elem(int i) const
|
||||
const real_t &Vector::Elem(bigint i) const
|
||||
{
|
||||
return operator()(i);
|
||||
}
|
||||
@@ -187,7 +185,7 @@ real_t Vector::operator*(const real_t *v) const
|
||||
#ifdef MFEM_USE_LEGACY_OPENMP
|
||||
#pragma omp parallel for reduction(+:dot)
|
||||
#endif
|
||||
for (int i = 0; i < size; i++)
|
||||
for (bigint i = 0; i < size; i++)
|
||||
{
|
||||
dot += data[i] * v[i];
|
||||
}
|
||||
@@ -232,18 +230,22 @@ Vector &Vector::operator=(Vector &&v)
|
||||
Vector &Vector::operator=(real_t value)
|
||||
{
|
||||
const bool use_dev = UseDevice();
|
||||
const int N = size;
|
||||
auto y = Write(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i) { y[i] = value; });
|
||||
mfem::forall_switch(use_dev, size, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
y[i] = value;
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector &Vector::operator*=(real_t c)
|
||||
{
|
||||
const bool use_dev = UseDevice();
|
||||
const int N = size;
|
||||
auto y = ReadWrite(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i) { y[i] *= c; });
|
||||
mfem::forall_switch(use_dev, size, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
y[i] *= c;
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -252,20 +254,24 @@ Vector &Vector::operator*=(const Vector &v)
|
||||
MFEM_ASSERT(size == v.size, "incompatible Vectors!");
|
||||
|
||||
const bool use_dev = UseDevice() || v.UseDevice();
|
||||
const int N = size;
|
||||
const auto x = v.Read(use_dev);
|
||||
auto y = ReadWrite(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i) { y[i] *= x[i]; });
|
||||
mfem::forall_switch(use_dev, size, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
y[i] *= x[i];
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector &Vector::operator/=(real_t c)
|
||||
{
|
||||
const bool use_dev = UseDevice();
|
||||
const int N = size;
|
||||
const real_t m = 1.0/c;
|
||||
auto y = ReadWrite(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i) { y[i] *= m; });
|
||||
mfem::forall_switch(use_dev, size, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
y[i] *= m;
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -274,19 +280,23 @@ Vector &Vector::operator/=(const Vector &v)
|
||||
MFEM_ASSERT(size == v.size, "incompatible Vectors!");
|
||||
|
||||
const bool use_dev = UseDevice() || v.UseDevice();
|
||||
const int N = size;
|
||||
const auto x = v.Read(use_dev);
|
||||
auto y = ReadWrite(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i) { y[i] /= x[i]; });
|
||||
mfem::forall_switch(use_dev, size, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
y[i] /= x[i];
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector &Vector::operator-=(real_t c)
|
||||
{
|
||||
const bool use_dev = UseDevice();
|
||||
const int N = size;
|
||||
auto y = ReadWrite(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i) { y[i] -= c; });
|
||||
mfem::forall_switch(use_dev, size, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
y[i] -= c;
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -295,19 +305,23 @@ Vector &Vector::operator-=(const Vector &v)
|
||||
MFEM_ASSERT(size == v.size, "incompatible Vectors!");
|
||||
|
||||
const bool use_dev = UseDevice() || v.UseDevice();
|
||||
const int N = size;
|
||||
const auto x = v.Read(use_dev);
|
||||
auto y = ReadWrite(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i) { y[i] -= x[i]; });
|
||||
mfem::forall_switch(use_dev, size, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
y[i] -= x[i];
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector &Vector::operator+=(real_t c)
|
||||
{
|
||||
const bool use_dev = UseDevice();
|
||||
const int N = size;
|
||||
auto y = ReadWrite(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i) { y[i] += c; });
|
||||
mfem::forall_switch(use_dev, size, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
y[i] += c;
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -316,10 +330,12 @@ Vector &Vector::operator+=(const Vector &v)
|
||||
MFEM_ASSERT(size == v.size, "incompatible Vectors!");
|
||||
|
||||
const bool use_dev = UseDevice() || v.UseDevice();
|
||||
const int N = size;
|
||||
const auto x = v.Read(use_dev);
|
||||
auto y = ReadWrite(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i) { y[i] += x[i]; });
|
||||
mfem::forall_switch(use_dev, size, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
y[i] += x[i];
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -329,11 +345,13 @@ Vector &Vector::Add(const real_t a, const Vector &Va)
|
||||
|
||||
if (a != 0.0)
|
||||
{
|
||||
const int N = size;
|
||||
const bool use_dev = UseDevice() || Va.UseDevice();
|
||||
const auto x = Va.Read(use_dev);
|
||||
auto y = ReadWrite(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i) { y[i] += a * x[i]; });
|
||||
mfem::forall_switch(use_dev, size, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
y[i] += a * x[i];
|
||||
});
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -343,58 +361,69 @@ Vector &Vector::Set(const real_t a, const Vector &Va)
|
||||
MFEM_ASSERT(size == Va.size, "incompatible Vectors!");
|
||||
|
||||
const bool use_dev = UseDevice() || Va.UseDevice();
|
||||
const int N = size;
|
||||
const auto x = Va.Read(use_dev);
|
||||
auto y = Write(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i) { y[i] = a * x[i]; });
|
||||
mfem::forall_switch(use_dev, size, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
y[i] = a * x[i];
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Vector::SetVector(const Vector &v, int offset)
|
||||
void Vector::SetVector(const Vector &v, bigint offset)
|
||||
{
|
||||
MFEM_ASSERT(v.Size() + offset <= size, "invalid sub-vector");
|
||||
|
||||
const bool use_dev = UseDevice() || v.UseDevice();
|
||||
const int vs = v.Size();
|
||||
const bigint vs = v.Size();
|
||||
const auto vp = v.Read(use_dev);
|
||||
// Use read+write access for *this - we only modify some of its entries
|
||||
auto p = ReadWrite(use_dev) + offset;
|
||||
mfem::forall_switch(use_dev, vs, [=] MFEM_HOST_DEVICE (int i) { p[i] = vp[i]; });
|
||||
mfem::forall_switch(use_dev, vs, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
p[i] = vp[i];
|
||||
});
|
||||
}
|
||||
|
||||
void Vector::AddSubVector(const Vector &v, int offset)
|
||||
void Vector::AddSubVector(const Vector &v, bigint offset)
|
||||
{
|
||||
MFEM_ASSERT(v.Size() + offset <= size, "invalid sub-vector");
|
||||
|
||||
const bool use_dev = UseDevice() || v.UseDevice();
|
||||
const int vs = v.Size();
|
||||
const bigint vs = v.Size();
|
||||
const auto vp = v.Read(use_dev);
|
||||
auto p = ReadWrite(use_dev) + offset;
|
||||
mfem::forall_switch(use_dev, vs, [=] MFEM_HOST_DEVICE (int i) { p[i] += vp[i]; });
|
||||
mfem::forall_switch(use_dev, vs, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
p[i] += vp[i];
|
||||
});
|
||||
}
|
||||
|
||||
void Vector::Neg()
|
||||
{
|
||||
const bool use_dev = UseDevice();
|
||||
const int N = size;
|
||||
auto y = ReadWrite(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i) { y[i] = -y[i]; });
|
||||
mfem::forall_switch(use_dev, size, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
y[i] = -y[i];
|
||||
});
|
||||
}
|
||||
|
||||
void Vector::Reciprocal()
|
||||
{
|
||||
const bool use_dev = UseDevice();
|
||||
const int N = size;
|
||||
auto y = ReadWrite(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i) { y[i] = 1.0/y[i]; });
|
||||
mfem::forall_switch(use_dev, size, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
y[i] = 1.0/y[i];
|
||||
});
|
||||
}
|
||||
|
||||
void Vector::Abs()
|
||||
{
|
||||
const bool use_dev = UseDevice();
|
||||
const int N = size;
|
||||
auto y = ReadWrite(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i)
|
||||
mfem::forall_switch(use_dev, size, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
y[i] = std::abs(y[i]);
|
||||
});
|
||||
@@ -403,9 +432,8 @@ void Vector::Abs()
|
||||
void Vector::Pow(const real_t p)
|
||||
{
|
||||
const bool use_dev = UseDevice();
|
||||
const int N = size;
|
||||
auto y = ReadWrite(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i)
|
||||
mfem::forall_switch(use_dev, size, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
y[i] = std::pow(y[i], p);
|
||||
});
|
||||
@@ -418,15 +446,18 @@ void add(const Vector &v1, const Vector &v2, Vector &v)
|
||||
|
||||
#if !defined(MFEM_USE_LEGACY_OPENMP)
|
||||
const bool use_dev = v1.UseDevice() || v2.UseDevice() || v.UseDevice();
|
||||
const int N = v.size;
|
||||
const bigint N = v.size;
|
||||
// Note: get read access first, in case v is the same as v1/v2.
|
||||
const auto x1 = v1.Read(use_dev);
|
||||
const auto x2 = v2.Read(use_dev);
|
||||
auto y = v.Write(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i) { y[i] = x1[i] + x2[i]; });
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
y[i] = x1[i] + x2[i];
|
||||
});
|
||||
#else
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < v.size; i++)
|
||||
for (bigint i = 0; i < v.size; i++)
|
||||
{
|
||||
v.data[i] = v1.data[i] + v2.data[i];
|
||||
}
|
||||
@@ -450,21 +481,21 @@ void add(const Vector &v1, real_t alpha, const Vector &v2, Vector &v)
|
||||
{
|
||||
#if !defined(MFEM_USE_LEGACY_OPENMP)
|
||||
const bool use_dev = v1.UseDevice() || v2.UseDevice() || v.UseDevice();
|
||||
const int N = v.size;
|
||||
const bigint N = v.size;
|
||||
// Note: get read access first, in case v is the same as v1/v2.
|
||||
const auto d_x = v1.Read(use_dev);
|
||||
const auto d_y = v2.Read(use_dev);
|
||||
auto d_z = v.Write(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i)
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
d_z[i] = d_x[i] + alpha * d_y[i];
|
||||
});
|
||||
#else
|
||||
const real_t *v1p = v1.data, *v2p = v2.data;
|
||||
real_t *vp = v.data;
|
||||
const int s = v.size;
|
||||
const bigint s = v.size;
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < s; i++)
|
||||
for (bigint i = 0; i < s; i++)
|
||||
{
|
||||
vp[i] = v1p[i] + alpha*v2p[i];
|
||||
}
|
||||
@@ -489,12 +520,12 @@ void add(const real_t a, const Vector &x, const Vector &y, Vector &z)
|
||||
{
|
||||
#if !defined(MFEM_USE_LEGACY_OPENMP)
|
||||
const bool use_dev = x.UseDevice() || y.UseDevice() || z.UseDevice();
|
||||
const int N = x.size;
|
||||
const bigint N = x.size;
|
||||
// Note: get read access first, in case z is the same as x/y.
|
||||
const auto xd = x.Read(use_dev);
|
||||
const auto yd = y.Read(use_dev);
|
||||
auto zd = z.Write(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i)
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
zd[i] = a * (xd[i] + yd[i]);
|
||||
});
|
||||
@@ -502,9 +533,9 @@ void add(const real_t a, const Vector &x, const Vector &y, Vector &z)
|
||||
const real_t *xp = x.data;
|
||||
const real_t *yp = y.data;
|
||||
real_t *zp = z.data;
|
||||
const int s = x.size;
|
||||
const bigint s = x.size;
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < s; i++)
|
||||
for (bigint i = 0; i < s; i++)
|
||||
{
|
||||
zp[i] = a * (xp[i] + yp[i]);
|
||||
}
|
||||
@@ -544,12 +575,12 @@ void add(const real_t a, const Vector &x,
|
||||
{
|
||||
#if !defined(MFEM_USE_LEGACY_OPENMP)
|
||||
const bool use_dev = x.UseDevice() || y.UseDevice() || z.UseDevice();
|
||||
const int N = x.size;
|
||||
const bigint N = x.size;
|
||||
// Note: get read access first, in case z is the same as x/y.
|
||||
const auto xd = x.Read(use_dev);
|
||||
const auto yd = y.Read(use_dev);
|
||||
auto zd = z.Write(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i)
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
zd[i] = a * xd[i] + b * yd[i];
|
||||
});
|
||||
@@ -557,9 +588,9 @@ void add(const real_t a, const Vector &x,
|
||||
const real_t *xp = x.data;
|
||||
const real_t *yp = y.data;
|
||||
real_t *zp = z.data;
|
||||
const int s = x.size;
|
||||
const bigint s = x.size;
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < s; i++)
|
||||
for (bigint i = 0; i < s; i++)
|
||||
{
|
||||
zp[i] = a * xp[i] + b * yp[i];
|
||||
}
|
||||
@@ -574,12 +605,12 @@ void subtract(const Vector &x, const Vector &y, Vector &z)
|
||||
|
||||
#if !defined(MFEM_USE_LEGACY_OPENMP)
|
||||
const bool use_dev = x.UseDevice() || y.UseDevice() || z.UseDevice();
|
||||
const int N = x.size;
|
||||
const bigint N = x.size;
|
||||
// Note: get read access first, in case z is the same as x/y.
|
||||
const auto xd = x.Read(use_dev);
|
||||
const auto yd = y.Read(use_dev);
|
||||
auto zd = z.Write(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i)
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
zd[i] = xd[i] - yd[i];
|
||||
});
|
||||
@@ -587,9 +618,9 @@ void subtract(const Vector &x, const Vector &y, Vector &z)
|
||||
const real_t *xp = x.data;
|
||||
const real_t *yp = y.data;
|
||||
real_t *zp = z.data;
|
||||
const int s = x.size;
|
||||
const bigint s = x.size;
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < s; i++)
|
||||
for (bigint i = 0; i < s; i++)
|
||||
{
|
||||
zp[i] = xp[i] - yp[i];
|
||||
}
|
||||
@@ -613,12 +644,12 @@ void subtract(const real_t a, const Vector &x, const Vector &y, Vector &z)
|
||||
{
|
||||
#if !defined(MFEM_USE_LEGACY_OPENMP)
|
||||
const bool use_dev = x.UseDevice() || y.UseDevice() || z.UseDevice();
|
||||
const int N = x.size;
|
||||
const bigint N = x.size;
|
||||
// Note: get read access first, in case z is the same as x/y.
|
||||
const auto xd = x.Read(use_dev);
|
||||
const auto yd = y.Read(use_dev);
|
||||
auto zd = z.Write(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i)
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
zd[i] = a * (xd[i] - yd[i]);
|
||||
});
|
||||
@@ -626,9 +657,9 @@ void subtract(const real_t a, const Vector &x, const Vector &y, Vector &z)
|
||||
const real_t *xp = x.data;
|
||||
const real_t *yp = y.data;
|
||||
real_t *zp = z.data;
|
||||
const int s = x.size;
|
||||
const bigint s = x.size;
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < s; i++)
|
||||
for (bigint i = 0; i < s; i++)
|
||||
{
|
||||
zp[i] = a * (xp[i] - yp[i]);
|
||||
}
|
||||
@@ -655,12 +686,12 @@ void Vector::median(const Vector &lo, const Vector &hi)
|
||||
"incompatible Vectors!");
|
||||
|
||||
const bool use_dev = UseDevice() || lo.UseDevice() || hi.UseDevice();
|
||||
const int N = size;
|
||||
const bigint N = size;
|
||||
// Note: get read access first, in case *this is the same as lo/hi.
|
||||
const auto l = lo.Read(use_dev);
|
||||
const auto h = hi.Read(use_dev);
|
||||
auto m = Write(use_dev);
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i)
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
if (m[i] < l[i])
|
||||
{
|
||||
@@ -675,13 +706,13 @@ void Vector::median(const Vector &lo, const Vector &hi)
|
||||
|
||||
void Vector::GetSubVector(const Array<int> &dofs, Vector &elemvect) const
|
||||
{
|
||||
const int n = dofs.Size();
|
||||
const bigint n = dofs.Size();
|
||||
elemvect.SetSize(n);
|
||||
const bool use_dev = dofs.UseDevice() || elemvect.UseDevice();
|
||||
const auto d_X = Read(use_dev);
|
||||
const auto d_dofs = dofs.Read(use_dev);
|
||||
auto d_y = elemvect.Write(use_dev);
|
||||
mfem::forall_switch(use_dev, n, [=] MFEM_HOST_DEVICE (int i)
|
||||
mfem::forall_switch(use_dev, n, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
const int dof_i = d_dofs[i];
|
||||
d_y[i] = dof_i >= 0 ? d_X[dof_i] : -d_X[-dof_i-1];
|
||||
@@ -691,8 +722,8 @@ void Vector::GetSubVector(const Array<int> &dofs, Vector &elemvect) const
|
||||
void Vector::GetSubVector(const Array<int> &dofs, real_t *elem_data) const
|
||||
{
|
||||
HostRead();
|
||||
const int n = dofs.Size();
|
||||
for (int i = 0; i < n; i++)
|
||||
const bigint n = dofs.Size();
|
||||
for (bigint i = 0; i < n; i++)
|
||||
{
|
||||
const int j = dofs[i];
|
||||
elem_data[i] = (j >= 0) ? data[j] : -data[-1-j];
|
||||
@@ -702,11 +733,11 @@ void Vector::GetSubVector(const Array<int> &dofs, real_t *elem_data) const
|
||||
void Vector::SetSubVector(const Array<int> &dofs, const real_t value)
|
||||
{
|
||||
const bool use_dev = UseDevice() || dofs.UseDevice();
|
||||
const int n = dofs.Size();
|
||||
const bigint n = dofs.Size();
|
||||
// Use read+write access for *this - we only modify some of its entries
|
||||
auto d_X = ReadWrite(use_dev);
|
||||
const auto d_dofs = dofs.Read(use_dev);
|
||||
mfem::forall_switch(use_dev, n, [=] MFEM_HOST_DEVICE (int i)
|
||||
mfem::forall_switch(use_dev, n, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
const int j = d_dofs[i];
|
||||
if (j >= 0)
|
||||
@@ -723,7 +754,7 @@ void Vector::SetSubVector(const Array<int> &dofs, const real_t value)
|
||||
void Vector::SetSubVectorHost(const Array<int> &dofs, const real_t value)
|
||||
{
|
||||
HostReadWrite();
|
||||
for (int i = 0; i < dofs.Size(); ++i)
|
||||
for (bigint i = 0; i < dofs.Size(); ++i)
|
||||
{
|
||||
const int j = dofs[i];
|
||||
if (j >= 0)
|
||||
@@ -744,12 +775,12 @@ void Vector::SetSubVector(const Array<int> &dofs, const Vector &elemvect)
|
||||
<< ", length of elemvect is " << elemvect.Size());
|
||||
|
||||
const bool use_dev = dofs.UseDevice() || elemvect.UseDevice();
|
||||
const int n = dofs.Size();
|
||||
const bigint n = dofs.Size();
|
||||
// Use read+write access for X - we only modify some of its entries
|
||||
auto d_X = ReadWrite(use_dev);
|
||||
const auto d_y = elemvect.Read(use_dev);
|
||||
const auto d_dofs = dofs.Read(use_dev);
|
||||
mfem::forall_switch(use_dev, n, [=] MFEM_HOST_DEVICE (int i)
|
||||
mfem::forall_switch(use_dev, n, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
const int dof_i = d_dofs[i];
|
||||
if (dof_i >= 0)
|
||||
@@ -767,10 +798,10 @@ void Vector::SetSubVector(const Array<int> &dofs, real_t *elem_data)
|
||||
{
|
||||
// Use read+write access because we overwrite only part of the data.
|
||||
HostReadWrite();
|
||||
const int n = dofs.Size();
|
||||
for (int i = 0; i < n; i++)
|
||||
const bigint n = dofs.Size();
|
||||
for (bigint i = 0; i < n; i++)
|
||||
{
|
||||
const int j= dofs[i];
|
||||
const int j = dofs[i];
|
||||
if (j >= 0)
|
||||
{
|
||||
operator()(j) = elem_data[i];
|
||||
@@ -789,11 +820,11 @@ void Vector::AddElementVector(const Array<int> &dofs, const Vector &elemvect)
|
||||
", length of elemvect is " << elemvect.Size());
|
||||
|
||||
const bool use_dev = dofs.UseDevice() || elemvect.UseDevice();
|
||||
const int n = dofs.Size();
|
||||
const bigint n = dofs.Size();
|
||||
const auto d_y = elemvect.Read(use_dev);
|
||||
const auto d_dofs = dofs.Read(use_dev);
|
||||
auto d_X = ReadWrite(use_dev);
|
||||
mfem::forall_switch(use_dev, n, [=] MFEM_HOST_DEVICE (int i)
|
||||
mfem::forall_switch(use_dev, n, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
const int j = d_dofs[i];
|
||||
if (j >= 0)
|
||||
@@ -810,8 +841,8 @@ void Vector::AddElementVector(const Array<int> &dofs, const Vector &elemvect)
|
||||
void Vector::AddElementVector(const Array<int> &dofs, real_t *elem_data)
|
||||
{
|
||||
HostReadWrite();
|
||||
const int n = dofs.Size();
|
||||
for (int i = 0; i < n; i++)
|
||||
const bigint n = dofs.Size();
|
||||
for (bigint i = 0; i < n; i++)
|
||||
{
|
||||
const int j = dofs[i];
|
||||
if (j >= 0)
|
||||
@@ -833,11 +864,11 @@ void Vector::AddElementVector(const Array<int> &dofs, const real_t a,
|
||||
", length of elemvect is " << elemvect.Size());
|
||||
|
||||
const bool use_dev = dofs.UseDevice() || elemvect.UseDevice();
|
||||
const int n = dofs.Size();
|
||||
const bigint n = dofs.Size();
|
||||
const auto d_x = elemvect.Read(use_dev);
|
||||
const auto d_dofs = dofs.Read(use_dev);
|
||||
auto d_y = ReadWrite(use_dev);
|
||||
mfem::forall_switch(use_dev, n, [=] MFEM_HOST_DEVICE (int i)
|
||||
mfem::forall_switch(use_dev, n, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
const int j = d_dofs[i];
|
||||
if (j >= 0)
|
||||
@@ -854,17 +885,26 @@ void Vector::AddElementVector(const Array<int> &dofs, const real_t a,
|
||||
void Vector::SetSubVectorComplement(const Array<int> &dofs, const real_t val)
|
||||
{
|
||||
const bool use_dev = UseDevice() || dofs.UseDevice();
|
||||
const int n = dofs.Size();
|
||||
const int N = size;
|
||||
const bigint n = dofs.Size();
|
||||
const bigint N = size;
|
||||
Vector dofs_vals(n, use_dev ?
|
||||
Device::GetDeviceMemoryType() :
|
||||
Device::GetHostMemoryType());
|
||||
auto d_data = ReadWrite(use_dev);
|
||||
auto d_dofs_vals = dofs_vals.Write(use_dev);
|
||||
const auto d_dofs = dofs.Read(use_dev);
|
||||
mfem::forall_switch(use_dev, n, [=] MFEM_HOST_DEVICE (int i) { d_dofs_vals[i] = d_data[d_dofs[i]]; });
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (int i) { d_data[i] = val; });
|
||||
mfem::forall_switch(use_dev, n, [=] MFEM_HOST_DEVICE (int i) { d_data[d_dofs[i]] = d_dofs_vals[i]; });
|
||||
mfem::forall_switch(use_dev, n, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
d_dofs_vals[i] = d_data[d_dofs[i]];
|
||||
});
|
||||
mfem::forall_switch(use_dev, N, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
d_data[i] = val;
|
||||
});
|
||||
mfem::forall_switch(use_dev, n, [=] MFEM_HOST_DEVICE (bigint i)
|
||||
{
|
||||
d_data[d_dofs[i]] = d_dofs_vals[i];
|
||||
});
|
||||
}
|
||||
|
||||
void Vector::Print(std::ostream &os, int width) const
|
||||
@@ -903,7 +943,6 @@ void Vector::Print(adios2stream &os,
|
||||
|
||||
void Vector::Print_HYPRE(std::ostream &os) const
|
||||
{
|
||||
int i;
|
||||
std::ios::fmtflags old_fmt = os.flags();
|
||||
os.setf(std::ios::scientific);
|
||||
std::streamsize old_prec = os.precision(14);
|
||||
@@ -911,7 +950,7 @@ void Vector::Print_HYPRE(std::ostream &os) const
|
||||
os << size << '\n'; // number of rows
|
||||
|
||||
data.Read(MemoryClass::HOST, size);
|
||||
for (i = 0; i < size; i++)
|
||||
for (bigint i = 0; i < size; i++)
|
||||
{
|
||||
os << ZeroSubnormal(data[i]) << '\n';
|
||||
}
|
||||
@@ -931,7 +970,7 @@ void Vector::PrintMathematica(std::ostream & os) const
|
||||
os << "{\n";
|
||||
|
||||
data.Read(MemoryClass::HOST, size);
|
||||
for (int i = 0; i < size; i++)
|
||||
for (bigint i = 0; i < size; i++)
|
||||
{
|
||||
os << "Internal`StringToMReal[\"" << ZeroSubnormal(data[i]) << "\"]";
|
||||
if (i < size - 1) { os << ','; }
|
||||
@@ -959,7 +998,7 @@ void Vector::Randomize(int seed)
|
||||
srand((unsigned)seed);
|
||||
|
||||
HostWrite();
|
||||
for (int i = 0; i < size; i++)
|
||||
for (bigint i = 0; i < size; i++)
|
||||
{
|
||||
data[i] = rand_real();
|
||||
}
|
||||
@@ -978,6 +1017,7 @@ real_t Vector::Norml2() const
|
||||
res.first = 0;
|
||||
res.second = 0;
|
||||
// first compute sum (|m_data|/scale)^2
|
||||
// FIXME: bigint support
|
||||
reduce(size, res, [=] MFEM_HOST_DEVICE(int i, value_type &r)
|
||||
{
|
||||
real_t n = fabs(m_data[i]);
|
||||
@@ -1007,6 +1047,7 @@ real_t Vector::Normlinf() const
|
||||
|
||||
real_t res = 0;
|
||||
const auto m_data = Read(UseDevice());
|
||||
// FIXME: bigint support
|
||||
reduce(size, res, [=] MFEM_HOST_DEVICE(int i, real_t &r)
|
||||
{
|
||||
r = fmax(r, fabs(m_data[i]));
|
||||
@@ -1021,6 +1062,7 @@ real_t Vector::Norml1() const
|
||||
|
||||
real_t res = 0;
|
||||
const auto m_data = Read(UseDevice());
|
||||
// FIXME: bigint support
|
||||
reduce(size, res, [=] MFEM_HOST_DEVICE(int i, real_t &r)
|
||||
{
|
||||
r += fabs(m_data[i]);
|
||||
@@ -1050,6 +1092,7 @@ real_t Vector::Normlp(real_t p) const
|
||||
res.second = 0;
|
||||
const auto m_data = Read(UseDevice());
|
||||
// first compute sum (|m_data|/scale)^p
|
||||
// FIXME: bigint support
|
||||
reduce(size, res, [=] MFEM_HOST_DEVICE(int i, value_type &r)
|
||||
{
|
||||
real_t n = fabs(m_data[i]);
|
||||
@@ -1097,6 +1140,7 @@ real_t Vector::operator*(const Vector &v) const
|
||||
const auto compute_dot = [&]()
|
||||
{
|
||||
real_t res = 0;
|
||||
// FIXME: bigint support
|
||||
reduce(size, res, [=] MFEM_HOST_DEVICE (int i, real_t &r)
|
||||
{
|
||||
r += m_data[i] * v_data[i];
|
||||
@@ -1122,11 +1166,11 @@ real_t Vector::operator*(const Vector &v) const
|
||||
#pragma omp master
|
||||
th_dot.SetSize(nt);
|
||||
const int tid = omp_get_thread_num();
|
||||
const int stride = (size + nt - 1) / nt;
|
||||
const int start = tid * stride;
|
||||
const int stop = std::min(start + stride, size);
|
||||
const bigint stride = (size + nt - 1) / nt;
|
||||
const bigint start = tid * stride;
|
||||
const bigint stop = std::min(start + stride, size);
|
||||
real_t my_dot = 0.0;
|
||||
for (int i = start; i < stop; i++)
|
||||
for (bigint i = start; i < stop; i++)
|
||||
{
|
||||
my_dot += m_data[i] * v_data[i];
|
||||
}
|
||||
@@ -1138,7 +1182,7 @@ real_t Vector::operator*(const Vector &v) const
|
||||
// The standard way of computing the dot product is non-deterministic
|
||||
real_t prod = 0.0;
|
||||
#pragma omp parallel for reduction(+ : prod)
|
||||
for (int i = 0; i < size; i++)
|
||||
for (bigint i = 0; i < size; i++)
|
||||
{
|
||||
prod += m_data[i] * v_data[i];
|
||||
}
|
||||
@@ -1168,6 +1212,7 @@ real_t Vector::Min() const
|
||||
const auto compute_min = [&]()
|
||||
{
|
||||
real_t res = infinity();
|
||||
// FIXME: bigint support
|
||||
reduce(size, res, [=] MFEM_HOST_DEVICE(int i, real_t &r)
|
||||
{
|
||||
r = fmin(r, m_data[i]);
|
||||
@@ -1185,7 +1230,7 @@ real_t Vector::Min() const
|
||||
{
|
||||
real_t minimum = m_data[0];
|
||||
#pragma omp parallel for reduction(min:minimum)
|
||||
for (int i = 0; i < size; i++)
|
||||
for (bigint i = 0; i < size; i++)
|
||||
{
|
||||
minimum = std::min(minimum, m_data[i]);
|
||||
}
|
||||
@@ -1214,6 +1259,7 @@ real_t Vector::Max() const
|
||||
const auto compute_max = [&]()
|
||||
{
|
||||
real_t res = -infinity();
|
||||
// FIXME: bigint support
|
||||
reduce(size, res, [=] MFEM_HOST_DEVICE(int i, real_t &r)
|
||||
{
|
||||
r = fmax(r, m_data[i]);
|
||||
@@ -1231,7 +1277,7 @@ real_t Vector::Max() const
|
||||
{
|
||||
real_t maximum = m_data[0];
|
||||
#pragma omp parallel for reduction(max : maximum)
|
||||
for (int i = 0; i < size; i++)
|
||||
for (bigint i = 0; i < size; i++)
|
||||
{
|
||||
maximum = fmax(maximum, m_data[i]);
|
||||
}
|
||||
@@ -1249,6 +1295,7 @@ real_t Vector::Sum() const
|
||||
|
||||
real_t res = 0;
|
||||
const auto m_data = Read(UseDevice());
|
||||
// FIXME: bigint support
|
||||
reduce(size, res, [=] MFEM_HOST_DEVICE(int i, real_t &r)
|
||||
{
|
||||
r += m_data[i];
|
||||
@@ -1266,10 +1313,13 @@ void Vector::DeleteAt(const Array<int> &indices)
|
||||
// extra entry for number of selected out
|
||||
Array<int> workspace(size + 1);
|
||||
const auto d_flag = workspace.Write(use_dev);
|
||||
mfem::forall_switch(use_dev, size,
|
||||
[=] MFEM_HOST_DEVICE(int i) { d_flag[i] = true; });
|
||||
mfem::forall_switch(use_dev, size, [=] MFEM_HOST_DEVICE(bigint i)
|
||||
{
|
||||
d_flag[i] = true;
|
||||
});
|
||||
const auto d_indices = indices.Read(use_dev);
|
||||
mfem::forall_switch(use_dev, indices.Size(), [=] MFEM_HOST_DEVICE(int i)
|
||||
mfem::forall_switch(
|
||||
use_dev, indices.Size(), [=] MFEM_HOST_DEVICE(bigint i)
|
||||
{
|
||||
// fine as long as indices are unique; to support non-unique indices
|
||||
// assignment to d_flag must be atomic
|
||||
|
||||
+51
-47
@@ -40,7 +40,7 @@ namespace mfem
|
||||
|
||||
/** Count the number of entries in an array of doubles for which isfinite
|
||||
is false, i.e. the entry is a NaN or +/-Inf. */
|
||||
inline int CheckFinite(const real_t *v, const int n);
|
||||
inline bigint CheckFinite(const real_t *v, const bigint n);
|
||||
|
||||
/// Define a shortcut for std::numeric_limits<double>::infinity()
|
||||
#ifndef __CYGWIN__
|
||||
@@ -83,7 +83,7 @@ class Vector
|
||||
protected:
|
||||
|
||||
Memory<real_t> data;
|
||||
int size;
|
||||
bigint size;
|
||||
|
||||
public:
|
||||
|
||||
@@ -99,30 +99,30 @@ public:
|
||||
|
||||
/// @brief Creates vector of size s.
|
||||
/// @warning Entries are not initialized to zero!
|
||||
explicit Vector(int s);
|
||||
explicit Vector(bigint s);
|
||||
|
||||
/// Creates a vector referencing an array of doubles, owned by someone else.
|
||||
/** The pointer @a data_ can be NULL. The data array can be replaced later
|
||||
with SetData(). */
|
||||
Vector(real_t *data_, int size_)
|
||||
Vector(real_t *data_, bigint size_)
|
||||
{ data.Wrap(data_, size_, false); size = size_; }
|
||||
|
||||
/** @brief Create a Vector referencing a sub-vector of the Vector @a base
|
||||
starting at the given offset, @a base_offset, and size @a size_. */
|
||||
Vector(Vector &base, int base_offset, int size_)
|
||||
Vector(Vector &base, bigint base_offset, bigint size_)
|
||||
: data(base.data, base_offset, size_), size(size_) { }
|
||||
|
||||
/// Create a Vector of size @a size_ using MemoryType @a mt.
|
||||
Vector(int size_, MemoryType mt)
|
||||
Vector(bigint size_, MemoryType mt)
|
||||
: data(size_, mt), size(size_) { }
|
||||
|
||||
/** @brief Create a Vector of size @a size_ using host MemoryType @a h_mt and
|
||||
device MemoryType @a d_mt. */
|
||||
Vector(int size_, MemoryType h_mt, MemoryType d_mt)
|
||||
Vector(bigint size_, MemoryType h_mt, MemoryType d_mt)
|
||||
: data(size_, h_mt, d_mt), size(size_) { }
|
||||
|
||||
/// Create a vector from a statically sized C-style array of convertible type
|
||||
template <typename CT, int N>
|
||||
template <typename CT, bigint N>
|
||||
explicit Vector(const CT (&values)[N]) : Vector(N)
|
||||
{ std::copy(values, values + N, begin()); }
|
||||
|
||||
@@ -130,7 +130,7 @@ public:
|
||||
template <typename CT, typename std::enable_if<
|
||||
std::is_convertible<CT,real_t>::value,bool>::type = true>
|
||||
explicit Vector(std::initializer_list<CT> values) :
|
||||
Vector(static_cast<int> (values.size()))
|
||||
Vector(static_cast<bigint> (values.size()))
|
||||
{ std::copy(values.begin(), values.end(), begin()); }
|
||||
|
||||
/// Enable execution of Vector operations using the mfem::Device.
|
||||
@@ -151,10 +151,10 @@ public:
|
||||
void Load(std::istream ** in, int np, int * dim);
|
||||
|
||||
/// Load a vector from an input stream.
|
||||
void Load(std::istream &in, int Size);
|
||||
void Load(std::istream &in, bigint Size);
|
||||
|
||||
/// Load a vector from an input stream, reading the size from the stream.
|
||||
void Load(std::istream &in) { int s; in >> s; Load(in, s); }
|
||||
void Load(std::istream &in) { bigint s; in >> s; Load(in, s); }
|
||||
|
||||
/// @brief Resize the vector to size @a s.
|
||||
/** If the new size is less than or equal to Capacity() then the internal
|
||||
@@ -164,16 +164,18 @@ public:
|
||||
@warning In the second case above (new size greater than current one),
|
||||
the vector will allocate new data array, even if it did not own the
|
||||
original data! Also, new entries are not initialized! */
|
||||
void SetSize(int s);
|
||||
void SetSize(bigint s);
|
||||
|
||||
/// Resize the vector to size @a s using MemoryType @a mt.
|
||||
void SetSize(int s, MemoryType mt);
|
||||
void SetSize(bigint s, MemoryType mt);
|
||||
|
||||
/// Resize the vector to size @a s using the MemoryType of @a v.
|
||||
void SetSize(int s, const Vector &v) { SetSize(s, v.GetMemory().GetMemoryType()); }
|
||||
void SetSize(bigint s, const Vector &v)
|
||||
{ SetSize(s, v.GetMemory().GetMemoryType()); }
|
||||
|
||||
/// Update \ref Capacity() to @a res (if less than current), keeping existing entries.
|
||||
void Reserve(int res);
|
||||
/** @brief Update \ref Capacity() to @a res (if less than current), keeping
|
||||
existing entries. */
|
||||
void Reserve(bigint res);
|
||||
|
||||
/// Delete entries at @a indices and resize vector accordingly.
|
||||
/// @warning Indices must be unique!
|
||||
@@ -188,13 +190,14 @@ public:
|
||||
also used as the new Capacity().
|
||||
@warning This method should be called only when OwnsData() is false.
|
||||
@sa NewDataAndSize(). */
|
||||
void SetDataAndSize(real_t *d, int s) { data.Wrap(d, s, false); size = s; }
|
||||
void SetDataAndSize(real_t *d, bigint s)
|
||||
{ data.Wrap(d, s, false); size = s; }
|
||||
|
||||
/// Set the Vector data and size, deleting the old data, if owned.
|
||||
/** The Vector does not assume ownership of the new data. The new size is
|
||||
also used as the new Capacity().
|
||||
@sa SetDataAndSize(). */
|
||||
void NewDataAndSize(real_t *d, int s)
|
||||
void NewDataAndSize(real_t *d, bigint s)
|
||||
{
|
||||
data.Delete();
|
||||
SetDataAndSize(d, s);
|
||||
@@ -209,14 +212,15 @@ public:
|
||||
the Vector object takes ownership of all pointers owned by @a mem.
|
||||
|
||||
@sa NewDataAndSize(). */
|
||||
inline void NewMemoryAndSize(const Memory<real_t> &mem, int s, bool own_mem);
|
||||
inline void NewMemoryAndSize(const Memory<real_t> &mem, bigint s,
|
||||
bool own_mem);
|
||||
|
||||
/// Reset the Vector to be a reference to a sub-vector of @a base.
|
||||
inline void MakeRef(Vector &base, int offset, int size);
|
||||
inline void MakeRef(Vector &base, bigint offset, bigint size);
|
||||
|
||||
/** @brief Reset the Vector to be a reference to a sub-vector of @a base
|
||||
without changing its current size. */
|
||||
inline void MakeRef(Vector &base, int offset);
|
||||
inline void MakeRef(Vector &base, bigint offset);
|
||||
|
||||
/// Set the Vector data (host pointer) ownership flag.
|
||||
void MakeDataOwner() const { data.SetHostPtrOwner(true); }
|
||||
@@ -231,11 +235,11 @@ public:
|
||||
{ data.DeleteDevice(copy_to_host); }
|
||||
|
||||
/// Returns the size of the vector.
|
||||
inline int Size() const { return size; }
|
||||
inline bigint Size() const { return size; }
|
||||
|
||||
/// Return the size of the currently allocated data array.
|
||||
/** It is always true that Capacity() >= Size(). */
|
||||
inline int Capacity() const { return data.Capacity(); }
|
||||
inline bigint Capacity() const { return data.Capacity(); }
|
||||
|
||||
/// Return a pointer to the beginning of the Vector data.
|
||||
/** @warning This method should be used with caution as it gives write access
|
||||
@@ -286,26 +290,26 @@ public:
|
||||
inline real_t *StealData() { real_t *p; StealData(&p); return p; }
|
||||
|
||||
/// Access Vector entries. Index i = 0 .. size-1.
|
||||
real_t &Elem(int i);
|
||||
real_t &Elem(bigint i);
|
||||
|
||||
/// Read only access to Vector entries. Index i = 0 .. size-1.
|
||||
const real_t &Elem(int i) const;
|
||||
const real_t &Elem(bigint i) const;
|
||||
|
||||
/// Access Vector entries using () for 0-based indexing.
|
||||
/** @note If MFEM_DEBUG is enabled, bounds checking is performed. */
|
||||
inline real_t &operator()(int i);
|
||||
inline real_t &operator()(bigint i);
|
||||
|
||||
/// Read only access to Vector entries using () for 0-based indexing.
|
||||
/** @note If MFEM_DEBUG is enabled, bounds checking is performed. */
|
||||
inline const real_t &operator()(int i) const;
|
||||
inline const real_t &operator()(bigint i) const;
|
||||
|
||||
/// Access Vector entries using [] for 0-based indexing.
|
||||
/** @note If MFEM_DEBUG is enabled, bounds checking is performed. */
|
||||
inline real_t &operator[](int i) { return (*this)(i); }
|
||||
inline real_t &operator[](bigint i) { return (*this)(i); }
|
||||
|
||||
/// Read only access to Vector entries using [] for 0-based indexing.
|
||||
/** @note If MFEM_DEBUG is enabled, bounds checking is performed. */
|
||||
inline const real_t &operator[](int i) const { return (*this)(i); }
|
||||
inline const real_t &operator[](bigint i) const { return (*this)(i); }
|
||||
|
||||
/// Dot product with a `double *` array.
|
||||
/// This function always executes on the CPU. A HostRead() will be called if
|
||||
@@ -357,10 +361,10 @@ public:
|
||||
Vector &Set(const real_t a, const Vector &x);
|
||||
|
||||
/// (*this)[i + offset] = v[i]
|
||||
void SetVector(const Vector &v, int offset);
|
||||
void SetVector(const Vector &v, bigint offset);
|
||||
|
||||
/// (*this)[i + offset] += v[i]
|
||||
void AddSubVector(const Vector &v, int offset);
|
||||
void AddSubVector(const Vector &v, bigint offset);
|
||||
|
||||
/// (*this) = -(*this)
|
||||
void Neg();
|
||||
@@ -511,7 +515,7 @@ public:
|
||||
|
||||
/** @brief Count the number of entries in the Vector for which isfinite
|
||||
is false, i.e. the entry is a NaN or +/-Inf. */
|
||||
int CheckFinite() const { return mfem::CheckFinite(HostRead(), size); }
|
||||
bigint CheckFinite() const { return mfem::CheckFinite(HostRead(), size); }
|
||||
|
||||
/// Destroys vector.
|
||||
virtual ~Vector();
|
||||
@@ -561,17 +565,17 @@ inline bool IsFinite(const real_t &val)
|
||||
#endif
|
||||
}
|
||||
|
||||
inline int CheckFinite(const real_t *v, const int n)
|
||||
inline bigint CheckFinite(const real_t *v, const bigint n)
|
||||
{
|
||||
int bad = 0;
|
||||
for (int i = 0; i < n; i++)
|
||||
bigint bad = 0;
|
||||
for (bigint i = 0; i < n; i++)
|
||||
{
|
||||
if (!IsFinite(v[i])) { bad++; }
|
||||
}
|
||||
return bad;
|
||||
}
|
||||
|
||||
inline Vector::Vector(int s)
|
||||
inline Vector::Vector(bigint s)
|
||||
{
|
||||
MFEM_ASSERT(s>=0,"Unexpected negative size.");
|
||||
size = s;
|
||||
@@ -581,7 +585,7 @@ inline Vector::Vector(int s)
|
||||
}
|
||||
}
|
||||
|
||||
inline void Vector::SetSize(int s)
|
||||
inline void Vector::SetSize(bigint s)
|
||||
{
|
||||
if (s == size)
|
||||
{
|
||||
@@ -601,7 +605,7 @@ inline void Vector::SetSize(int s)
|
||||
data.UseDevice(use_dev);
|
||||
}
|
||||
|
||||
inline void Vector::SetSize(int s, MemoryType mt)
|
||||
inline void Vector::SetSize(bigint s, MemoryType mt)
|
||||
{
|
||||
if (mt == data.GetMemoryType())
|
||||
{
|
||||
@@ -630,7 +634,7 @@ inline void Vector::SetSize(int s, MemoryType mt)
|
||||
data.UseDevice(use_dev);
|
||||
}
|
||||
|
||||
inline void Vector::Reserve(int res)
|
||||
inline void Vector::Reserve(bigint res)
|
||||
{
|
||||
if (res > Capacity())
|
||||
{
|
||||
@@ -642,7 +646,7 @@ inline void Vector::Reserve(int res)
|
||||
}
|
||||
}
|
||||
|
||||
inline void Vector::NewMemoryAndSize(const Memory<real_t> &mem, int s,
|
||||
inline void Vector::NewMemoryAndSize(const Memory<real_t> &mem, bigint s,
|
||||
bool own_mem)
|
||||
{
|
||||
data.Delete();
|
||||
@@ -657,14 +661,14 @@ inline void Vector::NewMemoryAndSize(const Memory<real_t> &mem, int s,
|
||||
}
|
||||
}
|
||||
|
||||
inline void Vector::MakeRef(Vector &base, int offset, int s)
|
||||
inline void Vector::MakeRef(Vector &base, bigint offset, bigint s)
|
||||
{
|
||||
data.Delete();
|
||||
size = s;
|
||||
data.MakeAlias(base.GetMemory(), offset, s);
|
||||
}
|
||||
|
||||
inline void Vector::MakeRef(Vector &base, int offset)
|
||||
inline void Vector::MakeRef(Vector &base, bigint offset)
|
||||
{
|
||||
data.Delete();
|
||||
data.MakeAlias(base.GetMemory(), offset, size);
|
||||
@@ -678,7 +682,7 @@ inline void Vector::Destroy()
|
||||
data.UseDevice(use_dev);
|
||||
}
|
||||
|
||||
inline real_t &Vector::operator()(int i)
|
||||
inline real_t &Vector::operator()(bigint i)
|
||||
{
|
||||
MFEM_ASSERT(data && i >= 0 && i < size,
|
||||
"index [" << i << "] is out of range [0," << size << ")");
|
||||
@@ -686,7 +690,7 @@ inline real_t &Vector::operator()(int i)
|
||||
return data[i];
|
||||
}
|
||||
|
||||
inline const real_t &Vector::operator()(int i) const
|
||||
inline const real_t &Vector::operator()(bigint i) const
|
||||
{
|
||||
MFEM_ASSERT(data && i >= 0 && i < size,
|
||||
"index [" << i << "] is out of range [0," << size << ")");
|
||||
@@ -712,11 +716,11 @@ inline Vector::~Vector()
|
||||
data.Delete();
|
||||
}
|
||||
|
||||
inline real_t DistanceSquared(const real_t *x, const real_t *y, const int n)
|
||||
inline real_t DistanceSquared(const real_t *x, const real_t *y, const bigint n)
|
||||
{
|
||||
real_t d = 0.0;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
for (bigint i = 0; i < n; i++)
|
||||
{
|
||||
d += (x[i]-y[i])*(x[i]-y[i]);
|
||||
}
|
||||
@@ -724,7 +728,7 @@ inline real_t DistanceSquared(const real_t *x, const real_t *y, const int n)
|
||||
return d;
|
||||
}
|
||||
|
||||
inline real_t Distance(const real_t *x, const real_t *y, const int n)
|
||||
inline real_t Distance(const real_t *x, const real_t *y, const bigint n)
|
||||
{
|
||||
return std::sqrt(DistanceSquared(x, y, n));
|
||||
}
|
||||
|
||||
+8
-8
@@ -15234,17 +15234,17 @@ void GeometricFactors::Compute(const GridFunction &nodes,
|
||||
Device::GetDeviceMemoryType();
|
||||
if (computed_factors & GeometricFactors::COORDINATES)
|
||||
{
|
||||
X.SetSize(vdim*NQ*NE, my_d_mt); // NQ x SDIM x NE
|
||||
X.SetSize(bigint(vdim)*NQ*NE, my_d_mt); // NQ x SDIM x NE
|
||||
eval_flags |= QuadratureInterpolator::VALUES;
|
||||
}
|
||||
if (computed_factors & GeometricFactors::JACOBIANS)
|
||||
{
|
||||
J.SetSize(dim*vdim*NQ*NE, my_d_mt); // NQ x SDIM x DIM x NE
|
||||
J.SetSize(bigint(dim)*vdim*NQ*NE, my_d_mt); // NQ x SDIM x DIM x NE
|
||||
eval_flags |= QuadratureInterpolator::DERIVATIVES;
|
||||
}
|
||||
if (computed_factors & GeometricFactors::DETERMINANTS)
|
||||
{
|
||||
detJ.SetSize(NQ*NE, my_d_mt); // NQ x NE
|
||||
detJ.SetSize(bigint(NQ)*NE, my_d_mt); // NQ x NE
|
||||
eval_flags |= QuadratureInterpolator::DETERMINANTS;
|
||||
}
|
||||
|
||||
@@ -15262,7 +15262,7 @@ void GeometricFactors::Compute(const GridFunction &nodes,
|
||||
|
||||
if (elem_restr) // Always true as of 2021-04-27
|
||||
{
|
||||
Vector Enodes(vdim*ND*NE, my_d_mt);
|
||||
Vector Enodes(bigint(vdim)*ND*NE, my_d_mt);
|
||||
elem_restr->Mult(nodes, Enodes);
|
||||
qi->Mult(Enodes, eval_flags, X, J, detJ);
|
||||
}
|
||||
@@ -15304,22 +15304,22 @@ FaceGeometricFactors::FaceGeometricFactors(const Mesh *mesh,
|
||||
|
||||
if (flags & FaceGeometricFactors::COORDINATES)
|
||||
{
|
||||
X.SetSize(vdim*NQ*NF, my_d_mt);
|
||||
X.SetSize(bigint(vdim)*NQ*NF, my_d_mt);
|
||||
eval_flags |= FaceQuadratureInterpolator::VALUES;
|
||||
}
|
||||
if (flags & FaceGeometricFactors::JACOBIANS)
|
||||
{
|
||||
J.SetSize(vdim*(mesh->Dimension() - 1)*NQ*NF, my_d_mt);
|
||||
J.SetSize(bigint(vdim)*(mesh->Dimension() - 1)*NQ*NF, my_d_mt);
|
||||
eval_flags |= FaceQuadratureInterpolator::DERIVATIVES;
|
||||
}
|
||||
if (flags & FaceGeometricFactors::DETERMINANTS)
|
||||
{
|
||||
detJ.SetSize(NQ*NF, my_d_mt);
|
||||
detJ.SetSize(bigint(NQ)*NF, my_d_mt);
|
||||
eval_flags |= FaceQuadratureInterpolator::DETERMINANTS;
|
||||
}
|
||||
if (flags & FaceGeometricFactors::NORMALS)
|
||||
{
|
||||
normal.SetSize(vdim*NQ*NF, my_d_mt);
|
||||
normal.SetSize(bigint(vdim)*NQ*NF, my_d_mt);
|
||||
eval_flags |= FaceQuadratureInterpolator::NORMALS;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ ParNCSubMesh::ParNCSubMesh(ParSubMesh& submesh, const ParNCMesh &parent,
|
||||
#ifdef MFEM_DEBUG
|
||||
// Check all processors have the same number of roots
|
||||
{
|
||||
int p[2] = {root_state.Size(), -root_state.Size()};
|
||||
int p[2] = {(int)root_state.Size(), -(int)root_state.Size()};
|
||||
MPI_Allreduce(MPI_IN_PLACE, p, 2, MPI_INT, MPI_MIN, submesh.GetComm());
|
||||
MFEM_ASSERT(p[0] == -p[1], "Ranks must agree on number of root elements: min "
|
||||
<< p[0] << " max " << -p[1] << " local " << root_state.Size() << " MyRank " <<
|
||||
@@ -154,4 +154,4 @@ ParNCSubMesh::ParNCSubMesh(ParSubMesh& submesh, const ParNCMesh &parent,
|
||||
|
||||
} // namespace mfem
|
||||
|
||||
#endif // MFEM_USE_MPI
|
||||
#endif // MFEM_USE_MPI
|
||||
|
||||
@@ -213,7 +213,7 @@ void test_derefine_L2_element(int order, Element::Type el_type, int basis_type)
|
||||
double eps = 1.e-3;
|
||||
|
||||
// limit to max 20 dofs for efficiency in 3D
|
||||
int test_ndofs = std::min(coarse_soln_v.Size(), 20);
|
||||
int test_ndofs = std::min(coarse_soln_v.Size(), bigint(20));
|
||||
for (int i = 0; i < test_ndofs; i++)
|
||||
{
|
||||
for (int f = -1; f <= 1; f += 2)
|
||||
|
||||
Reference in New Issue
Block a user