42 #ifndef TPETRA_DETAILS_NORMIMPL_HPP
43 #define TPETRA_DETAILS_NORMIMPL_HPP
54 #include "TpetraCore_config.h"
55 #include "Kokkos_Core.hpp"
56 #include "Teuchos_ArrayView.hpp"
57 #include "Teuchos_CommHelpers.hpp"
58 #include "KokkosBlas.hpp"
59 #include "Kokkos_ArithTraits.hpp"
61 #ifndef DOXYGEN_SHOULD_SKIP_THIS
65 template<
class OrdinalType>
68 #endif // DOXYGEN_SHOULD_SKIP_THIS
85 template <
class ValueType,
91 const Kokkos::View<const ValueType**, ArrayLayout, DeviceType>& X,
93 const Teuchos::ArrayView<const size_t>& whichVecs,
94 const bool isConstantStride,
95 const bool isDistributed,
96 const Teuchos::Comm<int>* comm);
109 template<
class RV,
class XMV>
111 lclNormImpl (
const RV& normsOut,
113 const size_t numVecs,
114 const Teuchos::ArrayView<const size_t>& whichVecs,
115 const bool constantStride,
119 using Kokkos::subview;
120 using mag_type =
typename RV::non_const_value_type;
122 static_assert (static_cast<int> (RV::Rank) == 1,
123 "Tpetra::MultiVector::lclNormImpl: "
124 "The first argument normsOut must have rank 1.");
125 static_assert (Kokkos::Impl::is_view<XMV>::value,
126 "Tpetra::MultiVector::lclNormImpl: "
127 "The second argument X is not a Kokkos::View.");
128 static_assert (static_cast<int> (XMV::Rank) == 2,
129 "Tpetra::MultiVector::lclNormImpl: "
130 "The second argument X must have rank 2.");
132 const size_t lclNumRows =
static_cast<size_t> (X.extent (0));
133 TEUCHOS_TEST_FOR_EXCEPTION
134 (lclNumRows != 0 && constantStride &&
135 static_cast<size_t> (X.extent (1)) != numVecs,
136 std::logic_error,
"Constant Stride X's dimensions are " << X.extent (0)
137 <<
" x " << X.extent (1) <<
", which differ from the local dimensions "
138 << lclNumRows <<
" x " << numVecs <<
". Please report this bug to "
139 "the Tpetra developers.");
140 TEUCHOS_TEST_FOR_EXCEPTION
141 (lclNumRows != 0 && ! constantStride &&
142 static_cast<size_t> (X.extent (1)) < numVecs,
143 std::logic_error,
"Strided X's dimensions are " << X.extent (0) <<
" x "
144 << X.extent (1) <<
", which are incompatible with the local dimensions "
145 << lclNumRows <<
" x " << numVecs <<
". Please report this bug to "
146 "the Tpetra developers.");
148 if (lclNumRows == 0) {
149 const mag_type zeroMag = Kokkos::ArithTraits<mag_type>::zero ();
153 if (constantStride) {
154 if (whichNorm == NORM_INF) {
155 KokkosBlas::nrminf (normsOut, X);
157 else if (whichNorm == NORM_ONE) {
158 KokkosBlas::nrm1 (normsOut, X);
160 else if (whichNorm == NORM_TWO) {
161 KokkosBlas::nrm2_squared (normsOut, X);
164 TEUCHOS_TEST_FOR_EXCEPTION
165 (
true, std::logic_error,
"Should never get here!");
174 for (
size_t k = 0; k < numVecs; ++k) {
175 const size_t X_col = constantStride ? k : whichVecs[k];
176 if (whichNorm == NORM_INF) {
177 KokkosBlas::nrminf (subview (normsOut, k),
178 subview (X, ALL (), X_col));
180 else if (whichNorm == NORM_ONE) {
181 KokkosBlas::nrm1 (subview (normsOut, k),
182 subview (X, ALL (), X_col));
184 else if (whichNorm == NORM_TWO) {
185 KokkosBlas::nrm2_squared (subview (normsOut, k),
186 subview (X, ALL (), X_col));
189 TEUCHOS_TEST_FOR_EXCEPTION
190 (
true, std::logic_error,
"Should never get here!");
199 template<
class ViewType>
200 class SquareRootFunctor {
202 typedef typename ViewType::execution_space execution_space;
203 typedef typename ViewType::size_type size_type;
205 SquareRootFunctor (
const ViewType& theView) :
209 KOKKOS_INLINE_FUNCTION
void
210 operator() (
const size_type& i)
const
212 typedef typename ViewType::non_const_value_type value_type;
213 typedef Kokkos::Details::ArithTraits<value_type> KAT;
214 theView_(i) = KAT::sqrt (theView_(i));
223 gblNormImpl (
const RV& normsOut,
224 const Teuchos::Comm<int>*
const comm,
225 const bool distributed,
228 using Teuchos::REDUCE_MAX;
229 using Teuchos::REDUCE_SUM;
230 using Teuchos::reduceAll;
231 typedef typename RV::non_const_value_type mag_type;
233 const size_t numVecs = normsOut.extent (0);
248 if (distributed && comm !=
nullptr) {
254 RV lclNorms (
"MV::normImpl lcl", numVecs);
256 const mag_type*
const lclSum = lclNorms.data ();
257 mag_type*
const gblSum = normsOut.data ();
258 const int nv =
static_cast<int> (numVecs);
259 if (whichNorm == NORM_INF) {
260 reduceAll<int, mag_type> (*comm, REDUCE_MAX, nv, lclSum, gblSum);
262 reduceAll<int, mag_type> (*comm, REDUCE_SUM, nv, lclSum, gblSum);
266 if (whichNorm == NORM_TWO) {
272 const bool inHostMemory =
273 std::is_same<
typename RV::memory_space,
274 typename RV::host_mirror_space::memory_space>::value;
276 for (
size_t j = 0; j < numVecs; ++j) {
277 normsOut(j) = Kokkos::Details::ArithTraits<mag_type>::sqrt (normsOut(j));
285 SquareRootFunctor<RV> f (normsOut);
286 typedef typename RV::execution_space execution_space;
287 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
288 Kokkos::parallel_for (range_type (0, numVecs), f);
295 template <
class ValueType,
301 const Kokkos::View<const ValueType**, ArrayLayout, DeviceType>& X,
303 const Teuchos::ArrayView<const size_t>& whichVecs,
304 const bool isConstantStride,
305 const bool isDistributed,
306 const Teuchos::Comm<int>* comm)
308 using RV = Kokkos::View<MagnitudeType*, Kokkos::HostSpace>;
312 const size_t numVecs = isConstantStride ?
313 static_cast<size_t> (X.extent (1)) :
314 static_cast<size_t> (whichVecs.size ());
318 RV normsOut (norms, numVecs);
320 Impl::lclNormImpl (normsOut, X, numVecs, whichVecs,
321 isConstantStride, whichNorm);
322 Impl::gblNormImpl (normsOut, comm, isDistributed, whichNorm);
328 #endif // TPETRA_DETAILS_NORMIMPL_HPP
void deep_copy(MultiVector< DS, DL, DG, DN > &dst, const MultiVector< SS, SL, SG, SN > &src)
Copy the contents of the MultiVector src into dst.
void normImpl(MagnitudeType norms[], const Kokkos::View< const ValueType **, ArrayLayout, DeviceType > &X, const EWhichNorm whichNorm, const Teuchos::ArrayView< const size_t > &whichVecs, const bool isConstantStride, const bool isDistributed, const Teuchos::Comm< int > *comm)
Implementation of MultiVector norms.
EWhichNorm
Input argument for normImpl() (which see).