diff --git a/core/src/Cabana_AoSoA.hpp b/core/src/Cabana_AoSoA.hpp
index 2387d47cd36caea2a638327255464f23859dcb6e..3da4eecef12539f615a78eeb1adb3d5074728099 100644
--- a/core/src/Cabana_AoSoA.hpp
+++ b/core/src/Cabana_AoSoA.hpp
@@ -2,36 +2,189 @@
 #define CABANA_AOSOA_HPP
 
 #include <Cabana_MemberDataTypes.hpp>
-#include <Cabana_MemoryPolicy.hpp>
 #include <Cabana_SoA.hpp>
 #include <Cabana_Index.hpp>
+#include <Cabana_InnerArraySize.hpp>
 
+#include <Kokkos_Core.hpp>
+#include <Kokkos_Core_fwd.hpp>
 #include <Kokkos_Macros.hpp>
+#include <Kokkos_HostSpace.hpp>
+#include <Kokkos_MemoryTraits.hpp>
+#include <Kokkos_ExecPolicy.hpp>
 
 #include <type_traits>
 #include <memory>
 #include <cmath>
 #include <cstdlib>
+#include <string>
 
 namespace Cabana
 {
+//---------------------------------------------------------------------------//
+/*! \class AoSoATraits
+  \brief Traits class for accessing attributes of a AoSoA.
+
+  This is an implementation detail of AoSoA.  It is only of interest
+  to developers implementing a new specialization of AoSoA.
+
+  Template argument options:
+  - AoSoA< DataTypes >
+  - AoSoA< DataTypes , Space >
+  - AoSoA< DataTypes , Space , MemoryTraits >
+  - AoSoA< DataTypes , ArraySize >
+  - AoSoA< DataTypes , ArraySize , Space >
+  - AoSoA< DataTypes , ArraySize , MemoryTraits >
+  - AoSoA< DataTypes , ArraySize , Space , MemoryTraits >
+  - AoSoA< DataTypes , MemoryTraits >
+
+  Note that this is effectively a reimplementation of Kokkos::ViewTraits for
+  the AoSoA with ArrayLayout replaced by ArraySize.
+*/
+template<class DataTypes , class ... Properties>
+class AoSoATraits ;
+
+// Void specialization.
+template<>
+class AoSoATraits<void>
+{
+  public:
+    using execution_space = void;
+    using memory_space = void;
+    using host_mirror_space = void;
+    using array_size = void;
+    using memory_traits = void;
+};
+
+// Extract the array size.
+template<class ArraySize, class ... Properties>
+class AoSoATraits<
+    typename std::enable_if<is_inner_array_size<ArraySize>::value>::type,
+    ArraySize, Properties...>
+{
+  public:
+    using execution_space = typename AoSoATraits<void,Properties...>::execution_space;
+    using memory_space = typename AoSoATraits<void,Properties...>::memory_space;
+    using host_mirror_space = typename AoSoATraits<void,Properties...>::host_mirror_space;
+    using array_size = ArraySize;
+    using memory_traits = typename AoSoATraits<void,Properties...>::memory_traits;
+};
+
+// Extract the space - either a Kokkos memory space or execution space. Can be
+// on or the other but not both.
+template<class Space, class ... Properties>
+class AoSoATraits<
+    typename std::enable_if<Kokkos::Impl::is_space<Space>::value>::type,
+    Space, Properties ...>
+{
+  public:
+    static_assert(
+        std::is_same<typename AoSoATraits<void,Properties...>::execution_space,void>::value &&
+        std::is_same<typename AoSoATraits<void,Properties...>::memory_space,void>::value &&
+        std::is_same<typename AoSoATraits<void,Properties...>::host_mirror_space,void>::value &&
+        std::is_same<typename AoSoATraits<void,Properties...>::array_size,void>::value
+        , "Only one AoSoA Execution or Memory Space template argument" );
+
+    using execution_space = typename Space::execution_space;
+    using memory_space = typename Space::memory_space;
+    using host_mirror_space = typename Kokkos::Impl::HostMirror<Space>::Space;
+    using array_size = ExecutionSpaceInnerArraySize<execution_space>;
+    using memory_traits = typename AoSoATraits<void,Properties...>::memory_traits;
+};
+
+// Extract the memory traits - this must be the last template parameter in the pack.
+template<class MemoryTraits, class ... Properties>
+class AoSoATraits<
+    typename std::enable_if<Kokkos::Impl::is_memory_traits<MemoryTraits>::value>::type,
+    MemoryTraits, Properties...>
+{
+  public:
+    static_assert( std::is_same<typename AoSoATraits<void,Properties...>::execution_space,void>::value &&
+                   std::is_same<typename AoSoATraits<void,Properties...>::memory_space,void>::value &&
+                   std::is_same<typename AoSoATraits<void,Properties...>::array_size,void>::value &&
+                   std::is_same<typename AoSoATraits<void,Properties...>::memory_traits,void>::value
+                   , "MemoryTrait is the final optional template argument for a AoSoA" );
+
+    using execution_space = void;
+    using memory_space = void;
+    using host_mirror_space = void;
+    using array_size = void;
+    using memory_traits = MemoryTraits;
+};
+
+// Set the traits for a given set of properties.
+template<class DataTypes, class ... Properties>
+class AoSoATraits
+{
+  private:
+
+    typedef AoSoATraits<void,Properties...>  properties;
+
+    using ExecutionSpace =
+        typename
+        std::conditional<
+        !std::is_same<typename properties::execution_space,void>::value,
+        typename properties::execution_space,
+        Kokkos::DefaultExecutionSpace
+        >::type;
+
+    using MemorySpace =
+        typename std::conditional<
+        !std::is_same<typename properties::memory_space,void>::value,
+        typename properties::memory_space,
+        typename ExecutionSpace::memory_space
+        >::type;
+
+    using ArraySize =
+        typename std::conditional<
+        !std::is_same<typename properties::array_size,void>::value,
+        typename properties::array_size,
+        ExecutionSpaceInnerArraySize<ExecutionSpace>
+        >::type;
+
+    using HostMirrorSpace =
+        typename std::conditional<
+        !std::is_same<typename properties::host_mirror_space,void>::value,
+        typename properties::host_mirror_space,
+        typename Kokkos::Impl::HostMirror<ExecutionSpace>::Space
+        >::type;
+
+    using MemoryTraits =
+        typename std::conditional<
+        !std::is_same<typename properties::memory_traits,void>::value,
+        typename properties::memory_traits,
+        typename Kokkos::MemoryManaged
+        >::type;
+
+  public:
+
+    using data_types = DataTypes;
+    using execution_space = ExecutionSpace;
+    using memory_space = MemorySpace;
+    using device_type = Kokkos::Device<ExecutionSpace,MemorySpace>;
+    using memory_traits = MemoryTraits;
+    using host_mirror_space = HostMirrorSpace;
+    using size_type = typename memory_space::size_type;
+
+    static constexpr std::size_t array_size = ArraySize::value;
+};
+
 //---------------------------------------------------------------------------//
 // Forward declaration.
-template<typename DataTypes, typename Device, std::size_t ArraySize>
+template<typename DataTypes, typename ... Properties>
 class AoSoA;
 
 //---------------------------------------------------------------------------//
 // Static type checker.
-template<typename >
-struct is_aosoa
-    : public std::false_type {};
+template<class >
+struct is_aosoa : public std::false_type {};
 
-template<typename DataTypes, typename Device, std::size_t ArraySize>
-struct is_aosoa<AoSoA<DataTypes,Device,ArraySize> >
+template<class DataTypes, class ... Properties>
+struct is_aosoa<AoSoA<DataTypes,Properties...> >
     : public std::true_type {};
 
-template<typename DataTypes, typename Device, std::size_t ArraySize>
-struct is_aosoa<const AoSoA<DataTypes,Device,ArraySize> >
+template<class DataTypes, class ... Properties>
+struct is_aosoa<const AoSoA<DataTypes,Properties...> >
     : public std::true_type {};
 
 //---------------------------------------------------------------------------//
@@ -39,22 +192,19 @@ struct is_aosoa<const AoSoA<DataTypes,Device,ArraySize> >
   \class AoSoA
   \brief Array-of-Structs-of-Arrays
 */
-template<typename Device, std::size_t ArraySize, typename... Types>
-class AoSoA<MemberDataTypes<Types...>,Device,ArraySize>
+template<class ... Types, class ... Properties>
+class AoSoA<MemberDataTypes<Types...>,Properties...>
 {
   public:
 
-    // AoSoA type.
-    using aosoa_type = AoSoA<MemberDataTypes<Types...>,Device,ArraySize>;
-
-    // Device type.
-    using device_type = Device;
+    // Traits.
+    using traits = AoSoATraits<MemberDataTypes<Types...>,Properties...>;
 
-    // Memory policy.
-    using memory_policy = MemoryPolicy<device_type>;
+    // AoSoA type.
+    using aosoa_type = AoSoA<MemberDataTypes<Types...>,Properties...>;
 
-    // Inner array size (size of the arrays held by the structs).
-    static constexpr std::size_t array_size = ArraySize;
+    // Array size.
+    static constexpr std::size_t array_size = traits::array_size;
 
     // SoA type.
     using soa_type = SoA<array_size,Types...>;
@@ -173,10 +323,10 @@ class AoSoA<MemberDataTypes<Types...>,Device,ArraySize>
     // by inserting or erasing elements from it.
     void resize( const std::size_t n )
     {
+        reserve( n );
         _size = n;
         _num_soa = std::floor( n / array_size );
         if ( 0 < n % array_size ) ++_num_soa;
-        reserve( _size );
     }
 
     // Requests that the container capacity be at least enough to contain n
@@ -199,13 +349,16 @@ class AoSoA<MemberDataTypes<Types...>,Device,ArraySize>
         if ( 0 < n % array_size ) ++num_soa_alloc;
         _capacity = num_soa_alloc * array_size;
 
-        soa_type* data_block;
-        memory_policy::allocate( data_block, num_soa_alloc );
-        std::shared_ptr<soa_type> sp(
-            data_block, memory_policy::template deallocate<soa_type> );
+        std::shared_ptr<void> sp(
+            Kokkos::kokkos_malloc(num_soa_alloc * sizeof(soa_type)),
+            Kokkos::kokkos_free<typename traits::memory_space> );
 
         if ( _managed_data != nullptr )
-            memory_policy::copy( data_block, _managed_data.get(), _num_soa );
+            Kokkos::Impl::DeepCopy<
+                typename traits::memory_space,
+                typename traits::memory_space,
+                typename traits::execution_space>(
+                    sp.get(), _managed_data.get(), _num_soa * sizeof(soa_type) );
 
         std::swap( _managed_data, sp );
 
@@ -448,7 +601,8 @@ class AoSoA<MemberDataTypes<Types...>,Device,ArraySize>
     {
         static_assert( 0 <= N && N < number_of_members,
                        "Static loop out of bounds!" );
-        soa_type* data_block = _managed_data.get();
+        soa_type* data_block =
+            std::static_pointer_cast<soa_type>(_managed_data).get();
         _pointers[N] =
             static_cast<void*>( getStructMember<N>(data_block[0]) );
         static_assert( 0 ==
@@ -542,8 +696,9 @@ class AoSoA<MemberDataTypes<Types...>,Device,ArraySize>
     // Structs-of-Arrays managed data. This shared pointer manages the block
     // of memory owned by this class such that the copy constructor and
     // assignment operator for this class perform a shallow and reference
-    // counted copy of the data.
-    std::shared_ptr<soa_type> _managed_data;
+    // counted copy of the data. The underlying pointer is to an array of
+    // soa_type objects.
+    std::shared_ptr<void> _managed_data;
 
     // Pointers to the first element of each member.
     void* _pointers[number_of_members];
diff --git a/core/src/Cabana_Cuda.hpp b/core/src/Cabana_Cuda.hpp
deleted file mode 100644
index 20633a91587ecab6a20e4ec8a42202a7a437d79f..0000000000000000000000000000000000000000
--- a/core/src/Cabana_Cuda.hpp
+++ /dev/null
@@ -1,96 +0,0 @@
-#ifndef CABANA_CUDA_HPP
-#define CABANA_CUDA_HPP
-
-#if defined( __NVCC__ )
-
-#include <type_traits>
-#include <cstdlib>
-
-#include <cuda.h>
-#include <cuda_runtime.h>
-
-namespace Cabana
-{
-//---------------------------------------------------------------------------//
-// Cuda tag.
-struct Cuda {};
-
-//---------------------------------------------------------------------------//
-/*!
- * \brief Memory policy for Cuda computations.
- */
-template<>
-struct MemoryPolicy<Cuda>
-{
-    //! Allocate array of a number of objects of type T. This will only work
-    //! if T is of trivial type (trivially copyable and contiguous).
-    template<class T>
-    static
-    typename std::enable_if<std::is_trivial<T>::value,void>::type
-    allocate( T*& ptr, const std::size_t num_t )
-    {
-        cudaMalloc( (void**) &ptr, num_t * sizeof(T) );
-    }
-
-    //! Dellocate an array.
-    template<class T>
-    static void deallocate( T* ptr )
-    {
-        cudaFree( ptr );
-    }
-
-    //! Copy from one address in the memory space to another in the same
-    //! memory space.
-    template<class T>
-    static void copy( T* destination, const T* source, const std::size_t count )
-    {
-        cudaMemcpy(
-            destination, source, count*sizeof(T), cudaMemcpyDeviceToDevice );
-    }
-};
-
-//---------------------------------------------------------------------------//
-// CudaUVM tag.
-struct CudaUVM {};
-
-//---------------------------------------------------------------------------//
-/*!
- * \brief Memory policy for Cuda computations with unified-virtual-memory.
- */
-template<>
-struct MemoryPolicy<CudaUVM>
-{
-    //! Allocate array of a number of objects of type T. This will only work
-    //! if T is of trivial type (trivially copyable and contiguous).
-    template<class T>
-    static
-    typename std::enable_if<std::is_trivial<T>::value,void>::type
-    allocate( T*& ptr, const std::size_t num_t )
-    {
-        cudaMallocManaged( (void**) &ptr, num_t * sizeof(T) );
-    }
-
-    //! Dellocate an array.
-    template<class T>
-    static void deallocate( T* ptr )
-    {
-        cudaFree( ptr );
-    }
-
-    //! Copy from one address in the memory space to another in the same
-    //! memory space.
-    template<class T>
-    static void copy( T* destination, const T* source, const std::size_t count )
-    {
-        cudaMemcpy(
-            destination, source, count*sizeof(T), cudaMemcpyDeviceToDevice );
-    }
-};
-
-//---------------------------------------------------------------------------//
-
-} // end namespace Cabana
-
-#endif // end defined( __NVCC__ )
-
-#endif // end CABANA_CUDA_HPP
diff --git a/core/src/Cabana_InnerArraySize.hpp b/core/src/Cabana_InnerArraySize.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..7c3e8380912e5491f96f93a48837ae7062aa6770
--- /dev/null
+++ b/core/src/Cabana_InnerArraySize.hpp
@@ -0,0 +1,81 @@
+#ifndef CABANA_INNERARRAYSIZE_HPP
+#define CABANA_INNERARRAYSIZE_HPP
+
+#include <Kokkos_Core.hpp>
+
+#include <type_traits>
+
+namespace Cabana
+{
+//---------------------------------------------------------------------------//
+/*!
+  \class InnerArraySize
+  \brief Static inner array size definition. This is the size of the arrays in
+  the struct-of-arrays.
+*/
+template<std::size_t N>
+class InnerArraySize : public std::integral_constant<std::size_t,N> {};
+
+//---------------------------------------------------------------------------//
+// Static type checker.
+template<class >
+struct is_inner_array_size : public std::false_type {};
+
+template<std::size_t N>
+struct is_inner_array_size<InnerArraySize<N> > : public std::true_type {};
+
+template<std::size_t N>
+struct is_inner_array_size<const InnerArraySize<N> > : public std::true_type {};
+
+//---------------------------------------------------------------------------//
+/*!
+  \class ExecutionSpaceInnerArraySize
+  \brief Inner array sizes specific for execution spaces.
+
+  Default version has an inner array size of 1. Specializations will set this
+  specifically for the given space.
+*/
+template<class ExecutionSpace>
+class ExecutionSpaceInnerArraySize : public InnerArraySize<1> {};
+
+//---------------------------------------------------------------------------//
+// Serial specialization.
+#if defined( KOKKOS_ENABLE_SERIAL )
+
+#endif
+
+//---------------------------------------------------------------------------//
+// OpenMP specialization.
+#if defined( KOKKOS_ENABLE_OPENMP )
+
+#endif
+
+//---------------------------------------------------------------------------//
+// Qthread specialization
+#if defined( KOKKOS_ENABLE_QTHREADS )
+
+#endif
+
+//---------------------------------------------------------------------------//
+// Threads specialization.
+#if defined( KOKKOS_ENABLE_THREADS )
+
+#endif
+
+//---------------------------------------------------------------------------//
+// Cuda specialization.
+#if defined( KOKKOS_ENABLE_CUDA )
+
+#endif
+
+//---------------------------------------------------------------------------//
+// ROCm specialization.
+#if defined( KOKKOS_ENABLE_ROCM )
+
+#endif
+
+//---------------------------------------------------------------------------//
+
+} // end namespace Cabana
+
+#endif // end CABANA_INNERARRAYSIZE_HPP
diff --git a/core/src/Cabana_MemberSlice.hpp b/core/src/Cabana_MemberSlice.hpp
index ff786b80bc457db996c37d6d31c1059f1b0a4b3e..b376c9af65e3edb75430d2cc969f071c9e21c468 100644
--- a/core/src/Cabana_MemberSlice.hpp
+++ b/core/src/Cabana_MemberSlice.hpp
@@ -50,9 +50,6 @@ class MemberSlice
     // AoSoA type this slice wraps.
     using aosoa_type = AoSoA_t;
 
-    // Device type.
-    using device_type = typename aosoa_type::device_type;
-
     // Inner array size.
     static constexpr std::size_t array_size = aosoa_type::array_size;
 
diff --git a/core/src/Cabana_MemoryPolicy.hpp b/core/src/Cabana_MemoryPolicy.hpp
deleted file mode 100644
index c8a2eba6afe8adb3c53c178a99046e13ca807d8e..0000000000000000000000000000000000000000
--- a/core/src/Cabana_MemoryPolicy.hpp
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef CABANA_MEMORYPOLICY_HPP
-#define CABANA_MEMORYPOLICY_HPP
-
-namespace Cabana
-{
-//---------------------------------------------------------------------------//
-template<typename >
-struct MemoryPolicy;
-
-//---------------------------------------------------------------------------//
-
-} // end namespace Cabana
-
-#endif // CABANA_MEMORYPOLICY_HPP
diff --git a/core/src/Cabana_Serial.hpp b/core/src/Cabana_Serial.hpp
deleted file mode 100644
index 2be1a15cc11ad47a4adaa7eab8225972022f5949..0000000000000000000000000000000000000000
--- a/core/src/Cabana_Serial.hpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef CABANA_SERIAL_HPP
-#define CABANA_SERIAL_HPP
-
-#include <type_traits>
-#include <cstdlib>
-
-namespace Cabana
-{
-//---------------------------------------------------------------------------//
-// Serial tag.
-struct Serial {};
-
-//---------------------------------------------------------------------------//
-/*!
- * \brief Memory policy for serial computations.
- */
-template<>
-struct MemoryPolicy<Serial>
-{
-    //! Allocate array of a number of objects of type T. This will only work
-    //! if T is of trivial type (trivially copyable and contiguous).
-    template<class T>
-    static
-    typename std::enable_if<std::is_trivial<T>::value,void>::type
-    allocate( T*& ptr, const std::size_t n )
-    {
-        ptr = (T*) malloc( n * sizeof(T) );
-    }
-
-    //! Dellocate an array.
-    template<class T>
-    static void deallocate( T* ptr )
-    {
-        free( ptr );
-    }
-
-    //! Copy from one address in the memory space to another in the same
-    //! memory space.
-    template<class T>
-    static void copy( T* destination, const T* source, const std::size_t count )
-    {
-        std::copy( source, source + count, destination );
-    }
-};
-
-//---------------------------------------------------------------------------//
-
-} // end namespace Cabana
-
-#endif // end CABANA_SERIAL_HPP
diff --git a/core/unit_test/tstAoSoA.cpp b/core/unit_test/tstAoSoA.cpp
index 866809637308d01a9b274b7bda8cdd75364de993..4653c34bdadbb3f36eaa532da2ae4c5563675b93 100644
--- a/core/unit_test/tstAoSoA.cpp
+++ b/core/unit_test/tstAoSoA.cpp
@@ -1,5 +1,4 @@
 #include <Cabana_AoSoA.hpp>
-#include <Cabana_Serial.hpp>
 
 #include <boost/test/unit_test.hpp>
 
@@ -48,8 +47,8 @@ void checkDataMembers(
 //---------------------------------------------------------------------------//
 BOOST_AUTO_TEST_CASE( aosoa_serial_api_test )
 {
-    // Inner array size.
-    const std::size_t array_size = 10;
+    // Manually set the inner array size.
+    using inner_array_size = Cabana::InnerArraySize<10>;
 
     // Data dimensions.
     const std::size_t dim_1 = 3;
@@ -67,7 +66,7 @@ BOOST_AUTO_TEST_CASE( aosoa_serial_api_test )
                                 >;
 
     // Declare the AoSoA type.
-    using AoSoA_t = Cabana::AoSoA<DataTypes,Cabana::Serial,array_size>;
+    using AoSoA_t = Cabana::AoSoA<DataTypes,inner_array_size,Kokkos::Serial>;
 
     // Make sure that it is actually an AoSoA.
     BOOST_TEST( Cabana::is_aosoa<AoSoA_t>::value );
@@ -224,8 +223,8 @@ BOOST_AUTO_TEST_CASE( aosoa_serial_api_test )
 //---------------------------------------------------------------------------//
 BOOST_AUTO_TEST_CASE( aosoa_raw_data_test )
 {
-    // Inner array size.
-    const std::size_t array_size = 103;
+    // Manually set the inner array size.
+    using inner_array_size = Cabana::InnerArraySize<103>;
 
     // Multi dimensional member sizes.
     const std::size_t dim_1 = 3;
@@ -241,7 +240,7 @@ BOOST_AUTO_TEST_CASE( aosoa_raw_data_test )
                                 >;
 
     // Declare the AoSoA type.
-    using AoSoA_t = Cabana::AoSoA<DataTypes,Cabana::Serial,array_size>;
+    using AoSoA_t = Cabana::AoSoA<DataTypes,inner_array_size,Kokkos::Serial>;
 
     // Create an AoSoA using the default constructor.
     std::size_t num_data = 350;
diff --git a/core/unit_test/tstMemberSlice.cpp b/core/unit_test/tstMemberSlice.cpp
index c87a4f8aa4f85aa42c0c64b572505b052dd4dc22..1550426f13376bd61a8ff22b6378f936b235ee96 100644
--- a/core/unit_test/tstMemberSlice.cpp
+++ b/core/unit_test/tstMemberSlice.cpp
@@ -1,6 +1,5 @@
 #include <Cabana_MemberSlice.hpp>
 #include <Cabana_AoSoA.hpp>
-#include <Cabana_Serial.hpp>
 
 #include <boost/test/unit_test.hpp>
 
@@ -49,8 +48,8 @@ void checkDataMembers(
 //---------------------------------------------------------------------------//
 BOOST_AUTO_TEST_CASE( slice_serial_api_test )
 {
-    // Inner array size.
-    const std::size_t array_size = 10;
+    // Manually set the inner array size.
+    using inner_array_size = Cabana::InnerArraySize<10>;
 
     // Data dimensions.
     const std::size_t dim_1 = 3;
@@ -68,7 +67,7 @@ BOOST_AUTO_TEST_CASE( slice_serial_api_test )
                                 >;
 
     // Declare the AoSoA type.
-    using AoSoA_t = Cabana::AoSoA<DataTypes,Cabana::Serial,array_size>;
+    using AoSoA_t = Cabana::AoSoA<DataTypes,inner_array_size,Kokkos::Serial>;
 
     // Make sure that it is actually an AoSoA.
     BOOST_TEST( Cabana::is_aosoa<AoSoA_t>::value );