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");
122 : data(std::move(v.data)), size(v.size)
132 for (i = 0; i < np; i++)
141 for (i = 0; i < np; i++)
143 for (j = 0; j <
dim[i]; j++)
148 if (!*in[i] && errno == ERANGE)
161 for (
int i = 0; i <
size; i++)
166 if (!in && errno == ERANGE)
187#ifdef MFEM_USE_LEGACY_OPENMP
188 #pragma omp parallel for reduction(+:dot)
190 for (
int i = 0; i <
size; i++)
192 dot +=
data[i] * v[i];
212 const bool use_dev =
UseDevice() || vuse;
213 if (use_dev != vuse) { v.
UseDevice(use_dev); }
215 if (use_dev) {
Write(); }
217 if (use_dev != vuse) { v.
UseDevice(vuse); }
236 auto y =
Write(use_dev);
252 MFEM_ASSERT(
size == v.
size,
"incompatible Vectors!");
256 const auto x = v.
Read(use_dev);
274 MFEM_ASSERT(
size == v.
size,
"incompatible Vectors!");
278 const auto x = v.
Read(use_dev);
295 MFEM_ASSERT(
size == v.
size,
"incompatible Vectors!");
299 const auto x = v.
Read(use_dev);
316 MFEM_ASSERT(
size == v.
size,
"incompatible Vectors!");
320 const auto x = v.
Read(use_dev);
328 MFEM_ASSERT(
size == Va.
size,
"incompatible Vectors!");
334 const auto x = Va.
Read(use_dev);
343 MFEM_ASSERT(
size == Va.
size,
"incompatible Vectors!");
347 const auto x = Va.
Read(use_dev);
348 auto y =
Write(use_dev);
355 MFEM_ASSERT(v.
Size() + offset <=
size,
"invalid sub-vector");
358 const int vs = v.
Size();
359 const auto vp = v.
Read(use_dev);
367 MFEM_ASSERT(v.
Size() + offset <=
size,
"invalid sub-vector");
370 const int vs = v.
Size();
371 const auto vp = v.
Read(use_dev);
399 y[i] = std::abs(y[i]);
410 y[i] = std::pow(y[i],
p);
417 "incompatible Vectors!");
419#if !defined(MFEM_USE_LEGACY_OPENMP)
421 const int N = v.
size;
423 const auto x1 = v1.
Read(use_dev);
424 const auto x2 = v2.
Read(use_dev);
425 auto y = v.
Write(use_dev);
428 #pragma omp parallel for
429 for (
int i = 0; i < v.
size; i++)
439 "incompatible Vectors!");
445 else if (
alpha == 1.0)
451#if !defined(MFEM_USE_LEGACY_OPENMP)
453 const int N = v.
size;
455 const auto d_x = v1.
Read(use_dev);
456 const auto d_y = v2.
Read(use_dev);
457 auto d_z = v.
Write(use_dev);
460 d_z[i] = d_x[i] +
alpha * d_y[i];
465 const int s = v.
size;
466 #pragma omp parallel for
467 for (
int i = 0; i < s; i++)
469 vp[i] = v1p[i] +
alpha*v2p[i];
478 "incompatible Vectors!");
490#if !defined(MFEM_USE_LEGACY_OPENMP)
492 const int N = x.
size;
494 const auto xd = x.
Read(use_dev);
495 const auto yd = y.
Read(use_dev);
496 auto zd = z.
Write(use_dev);
499 zd[i] =
a * (xd[i] + yd[i]);
505 const int s = x.
size;
506 #pragma omp parallel for
507 for (
int i = 0; i < s; i++)
509 zp[i] =
a * (xp[i] + yp[i]);
519 "incompatible Vectors!");
545#if !defined(MFEM_USE_LEGACY_OPENMP)
547 const int N = x.
size;
549 const auto xd = x.
Read(use_dev);
550 const auto yd = y.
Read(use_dev);
551 auto zd = z.
Write(use_dev);
554 zd[i] =
a * xd[i] +
b * yd[i];
560 const int s = x.
size;
561 #pragma omp parallel for
562 for (
int i = 0; i < s; i++)
564 zp[i] =
a * xp[i] +
b * yp[i];
573 "incompatible Vectors!");
575#if !defined(MFEM_USE_LEGACY_OPENMP)
577 const int N = x.
size;
579 const auto xd = x.
Read(use_dev);
580 const auto yd = y.
Read(use_dev);
581 auto zd = z.
Write(use_dev);
584 zd[i] = xd[i] - yd[i];
590 const int s = x.
size;
591 #pragma omp parallel for
592 for (
int i = 0; i < s; i++)
594 zp[i] = xp[i] - yp[i];
602 "incompatible Vectors!");
614#if !defined(MFEM_USE_LEGACY_OPENMP)
616 const int N = x.
size;
618 const auto xd = x.
Read(use_dev);
619 const auto yd = y.
Read(use_dev);
620 auto zd = z.
Write(use_dev);
623 zd[i] =
a * (xd[i] - yd[i]);
629 const int s = x.
size;
630 #pragma omp parallel for
631 for (
int i = 0; i < s; i++)
633 zp[i] =
a * (xp[i] - yp[i]);
644 MFEM_VERIFY(
size == 3,
"Only 3D vectors supported in cross.");
645 MFEM_VERIFY(vin.
Size() == 3,
"Only 3D vectors supported in cross.");
647 vout(0) =
data[1]*vin(2)-
data[2]*vin(1);
648 vout(1) =
data[2]*vin(0)-
data[0]*vin(2);
649 vout(2) =
data[0]*vin(1)-
data[1]*vin(0);
655 "incompatible Vectors!");
660 const auto l = lo.
Read(use_dev);
661 const auto h = hi.
Read(use_dev);
662 auto m =
Write(use_dev);
669 else if (m[i] > h[i])
678 const int n = dofs.
Size();
681 const auto d_X =
Read(use_dev);
682 const auto d_dofs = dofs.
Read(use_dev);
683 auto d_y = elemvect.
Write(use_dev);
686 const int dof_i = d_dofs[i];
687 d_y[i] = dof_i >= 0 ? d_X[dof_i] : -d_X[-dof_i-1];
694 const int n = dofs.
Size();
695 for (
int i = 0; i < n; i++)
697 const int j = dofs[i];
698 elem_data[i] = (j >= 0) ?
data[j] : -
data[-1-j];
705 const int n = dofs.
Size();
708 const auto d_dofs = dofs.
Read(use_dev);
711 const int j = d_dofs[i];
726 for (
int i = 0; i < dofs.
Size(); ++i)
728 const int j = dofs[i];
735 (*this)[-1-j] = -value;
742 MFEM_ASSERT(dofs.
Size() <= elemvect.
Size(),
743 "Size mismatch: length of dofs is " << dofs.
Size()
744 <<
", length of elemvect is " << elemvect.
Size());
747 const int n = dofs.
Size();
750 const auto d_y = elemvect.
Read(use_dev);
751 const auto d_dofs = dofs.
Read(use_dev);
754 const int dof_i = d_dofs[i];
761 d_X[-1-dof_i] = -d_y[i];
770 const int n = dofs.
Size();
771 for (
int i = 0; i < n; i++)
773 const int j= dofs[i];
787 MFEM_ASSERT(dofs.
Size() <= elemvect.
Size(),
"Size mismatch: "
788 "length of dofs is " << dofs.
Size() <<
789 ", length of elemvect is " << elemvect.
Size());
792 const int n = dofs.
Size();
793 const auto d_y = elemvect.
Read(use_dev);
794 const auto d_dofs = dofs.
Read(use_dev);
798 const int j = d_dofs[i];
813 const int n = dofs.
Size();
814 for (
int i = 0; i < n; i++)
816 const int j = dofs[i];
831 MFEM_ASSERT(dofs.
Size() <= elemvect.
Size(),
"Size mismatch: "
832 "length of dofs is " << dofs.
Size() <<
833 ", length of elemvect is " << elemvect.
Size());
836 const int n = dofs.
Size();
837 const auto d_x = elemvect.
Read(use_dev);
838 const auto d_dofs = dofs.
Read(use_dev);
842 const int j = d_dofs[i];
845 d_y[j] +=
a * d_x[i];
849 d_y[-1-j] -=
a * d_x[i];
857 const int n = dofs.
Size();
859 Vector dofs_vals(n, use_dev ?
863 auto d_dofs_vals = dofs_vals.
Write(use_dev);
864 const auto d_dofs = dofs.
Read(use_dev);
865 mfem::forall_switch(use_dev, n, [=] MFEM_HOST_DEVICE (
int i) { d_dofs_vals[i] = d_data[d_dofs[i]]; });
867 mfem::forall_switch(use_dev, n, [=] MFEM_HOST_DEVICE (
int i) { d_data[d_dofs[i]] = d_dofs_vals[i]; });
872 if (!
size) {
return; }
882 if ( i % width == 0 )
894#ifdef MFEM_USE_ADIOS2
896 const std::string& variable_name)
const
898 if (!
size) {
return; }
900 os.engine.Put(variable_name, &
data[0] );
907 std::ios::fmtflags old_fmt = os.flags();
908 os.setf(std::ios::scientific);
909 std::streamsize old_prec = os.precision(14);
914 for (i = 0; i <
size; i++)
919 os.precision(old_prec);
925 std::ios::fmtflags old_fmt = os.flags();
926 os.setf(std::ios::scientific);
927 std::streamsize old_prec = os.precision(14);
929 os <<
"(* Read file into Mathematica using: "
930 <<
"myVec = Get[\"this_file_name\"] *)\n";
934 for (
int i = 0; i <
size; i++)
937 if (i <
size - 1) { os <<
','; }
943 os.precision(old_prec);
949 os <<
"size: " <<
size <<
'\n';
952 os <<
"hash: " << hf.
GetHash() <<
'\n';
957 if (seed == 0) { seed = (int)time(0); }
959 srand((
unsigned)seed);
962 for (
int i = 0; i <
size; i++)
973 if (
size == 0) {
return 0.0; }
981 reduce(
size, res, [=] MFEM_HOST_DEVICE(
int i, value_type &r)
983 real_t n = fabs(m_data[i]);
988 real_t arg = r.second / n;
989 r.first = r.first * (arg * arg) + 1;
994 real_t arg = n / r.second;
995 r.first += arg * arg;
999 L2Reducer{},
UseDevice(), Lpvector_workspace());
1001 return res.second * sqrt(res.first);
1006 if (
size == 0) {
return 0; }
1012 r = fmax(r, fabs(m_data[i]));
1020 if (
size == 0) {
return 0.0; }
1026 r += fabs(m_data[i]);
1034 MFEM_ASSERT(
p > 0.0,
"Vector::Normlp");
1036 if (
p == 1.0) {
return Norml1(); }
1038 if (
p == 2.0) {
return Norml2(); }
1045 if (
size == 0) {
return 0.0; }
1053 reduce(
size, res, [=] MFEM_HOST_DEVICE(
int i, value_type &r)
1055 real_t n = fabs(m_data[i]);
1060 real_t arg = r.second / n;
1061 r.first = r.first * pow(arg,
p) + 1;
1066 real_t arg = n / r.second;
1067 r.first += pow(arg,
p);
1071 LpReducer{
p},
UseDevice(), Lpvector_workspace());
1073 return res.second * pow(res.first, 1.0 /
p);
1081 MFEM_ASSERT(
size == v.
size,
"incompatible Vectors!");
1083 if (
size == 0) {
return 0.0; }
1086 const auto m_data =
Read(use_dev), v_data = v.
Read(use_dev);
1092 return occa::linalg::dot<real_t, real_t, real_t>(
1097 const auto compute_dot = [&]()
1102 r += m_data[i] * v_data[i];
1112#ifdef MFEM_USE_OPENMP
1116#define MFEM_USE_OPENMP_DETERMINISTIC_DOT
1117#ifdef MFEM_USE_OPENMP_DETERMINISTIC_DOT
1119 #pragma omp parallel
1121 const int nt = omp_get_num_threads();
1124 const int tid = omp_get_thread_num();
1125 const int stride = (
size + nt - 1) / nt;
1126 const int start = tid * stride;
1127 const int stop = std::min(start + stride,
size);
1129 for (
int i = start; i < stop; i++)
1131 my_dot += m_data[i] * v_data[i];
1134 th_dot(tid) = my_dot;
1136 return th_dot.
Sum();
1140 #pragma omp parallel for reduction(+ : prod)
1141 for (
int i = 0; i <
size; i++)
1143 prod += m_data[i] * v_data[i];
1151 return compute_dot();
1159 const auto m_data =
Read(use_dev);
1168 const auto compute_min = [&]()
1173 r = fmin(r, m_data[i]);
1183#ifdef MFEM_USE_OPENMP
1186 real_t minimum = m_data[0];
1187 #pragma omp parallel for reduction(min:minimum)
1188 for (
int i = 0; i <
size; i++)
1190 minimum = std::min(minimum, m_data[i]);
1197 return compute_min();
1205 const auto m_data =
Read(use_dev);
1214 const auto compute_max = [&]()
1219 r = fmax(r, m_data[i]);
1229#ifdef MFEM_USE_OPENMP
1232 real_t maximum = m_data[0];
1233 #pragma omp parallel for reduction(max : maximum)
1234 for (
int i = 0; i <
size; i++)
1236 maximum = fmax(maximum, m_data[i]);
1243 return compute_max();
1248 if (
size == 0) {
return 0.0; }
1268 const auto d_flag = workspace.
Write(use_dev);
1270 [=] MFEM_HOST_DEVICE(
int i) { d_flag[i] =
true; });
1271 const auto d_indices = indices.
Read(use_dev);
1276 d_flag[d_indices[i]] =
false;
1280 auto d_in = copy.Read(use_dev);
1281 auto d_out =
Write(use_dev);
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.
T * Write(bool on_dev=true)
Shortcut for mfem::Write(a.GetMemory(), a.Size(), on_dev).
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.
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.
void Pow(const real_t p)
(*this)(i) = pow((*this)(i), p)
real_t & Elem(int i)
Access Vector entries. Index i = 0 .. size-1.
void SetVector(const Vector &v, int offset)
(*this)[i + offset] = v[i]
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 SetSubVectorHost(const Array< int > &dofs, const real_t value)
Set the entries listed in dofs to the given value (always on host).
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)
(*this)[i + offset] += v[i]
void Swap(Vector &other)
Swap the contents of two Vectors.
void DeleteAt(const Array< int > &indices)
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.
void Abs()
(*this)(i) = abs((*this)(i))
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.
virtual real_t * HostReadWrite()
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), false).
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)
MFEM_HOST_DEVICE dual< value_type, gradient_type > pow(dual< value_type, gradient_type > a, dual< value_type, gradient_type > b)
implementation of a (dual) raised to the b (dual) power
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....
void CopyFlagged(bool use_dev, InputIt d_in, FlagIt d_flags, OutputIt d_out, NumSelectedIt d_num_selected_out, size_t num_items)
Equivalent to *d_num_selected_out = std::copy_if(d_in, d_in+num_items, d_out, [=](auto iter){ return ...
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)
@ DEVICE_MASK
Biwise-OR of all device backends.
@ OMP_MASK
Biwise-OR of all OpenMP backends.
Pair of values which can be used in device code.