[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
4.14.1 Indexed quantities and their indices
Indexed expressions in GiNaC are constructed of two special types of objects, index objects and indexed objects.
- Index objects are of class
idx
or a subclass. Every index has a value and a dimension (which is the dimension of the space the index lives in) which can both be arbitrary expressions but are usually a number or a simple symbol. In addition, indices of classvaridx
have a variance (they can be co- or contravariant), and indices of classspinidx
have a variance and can be dotted or undotted. - Indexed objects are of class
indexed
or a subclass. They contain a base expression (which is the expression being indexed), and one or more indices.
Please notice: when printing expressions, covariant indices and indices without variance are denoted ‘.i’ while contravariant indices are denoted ‘~i’. Dotted indices have a ‘*’ in front of the index value. In the following, we are going to use that notation in the text so instead of A^i_jk we will write ‘A~i.j.k’. Index dimensions are not visible in the output.
A simple example shall illustrate the concepts:
#include <iostream> #include <ginac/ginac.h> using namespace std; using namespace GiNaC; int main() { symbol i_sym("i"), j_sym("j"); idx i(i_sym, 3), j(j_sym, 3); symbol A("A"); cout << indexed(A, i, j) << endl; // -> A.i.j cout << index_dimensions << indexed(A, i, j) << endl; // -> A.i[3].j[3] cout << dflt; // reset cout to default output format (dimensions hidden) ... |
The idx
constructor takes two arguments, the index value and the
index dimension. First we define two index objects, i
and j
,
both with the numeric dimension 3. The value of the index i
is the
symbol i_sym
(which prints as ‘i’) and the value of the index
j
is the symbol j_sym
(which prints as ‘j’). Next we
construct an expression containing one indexed object, ‘A.i.j’. It has
the symbol A
as its base expression and the two indices i
and
j
.
The dimensions of indices are normally not visible in the output, but one
can request them to be printed with the index_dimensions
manipulator,
as shown above.
Note the difference between the indices i
and j
which are of
class idx
, and the index values which are the symbols i_sym
and j_sym
. The indices of indexed objects cannot directly be symbols
or numbers but must be index objects. For example, the following is not
correct and will raise an exception:
symbol i("i"), j("j"); e = indexed(A, i, j); // ERROR: indices must be of type idx |
You can have multiple indexed objects in an expression, index values can be numeric, and index dimensions symbolic:
... symbol B("B"), dim("dim"); cout << 4 * indexed(A, i) + indexed(B, idx(j_sym, 4), idx(2, 3), idx(i_sym, dim)) << endl; // -> B.j.2.i+4*A.i ... |
B
has a 4-dimensional symbolic index ‘k’, a 3-dimensional numeric
index of value 2, and a symbolic index ‘i’ with the symbolic dimension
‘dim’. Note that GiNaC doesn't automatically notify you that the free
indices of ‘A’ and ‘B’ in the sum don't match (you have to call
simplify_indexed()
for that, see below).
In fact, base expressions, index values and index dimensions can be arbitrary expressions:
... cout << indexed(A+B, idx(2*i_sym+1, dim/2)) << endl; // -> (B+A).(1+2*i) ... |
It's also possible to construct nonsense like ‘Pi.sin(x)’. You will not get an error message from this but you will probably not be able to do anything useful with it.
The methods
ex idx::get_value(); ex idx::get_dim(); |
return the value and dimension of an idx
object. If you have an index
in an expression, such as returned by calling .op()
on an indexed
object, you can get a reference to the idx
object with the function
ex_to<idx>()
on the expression.
There are also the methods
bool idx::is_numeric(); bool idx::is_symbolic(); bool idx::is_dim_numeric(); bool idx::is_dim_symbolic(); |
for checking whether the value and dimension are numeric or symbolic
(non-numeric). Using the info()
method of an index (see Getting information about expressions) returns information about the index value.
If you need co- and contravariant indices, use the varidx
class:
... symbol mu_sym("mu"), nu_sym("nu"); varidx mu(mu_sym, 4), nu(nu_sym, 4); // default is contravariant ~mu, ~nu varidx mu_co(mu_sym, 4, true); // covariant index .mu cout << indexed(A, mu, nu) << endl; // -> A~mu~nu cout << indexed(A, mu_co, nu) << endl; // -> A.mu~nu cout << indexed(A, mu.toggle_variance(), nu) << endl; // -> A.mu~nu ... |
A varidx
is an idx
with an additional flag that marks it as
co- or contravariant. The default is a contravariant (upper) index, but
this can be overridden by supplying a third argument to the varidx
constructor. The two methods
bool varidx::is_covariant(); bool varidx::is_contravariant(); |
allow you to check the variance of a varidx
object (use ex_to<varidx>()
to get the object reference from an expression). There's also the very useful
method
ex varidx::toggle_variance(); |
which makes a new index with the same value and dimension but the opposite variance. By using it you only have to define the index once.
The spinidx
class provides dotted and undotted variant indices, as
used in the Weyl-van-der-Waerden spinor formalism:
... symbol K("K"), C_sym("C"), D_sym("D"); spinidx C(C_sym, 2), D(D_sym); // default is 2-dimensional, // contravariant, undotted spinidx C_co(C_sym, 2, true); // covariant index spinidx D_dot(D_sym, 2, false, true); // contravariant, dotted spinidx D_co_dot(D_sym, 2, true, true); // covariant, dotted cout << indexed(K, C, D) << endl; // -> K~C~D cout << indexed(K, C_co, D_dot) << endl; // -> K.C~*D cout << indexed(K, D_co_dot, D) << endl; // -> K.*D~D ... |
A spinidx
is a varidx
with an additional flag that marks it as
dotted or undotted. The default is undotted but this can be overridden by
supplying a fourth argument to the spinidx
constructor. The two
methods
bool spinidx::is_dotted(); bool spinidx::is_undotted(); |
allow you to check whether or not a spinidx
object is dotted (use
ex_to<spinidx>()
to get the object reference from an expression).
Finally, the two methods
ex spinidx::toggle_dot(); ex spinidx::toggle_variance_dot(); |
create a new index with the same value and dimension but opposite dottedness and the same or opposite variance.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |