10 #ifndef TPETRA_DETAILS_NORMIMPL_HPP
11 #define TPETRA_DETAILS_NORMIMPL_HPP
22 #include "TpetraCore_config.h"
23 #include "Kokkos_Core.hpp"
24 #include "Teuchos_ArrayView.hpp"
25 #include "Teuchos_CommHelpers.hpp"
26 #include "KokkosBlas.hpp"
27 #include "Kokkos_ArithTraits.hpp"
29 #ifndef DOXYGEN_SHOULD_SKIP_THIS
33 template<
class OrdinalType>
36 #endif // DOXYGEN_SHOULD_SKIP_THIS
53 template <
class ValueType,
59 const Kokkos::View<const ValueType**, ArrayLayout, DeviceType>& X,
61 const Teuchos::ArrayView<const size_t>& whichVecs,
62 const bool isConstantStride,
63 const bool isDistributed,
64 const Teuchos::Comm<int>* comm);
77 template<
class RV,
class XMV>
79 lclNormImpl (
const RV& normsOut,
82 const Teuchos::ArrayView<const size_t>& whichVecs,
83 const bool constantStride,
87 using Kokkos::subview;
88 using mag_type =
typename RV::non_const_value_type;
90 static_assert (static_cast<int> (RV::rank) == 1,
91 "Tpetra::MultiVector::lclNormImpl: "
92 "The first argument normsOut must have rank 1.");
93 static_assert (Kokkos::is_view<XMV>::value,
94 "Tpetra::MultiVector::lclNormImpl: "
95 "The second argument X is not a Kokkos::View.");
96 static_assert (static_cast<int> (XMV::rank) == 2,
97 "Tpetra::MultiVector::lclNormImpl: "
98 "The second argument X must have rank 2.");
100 const size_t lclNumRows =
static_cast<size_t> (X.extent (0));
101 TEUCHOS_TEST_FOR_EXCEPTION
102 (lclNumRows != 0 && constantStride &&
103 static_cast<size_t> (X.extent (1)) != numVecs,
104 std::logic_error,
"Constant Stride X's dimensions are " << X.extent (0)
105 <<
" x " << X.extent (1) <<
", which differ from the local dimensions "
106 << lclNumRows <<
" x " << numVecs <<
". Please report this bug to "
107 "the Tpetra developers.");
108 TEUCHOS_TEST_FOR_EXCEPTION
109 (lclNumRows != 0 && ! constantStride &&
110 static_cast<size_t> (X.extent (1)) < numVecs,
111 std::logic_error,
"Strided X's dimensions are " << X.extent (0) <<
" x "
112 << X.extent (1) <<
", which are incompatible with the local dimensions "
113 << lclNumRows <<
" x " << numVecs <<
". Please report this bug to "
114 "the Tpetra developers.");
116 if (lclNumRows == 0) {
117 const mag_type zeroMag = Kokkos::ArithTraits<mag_type>::zero ();
119 using execution_space =
typename RV::execution_space;
123 if (constantStride) {
124 if (whichNorm == NORM_INF) {
125 KokkosBlas::nrminf (normsOut, X);
127 else if (whichNorm == NORM_ONE) {
128 KokkosBlas::nrm1 (normsOut, X);
130 else if (whichNorm == NORM_TWO) {
131 KokkosBlas::nrm2_squared (normsOut, X);
134 TEUCHOS_TEST_FOR_EXCEPTION
135 (
true, std::logic_error,
"Should never get here!");
144 for (
size_t k = 0; k < numVecs; ++k) {
145 const size_t X_col = constantStride ? k : whichVecs[k];
146 if (whichNorm == NORM_INF) {
147 KokkosBlas::nrminf (subview (normsOut, k),
148 subview (X, ALL (), X_col));
150 else if (whichNorm == NORM_ONE) {
151 KokkosBlas::nrm1 (subview (normsOut, k),
152 subview (X, ALL (), X_col));
154 else if (whichNorm == NORM_TWO) {
155 KokkosBlas::nrm2_squared (subview (normsOut, k),
156 subview (X, ALL (), X_col));
159 TEUCHOS_TEST_FOR_EXCEPTION
160 (
true, std::logic_error,
"Should never get here!");
169 template<
class ViewType>
170 class SquareRootFunctor {
172 typedef typename ViewType::execution_space execution_space;
173 typedef typename ViewType::size_type size_type;
175 SquareRootFunctor (
const ViewType& theView) :
179 KOKKOS_INLINE_FUNCTION
void
180 operator() (
const size_type& i)
const
182 typedef typename ViewType::non_const_value_type value_type;
183 typedef Kokkos::ArithTraits<value_type> KAT;
184 theView_(i) = KAT::sqrt (theView_(i));
193 gblNormImpl (
const RV& normsOut,
194 const Teuchos::Comm<int>*
const comm,
195 const bool distributed,
198 using Teuchos::REDUCE_MAX;
199 using Teuchos::REDUCE_SUM;
200 using Teuchos::reduceAll;
201 typedef typename RV::non_const_value_type mag_type;
203 const size_t numVecs = normsOut.extent (0);
218 if (distributed && comm !=
nullptr) {
222 const int nv =
static_cast<int> (numVecs);
223 const bool commIsInterComm = ::Tpetra::Details::isInterComm (*comm);
225 if (commIsInterComm) {
226 RV lclNorms (Kokkos::ViewAllocateWithoutInitializing (
"MV::normImpl lcl"), numVecs);
228 using execution_space =
typename RV::execution_space;
230 const mag_type*
const lclSum = lclNorms.data ();
231 mag_type*
const gblSum = normsOut.data ();
233 if (whichNorm == NORM_INF) {
234 reduceAll<int, mag_type> (*comm, REDUCE_MAX, nv, lclSum, gblSum);
236 reduceAll<int, mag_type> (*comm, REDUCE_SUM, nv, lclSum, gblSum);
239 mag_type*
const gblSum = normsOut.data ();
240 if (whichNorm == NORM_INF) {
241 reduceAll<int, mag_type> (*comm, REDUCE_MAX, nv, gblSum, gblSum);
243 reduceAll<int, mag_type> (*comm, REDUCE_SUM, nv, gblSum, gblSum);
248 if (whichNorm == NORM_TWO) {
254 const bool inHostMemory =
255 std::is_same<
typename RV::memory_space,
256 typename RV::host_mirror_space::memory_space>::value;
258 for (
size_t j = 0; j < numVecs; ++j) {
259 normsOut(j) = Kokkos::ArithTraits<mag_type>::sqrt (normsOut(j));
267 SquareRootFunctor<RV> f (normsOut);
268 typedef typename RV::execution_space execution_space;
269 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
270 Kokkos::parallel_for (range_type (0, numVecs), f);
277 template <
class ValueType,
283 const Kokkos::View<const ValueType**, ArrayLayout, DeviceType>& X,
285 const Teuchos::ArrayView<const size_t>& whichVecs,
286 const bool isConstantStride,
287 const bool isDistributed,
288 const Teuchos::Comm<int>* comm)
290 using execution_space =
typename DeviceType::execution_space;
291 using RV = Kokkos::View<MagnitudeType*, Kokkos::HostSpace>;
295 const size_t numVecs = isConstantStride ?
296 static_cast<size_t> (X.extent (1)) :
297 static_cast<size_t> (whichVecs.size ());
301 RV normsOut (norms, numVecs);
303 Impl::lclNormImpl (normsOut, X, numVecs, whichVecs,
304 isConstantStride, whichNorm);
311 execution_space exec_space_instance = execution_space();
312 exec_space_instance.fence();
314 Impl::gblNormImpl (normsOut, comm, isDistributed, whichNorm);
320 #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).