Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Stokhos_Tpetra_UQ_PCE.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Stokhos Package
5 // Copyright (2009) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Eric T. Phipps (etphipp@sandia.gov).
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 #ifndef STOKHOS_TPETRA_UQ_PCE_HPP
43 #define STOKHOS_TPETRA_UQ_PCE_HPP
44 
45 // This header file should be included whenever compiling any Tpetra
46 // code with Stokhos scalar types
47 
48 // MP includes and specializations
50 
51 // Kokkos includes
52 #include "Tpetra_ConfigDefs.hpp"
53 #include "Tpetra_MultiVector_fwd.hpp"
54 #include "Tpetra_Vector_fwd.hpp"
55 #include "Kokkos_Core.hpp"
56 #include "Kokkos_BufferMacros.hpp"
57 #include "KokkosCompat_ClassicNodeAPI_Wrapper.hpp"
58 #include "KokkosCompat_View.hpp"
59 #include "KokkosCompat_View_def.hpp"
60 
61 // Hack for mean-based prec-setup where we get the PCE size from the first
62 // entry in the Teuchos::ArrayView. This is clearly quite dangerous and is
63 // likely to bite us in the ass at some point!
64 namespace Kokkos {
65  namespace Compat {
66  template <typename D, typename S>
67  Kokkos::View<Sacado::UQ::PCE<S>*,D>
69  typedef Sacado::UQ::PCE<S> T;
70  typedef typename Kokkos::Impl::if_c<
71  ::Kokkos::Impl::VerifyExecutionCanAccessMemorySpace< D, Kokkos::HostSpace>::value,
72  typename D::execution_space, Kokkos::HostSpace>::type
73  HostDevice;
74  typedef Kokkos::View<T*,D> view_type;
75  typedef Kokkos::View<T*,typename view_type::array_layout,HostDevice,Kokkos::MemoryUnmanaged> unmanaged_host_view_type;
76  if (a.size() == 0)
77  return view_type();
78  view_type v("", a.size(), a[0].size());
79  unmanaged_host_view_type hv(a.getRawPtr(), a.size(), a[0].size());
80  Kokkos::deep_copy(v,hv);
81  return v;
82  }
83 
84  template <typename D, typename S>
85  Kokkos::View<const Sacado::UQ::PCE<S>*,D>
87  typedef Sacado::UQ::PCE<S> T;
88  typedef typename Kokkos::Impl::if_c<
89  ::Kokkos::Impl::VerifyExecutionCanAccessMemorySpace< D, Kokkos::HostSpace>::value,
90  typename D::execution_space, Kokkos::HostSpace>::type
91  HostDevice;
92  typedef Kokkos::View<T*,D> view_type;
93  typedef Kokkos::View<const T*,typename view_type::array_layout,HostDevice,Kokkos::MemoryUnmanaged> unmanaged_host_view_type;
94  if (a.size() == 0)
95  return view_type();
96  view_type v("", a.size(), a[0].size());
97  unmanaged_host_view_type hv(a.getRawPtr(), a.size(), a[0].size());
98  Kokkos::deep_copy(v,hv);
99  return v;
100  }
101  }
102 }
103 
104 // Kokkos-Linalg
107 #include "Kokkos_MV_UQ_PCE.hpp"
114 #include "Kokkos_Random_UQ_PCE.hpp"
115 
116 namespace Stokhos {
117 
118 // Traits for determining device type from node type
119 template <typename Node>
121  // Prefer Serial execution space as the default, but if that's not
122  // available, use the Host memory space's default execution space.
123 #if defined(KOKKOS_ENABLE_SERIAL)
124  typedef Kokkos::Serial type;
125 #else
127 #endif // defined(KOKKOS_ENABLE_SERIAL)
128 };
129 
130 template <typename Device>
131 struct DeviceForNode2< Kokkos::Compat::KokkosDeviceWrapperNode<Device> > {
132  typedef Device type;
133 };
134 
135 }
136 
137 #include "Tpetra_Details_PackTraits.hpp"
138 
139 namespace Tpetra {
140 namespace Details {
141 
146 template<typename S, typename D>
147 struct PackTraits< Sacado::UQ::PCE<S>, D > {
150  typedef D device_type;
151  typedef typename execution_space::size_type size_type;
152 
155  static const bool compileTimeSize = false;
156 
157  typedef Kokkos::View<const char*, device_type, Kokkos::MemoryUnmanaged> input_buffer_type;
158  typedef Kokkos::View<char*, device_type, Kokkos::MemoryUnmanaged> output_buffer_type;
159  typedef Kokkos::View<const value_type*, device_type, Kokkos::MemoryUnmanaged> input_array_type;
160  typedef Kokkos::View<value_type*, device_type, Kokkos::MemoryUnmanaged> output_array_type;
161 
163  typedef PackTraits< scalar_value_type, device_type > SPT;
164  typedef typename SPT::input_array_type scalar_input_array_type;
165  typedef typename SPT::output_array_type scalar_output_array_type;
166 
167  KOKKOS_INLINE_FUNCTION
168  static size_t numValuesPerScalar (const value_type& x) {
169  return x.size ();
170  }
171 
172  static Kokkos::View<value_type*, device_type>
173  allocateArray (const value_type& x, const size_t numEnt, const std::string& label = "")
174  {
175  typedef Kokkos::View<value_type*, device_type> view_type;
176 
177  const size_type numVals = numValuesPerScalar (x);
178  return view_type (label, static_cast<size_type> (numEnt), numVals);
179  }
180 
181  KOKKOS_INLINE_FUNCTION
182  static Kokkos::pair<int, size_t>
183  packArray (char outBuf[],
184  const value_type inBuf[],
185  const size_t numEnt)
186  {
187  typedef Kokkos::pair<int, size_t> return_type;
188  size_t numBytes = 0;
189  int errorCode = 0;
190 
191  if (numEnt == 0) {
192  return return_type (errorCode, numBytes);
193  }
194  else {
195  // Check whether input array is contiguously allocated based on the size
196  // of the first entry. We can only pack contiguously allocated data
197  // since that is the only way we can guarrantee all of the PCE arrays
198  // are the same size and the buffer will allocated correctly.
199  const size_t scalar_size = numValuesPerScalar (inBuf[0]);
200  const scalar_value_type* last_coeff = inBuf[numEnt - 1].coeff ();
201  const scalar_value_type* last_coeff_expected =
202  inBuf[0].coeff () + (numEnt - 1)*scalar_size;
203  const bool is_contiguous = (last_coeff == last_coeff_expected);
204  if (! is_contiguous) {
205  // Cannot pack non-contiguous PCE array since buffer size calculation
206  // is likely wrong.
207  errorCode = 3;
208  return return_type (errorCode, numBytes);
209  }
210 
211  // Check we are packing length-1 PCE arrays (mean-based preconditioner).
212  // We can technically pack length > 1, but the unpack assumes the
213  // output array is sized appropriately. Currently this is not the case
214  // in Tpetra::CrsMatrix::transferAndFillComplete() which allocates a
215  // local Teuchos::Array for the CSR values, which will only be length-1
216  // by default.
217  if (scalar_size != 1) {
218  // Cannot pack PCE array with pce_size > 1 since unpack array
219  // may not be allocated correctly.
220  errorCode = 4;
221  return return_type (errorCode, numBytes);
222  }
223 
224  const size_t flat_numEnt = numEnt * scalar_size;
225  return SPT::packArray (outBuf, inBuf[0].coeff (), flat_numEnt);
226  }
227  }
228 
229  KOKKOS_INLINE_FUNCTION
230  static Kokkos::pair<int, size_t>
232  const char inBuf[],
233  const size_t numEnt)
234  {
235  typedef Kokkos::pair<int, size_t> return_type;
236  size_t numBytes = 0;
237  int errorCode = 0;
238 
239  if (numEnt == 0) {
240  return return_type (errorCode, numBytes);
241  }
242  else {
243  // Check whether output array is contiguously allocated based on the size
244  // of the first entry. We have a simpler method to unpack in this case
245  const size_type scalar_size = numValuesPerScalar (outBuf[0]);
246  const scalar_value_type* last_coeff = outBuf[numEnt - 1].coeff ();
247  const scalar_value_type* last_coeff_expected =
248  outBuf[0].coeff () + (numEnt - 1) * scalar_size;
249  const bool is_contiguous = (last_coeff == last_coeff_expected);
250 
251  if (is_contiguous) {
252  // Unpack all of the PCE coefficients for the whole array
253  const size_t flat_numEnt = numEnt * scalar_size;
254  return SPT::unpackArray (outBuf[0].coeff (), inBuf, flat_numEnt);
255  }
256  else {
257  // Unpack one entry at a time. This assumes each entry of outBuf
258  // is the correct size based on the packing. This is is only
259  // guarranteed to be true for pce_size == 1, hence the check in
260  // packArray().
261  size_t numBytesTotal = 0;
262  for (size_t i = 0; i < numEnt; ++i) {
263  const char* inBufVal = inBuf + numBytesTotal;
264  const size_t numBytes = unpackValue (outBuf[i], inBufVal);
265  numBytesTotal += numBytes;
266  }
267  return return_type (errorCode, numBytesTotal);
268  }
269  }
270  }
271 
272  KOKKOS_INLINE_FUNCTION
273  static size_t
274  packValueCount (const value_type& inVal)
275  {
276  return inVal.size () * SPT::packValueCount (inVal.val ());
277  }
278 
279  KOKKOS_INLINE_FUNCTION
280  static size_t
281  packValue (char outBuf[],
282  const value_type& inVal)
283  {
284  const size_t numBytes = packValueCount (inVal);
285  memcpy (outBuf, inVal.coeff (), numBytes);
286  return numBytes;
287  }
288 
289  KOKKOS_INLINE_FUNCTION
290  static size_t
291  packValue (char outBuf[],
292  const size_t outBufIndex,
293  const value_type& inVal)
294  {
295  const size_t numBytes = packValueCount (inVal);
296  const size_t offset = outBufIndex * numBytes;
297  memcpy (outBuf + offset, inVal.coeff (), numBytes);
298  return numBytes;
299  }
300 
301  KOKKOS_INLINE_FUNCTION
302  static size_t
303  unpackValue (value_type& outVal, const char inBuf[])
304  {
305  const size_t numBytes = packValueCount (outVal);
306  memcpy (outVal.coeff (), inBuf, numBytes);
307  return numBytes;
308  }
309 }; // struct PackTraits
310 
311 } // namespace Details
312 } // namespace Tpetra
313 
314 namespace Kokkos {
315  template <class S, class L, class G, class N>
316  size_t dimension_scalar(const Tpetra::MultiVector<S,L,G,N>& mv) {
317  if ( mv.need_sync_device() ) {
318  // NOTE (mfh 02 Apr 2019) This doesn't look right. Shouldn't I
319  // want the most recently updated View, which in this case would
320  // be the host View? However, this is what I found when I
321  // changed these lines not to call deprecated code, so I'm
322  // leaving it.
323  return dimension_scalar(mv.getLocalViewDevice());
324  }
325  return dimension_scalar(mv.getLocalViewHost());
326  }
327 
328  template <class S, class L, class G, class N>
329  size_t dimension_scalar(const Tpetra::Vector<S,L,G,N>& v) {
330  if ( v.need_sync_device() ) {
331  // NOTE (mfh 02 Apr 2019) This doesn't look right. Shouldn't I
332  // want the most recently updated View, which in this case would
333  // be the host View? However, this is what I found when I
334  // changed these lines not to call deprecated code, so I'm
335  // leaving it.
336  return dimension_scalar(v.getLocalViewDevice());
337  }
338  return dimension_scalar(v.getLocalViewHost());
339  }
340 }
341 
342 #endif // STOKHOS_TPETRA_UQ_PCE_HPP
Kokkos::View< const char *, device_type, Kokkos::MemoryUnmanaged > input_buffer_type
PackTraits< scalar_value_type, device_type > SPT
Kokkos::DefaultExecutionSpace execution_space
Kokkos::View< Sacado::UQ::PCE< S > *, D > getKokkosViewDeepCopy(const Teuchos::ArrayView< Sacado::UQ::PCE< S > > &a)
KOKKOS_INLINE_FUNCTION constexpr std::enable_if< is_view_uq_pce< View< T, P...> >::value, unsigned >::type dimension_scalar(const View< T, P...> &view)
Kokkos::HostSpace::execution_space type
Kokkos::View< const value_type *, device_type, Kokkos::MemoryUnmanaged > input_array_type
static KOKKOS_INLINE_FUNCTION size_t numValuesPerScalar(const value_type &x)
void deep_copy(const Stokhos::CrsMatrix< ValueType, DstDevice, Layout > &dst, const Stokhos::CrsMatrix< ValueType, SrcDevice, Layout > &src)
static KOKKOS_INLINE_FUNCTION size_t packValueCount(const value_type &inVal)
static KOKKOS_INLINE_FUNCTION Kokkos::pair< int, size_t > unpackArray(value_type outBuf[], const char inBuf[], const size_t numEnt)
static Kokkos::View< value_type *, device_type > allocateArray(const value_type &x, const size_t numEnt, const std::string &label="")
static KOKKOS_INLINE_FUNCTION size_t packValue(char outBuf[], const value_type &inVal)
static KOKKOS_INLINE_FUNCTION size_t packValue(char outBuf[], const size_t outBufIndex, const value_type &inVal)
Kokkos::View< char *, device_type, Kokkos::MemoryUnmanaged > output_buffer_type
static KOKKOS_INLINE_FUNCTION size_t unpackValue(value_type &outVal, const char inBuf[])
Kokkos::View< value_type *, device_type, Kokkos::MemoryUnmanaged > output_array_type
static KOKKOS_INLINE_FUNCTION Kokkos::pair< int, size_t > packArray(char outBuf[], const value_type inBuf[], const size_t numEnt)