Chi-Tech
chi_math_vectorNX.h
Go to the documentation of this file.
1#ifndef chi_math_VectorNX_h
2#define chi_math_VectorNX_h
3
4namespace chi_mesh
5{
6 struct TensorRank2Dim3;
7 struct Vector3;
8}
9
10namespace chi_math
11{
12 template<int R, int N, class NumberFormat>
13 struct TensorRNX;
14}
15
16#include "mesh/chi_meshvector.h"
17
18#include <iostream>
19
20#include <vector>
21#include <array>
22#include <cmath>
23#include <sstream>
24
25#include<type_traits>
26
27namespace chi_math
28{
29 //#################################################################
30 /**Generalized vector notion.
31 * \author Jerry, Jan.*/
32 template <int N, class NumberFormat>
33 struct VectorNX
34 {
35 std::array<NumberFormat,N> elements;
36 const unsigned int dimension;
37
38 /**Default constructor. */
40 {
41 static_assert(std::is_floating_point<NumberFormat>::value,
42 "Only floating point number formats are supported for VectorNX." );
43
44 elements.fill(NumberFormat());
45 }
46
47 /** Constructor with value. */
48 VectorNX(const NumberFormat value) : dimension(N)
49 {
50 static_assert(std::is_floating_point<NumberFormat>::value,
51 "Only floating point number formats are supported for VectorNX." );
52
53 elements.fill(value);
54 }
55
56 /** Constructor with chi_mesh::Vector3. */
58 {
59 static_assert(std::is_floating_point<NumberFormat>::value,
60 "Only floating point number formats are supported for VectorNX." );
61
62 elements.fill(NumberFormat());
63
64 for (int i = 0; (i<N) and (i<3);++i)
65 elements[i] = that[i];
66 }
67
68 /** Constructor with array of values. This allows constructors of the
69 * form:
70 * \code
71 * chi_math::Vector3 ihat({1.0,0.0});
72 * chi_math::Vector3 jhat({0.0,1.0,0.0,1.0});
73 * chi_math::Vector3 khat({0.0,0.0,1.0});
74 * \endcode */
75 VectorNX(const std::vector<NumberFormat>& values) : dimension(N)
76 {
77 static_assert(std::is_floating_point<NumberFormat>::value,
78 "Only floating point number formats are supported for VectorNX." );
79
80 elements.fill(NumberFormat());
81 for (int i = 0; i<values.size() and i<dimension; ++i)
82 elements[i] = values[i];
83 }
84
85 /**Component-wise copy.*/
87 {
88 elements = rhs.elements;
89
90 return *this;
91 }
92
93 /**Component-wise from chi_mesh::Vector3.*/
95 {
96 for (int i = 0; (i<N) and (i<3);++i)
97 elements[i] = rhs[i];
98
99 return *this;
100 }
101
102 //=========================================== Addition
103 /**Component-wise addition of two vectors.
104 * \f$ \vec{w} = \vec{x} + \vec{y} \f$*/
105 VectorNX operator+(const VectorNX& rhs) const
106 {
107 VectorNX<N,NumberFormat> newVector;
108 for (int i = 0; i<N;++i)
109 newVector.elements[i] = elements[i] + rhs.elements[i];
110
111 return newVector;
112 }
113
114 /**In-place component-wise addition of two vectors.
115 * \f$ \vec{x} = \vec{x} + \vec{y} \f$*/
117 {
118 for (int i = 0; i<N;++i)
119 elements[i] += rhs.elements[i];
120
121 return *this;
122 }
123
124 /**Component-wise shift by scalar-value.
125 * \f$ \vec{w} = \vec{x} + \alpha \f$*/
126 VectorNX Shifted(const NumberFormat value) const
127 {
128 VectorNX<N,NumberFormat> newVector;
129 for (int i = 0; i<N;++i)
130 newVector.elements[i] = elements[i] + value;
131
132 return newVector;
133 }
134
135 /**In-place component-wise shift by scalar-value.
136 * \f$ \vec{x} = \vec{x} + \alpha \f$*/
137 VectorNX& Shift(const NumberFormat value)
138 {
139 for (int i = 0; i<N;++i)
140 elements[i] += value;
141
142 return *this;
143 }
144
145 //=========================================== Subtraction
146 /**Component-wise subtraction.
147 * \f$ \vec{w} = \vec{x} - \vec{y} \f$*/
148 VectorNX operator-(const VectorNX& rhs) const
149 {
150 VectorNX<N,NumberFormat> newVector;
151 for (int i = 0; i<N;++i)
152 newVector.elements[i] = elements[i] - rhs.elements[i];
153
154 return newVector;
155 }
156
157 /**In-place component-wise subtraction.
158 * \f$ \vec{x} = \vec{x} - \vec{y} \f$*/
160 {
161 for (int i = 0; i<N;++i)
162 elements[i] -= rhs.elements[i];
163
164 return *this;
165 }
166
167 //=========================================== Multiplication
168 /**Vector component-wise multiplication by scalar.
169 * \f$ \vec{w} = \vec{x} \alpha \f$*/
170 VectorNX operator*(const NumberFormat value) const
171 {
172 VectorNX<N,NumberFormat> newVector;
173 for (int i = 0;i<N;++i)
174 newVector.elements[i] = elements[i] * value;
175
176 return newVector;
177 }
178
179 /**Vector in-place component-wise multiplication by scalar.
180 * \f$ \vec{x} = \vec{x} \alpha \f$*/
181 VectorNX& operator*=(const NumberFormat value)
182 {
183 for (int i = 0;i<N;++i)
184 elements[i] *= value;
185
186 return *this;
187 }
188
189 /**Vector component-wise multiplication.
190 * \f$ w_i = x_i y_i \f$*/
191 VectorNX operator*(const VectorNX& rhs) const
192 {
193 VectorNX<N,NumberFormat> newVector;
194 for (int i = 0; i<N ; ++i)
195 newVector.elements[i] = elements[i] * rhs.elements[i];
196
197 return newVector;
198 }
199
200 /**Vector in-place component-wise multiplication.
201 * \f$ x_i = x_i y_i \f$*/
203 {
204 for (int i = 0; i<N ; ++i)
205 elements[i] *= rhs.elements[i];
206
207 return *this;
208 }
209
210 //=========================================== Division
211 /**Vector component-wise division by scalar.
212 * \f$ w_i = \frac{x_i}{\alpha} \f$*/
213 VectorNX operator/(const NumberFormat value) const
214 {
215 VectorNX<N,NumberFormat> newVector;
216 for (int i = 0;i<N;++i)
217 newVector.elements[i] = elements[i] / value;
218
219 return newVector;
220 }
221
222 /**Vector in-place component-wise division by scalar.
223 * \f$ x_i = \frac{x_i}{\alpha} \f$*/
224 VectorNX& operator/=(const NumberFormat value)
225 {
226 for (int i = 0;i<N;++i)
227 elements[i] /= value;
228
229 return *this;
230 }
231
232 /**Vector component-wise division.
233 * \f$ w_i = \frac{x_i}{y_i} \f$*/
234 VectorNX operator/(const VectorNX& rhs) const
235 {
236 VectorNX<N,NumberFormat> newVector;
237 for (int i = 0; i<N ; ++i)
238 newVector.elements[i] = elements[i] / rhs.elements[i];
239
240 return newVector;
241 }
242
243 /**Vector in-place component-wise division.
244 * \f$ x_i = \frac{x_i}{y_i} \f$*/
246 {
247 for (int i = 0; i<N ; ++i)
248 elements[i] /= rhs.elements[i];
249
250 return *this;
251 }
252
253 //=========================================== Element access
254 /**Returns a copy of the value at the given index.*/
255 NumberFormat operator[] (int i) const
256 {
257 return elements[i];
258 }
259
260 /**Returns a reference of the value at the given index.*/
261 NumberFormat& operator ()(int i)
262 {
263 return elements[i];
264 }
265
266 //=========================================== Tensor product
268 {
270 for (int i=0; i<N; ++i)
271 for (int j=0; j<N; ++j)
272 out_tensor(i)(j) = elements[i]*that.elements[j];
273
274 return out_tensor;
275 }
276
277 //=========================================== Tensor dot product
279 {
281 for (int i=0; i<N; ++i)
282 new_vec(i) = this->Dot(that.entries[i]);
283
284 return new_vec;
285 }
286
287 //=========================================== Operations
288 /**Vector cross-product.
289 * \f$ \vec{w} = \vec{x} \times \vec{y} \f$*/
291 {
292 static_assert(N == 2 or N ==3,
293 "chi_math::VectorNX::Cross only defined for dimension 2 or 3 vectors.");
294
295 VectorNX<3,NumberFormat> newVector;
296 if (dimension==3)
297 {
298 newVector(0) = -elements[2]*rhs.elements[1];
299 newVector(1) = elements[2]*rhs.elements[0];
300 newVector(2) = elements[0]*rhs.elements[1] - elements[1]*rhs.elements[0];
301 }
302 else
303 newVector(2) = elements[0]*rhs.elements[1] - elements[1]*rhs.elements[0];
304
305 return newVector;
306 }
307
308 /**Vector cross-product.
309 * \f$ \vec{w} = \vec{x} \times \vec{y} \f$*/
311 {
312 static_assert(N == 2 or N ==3,
313 "chi_math::VectorNX::Cross only defined for dimension 2 or 3 vectors.");
314
315 VectorNX<3,NumberFormat> newVector;
316 if (dimension==3)
317 {
318 newVector(0) = elements[1]*rhs.elements[2] - elements[2]*rhs.elements[1];
319 newVector(1) = elements[2]*rhs.elements[0] - elements[0]*rhs.elements[2];
320 newVector(2) = elements[0]*rhs.elements[1] - elements[1]*rhs.elements[0];
321 }
322 else
323 {
324 newVector(0) = elements[1]*rhs.elements[2];
325 newVector(1) = -elements[0]*rhs.elements[2];
326 newVector(2) = elements[0]*rhs.elements[1] - elements[1]*rhs.elements[0];
327 }
328
329 return newVector;
330 }
331
332 /**Vector dot-product.
333 * \f$ \vec{w} = \vec{x} \bullet \vec{y} \f$ */
334 NumberFormat Dot(const VectorNX& rhs) const
335 {
336 NumberFormat value = 0.0;
337 for (int i = 0; i<N; ++i)
338 value += elements[i]*rhs.elements[i];
339
340 return value;
341 }
342
343 /**Vector dot-product.
344 * \f$ \vec{w} = \vec{x} \bullet \vec{y} \f$ */
345 NumberFormat Dot(const chi_mesh::Vector3& rhs) const
346 {
347 NumberFormat value = 0.0;
348 for (int i = 0; (i<N) and (i<3); ++i)
349 value += elements[i]*rhs[i];
350
351 return value;
352 }
353
354 /**Computes the L2-norm of the vector. Otherwise known as the length of
355 * a 3D vector.*/
356 NumberFormat Norm() const
357 {
358 NumberFormat value = 0.0;
359 for (int i = 0; i<N;++i)
360 value += elements[i]*elements[i];
361
362 value = sqrt(value);
363 return value;
364 }
365
366 /**Computes the square of the L2-norm of the vector. This eliminates the
367 * usage of the square root and is therefore less expensive that a proper
368 * L2-norm. Useful if only comparing distances.*/
369 NumberFormat NormSquare() const
370 {
371 NumberFormat value = 0.0;
372 for (int i = 0; i<N;++i)
373 value += elements[i]*elements[i];
374
375 return value;
376 }
377
378 /**Normalizes the vector in-place.*/
380 {
381 NumberFormat norm = this->Norm();
382 for (int i = 0;i<N;++i)
383 elements[i] = elements[i]/norm;
384 }
385
386 /**Returns a normalized version of the vector.*/
388 {
389 NumberFormat norm = this->Norm();
390 VectorNX<N,NumberFormat> newVector;
391 for (int i = 0;i<N;++i)
392 newVector.elements[i] = elements[i]/norm;
393
394 return newVector;
395 }
396
397 /**Returns a vector v^* where each element is inverted provided
398 * that it is greater than the given tolerance, otherwise the offending entry
399 * is set to 0.0.*/
400 VectorNX InverseZeroIfSmaller(NumberFormat tol) const
401 {
402 VectorNX<N,NumberFormat> newVector;
403 for (int i = 0; i<N;++i)
404 newVector.elements[i] = (std::fabs(elements[i])>tol) ? 1.0/elements[i] : 0.0;
405
406 return newVector;
407 }
408
409 /**Returns a vector v^* where each element is inverted provided
410 * that it is greater than the given tolerance, otherwise the offending entry
411 * is set to 1.0.*/
412 VectorNX InverseOneIfSmaller(NumberFormat tol) const
413 {
414 VectorNX<N,NumberFormat> newVector;
415 for (int i = 0; i<N;++i)
416 newVector.elements[i] = (std::fabs(elements[i])>tol) ? 1.0/elements[i] : 1.0;
417
418 return newVector;
419 }
420
421 /**Returns a vector v^* where each element is inverted provided
422 * that the inversion is not infinite, otherwise it is zeroed.*/
424 {
425 VectorNX<N,NumberFormat> newVector;
426 for (int i = 0; i<N; ++i)
427 {
428 NumberFormat dn_inv = 1.0/elements[i];
429 newVector.elements[i] = (std::isinf(dn_inv))? dn_inv : 0.0;
430 }
431
432 return newVector;
433 }
434
435 /**Returns a vector v^* where each element is inverted without any
436 * check for division by zero.
437 * \f$ w_i = \frac{1.0}{x_i} \f$*/
439 {
440 VectorNX newVector;
441 for (int i = 0; i<N; ++i)
442 newVector.elements[i] = 1.0/elements[i];
443
444 return newVector;
445 }
446
447 /**prints the vector to standard cout*/
448 void Print() const
449 {
450 for (int i = 0; i<N-1; i++)
451 std::cout<<elements[i]<<" ";
452 std::cout<<elements[N-1];
453 }
454
455 //overloading <<
456
457
458 /**Prints the vector to a string and then returns the string.*/
459 std::string PrintS() const
460 {
461 std::stringstream out;
462 out<<"[";
463 for (int i = 0; i<N-1 ; ++i)
464 out<<elements[i]<<" ";
465 out<<elements[N-1]<<"]";
466
467 return out.str();
468 }
469 };
470 template<int N>
472
475
476}
477
478/**Multiplication by a scalar from the left.*/
479template<int N, class NumberFormat>
481operator*(const double value,const chi_math::VectorNX<N,NumberFormat>& that)
482{
484 for (int i = 0; i<N;++i)
485 newVector.elements[i] = that.elements[i]*value;
486 return newVector;
487}
488#endif
chi_math::VectorNX< N, NumberFormat > operator*(const double value, const chi_math::VectorNX< N, NumberFormat > &that)
VectorN< 3 > Vector3
std::vector< VectorNX< N, NumberFormat > > entries
VectorNX< 3, NumberFormat > Cross(const VectorNX< 3, NumberFormat > &rhs)
VectorNX & operator/=(const NumberFormat value)
VectorNX< N, NumberFormat > Dot(const TensorRNX< 2, N, NumberFormat > &that) const
VectorNX & operator=(const VectorNX &rhs)
VectorNX & operator=(const chi_mesh::Vector3 &rhs)
NumberFormat operator[](int i) const
std::string PrintS() const
NumberFormat & operator()(int i)
VectorNX< 3, NumberFormat > Cross(const VectorNX< 2, NumberFormat > &rhs)
VectorNX Shifted(const NumberFormat value) const
VectorNX operator*(const NumberFormat value) const
VectorNX & operator/=(const VectorNX &rhs)
VectorNX Normalized() const
VectorNX & operator*=(const VectorNX &rhs)
VectorNX(const chi_mesh::Vector3 &that)
VectorNX & Shift(const NumberFormat value)
VectorNX InverseZeroIfSmaller(NumberFormat tol) const
VectorNX & operator*=(const NumberFormat value)
NumberFormat Dot(const VectorNX &rhs) const
TensorRNX< 2, N, NumberFormat > OTimes(const VectorNX< N, NumberFormat > &that) const
std::array< NumberFormat, N > elements
VectorNX Inverse() const
VectorNX operator+(const VectorNX &rhs) const
VectorNX InverseZeroIfInf() const
VectorNX operator/(const NumberFormat value) const
VectorNX operator-(const VectorNX &rhs) const
VectorNX InverseOneIfSmaller(NumberFormat tol) const
VectorNX operator*(const VectorNX &rhs) const
VectorNX operator/(const VectorNX &rhs) const
const unsigned int dimension
NumberFormat Norm() const
VectorNX(const NumberFormat value)
NumberFormat Dot(const chi_mesh::Vector3 &rhs) const
NumberFormat NormSquare() const
VectorNX & operator+=(const VectorNX &rhs)
VectorNX & operator-=(const VectorNX &rhs)
VectorNX(const std::vector< NumberFormat > &values)