Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://www.mooseframework.org 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #pragma once 11 : 12 : #include "KokkosReferenceWrapper.h" 13 : 14 : #include <type_traits> 15 : #include <utility> 16 : 17 : #ifdef MOOSE_KOKKOS_SCOPE 18 : #define KOKKOS_SCALAR_FUNCTION KOKKOS_FUNCTION 19 : #else 20 : #define KOKKOS_SCALAR_FUNCTION 21 : #endif 22 : 23 : namespace Moose::Kokkos 24 : { 25 : 26 : /** 27 : * The Kokkos wrapper class that can hold the reference of an arithmetic scalar variable 28 : */ 29 : template <typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type> 30 : class Scalar : public ReferenceWrapper<T> 31 : { 32 : public: 33 : using value_type = T; 34 : 35 : /** 36 : * Constructor 37 : * @param value The writeable reference of the arithmetic scalar variable to store 38 : */ 39 59570 : Scalar(T & value) : ReferenceWrapper<T>(value) {} 40 : /** 41 : * Copy constructor 42 : */ 43 2786309 : Scalar(const Scalar & object) : ReferenceWrapper<T>(object) {} 44 : 45 : /** 46 : * Assign a scalar value to the underlying host reference 47 : * @param value The scalar value to be assigned 48 : */ 49 2 : auto & operator=(const Scalar & value) 50 : { 51 2 : this->_reference = static_cast<const T &>(value); 52 : 53 2 : return *this; 54 : } 55 : /** 56 : * Assign an arithmetic value to the underlying host reference 57 : * @param value The scalar value to be assigned 58 : */ 59 : template <typename U> 60 166 : auto operator=(const U & value) -> decltype(std::declval<T &>() = value, std::declval<Scalar &>()) 61 : { 62 166 : this->_reference = value; 63 : 64 166 : return *this; 65 : } 66 : 67 : /** 68 : * Get the positive value of the scalar 69 : * @returns The positive scalar value 70 : */ 71 4 : KOKKOS_SCALAR_FUNCTION auto operator+() const -> decltype(+std::declval<const T &>()) 72 : { 73 4 : return +value(); 74 : } 75 : /** 76 : * Get the negated value of the scalar 77 : * @returns The negated scalar value 78 : */ 79 573986 : KOKKOS_SCALAR_FUNCTION auto operator-() const -> decltype(-std::declval<const T &>()) 80 : { 81 573986 : return -value(); 82 : } 83 : 84 : /** 85 : * Add another value to the underlying host reference 86 : * @param value The value to add 87 : */ 88 : template <typename U> 89 4 : auto operator+=(const U & value) 90 : -> decltype(std::declval<T &>() += value, std::declval<Scalar &>()) 91 : { 92 4 : this->_reference += value; 93 : 94 4 : return *this; 95 : } 96 : /** 97 : * Subtract another value from the underlying host reference 98 : * @param value The value to subtract 99 : */ 100 : template <typename U> 101 2 : auto operator-=(const U & value) 102 : -> decltype(std::declval<T &>() -= value, std::declval<Scalar &>()) 103 : { 104 2 : this->_reference -= value; 105 : 106 2 : return *this; 107 : } 108 : /** 109 : * Multiply the underlying host reference by another value 110 : * @param value The value to multiply by 111 : */ 112 : template <typename U> 113 2 : auto operator*=(const U & value) 114 : -> decltype(std::declval<T &>() *= value, std::declval<Scalar &>()) 115 : { 116 2 : this->_reference *= value; 117 : 118 2 : return *this; 119 : } 120 : /** 121 : * Divide the underlying host reference by another value 122 : * @param value The value to divide by 123 : */ 124 : template <typename U> 125 2 : auto operator/=(const U & value) 126 : -> decltype(std::declval<T &>() /= value, std::declval<Scalar &>()) 127 : { 128 2 : this->_reference /= value; 129 : 130 2 : return *this; 131 : } 132 : /** 133 : * Assign the remainder after division by another value to the underlying host reference 134 : * @param value The divisor value 135 : */ 136 : template <typename U> 137 4 : auto operator%=(const U & value) 138 : -> decltype(std::declval<T &>() %= value, std::declval<Scalar &>()) 139 : { 140 4 : this->_reference %= value; 141 : 142 4 : return *this; 143 : } 144 : 145 : /** 146 : * Prefix increment the underlying host reference 147 : * @returns This scalar wrapper 148 : */ 149 : template <typename U = T> 150 2 : auto operator++() -> decltype(++std::declval<U &>(), std::declval<Scalar &>()) 151 : { 152 2 : ++this->_reference; 153 : 154 2 : return *this; 155 : } 156 : /** 157 : * Postfix increment the underlying host reference 158 : * @returns The previous scalar value 159 : */ 160 : template <typename U = T> 161 2 : auto operator++(int) -> decltype(std::declval<U &>()++) 162 : { 163 2 : return this->_reference++; 164 : } 165 : /** 166 : * Prefix decrement the underlying host reference 167 : * @returns This scalar wrapper 168 : */ 169 : template <typename U = T> 170 2 : auto operator--() -> decltype(--std::declval<U &>(), std::declval<Scalar &>()) 171 : { 172 2 : --this->_reference; 173 : 174 2 : return *this; 175 : } 176 : /** 177 : * Postfix decrement the underlying host reference 178 : * @returns The previous scalar value 179 : */ 180 : template <typename U = T> 181 2 : auto operator--(int) -> decltype(std::declval<U &>()--) 182 : { 183 2 : return this->_reference--; 184 : } 185 : 186 : /** 187 : * Add another value to this scalar 188 : * @param value The value to add 189 : * @returns The sum 190 : */ 191 : template <typename U> 192 159543 : KOKKOS_SCALAR_FUNCTION auto operator+(const U & value) const 193 : -> decltype(std::declval<const T &>() + value) 194 : { 195 159543 : return this->value() + value; 196 : } 197 : /** 198 : * Subtract another value from this scalar 199 : * @param value The value to subtract 200 : * @returns The difference 201 : */ 202 : template <typename U> 203 178 : KOKKOS_SCALAR_FUNCTION auto operator-(const U & value) const 204 : -> decltype(std::declval<const T &>() - value) 205 : { 206 178 : return this->value() - value; 207 : } 208 : /** 209 : * Multiply this scalar by another value 210 : * @param value The value to multiply by 211 : * @returns The product 212 : */ 213 : template <typename U> 214 17554932 : KOKKOS_SCALAR_FUNCTION auto operator*(const U & value) const 215 : -> decltype(std::declval<const T &>() * value) 216 : { 217 17554932 : return this->value() * value; 218 : } 219 : /** 220 : * Divide this scalar by another value 221 : * @param value The value to divide by 222 : * @returns The quotient 223 : */ 224 : template <typename U> 225 28 : KOKKOS_SCALAR_FUNCTION auto operator/(const U & value) const 226 : -> decltype(std::declval<const T &>() / value) 227 : { 228 28 : return this->value() / value; 229 : } 230 : /** 231 : * Get the remainder after division by another value 232 : * @param value The divisor value 233 : * @returns The remainder 234 : */ 235 : template <typename U> 236 14 : KOKKOS_SCALAR_FUNCTION auto operator%(const U & value) const 237 : -> decltype(std::declval<const T &>() % value) 238 : { 239 14 : return this->value() % value; 240 : } 241 : 242 : private: 243 18288685 : KOKKOS_SCALAR_FUNCTION const T & value() const { return static_cast<const T &>(*this); } 244 : }; 245 : 246 : template <typename> 247 : struct is_scalar : std::false_type 248 : { 249 : }; 250 : 251 : template <typename T, typename Enable> 252 : struct is_scalar<Scalar<T, Enable>> : std::true_type 253 : { 254 : }; 255 : 256 : template <typename T, 257 : typename U, 258 : typename = typename std::enable_if<!is_scalar<typename std::decay<T>::type>::value>::type> 259 : KOKKOS_SCALAR_FUNCTION auto 260 131313 : operator+(const T & left, const Scalar<U> & right) -> decltype(left + static_cast<const U &>(right)) 261 : { 262 131313 : return left + static_cast<const U &>(right); 263 : } 264 : 265 : template <typename T, 266 : typename U, 267 : typename = typename std::enable_if<!is_scalar<typename std::decay<T>::type>::value>::type> 268 : KOKKOS_SCALAR_FUNCTION auto 269 490 : operator-(const T & left, const Scalar<U> & right) -> decltype(left - static_cast<const U &>(right)) 270 : { 271 490 : return left - static_cast<const U &>(right); 272 : } 273 : 274 : template <typename T, 275 : typename U, 276 : typename = typename std::enable_if<!is_scalar<typename std::decay<T>::type>::value>::type> 277 : KOKKOS_SCALAR_FUNCTION auto 278 6591604 : operator*(const T & left, const Scalar<U> & right) -> decltype(left * static_cast<const U &>(right)) 279 : { 280 6591604 : return left * static_cast<const U &>(right); 281 : } 282 : 283 : template <typename T, 284 : typename U, 285 : typename = typename std::enable_if<!is_scalar<typename std::decay<T>::type>::value>::type> 286 : KOKKOS_SCALAR_FUNCTION auto 287 28 : operator/(const T & left, const Scalar<U> & right) -> decltype(left / static_cast<const U &>(right)) 288 : { 289 28 : return left / static_cast<const U &>(right); 290 : } 291 : 292 : template <typename T, 293 : typename U, 294 : typename = typename std::enable_if<!is_scalar<typename std::decay<T>::type>::value>::type> 295 : KOKKOS_SCALAR_FUNCTION auto 296 14 : operator%(const T & left, const Scalar<U> & right) -> decltype(left % static_cast<const U &>(right)) 297 : { 298 14 : return left % static_cast<const U &>(right); 299 : } 300 : 301 : template <typename T> 302 : struct ArrayDeepCopy<Scalar<T>> 303 : { 304 : static constexpr bool value = true; 305 : }; 306 : 307 : // Mimic MOOSE convention 308 : using PostprocessorValue = Scalar<const PostprocessorValue>; 309 : 310 : } // namespace Moose::Kokkos