v0.14.0
src
ftensor
src
FTensor
Tensor2_antisymmetric
Tensor2_antisymmetric_value.hpp
Go to the documentation of this file.
1
#pragma once
2
3
/* A general version, not for pointers. */
4
5
#include <ostream>
6
7
namespace
FTensor
8
{
9
template
<
class
T,
int
Tensor_Dim>
class
Tensor2_antisymmetric
10
{
11
T
data
[(Tensor_Dim * (Tensor_Dim - 1)) / 2];
12
13
public
:
14
template
<
class
...
U
>
Tensor2_antisymmetric
(
U
...
d
) :
data
{
d
...}
15
{
16
static_assert(
sizeof
...(
d
) ==
sizeof
(
data
) /
sizeof
(T),
17
"Incorrect number of Arguments. Constructor should "
18
"initialize the entire Tensor"
);
19
}
20
21
Tensor2_antisymmetric
() {}
22
23
/* There are two ways of accessing the values inside,
24
unsafe(int,int) and operator(int,int). unsafe(int,int) will give
25
you a wrong answer if you aren't careful. The problem is that we
26
only store the minimal set of components, but some have different
27
signs. We can't return the negative of a component, and assign
28
something to it, because that would assign something to a
29
temporary. To get the correct answer if you don't want to change
30
the value, just use operator(int,int). */
31
32
T &
unsafe
(
const
int
N1,
const
int
N2)
33
{
34
#ifdef FTENSOR_DEBUG
35
if
(N1 >= Tensor_Dim || N1 < 0 || N2 >= Tensor_Dim || N2 < 0 || N1 >= N2)
36
{
37
std::stringstream s;
38
s <<
"Bad index in Tensor2_antisymmetric<T,"
<< Tensor_Dim
39
<<
">.operator("
<< N1 <<
","
<< N2 <<
")"
<< std::endl;
40
throw
std::out_of_range(s.str());
41
}
42
#endif
43
return
data
[(N2 - 1) + (N1 * (2 * (Tensor_Dim - 1) - N1 - 1)) / 2];
44
}
45
46
T
operator()
(
const
int
N1,
const
int
N2)
const
47
{
48
#ifdef FTENSOR_DEBUG
49
if
(N1 >= Tensor_Dim || N1 < 0 || N2 >= Tensor_Dim || N2 < 0)
50
{
51
std::stringstream s;
52
s <<
"Bad index in Tensor2_antisymmetric<T,"
<< Tensor_Dim
53
<<
">.operator("
<< N1 <<
","
<< N2 <<
") const"
<< std::endl;
54
throw
std::out_of_range(s.str());
55
}
56
#endif
57
return
N1 == N2
58
? 0
59
: (N1 < N2
60
?
data
[(N2 - 1)
61
+ (N1 * (2 * (Tensor_Dim - 1) - N1 - 1)) / 2]
62
: -
data
[(N1 - 1)
63
+ (N2 * (2 * (Tensor_Dim - 1) - N2 - 1)) / 2]);
64
}
65
66
/* These operator()'s are the first part in constructing template
67
expressions. They can be used to slice off lower dimensional
68
parts. They are not entirely safe, since you can accidently use a
69
higher dimension than what is really allowed (like Dim=5). */
70
71
/* This returns a Tensor2_Expr, since the indices are not really
72
antisymmetric anymore since they cover different dimensions. */
73
74
template
<
char
i,
char
j,
int
Dim0,
int
Dim1>
75
typename
std::enable_if
<(Tensor_Dim >= Dim0 && Tensor_Dim >= Dim1),
76
Tensor2_Expr
<
Tensor2_antisymmetric<T, Tensor_Dim>
,
77
T, Dim0, Dim1,
i
,
j
>>::
type
78
operator
()(
const
Index<i, Dim0>
,
const
Index<j, Dim1>
)
79
{
80
return
Tensor2_Expr<Tensor2_antisymmetric<T, Tensor_Dim>
, T, Dim0, Dim1,
81
i
,
j
>(*this);
82
}
83
84
template
<
char
i,
char
j,
int
Dim0,
int
Dim1>
85
typename
std::enable_if
<
86
(Tensor_Dim >= Dim0 && Tensor_Dim >= Dim1),
87
Tensor2_Expr
<
const
Tensor2_antisymmetric<T, Tensor_Dim>
, T, Dim0, Dim1,
88
i
,
j
>>::
type
89
operator
()(
const
Index<i, Dim0>
,
const
Index<j, Dim1>
)
const
90
{
91
return
Tensor2_Expr<const Tensor2_antisymmetric<T, Tensor_Dim>
, T, Dim0,
92
Dim1,
i
,
j
>(*this);
93
}
94
95
/* This returns a Tensor2_antisymmetric_Expr, since the indices are still
96
antisymmetric on the lower dimensions. */
97
98
template
<
char
i,
char
j,
int
Dim>
99
typename
std::enable_if
<
100
(Tensor_Dim >= Dim),
101
Tensor2_antisymmetric_Expr
<
Tensor2_antisymmetric<T, Tensor_Dim>
, T, Dim,
102
i
,
j
>>::
type
103
operator
()(
const
Index<i, Dim>
index1,
const
Index<j, Dim>
index2)
104
{
105
return
Tensor2_antisymmetric_Expr<Tensor2_antisymmetric<T, Tensor_Dim>
,
106
T, Dim,
i
,
j
>(*this);
107
}
108
109
template
<
char
i,
char
j,
int
Dim>
110
typename
std::enable_if
<
111
(Tensor_Dim >= Dim),
112
Tensor2_antisymmetric_Expr
<
const
Tensor2_antisymmetric<T, Tensor_Dim>
, T,
113
Dim,
i
,
j
>>::
type
114
operator
()(
const
Index<i, Dim>
index1,
const
Index<j, Dim>
index2)
const
115
{
116
return
Tensor2_antisymmetric_Expr
<
117
const
Tensor2_antisymmetric<T, Tensor_Dim>
, T, Dim,
i
,
j
>(*this);
118
}
119
120
/* This is for expressions where a number is used for one slot, and
121
an index for another, yielding a Tensor1_Expr. The non-const
122
versions don't actually create a Tensor2_number_rhs_[01] object.
123
They create a Tensor1_Expr directly, which provides the
124
appropriate indexing operators. The const versions do create a
125
Tensor2_number_[01]. */
126
127
template
<
char
i,
int
N,
int
Dim>
128
typename
std::enable_if
<
129
(Tensor_Dim >= Dim && Tensor_Dim >
N
),
130
Tensor1_Expr
<
131
Tensor2_number_rhs_1
<
Tensor2_antisymmetric<T, Tensor_Dim>
, T,
N
>, T,
132
Dim,
i
>>::
type
133
operator
()(
const
Index<i, Dim>
index1,
const
Number<N>
)
134
{
135
using
TensorExpr
136
=
Tensor2_number_rhs_1<Tensor2_antisymmetric<T, Tensor_Dim>
, T,
N
>;
137
return
Tensor1_Expr<TensorExpr, T, Dim, i>
(*
this
);
138
}
139
140
template
<
char
i,
int
N,
int
Dim>
141
typename
std::enable_if
<
142
(Tensor_Dim >= Dim && Tensor_Dim >
N
),
143
Tensor1_Expr
<
const
Tensor2_number_1
<
144
const
Tensor2_antisymmetric<T, Tensor_Dim>
, T,
N
>,
145
T, Dim,
i
>>::
type
146
operator
()(
const
Index<i, Dim>
index1,
const
Number<N>
)
const
147
{
148
using
TensorExpr
149
=
Tensor2_number_1<const Tensor2_antisymmetric<T, Tensor_Dim>
, T,
N
>;
150
return
Tensor1_Expr<TensorExpr, T, Dim, i>
(TensorExpr(*
this
));
151
}
152
153
template
<
char
i,
int
N,
int
Dim>
154
typename
std::enable_if
<
155
(Tensor_Dim >
N
&& Tensor_Dim >= Dim),
156
Tensor1_Expr
<
157
Tensor2_number_rhs_0
<
Tensor2_antisymmetric<T, Tensor_Dim>
, T,
N
>, T,
158
Dim,
i
>>::
type
159
operator
()(
const
Number<N>
,
const
Index<i, Dim>
index1)
160
{
161
using
TensorExpr
162
=
Tensor2_number_rhs_0<Tensor2_antisymmetric<T, Tensor_Dim>
, T,
N
>;
163
return
Tensor1_Expr<TensorExpr, T, Dim, i>
(*
this
);
164
}
165
166
template
<
char
i,
int
N,
int
Dim>
167
typename
std::enable_if
<
168
(Tensor_Dim >
N
&& Tensor_Dim >= Dim),
169
Tensor1_Expr
<
const
Tensor2_number_0
<
170
const
Tensor2_antisymmetric<T, Tensor_Dim>
, T,
N
>,
171
T, Dim,
i
>>::
type
172
operator
()(
const
Number<N>
&n1,
const
Index<i, Dim>
index1)
const
173
{
174
using
TensorExpr
175
=
Tensor2_number_0<const Tensor2_antisymmetric<T, Tensor_Dim>
, T,
N
>;
176
return
Tensor1_Expr<TensorExpr, T, Dim, i>
(TensorExpr(*
this
));
177
}
178
179
/* Specializations for using actual numbers instead of Number<> */
180
181
template
<
char
i,
int
Dim>
182
typename
std::enable_if
<
183
(Tensor_Dim >= Dim),
184
Tensor1_Expr
<
185
const
Tensor2_numeral_1
<
const
Tensor2_antisymmetric<T, Tensor_Dim>
, T>,
186
T, Dim,
i
>>::
type
187
operator
()(
const
Index<i, Dim>
index1,
const
int
N
)
const
188
{
189
using
TensorExpr
190
=
Tensor2_numeral_1<const Tensor2_antisymmetric<T, Tensor_Dim>
, T>;
191
return
Tensor1_Expr<TensorExpr, T, Dim, i>
(TensorExpr(*
this
,
N
));
192
}
193
194
template
<
char
i,
int
Dim>
195
typename
std::enable_if
<
196
(Tensor_Dim >= Dim),
197
Tensor1_Expr
<
198
const
Tensor2_numeral_0
<
const
Tensor2_antisymmetric<T, Tensor_Dim>
, T>,
199
T, Dim,
i
>>::
type
200
operator
()(
const
int
N
,
const
Index<i, Dim>
index1)
const
201
{
202
using
TensorExpr
203
=
Tensor2_numeral_0<const Tensor2_antisymmetric<T, Tensor_Dim>
, T>;
204
return
Tensor1_Expr<TensorExpr, T, Dim, i>
(TensorExpr(*
this
,
N
));
205
}
206
207
/* These two operator()'s return the Tensor2 with internal
208
contractions, yielding a T. I have to specify one for both
209
const and non-const because otherwise the compiler will use the
210
operator() which gives a Tensor2_Expr<>. */
211
212
/* TODO Here is a good question. It wont create a problem if i put
213
a higher dimension Index in here but it would be
214
grammatically wrong. Im gonna add it for now, we can discuss it*/
215
216
template
<
char
i,
int
Dim>
217
typename
std::enable_if
<(Tensor_Dim >= Dim), T>::
type
218
operator
()(
const
Index<i, Dim>
index1,
const
Index<i, Dim>
index2)
219
{
220
return
0;
221
}
222
223
template
<
char
i,
int
Dim>
224
typename
std::enable_if
<(Tensor_Dim >= Dim), T>::
type
225
operator
()(
const
Index<i, Dim>
index1,
const
Index<i, Dim>
index2)
const
226
{
227
return
0;
228
}
229
};
230
}
231
232
/// JSON compatible output. It only outputs unique, non-zero elments,
233
/// so a 3x3 antisymmetric matrix only outputs 3 elements.
234
235
namespace
FTensor
236
{
237
template
<
class
T,
int
Tensor_Dim>
238
std::ostream &
Tensor2_antisymmetric_ostream_row
(
239
std::ostream &os,
const
FTensor::Tensor2_antisymmetric<T, Tensor_Dim>
&
t
,
240
const
int
&
i
)
241
{
242
os <<
'['
;
243
for
(
int
j
=
i
+ 1;
j
+ 1 < Tensor_Dim; ++
j
)
244
{
245
os <<
t
(
i
,
j
) <<
','
;
246
}
247
if
(Tensor_Dim > 0)
248
{
249
os <<
t
(
i
, Tensor_Dim - 1);
250
}
251
os <<
']'
;
252
return
os;
253
}
254
}
255
256
template
<
class
T,
int
Tensor_Dim>
257
std::ostream &
258
operator<<
(std::ostream &os,
259
const
FTensor::Tensor2_antisymmetric<T, Tensor_Dim>
&
t
)
260
{
261
os <<
'['
;
262
for
(
int
i
= 0;
i
+ 2 < Tensor_Dim; ++
i
)
263
{
264
FTensor::Tensor2_antisymmetric_ostream_row
(os,
t
,
i
);
265
os <<
','
;
266
}
267
if
(Tensor_Dim > 1)
268
{
269
FTensor::Tensor2_antisymmetric_ostream_row
(os,
t
, Tensor_Dim - 2);
270
}
271
os <<
']'
;
272
return
os;
273
}
274
275
namespace
FTensor
276
{
277
template
<
class
T,
int
Tensor_Dim>
278
std::istream &
Tensor2_antisymmetric_istream_row
(
279
std::istream &is,
FTensor::Tensor2_antisymmetric<T, Tensor_Dim>
&
t
,
280
const
int
&
i
)
281
{
282
char
c
;
283
is >>
c
;
284
for
(
int
j
=
i
+ 1;
j
+ 1 < Tensor_Dim; ++
j
)
285
{
286
is >>
t
.unsafe(
i
,
j
) >>
c
;
287
}
288
if
(Tensor_Dim > 0)
289
{
290
is >>
t
.unsafe(
i
, Tensor_Dim - 1);
291
}
292
is >>
c
;
293
return
is;
294
}
295
}
296
297
template
<
class
T,
int
Tensor_Dim>
298
std::istream &
299
operator>>
(std::istream &is,
FTensor::Tensor2_antisymmetric<T, Tensor_Dim>
&
t
)
300
{
301
char
c
;
302
is >>
c
;
303
for
(
int
i
= 0;
i
+ 2 < Tensor_Dim; ++
i
)
304
{
305
FTensor::Tensor2_antisymmetric_istream_row
(is,
t
,
i
);
306
is >>
c
;
307
}
308
if
(Tensor_Dim > 1)
309
{
310
FTensor::Tensor2_antisymmetric_istream_row
(is,
t
, Tensor_Dim - 2);
311
}
312
is >>
c
;
313
return
is;
314
}
FTensor
JSON compatible output.
Definition:
Christof_constructor.hpp:6
FTensor::Tensor2_antisymmetric_Expr
Definition:
Tensor2_antisymmetric_Expr.hpp:9
FTensor::Tensor2_antisymmetric::unsafe
T & unsafe(const int N1, const int N2)
Definition:
Tensor2_antisymmetric_value.hpp:32
FTensor::Tensor2_number_rhs_1
Definition:
Tensor2_number.hpp:29
FTensor::Tensor2_numeral_1
Definition:
Tensor2_numeral.hpp:8
FTensor::Tensor2_Expr
Definition:
Tensor2_Expr.hpp:26
FTensor::d
const Tensor1_Expr< const dTensor0< T, Dim, i >, typename promote< T, double >::V, Dim, i > d(const Tensor0< T * > &a, const Index< i, Dim > index, const Tensor1< int, Dim > &d_ijk, const Tensor1< double, Dim > &d_xyz)
Definition:
dTensor0.hpp:27
FTensor::Tensor2_antisymmetric::Tensor2_antisymmetric
Tensor2_antisymmetric(U... d)
Definition:
Tensor2_antisymmetric_value.hpp:14
operator<<
std::ostream & operator<<(std::ostream &os, const FTensor::Tensor2_antisymmetric< T, Tensor_Dim > &t)
Definition:
Tensor2_antisymmetric_value.hpp:258
FTensor::Tensor2_number_1
Definition:
Tensor2_number.hpp:8
c
const double c
speed of light (cm/ns)
Definition:
initial_diffusion.cpp:39
FTensor::Tensor2_antisymmetric_istream_row
std::istream & Tensor2_antisymmetric_istream_row(std::istream &is, FTensor::Tensor2_antisymmetric< T, Tensor_Dim > &t, const int &i)
Definition:
Tensor2_antisymmetric_value.hpp:278
FTensor::Tensor2_antisymmetric::Tensor2_antisymmetric
Tensor2_antisymmetric()
Definition:
Tensor2_antisymmetric_value.hpp:21
FTensor::Number
Definition:
Number.hpp:11
FTensor::Tensor1_Expr
Definition:
Tensor1_Expr.hpp:27
convert.type
type
Definition:
convert.py:64
FTensor::Tensor2_antisymmetric
Definition:
Tensor2_antisymmetric_value.hpp:9
FTensor::Tensor2_number_0
Definition:
Tensor2_number.hpp:17
t
constexpr double t
plate stiffness
Definition:
plate.cpp:58
i
FTensor::Index< 'i', SPACE_DIM > i
Definition:
hcurl_divergence_operator_2d.cpp:27
FTensor::Index
Definition:
Index.hpp:23
FTensor::Tensor2_antisymmetric::data
T data[(Tensor_Dim *(Tensor_Dim - 1))/2]
Definition:
Tensor2_antisymmetric_value.hpp:11
std::enable_if
Definition:
enable_if.hpp:7
N
const int N
Definition:
speed_test.cpp:3
FTensor::Tensor2_antisymmetric::operator()
T operator()(const int N1, const int N2) const
Definition:
Tensor2_antisymmetric_value.hpp:46
j
FTensor::Index< 'j', 3 > j
Definition:
matrix_function.cpp:19
FTensor::Tensor2_antisymmetric_ostream_row
std::ostream & Tensor2_antisymmetric_ostream_row(std::ostream &os, const FTensor::Tensor2_antisymmetric< T, Tensor_Dim > &t, const int &i)
Definition:
Tensor2_antisymmetric_value.hpp:238
FTensor::Tensor2_number_rhs_0
Definition:
Tensor2_number.hpp:26
operator>>
std::istream & operator>>(std::istream &is, FTensor::Tensor2_antisymmetric< T, Tensor_Dim > &t)
Definition:
Tensor2_antisymmetric_value.hpp:299
EshelbianPlasticity::U
@ U
Definition:
EshelbianContact.cpp:197
FTensor::Tensor2_numeral_0
Definition:
Tensor2_numeral.hpp:18
Generated by
Doxygen
1.8.17 and hosted at