Skip to content

Commit b6381bf

Browse files
committed
Add simple operators for type N tensors
to support idaholab/moose#32023
1 parent 4c8f1da commit b6381bf

1 file changed

Lines changed: 73 additions & 45 deletions

File tree

include/numerics/type_n_tensor.h

Lines changed: 73 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ namespace libMesh
3737
* This class will eventually define a rank-N tensor in \p LIBMESH_DIM
3838
* dimensional space of type T.
3939
*
40-
* Right now it defines a shim to allow for rank-independent code to
41-
* compile (but not give correct results) in the case of vector-valued
42-
* elements and second derivatives.
40+
* For routines that are too hard to implement with a general N-dimensional,
41+
* it defines a shim to allow for rank-independent code to
42+
* compile (but error on unimplemented).
4343
*
4444
* \author Roy Stogner
4545
* \date 2012
@@ -63,7 +63,7 @@ class TypeNTensor
6363

6464
TypeNTensor (const TypeNTensor<N,T> &) : _coords(std::vector<T>(int_pow(LIBMESH_DIM, N))) {}
6565

66-
TypeNTensor & operator = (const TypeNTensor<N,T> &) { libmesh_not_implemented(); return *this; }
66+
TypeNTensor & operator=(const TypeNTensor<N, T> &) { return *this; }
6767

6868
operator TypeVector<T> () const { libmesh_not_implemented(); return 0; }
6969
operator VectorValue<T> () const { libmesh_not_implemented(); return 0; }
@@ -104,42 +104,54 @@ class TypeNTensor
104104
/**
105105
* Add two tensors.
106106
*/
107-
template<typename T2>
108-
TypeNTensor<N,typename CompareTypes<T, T2>::supertype>
109-
operator + (const TypeNTensor<N,T2> &) const
107+
template <typename T2>
108+
TypeNTensor<N, typename CompareTypes<T, T2>::supertype>
109+
operator+(const TypeNTensor<N, T2> & other) const
110110
{
111-
libmesh_not_implemented();
112-
return TypeNTensor<N,typename CompareTypes<T,T2>::supertype>();
111+
TypeNTensor<N, typename CompareTypes<T, T2>::supertype> sum;
112+
unsigned int size = int_pow(LIBMESH_DIM, N);
113+
sum._coords.resize(size);
114+
for (unsigned int i = 0; i < size; i++)
115+
sum._coords[i] = _coords[i] + other._coords[i];
116+
return sum;
113117
}
114118

115119
/**
116120
* Add to this tensor.
117121
*/
118-
template<typename T2>
119-
const TypeNTensor<N,T> & operator += (const TypeNTensor<N,T2> &/*rhs*/)
122+
template <typename T2>
123+
const TypeNTensor<N, T> & operator+=(const TypeNTensor<N, T2> & other)
120124
{
121-
libmesh_not_implemented();
125+
unsigned int size = int_pow(LIBMESH_DIM, N);
126+
for (unsigned int i = 0; i < size; i++)
127+
_coords[i] += other._coords[i];
122128
return *this;
123129
}
124130

125131
/**
126132
* Subtract two tensors.
127133
*/
128-
template<typename T2>
129-
TypeNTensor<N,typename CompareTypes<T, T2>::supertype>
130-
operator - (const TypeNTensor<N,T2> &) const
134+
template <typename T2>
135+
TypeNTensor<N, typename CompareTypes<T, T2>::supertype>
136+
operator-(const TypeNTensor<N, T2> & other) const
131137
{
132-
libmesh_not_implemented();
133-
return TypeNTensor<N,typename CompareTypes<T,T2>::supertype>();
138+
TypeNTensor<N, typename CompareTypes<T, T2>::supertype> subtract;
139+
unsigned int size = int_pow(LIBMESH_DIM, N);
140+
subtract._coords.resize(size);
141+
for (unsigned int i = 0; i < size; i++)
142+
subtract._coords[i] = _coords[i] - other._coords[i];
143+
return subtract;
134144
}
135145

136146
/**
137147
* Subtract from this tensor.
138148
*/
139-
template<typename T2>
140-
const TypeNTensor<N,T> & operator -= (const TypeNTensor<N,T2> &)
149+
template <typename T2>
150+
const TypeNTensor<N, T> & operator-=(const TypeNTensor<N, T2> & other)
141151
{
142-
libmesh_not_implemented();
152+
unsigned int size = int_pow(LIBMESH_DIM, N);
153+
for (unsigned int i = 0; i < size; i++)
154+
_coords[i] -= other._coords[i];
143155
return *this;
144156
}
145157

