FrictionQPotFEM 0.23.3
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};
38
39template <class T, size_t N>
40struct is_std_array<std::array<T, N>> : std::true_type {
41};
42
46template <class T, std::size_t N>
47auto std_array_size_impl(const std::array<T, N>&) -> std::integral_constant<std::size_t, N>;
48
52template <class T>
53using std_array_size = decltype(std_array_size_impl(std::declval<const T&>()));
54
58template <class I, std::size_t L>
59std::array<I, L> to_std_array(const I (&shape)[L])
60{
61 std::array<I, L> r;
62 std::copy(&shape[0], &shape[0] + L, r.begin());
63 return r;
64}
65
69template <class T, class R, typename = void>
70struct asTensor_write {
71 static void impl(const T& arg, R& ret)
72 {
73 GOOSEFEM_ASSERT(arg.dimension() <= ret.dimension());
74 GOOSEFEM_ASSERT(detail::has_shape_begin(arg, ret));
75 using strides_type = typename T::strides_type::value_type;
76 std::vector<strides_type> ret_strides(ret.dimension());
77 std::copy(arg.strides().begin(), arg.strides().end(), ret_strides.begin());
78 std::fill(ret_strides.begin() + arg.dimension(), ret_strides.end(), 0);
79 ret = xt::strided_view(
80 arg, ret.shape(), std::move(ret_strides), 0ul, xt::layout_type::dynamic);
81 }
82};
83
87template <class T, class R>
88struct asTensor_write<
89 T,
90 R,
91 typename std::enable_if_t<xt::has_fixed_rank_t<T>::value && xt::has_fixed_rank_t<R>::value>> {
92 static void impl(const T& arg, R& ret)
93 {
94 static_assert(T::rank <= R::rank, "Return must be fixed rank too");
95 GOOSEFEM_ASSERT(detail::has_shape_begin(arg, ret));
96 using strides_type = typename T::strides_type::value_type;
97 std::array<strides_type, R::rank> ret_strides;
98 std::copy(arg.strides().begin(), arg.strides().end(), ret_strides.begin());
99 std::fill(ret_strides.begin() + T::rank, ret_strides.end(), 0);
100 ret = xt::strided_view(
101 arg, ret.shape(), std::move(ret_strides), 0ul, xt::layout_type::dynamic);
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
#define GOOSEFEM_ASSERT(expr)
All assertions are implementation as::
Definition: config.h:96
xt::xtensor< T, N > tensor
Fixed (static) rank array.
Definition: config.h:176
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