GooseFEM 1.4.1.dev2+g78f16df
Loading...
Searching...
No Matches
Allocate.h
Go to the documentation of this file.
1
9#ifndef GOOSEFEM_ALLOCATE_H
10#define GOOSEFEM_ALLOCATE_H
11
12#include "config.h"
13
14namespace GooseFEM {
15
16template <class T, class R>
17inline void asTensor(const T& arg, R& ret);
18
19namespace detail {
20
25template <class T, class S>
26inline bool has_shape_begin(const T& t, const S& s)
27{
28 return s.dimension() >= t.dimension() &&
29 std::equal(t.shape().cbegin(), t.shape().cend(), s.shape().begin());
30}
31
35template <class T>
36struct is_std_array : std::false_type {};
37
38template <class T, size_t N>
39struct is_std_array<std::array<T, N>> : std::true_type {};
40
44template <class T, std::size_t N>
45auto std_array_size_impl(const std::array<T, N>&) -> std::integral_constant<std::size_t, N>;
46
50template <class T>
51using std_array_size = decltype(std_array_size_impl(std::declval<const T&>()));
52
56template <class I, std::size_t L>
57std::array<I, L> to_std_array(const I (&shape)[L])
58{
59 std::array<I, L> r;
60 std::copy(&shape[0], &shape[0] + L, r.begin());
61 return r;
62}
63
67template <class T, class R, typename = void>
68struct asTensor_write {
69 static void impl(const T& arg, R& ret)
70 {
71 GOOSEFEM_ASSERT(arg.dimension() <= ret.dimension());
72 GOOSEFEM_ASSERT(detail::has_shape_begin(arg, ret));
73 using strides_type = typename T::strides_type::value_type;
74 std::vector<strides_type> ret_strides(ret.dimension());
75 std::copy(arg.strides().begin(), arg.strides().end(), ret_strides.begin());
76 std::fill(ret_strides.begin() + arg.dimension(), ret_strides.end(), 0);
77 ret = xt::strided_view(
78 arg, ret.shape(), std::move(ret_strides), 0ul, xt::layout_type::dynamic
79 );
80 }
81};
82
86template <class T, class R>
87struct asTensor_write<
88 T,
89 R,
90 typename std::enable_if_t<xt::has_fixed_rank_t<T>::value && xt::has_fixed_rank_t<R>::value>> {
91 static void impl(const T& arg, R& ret)
92 {
93 static_assert(T::rank <= R::rank, "Return must be fixed rank too");
94 GOOSEFEM_ASSERT(detail::has_shape_begin(arg, ret));
95 using strides_type = typename T::strides_type::value_type;
96 std::array<strides_type, R::rank> ret_strides;
97 std::copy(arg.strides().begin(), arg.strides().end(), ret_strides.begin());
98 std::fill(ret_strides.begin() + T::rank, ret_strides.end(), 0);
99 ret = xt::strided_view(
100 arg, ret.shape(), std::move(ret_strides), 0ul, xt::layout_type::dynamic
101 );
102 }
103};
104
108template <class T, class S, typename = void>
109struct asTensor_allocate {
110 static auto impl(const T& arg, const S& shape)
111 {
112 using value_type = typename T::value_type;
113 size_t dim = arg.dimension();
114 size_t rank = shape.size();
115 std::vector<size_t> ret_shape(dim + rank);
116 std::copy(arg.shape().begin(), arg.shape().end(), ret_shape.begin());
117 std::copy(shape.begin(), shape.end(), ret_shape.begin() + dim);
118 xt::xarray<value_type> ret(ret_shape);
119 GooseFEM::asTensor(arg, ret);
120 return ret;
121 }
122};
123
127template <class T, class S>
128struct asTensor_allocate<T, S, typename std::enable_if_t<detail::is_std_array<S>::value>> {
129 static auto impl(const T& arg, const S& shape)
130 {
131 using value_type = typename T::value_type;
132 static constexpr size_t dim = T::rank;
133 static constexpr size_t rank = std_array_size<S>::value;
134 std::array<size_t, dim + rank> ret_shape;
135 std::copy(arg.shape().begin(), arg.shape().end(), ret_shape.begin());
136 std::copy(shape.begin(), shape.end(), ret_shape.begin() + dim);
137 array_type::tensor<value_type, dim + rank> ret = xt::empty<value_type>(ret_shape);
138 detail::asTensor_write<std::decay_t<T>, decltype(ret)>::impl(arg, ret);
139 return ret;
140 }
141};
142
143} // namespace detail
144
152template <class T, class R>
153inline void asTensor(const T& arg, R& ret)
154{
155 detail::asTensor_write<std::decay_t<T>, std::decay_t<R>>::impl(arg, ret);
156}
157
166template <class T, class S>
167inline auto AsTensor(const T& arg, const S& shape)
168{
169 return detail::asTensor_allocate<std::decay_t<T>, std::decay_t<S>>::impl(arg, shape);
170}
171
175template <class T, class I, size_t L>
176inline auto AsTensor(const T& arg, const I (&shape)[L])
177{
178 auto s = detail::to_std_array(shape);
179 return detail::asTensor_allocate<std::decay_t<T>, decltype(s)>::impl(arg, s);
180}
181
191template <size_t rank, class T>
192inline auto AsTensor(const T& arg, size_t n)
193{
194 std::array<size_t, rank> shape;
195 std::fill(shape.begin(), shape.end(), n);
196 return detail::asTensor_allocate<std::decay_t<T>, decltype(shape)>::impl(arg, shape);
197}
198
208template <class T>
209inline auto AsTensor(size_t rank, const T& arg, size_t n)
210{
211 std::vector<size_t> shape(rank);
212 std::fill(shape.begin(), shape.end(), n);
213 return detail::asTensor_allocate<std::decay_t<T>, decltype(shape)>::impl(arg, shape);
214}
215
222template <class T>
223inline T as3d(const T& arg)
224{
225 GOOSEFEM_ASSERT(arg.dimension() == 2);
226 GOOSEFEM_ASSERT(arg.shape(1) > 0 && arg.shape(1) < 4);
227
228 if (arg.shape(1) == 3ul) {
229 return arg;
230 }
231
232 T ret = xt::zeros<typename T::value_type>(std::array<size_t, 2>{arg.shape(0), 3ul});
233
234 if (arg.shape(1) == 2ul) {
235 xt::view(ret, xt::all(), xt::keep(0, 1)) = arg;
236 }
237
238 if (arg.shape(1) == 1ul) {
239 xt::view(ret, xt::all(), xt::keep(0)) = arg;
240 }
241
242 return ret;
243}
244
245} // namespace GooseFEM
246
247#endif
Basic configuration:
#define GOOSEFEM_ASSERT(expr)
All assertions are implementation as::
Definition config.h:97
xt::xtensor< T, N > tensor
Fixed (static) rank array.
Definition config.h:177
Toolbox to perform finite element computations.
Definition Allocate.h:14
T as3d(const T &arg)
Zero-pad columns to a matrix until is that shape [m, 3].
Definition Allocate.h:223
auto AsTensor(const T &arg, const S &shape)
"Broadcast" a scalar stored in an array (e.g.
Definition Allocate.h:167
void asTensor(const T &arg, R &ret)
"Broadcast" a scalar stored in an array (e.g.
Definition Allocate.h:153