43 using value_type = DevicePair<real_t, real_t>;
44 static MFEM_HOST_DEVICE
void Join(value_type&
a,
const value_type &
b)
46 real_t scale = fmax(
a.second,
b.second);
52 a.first +=
b.first * s * s;
57 static MFEM_HOST_DEVICE
void SetInitialValue(value_type &
a)
77 using value_type = DevicePair<real_t, real_t>;
78 MFEM_HOST_DEVICE
void Join(value_type&
a,
const value_type &
b)
const
80 real_t scale = fmax(
a.second,
b.second);
83 a.first =
a.first * pow(
a.second / scale, p) +
84 b.first * pow(
b.second / scale, p);
89 static MFEM_HOST_DEVICE
void SetInitialValue(value_type &
a)
96static Array<real_t>& vector_workspace()
98 static Array<real_t> instance;
102static Array<DevicePair<real_t, real_t>> &Lpvector_workspace()
104 static Array<DevicePair<real_t, real_t>> instance;
110 const int s = v.
Size();
114 MFEM_ASSERT(!v.
data.
Empty(),
"invalid source vector");
123 *
this = std::move(v);
131 for (i = 0; i < np; i++)
140 for (i = 0; i < np; i++)
142 for (j = 0; j <
dim[i]; j++)
147 if (!*in[i] && errno == ERANGE)
160 for (
int i = 0; i <
size; i++)
165 if (!in && errno == ERANGE)
186#ifdef MFEM_USE_LEGACY_OPENMP
187 #pragma omp parallel for reduction(+:dot)
189 for (
int i = 0; i <
size; i++)
191 dot +=
data[i] * v[i];
211 const bool use_dev =
UseDevice() || vuse;
214 if (use_dev) {
Write(); }
224 if (
this != &v) { v.Destroy(); }
232 auto y =
Write(use_dev);
248 MFEM_ASSERT(
size == v.
size,
"incompatible Vectors!");
253 auto x = v.
Read(use_dev);
270 MFEM_ASSERT(
size == v.
size,
"incompatible Vectors!");
275 auto x = v.
Read(use_dev);
291 MFEM_ASSERT(
size == v.
size,
"incompatible Vectors!");
296 auto x = v.
Read(use_dev);
312 MFEM_ASSERT(
size == v.
size,
"incompatible Vectors!");
317 auto x = v.
Read(use_dev);
324 MFEM_ASSERT(
size == Va.
size,
"incompatible Vectors!");
331 auto x = Va.
Read(use_dev);
339 MFEM_ASSERT(
size == Va.
size,
"incompatible Vectors!");
343 auto x = Va.
Read(use_dev);
344 auto y =
Write(use_dev);
351 MFEM_ASSERT(v.
Size() + offset <=
size,
"invalid sub-vector");
353 const int vs = v.
Size();
356 for (
int i = 0; i < vs; i++)
364 MFEM_ASSERT(v.
Size() + offset <=
size,
"invalid sub-vector");
366 const int vs = v.
Size();
369 for (
int i = 0; i < vs; i++)
394 "incompatible Vectors!");
396#if !defined(MFEM_USE_LEGACY_OPENMP)
398 const int N = v.
size;
400 auto x1 = v1.
Read(use_dev);
401 auto x2 = v2.
Read(use_dev);
402 auto y = v.
Write(use_dev);
405 #pragma omp parallel for
406 for (
int i = 0; i < v.
size; i++)
416 "incompatible Vectors!");
422 else if (
alpha == 1.0)
428#if !defined(MFEM_USE_LEGACY_OPENMP)
430 const int N = v.
size;
432 auto d_x = v1.
Read(use_dev);
433 auto d_y = v2.
Read(use_dev);
434 auto d_z = v.
Write(use_dev);
437 d_z[i] = d_x[i] +
alpha * d_y[i];
442 const int s = v.
size;
443 #pragma omp parallel for
444 for (
int i = 0; i < s; i++)
446 vp[i] = v1p[i] +
alpha*v2p[i];
455 "incompatible Vectors!");
467#if !defined(MFEM_USE_LEGACY_OPENMP)
469 const int N = x.
size;
471 auto xd = x.
Read(use_dev);
472 auto yd = y.
Read(use_dev);
473 auto zd = z.
Write(use_dev);
476 zd[i] =
a * (xd[i] + yd[i]);
482 const int s = x.
size;
483 #pragma omp parallel for
484 for (
int i = 0; i < s; i++)
486 zp[i] =
a * (xp[i] + yp[i]);
496 "incompatible Vectors!");
522#if !defined(MFEM_USE_LEGACY_OPENMP)
524 const int N = x.
size;
526 auto xd = x.
Read(use_dev);
527 auto yd = y.
Read(use_dev);
528 auto zd = z.
Write(use_dev);
531 zd[i] =
a * xd[i] +
b * yd[i];
537 const int s = x.
size;
538 #pragma omp parallel for
539 for (
int i = 0; i < s; i++)
541 zp[i] =
a * xp[i] +
b * yp[i];
550 "incompatible Vectors!");
552#if !defined(MFEM_USE_LEGACY_OPENMP)
554 const int N = x.
size;
556 auto xd = x.
Read(use_dev);
557 auto yd = y.
Read(use_dev);
558 auto zd = z.
Write(use_dev);
561 zd[i] = xd[i] - yd[i];
567 const int s = x.
size;
568 #pragma omp parallel for
569 for (
int i = 0; i < s; i++)
571 zp[i] = xp[i] - yp[i];
579 "incompatible Vectors!");
591#if !defined(MFEM_USE_LEGACY_OPENMP)
593 const int N = x.
size;
595 auto xd = x.
Read(use_dev);
596 auto yd = y.
Read(use_dev);
597 auto zd = z.
Write(use_dev);
600 zd[i] =
a * (xd[i] - yd[i]);
606 const int s = x.
size;
607 #pragma omp parallel for
608 for (
int i = 0; i < s; i++)
610 zp[i] =
a * (xp[i] - yp[i]);
621 MFEM_VERIFY(
size == 3,
"Only 3D vectors supported in cross.");
622 MFEM_VERIFY(vin.
Size() == 3,
"Only 3D vectors supported in cross.");
624 vout(0) =
data[1]*vin(2)-
data[2]*vin(1);
625 vout(1) =
data[2]*vin(0)-
data[0]*vin(2);
626 vout(2) =
data[0]*vin(1)-
data[1]*vin(0);
632 "incompatible Vectors!");
637 auto l = lo.
Read(use_dev);
638 auto h = hi.
Read(use_dev);
639 auto m =
Write(use_dev);
646 else if (m[i] > h[i])
655 const int n = dofs.
Size();
658 auto d_y = elemvect.
Write(use_dev);
659 auto d_X =
Read(use_dev);
660 auto d_dofs = dofs.
Read(use_dev);
663 const int dof_i = d_dofs[i];
664 d_y[i] = dof_i >= 0 ? d_X[dof_i] : -d_X[-dof_i-1];
671 const int n = dofs.
Size();
672 for (
int i = 0; i < n; i++)
674 const int j = dofs[i];
675 elem_data[i] = (j >= 0) ?
data[j] : -
data[-1-j];
682 const int n = dofs.
Size();
685 auto d_dofs = dofs.
Read(use_dev);
688 const int j = d_dofs[i];
702 MFEM_ASSERT(dofs.
Size() <= elemvect.
Size(),
703 "Size mismatch: length of dofs is " << dofs.
Size()
704 <<
", length of elemvect is " << elemvect.
Size());
707 const int n = dofs.
Size();
710 auto d_y = elemvect.
Read(use_dev);
711 auto d_dofs = dofs.
Read(use_dev);
714 const int dof_i = d_dofs[i];
721 d_X[-1-dof_i] = -d_y[i];
730 const int n = dofs.
Size();
731 for (
int i = 0; i < n; i++)
733 const int j= dofs[i];
747 MFEM_ASSERT(dofs.
Size() <= elemvect.
Size(),
"Size mismatch: "
748 "length of dofs is " << dofs.
Size() <<
749 ", length of elemvect is " << elemvect.
Size());
752 const int n = dofs.
Size();
753 auto d_y = elemvect.
Read(use_dev);
755 auto d_dofs = dofs.
Read(use_dev);
758 const int j = d_dofs[i];
773 const int n = dofs.
Size();
774 for (
int i = 0; i < n; i++)
776 const int j = dofs[i];
791 MFEM_ASSERT(dofs.
Size() <= elemvect.
Size(),
"Size mismatch: "
792 "length of dofs is " << dofs.
Size() <<
793 ", length of elemvect is " << elemvect.
Size());
796 const int n = dofs.
Size();
798 auto d_x = elemvect.
Read(use_dev);
799 auto d_dofs = dofs.
Read(use_dev);
802 const int j = d_dofs[i];
805 d_y[j] +=
a * d_x[i];
809 d_y[-1-j] -=
a * d_x[i];
817 const int n = dofs.
Size();
819 Vector dofs_vals(n, use_dev ?
823 auto d_dofs_vals = dofs_vals.
Write(use_dev);
824 auto d_dofs = dofs.
Read(use_dev);
825 mfem::forall_switch(use_dev, n, [=] MFEM_HOST_DEVICE (
int i) { d_dofs_vals[i] = d_data[d_dofs[i]]; });
827 mfem::forall_switch(use_dev, n, [=] MFEM_HOST_DEVICE (
int i) { d_data[d_dofs[i]] = d_dofs_vals[i]; });
832 if (!
size) {
return; }
842 if ( i % width == 0 )
854#ifdef MFEM_USE_ADIOS2
856 const std::string& variable_name)
const
858 if (!
size) {
return; }
860 os.engine.Put(variable_name, &
data[0] );
867 std::ios::fmtflags old_fmt = os.flags();
868 os.setf(std::ios::scientific);
869 std::streamsize old_prec = os.precision(14);
874 for (i = 0; i <
size; i++)
879 os.precision(old_prec);
885 std::ios::fmtflags old_fmt = os.flags();
886 os.setf(std::ios::scientific);
887 std::streamsize old_prec = os.precision(14);
889 os <<
"(* Read file into Mathematica using: "
890 <<
"myVec = Get[\"this_file_name\"] *)\n";
894 for (
int i = 0; i <
size; i++)
897 if (i <
size - 1) { os <<
','; }
903 os.precision(old_prec);
909 os <<
"size: " <<
size <<
'\n';
912 os <<
"hash: " << hf.
GetHash() <<
'\n';
922 srand((
unsigned)seed);
925 for (
int i = 0; i <
size; i++)
949 [=] MFEM_HOST_DEVICE(
int i, value_type &r)
951 real_t n = fabs(m_data[i]);
956 real_t arg = r.second / n;
957 r.first = r.first * (arg * arg) + 1;
962 real_t arg = n / r.second;
963 r.first += arg * arg;
967 L2Reducer{},
UseDevice(), Lpvector_workspace());
969 return res.second * sqrt(res.first);
974 if (
size == 0) {
return 0; }
980 [=] MFEM_HOST_DEVICE(
int i,
real_t &r) { r = fmax(r, fabs(m_data[i])); },
987 if (
size == 0) {
return 0.0; }
993 [=] MFEM_HOST_DEVICE(
int i,
real_t &r) { r += fabs(m_data[i]); },
1000 MFEM_ASSERT(
p > 0.0,
"Vector::Normlp");
1028 [=] MFEM_HOST_DEVICE(
int i, value_type &r)
1030 real_t n = fabs(m_data[i]);
1035 real_t arg = r.second / n;
1036 r.first = r.first * pow(arg,
p) + 1;
1041 real_t arg = n / r.second;
1042 r.first += pow(arg,
p);
1046 LpReducer{
p},
UseDevice(), Lpvector_workspace());
1048 return res.second * pow(res.first, 1.0 /
p);
1056 MFEM_ASSERT(
size == v.
size,
"incompatible Vectors!");
1057 if (
size == 0) {
return 0.0; }
1061 auto m_data =
Read(use_dev);
1062 auto v_data = v.
Read(use_dev);
1070 return occa::linalg::dot<real_t, real_t, real_t>(
1075#ifdef MFEM_USE_OPENMP
1078#define MFEM_USE_OPENMP_DETERMINISTIC_DOT
1079#ifdef MFEM_USE_OPENMP_DETERMINISTIC_DOT
1082 #pragma omp parallel
1084 const int nt = omp_get_num_threads();
1087 const int tid = omp_get_thread_num();
1088 const int stride = (
size + nt - 1) / nt;
1089 const int start = tid * stride;
1090 const int stop = std::min(start + stride,
size);
1092 for (
int i = start; i < stop; i++)
1094 my_dot += m_data[i] * v_data[i];
1097 th_dot(tid) = my_dot;
1099 return th_dot.
Sum();
1103 #pragma omp parallel for reduction(+ : prod)
1104 for (
int i = 0; i <
size; i++)
1106 prod += m_data[i] * v_data[i];
1118 [=] MFEM_HOST_DEVICE(
int i,
real_t &r) { r += m_data[i] * v_data[i]; },
1128 auto m_data =
Read(use_dev);
1141#ifdef MFEM_USE_OPENMP
1144 real_t minimum = m_data[0];
1145 #pragma omp parallel for reduction(min:minimum)
1146 for (
int i = 0; i <
size; i++)
1148 minimum = std::min(minimum, m_data[i]);
1159 [=] MFEM_HOST_DEVICE(
int i,
real_t &r) { r = fmin(r, m_data[i]); },
1169 auto m_data =
Read(use_dev);
1181#ifdef MFEM_USE_OPENMP
1184 real_t maximum = m_data[0];
1185 #pragma omp parallel for reduction(max : maximum)
1186 for (
int i = 0; i <
size; i++)
1188 maximum = fmax(maximum, m_data[i]);
1199 [=] MFEM_HOST_DEVICE(
int i,
real_t &r) { r = fmax(r, m_data[i]); },
1206 if (
size == 0) {
return 0.0; }
1211 size, res, [=] MFEM_HOST_DEVICE(
int i,
real_t &r) { r += m_data[i]; },
int Size() const
Return the logical size of the array.
bool UseDevice() const
Return the device flag of the Memory object used by the Array.
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
static MemoryType GetHostMemoryType()
Get the current Host MemoryType. This is the MemoryType used by most MFEM classes when allocating mem...
static bool Allows(unsigned long b_mask)
Return true if any of the backends in the backend mask, b_mask, are allowed.
static MemoryType GetDeviceMemoryType()
Get the current Device MemoryType. This is the MemoryType used by most MFEM classes when allocating m...
Hash function for data sequences.
std::string GetHash() const
Return the hash string for the current sequence and reset (clear) the sequence.
HashFunction & AppendDoubles(const real_t *doubles, size_t num_doubles)
Add a sequence of doubles for hashing, given as a c-array.
void CopyFromHost(const T *src, int size)
Copy size entries from the host pointer src to *this.
T * ReadWrite(MemoryClass mc, int size)
Get read-write access to the memory with the given MemoryClass.
MemoryType GetMemoryType() const
Return a MemoryType that is currently valid. If both the host and the device pointers are currently v...
bool Empty() const
Return true if the Memory object is empty, see Reset().
const T * Read(MemoryClass mc, int size) const
Get read-only access to the memory with the given MemoryClass.
void CopyFrom(const Memory &src, int size)
Copy size entries from src to *this.
void New(int size)
Allocate host memory for size entries with the current host memory type returned by MemoryManager::Ge...
void Randomize(int seed=0)
Set random values in the vector.
void PrintHash(std::ostream &out) const
Print the Vector size and hash of its data.
real_t & Elem(int i)
Access Vector entries. Index i = 0 .. size-1.
void SetVector(const Vector &v, int offset)
virtual const real_t * HostRead() const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), false).
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
void median(const Vector &lo, const Vector &hi)
v = median(v,lo,hi) entrywise. Implementation assumes lo <= hi.
void Neg()
(*this) = -(*this)
void Print(std::ostream &out=mfem::out, int width=8) const
Prints vector to stream out.
virtual real_t * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
real_t operator*(const real_t *v) const
real_t Normlinf() const
Returns the l_infinity norm of the vector.
real_t Norml1() const
Returns the l_1 norm of the vector.
void SetSubVector(const Array< int > &dofs, const real_t value)
Set the entries listed in dofs to the given value.
void AddElementVector(const Array< int > &dofs, const Vector &elemvect)
Add elements of the elemvect Vector to the entries listed in dofs. Negative dof values cause the -dof...
void AddSubVector(const Vector &v, int offset)
void Swap(Vector &other)
Swap the contents of two Vectors.
Vector & operator*=(real_t c)
real_t Norml2() const
Returns the l2 norm of the vector.
void Load(std::istream **in, int np, int *dim)
Reads a vector from multiple files.
Vector & Set(const real_t a, const Vector &x)
(*this) = a * x
real_t Max() const
Returns the maximal element of the vector.
virtual bool UseDevice() const
Return the device flag of the Memory object used by the Vector.
int Size() const
Returns the size of the vector.
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
real_t Sum() const
Return the sum of the vector entries.
void PrintMathematica(std::ostream &out=mfem::out) const
Prints vector as a List for importing into Mathematica.
void Print_HYPRE(std::ostream &out) const
Prints vector to stream out in HYPRE_Vector format.
void SetSize(int s)
Resize the vector to size s.
void Reciprocal()
(*this)(i) = 1.0 / (*this)(i)
virtual real_t * HostWrite()
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), false).
real_t Normlp(real_t p) const
Returns the l_p norm of the vector.
Vector & operator-=(real_t c)
Vector & operator=(const real_t *v)
Copy Size() entries from v.
void SetSubVectorComplement(const Array< int > &dofs, const real_t val)
Set all vector entries NOT in the dofs Array to the given val.
real_t Min() const
Returns the minimal element of the vector.
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Extract entries listed in dofs to the output Vector elemvect.
Vector & operator+=(real_t c)
virtual real_t * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
Vector & Add(const real_t a, const Vector &Va)
(*this) += a * Va
real_t & operator()(int i)
Access Vector entries using () for 0-based indexing.
void cross3D(const Vector &vin, Vector &vout) const
Vector & operator/=(real_t c)
real_t infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
void reduce(int N, T &res, B &&body, const R &reducer, bool use_dev, Array< T > &workspace)
Performs a 1D reduction on the range [0,N). res initial value and where the result will be written....
real_t rand_real()
Generate a random real_t number in the interval [0,1) using rand().
void add(const Vector &v1, const Vector &v2, Vector &v)
bool DeviceCanUseOcca()
Function that determines if an OCCA kernel should be used, based on the current mfem::Device configur...
void subtract(const Vector &x, const Vector &y, Vector &z)
const occa::memory OccaMemoryRead(const Memory< T > &mem, size_t size)
Wrap a Memory object as occa::memory for read only access with the mfem::Device MemoryClass....
void forall_switch(bool use_dev, int N, lambda &&body)
real_t p(const Vector &x, real_t t)
@ OMP_MASK
Biwise-OR of all OpenMP backends.
Pair of values which can be used in device code.