@@ -148,52 +160,64 @@ class TypeNTensor
148160
*/
149161
TypeNTensor<N,T> operator - () const
150162
{
151-
libmesh_not_implemented();
152-
return *this;
163+
TypeNTensor<N, T> minus;
164+
unsigned int size = int_pow(LIBMESH_DIM, N);
165+
minus._coords.resize(size);
166+
for (unsigned int i = 0; i < size; i++)
167+
minus._coords[i] = -_coords[i];
168+
return minus;
153169
}
154170

155171
/**
156172
* Multiply every entry of a tensor by a number.
157173
*/
158174
template <typename Scalar>
159-
typename boostcopy::enable_if_c<
160-
ScalarTraits<Scalar>::value,
161-
TypeNTensor<N,typename CompareTypes<T, Scalar>::supertype>>::type
162-
operator * (const Scalar) const
175+
typename boostcopy::enable_if_c<ScalarTraits<Scalar>::value,
176+
TypeNTensor<N, typename CompareTypes<T, Scalar>::supertype>>::type
177+
operator*(const Scalar factor) const
163178
{
164-
libmesh_not_implemented();
165-
return TypeNTensor<N,typename CompareTypes<T, Scalar>::supertype>();
179+
TypeNTensor<N, T> multiplied;
180+
unsigned int size = int_pow(LIBMESH_DIM, N);
181+
multiplied._coords.resize(size);
182+
for (unsigned int i = 0; i < size; i++)
183+
multiplied._coords[i] = factor * _coords[i];
184+
return multiplied;
166185
}
167186

168187
/**
169188
* Multiply every entry of this tensor by a number.
170189
*/
171190
template <typename Scalar>
172-
const TypeNTensor<N,T> & operator *= (const Scalar)
191+
const TypeNTensor<N, T> & operator*=(const Scalar factor)
173192
{
174-
libmesh_not_implemented();
193+
unsigned int size = int_pow(LIBMESH_DIM, N);
194+
for (unsigned int i = 0; i < size; i++)
195+
_coords[i] *= factor;
175196
return *this;
176197
}
177198

178199
/**
179200
* Divide every entry of a tensor by a number.
180201
*/
181202
template <typename Scalar>
182-
typename boostcopy::enable_if_c<
183-
ScalarTraits<Scalar>::value,
184-
TypeNTensor<N,typename CompareTypes<T, Scalar>::supertype>>::type
185-
operator / (const Scalar) const
203+
typename boostcopy::enable_if_c<ScalarTraits<Scalar>::value,
204+
TypeNTensor<N, typename CompareTypes<T, Scalar>::supertype>>::type
205+
operator/(const Scalar factor) const
186206
{
187-
libmesh_not_implemented();
207+
unsigned int size = int_pow(LIBMESH_DIM, N);
208+
for (unsigned int i = 0; i < size; i++)
209+
_coords[i] /= factor;
188210
return *this;
189211
}
190212

191213
/**
192214
* Divide every entry of this tensor by a number.
193215
*/
194-
const TypeNTensor<N,T> & operator /= (const T)
216+
const TypeNTensor<N, T> & operator/=(const T factor)
195217
{
196-
libmesh_not_implemented();
218+
unsigned int size = int_pow(LIBMESH_DIM, N);
219+
for (unsigned int i = 0; i < size; i++)
220+
_coords[i] /= factor;
197221
return *this;
198222
}
199223

@@ -218,26 +242,30 @@ class TypeNTensor
218242
* \returns The Frobenius norm of the tensor, i.e. the square-root of
219243
* the sum of the elements squared.
220244
*/
221-
auto norm() const
222-
{
223-
libmesh_not_implemented();
224-
return 0.;
225-
}
245+
auto norm() const -> decltype(std::norm(T())) { return std::sqrt(norm_sq()); }
226246

227247
/**
228248
* \returns The Frobenius norm of the tensor squared, i.e. the sum of the
229249
* entry magnitudes squared.
230250
*/
231251
auto norm_sq() const
232252
{
233-
libmesh_not_implemented();
234-
return 0.;
253+
unsigned int size = int_pow(LIBMESH_DIM, N);
254+
auto norm = 0.;
255+
for (unsigned int i = 0; i < size; i++)
256+
norm += _coords[i] * _coords[i];
257+
return norm;
235258
}
236259

237260
/**
238261
* Set all entries of the tensor to 0.
239262
*/
240-
void zero() { libmesh_not_implemented(); }
263+
void zero()
264+
{
265+
unsigned int size = int_pow(LIBMESH_DIM, N);
266+
for (unsigned int i = 0; i < size; i++)
267+
_coords[i] = T(0);
268+
}
241269

242270
/**
243271
* \returns \p true if two tensors are equal, \p false otherwise.

0 commit comments

Comments
 (0)