@@ -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