NimbleSM
NimbleSM is a solid mechanics simulation code for dynamic systems
Loading...
Searching...
No Matches
nimble_view.h
Go to the documentation of this file.
1/*
2//@HEADER
3// ************************************************************************
4//
5// NimbleSM
6// Copyright 2018
7// National Technology & Engineering Solutions of Sandia, LLC (NTESS)
8//
9// Under the terms of Contract DE-NA0003525 with NTESS, the U.S. Government
10// retains certain rights in this software.
11//
12// Redistribution and use in source and binary forms, with or without
13// modification, are permitted provided that the following conditions are
14// met:
15//
16// 1. Redistributions of source code must retain the above copyright
17// notice, this list of conditions and the following disclaimer.
18//
19// 2. Redistributions in binary form must reproduce the above copyright
20// notice, this list of conditions and the following disclaimer in the
21// documentation and/or other materials provided with the distribution.
22//
23// 3. Neither the name of the Corporation nor the names of the
24// contributors may be used to endorse or promote products derived from
25// this software without specific prior written permission.
26//
27// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY EXPRESS OR IMPLIED
28// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
29// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
30// NO EVENT SHALL NTESS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
32// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37//
38// Questions? Contact David Littlewood (djlittl@sandia.gov)
39//
40// ************************************************************************
41//@HEADER
42*/
43
44#ifndef NIMBLE_VIEW_H
45#define NIMBLE_VIEW_H
46
47#include <array>
48#include <memory>
49#include <type_traits>
50
51#include "nimble_defs.h"
52
53enum class FieldEnum : int
54{
55 Scalar = 1,
56 Vector = 3,
59};
60
61namespace nimble {
62
63namespace details {
64
65template <std::size_t N>
66class AXPYResult;
67
68}
69
70template <std::size_t N = 2, class Scalar = double>
72{
73 public:
74 Viewify() : data_(nullptr)
75 {
76 len_.fill(0);
77 stride_.fill(0);
78 }
79
80 Viewify(Scalar* data, std::array<int, N> len, std::array<int, N> stride) : data_(data), len_(len), stride_(stride) {}
81
82 template <std::size_t NN = N, typename = typename std::enable_if<(NN == 1)>::type>
83 Viewify(Scalar* data, int len) : data_(data), len_({len}), stride_({1})
84 {
85 }
86
87 template <std::size_t NN = N>
88 NIMBLE_INLINE_FUNCTION typename std::enable_if<(NN == 1), Scalar>::type&
89 operator()(int i)
90 {
91 return data_[i];
92 }
93
94 template <std::size_t NN = N>
95 NIMBLE_INLINE_FUNCTION typename std::enable_if<(NN == 1), const Scalar>::type
96 operator()(int i) const
97 {
98 return data_[i];
99 }
100
101 template <std::size_t NN = N>
102 NIMBLE_INLINE_FUNCTION typename std::enable_if<(NN == 2), Scalar>::type&
103 operator()(int i, int j)
104 {
105 return data_[i * stride_[0] + j * stride_[1]];
106 }
107
108 template <std::size_t NN = N>
109 NIMBLE_INLINE_FUNCTION typename std::enable_if<(NN == 2), const Scalar>::type
110 operator()(int i, int j) const
111 {
112 return data_[i * stride_[0] + j * stride_[1]];
113 }
114
115 void
117 {
118 int mySize = stride_[0] * len_[0];
119 for (int ii = 0; ii < mySize; ++ii) data_[ii] = (Scalar)(0);
120 }
121
122 void
123 copy(const Viewify<N>& ref)
124 {
125 int mySize = stride_[0] * len_[0];
126 for (int ii = 0; ii < mySize; ++ii) data_[ii] = ref.data_[ii];
127 }
128
129 Scalar*
130 data() const
131 {
132 return data_;
133 }
134
135 template <class T = Scalar, typename = typename std::enable_if<!std::is_const<T>::value>::type>
138
139 std::array<int, N>
140 size() const
141 {
142 return len_;
143 }
144
145 std::array<int, N>
146 stride() const
147 {
148 return stride_;
149 }
150
151 protected:
153 std::array<int, N> len_;
154 std::array<int, N> stride_;
155};
156
157//----------------------------------
158
159namespace details {
160
161template <std::size_t N>
163{
164 AXPYResult(const nimble::Viewify<N> A, double alpha) : A_(A), alpha_(alpha) {}
165
166 /// \brief Compute "dest = (destCoef) * dest + rhsCoef * alpha_ * A_"
167 ///
168 /// \param[in] destCoef Scalar
169 /// \param[in] rhsCoef Scalar
170 /// \param[out] dest Viewify "vector" storing the result
171 ///
172 /// \note The routine does not check whether A_ and dest have the same length
173 /// and the same stride.
174 void
175 assignTo(double destCoef, double rhsCoef, nimble::Viewify<N>& dest) const;
176
178 double alpha_;
179};
180
181template <std::size_t N>
182void
183AXPYResult<N>::assignTo(double destCoef, double rhsCoef, nimble::Viewify<N>& dest) const
184{
185 const double prod = alpha_ * rhsCoef;
186
187 auto len = dest.size();
188 auto stride = dest.stride();
189 const long isize = len[0] * stride[0];
190
191 double* data = dest.data();
192 double* rhs_data = A_.data();
193
194 if (destCoef == 1.0) {
195 for (long ii = 0; ii < isize; ++ii) data[ii] += prod * rhs_data[ii];
196 } else if (destCoef == 0.0) {
197 for (long ii = 0; ii < isize; ++ii) data[ii] = prod * rhs_data[ii];
198 } else {
199 for (long ii = 0; ii < isize; ++ii) data[ii] = destCoef * data[ii] + prod * rhs_data[ii];
200 }
201}
202
203} // namespace details
204
205//----------------------------------
206
207template <std::size_t N, class Scalar>
208template <class T, typename>
211{
212 rhs.assignTo(1.0, 1.0, *this);
213 return *this;
214}
215
216template <std::size_t N>
218operator*(double alpha, const nimble::Viewify<N>& A)
219{
220 return {A, alpha};
221}
222
223//----------------------------------
224
225template <FieldEnum FieldT>
226class View
227{
228 public:
229 explicit View(int num_entries) : num_entries_(num_entries)
230 {
231 data_ = std::shared_ptr<double>(new double[num_entries_ * static_cast<int>(FieldT)], [](double* p) { delete[] p; });
232 data_ptr_ = data_.get();
233 }
234
235 ~View() = default;
236 View(const View&) = default;
237 View(View&&) noexcept = default;
238 View&
239 operator=(const View&) = default;
240 View&
241 operator=(View&&) noexcept = default;
242
243 double&
244 operator()(int i_entry) const
245 {
246 static_assert(FieldT == FieldEnum::Scalar, "Operator(int i_entry) called for non-scalar data.");
247 return data_ptr_[i_entry];
248 }
249
250 double&
251 operator()(int i_entry, int i_coord) const
252 {
253 static_assert(FieldT != FieldEnum::Scalar, "Operator(int i_entry, int i_coord) called for scalar data.");
254 return data_ptr_[i_entry * static_cast<int>(FieldT) + i_coord];
255 }
256
257 int
259 {
260 if (FieldT == FieldEnum::Scalar) { return 1; }
261 return 2;
262 }
263
264 int
265 extent(int dim)
266 {
267 if (dim == 0) {
268 return num_entries_;
269 } else if (dim == 1) {
270 return static_cast<int>(FieldT);
271 } else {
272 return 1;
273 }
274 }
275
276#ifdef NIMBLE_HAVE_DARMA
277 void
278 serialize(darma_runtime::serialization::SimplePackUnpackArchive& ar)
279 {
280 // The purpose for the serialize call can be determined with:
281 // ar.is_sizing()
282 // ar.is_packing()
283 // ar.is_unpacking()
284
285 const int size = num_entries_ * static_cast<int>(FieldT);
286 std::vector<double> data_vec(size);
287
288 if (!ar.is_unpacking()) {
289 for (int i = 0; i < size; i++) { data_vec[i] = data_ptr_[i]; }
290 }
291
292 ar | num_entries_ | data_vec;
293
294 if (ar.is_unpacking()) {
295 data_ =
296 std::shared_ptr<double>(new double[num_entries_ * static_cast<int>(FieldT)], [](double* p) { delete[] p; });
297 data_ptr_ = data_.get();
298 for (int i = 0; i < size; i++) { data_ptr_[i] = data_vec[i]; }
299 }
300 }
301#endif
302
303 private:
304 int num_entries_;
305 std::shared_ptr<double> data_;
306 double* data_ptr_;
307};
308
309} // namespace nimble
310
311#endif
View(const View &)=default
double & operator()(int i_entry, int i_coord) const
Definition nimble_view.h:251
View(View &&) noexcept=default
~View()=default
int extent(int dim)
Definition nimble_view.h:265
int rank()
Definition nimble_view.h:258
View(int num_entries)
Definition nimble_view.h:229
Definition nimble_view.h:72
void copy(const Viewify< N > &ref)
Definition nimble_view.h:123
std::array< int, N > size() const
Definition nimble_view.h:140
std::array< int, N > len_
Definition nimble_view.h:153
Scalar * data_
Definition nimble_view.h:152
void zero()
Definition nimble_view.h:116
Viewify()
Definition nimble_view.h:74
Scalar * data() const
Definition nimble_view.h:130
Viewify(Scalar *data, int len)
Definition nimble_view.h:83
std::array< int, N > stride() const
Definition nimble_view.h:146
std::array< int, N > stride_
Definition nimble_view.h:154
Viewify(Scalar *data, std::array< int, N > len, std::array< int, N > stride)
Definition nimble_view.h:80
Viewify< N, Scalar > & operator+=(const details::AXPYResult< N > &rhs)
Definition nimble_view.h:210
Definition nimble_view.h:163
double alpha_
Definition nimble_view.h:178
void assignTo(double destCoef, double rhsCoef, nimble::Viewify< N > &dest) const
Compute "dest = (destCoef) * dest + rhsCoef * alpha_ * A_".
Definition nimble_view.h:183
AXPYResult(const nimble::Viewify< N > A, double alpha)
Definition nimble_view.h:164
const nimble::Viewify< N > A_
Definition nimble_view.h:177
Definition bvh_contact_manager.cc:71
Definition kokkos_contact_manager.h:49
details::AXPYResult< N > operator*(double alpha, const nimble::Viewify< N > &A)
Definition nimble_view.h:218
#define NIMBLE_INLINE_FUNCTION
Definition nimble_defs.h:50
FieldEnum
Definition nimble_view.h:54
@ Vector
Definition nimble_view.h:56
@ Scalar
Definition nimble_view.h:55
@ SymTensor
Definition nimble_view.h:57
@ FullTensor
Definition nimble_view.h:58