]> www.ginac.de Git - ginac.git/commitdiff
implemented 4-dimensional delta, metric and epsilon tensors
authorChristian Bauer <Christian.Bauer@uni-mainz.de>
Mon, 1 Jul 2002 17:51:25 +0000 (17:51 +0000)
committerChristian Bauer <Christian.Bauer@uni-mainz.de>
Mon, 1 Jul 2002 17:51:25 +0000 (17:51 +0000)
ginac/tensor.cpp
ginac/tensor.h
ginac/tinfos.h

index bb710a220f86d693f563bca7901520d99435a2f8..afdd28cadb1053b6394c2e84474607cfc44495e7 100644 (file)
@@ -40,8 +40,10 @@ namespace GiNaC {
 
 GINAC_IMPLEMENT_REGISTERED_CLASS(tensor, basic)
 GINAC_IMPLEMENT_REGISTERED_CLASS(tensdelta, tensor)
+GINAC_IMPLEMENT_REGISTERED_CLASS(tens4delta, tensor)
 GINAC_IMPLEMENT_REGISTERED_CLASS(tensmetric, tensor)
 GINAC_IMPLEMENT_REGISTERED_CLASS(minkmetric, tensmetric)
+GINAC_IMPLEMENT_REGISTERED_CLASS(mink4metric, tensor)
 GINAC_IMPLEMENT_REGISTERED_CLASS(spinmetric, tensmetric)
 GINAC_IMPLEMENT_REGISTERED_CLASS(tensepsilon, tensor)
 
@@ -51,10 +53,12 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(tensepsilon, tensor)
 
 DEFAULT_CTORS(tensor)
 DEFAULT_CTORS(tensdelta)
+DEFAULT_CTORS(tens4delta)
 DEFAULT_CTORS(tensmetric)
 DEFAULT_COPY(spinmetric)
 DEFAULT_DESTROY(spinmetric)
 DEFAULT_DESTROY(minkmetric)
+DEFAULT_DESTROY(mink4metric)
 DEFAULT_DESTROY(tensepsilon)
 
 minkmetric::minkmetric() : pos_sig(false)
@@ -62,6 +66,11 @@ minkmetric::minkmetric() : pos_sig(false)
        tinfo_key = TINFO_minkmetric;
 }
 
+mink4metric::mink4metric() : pos_sig(false)
+{
+       tinfo_key = TINFO_mink4metric;
+}
+
 spinmetric::spinmetric()
 {
        tinfo_key = TINFO_spinmetric;
@@ -72,18 +81,29 @@ minkmetric::minkmetric(bool ps) : pos_sig(ps)
        tinfo_key = TINFO_minkmetric;
 }
 
+mink4metric::mink4metric(bool ps) : pos_sig(ps)
+{
+       tinfo_key = TINFO_mink4metric;
+}
+
 void minkmetric::copy(const minkmetric & other)
 {
        inherited::copy(other);
        pos_sig = other.pos_sig;
 }
 
-tensepsilon::tensepsilon() : minkowski(false), pos_sig(false)
+void mink4metric::copy(const mink4metric & other)
+{
+       inherited::copy(other);
+       pos_sig = other.pos_sig;
+}
+
+tensepsilon::tensepsilon() : minkowski(false), pos_sig(false), four_dim(false)
 {
        tinfo_key = TINFO_tensepsilon;
 }
 
-tensepsilon::tensepsilon(bool mink, bool ps) : minkowski(mink), pos_sig(ps)
+tensepsilon::tensepsilon(bool mink, bool ps, bool fd) : minkowski(mink), pos_sig(ps), four_dim(fd)
 {
        tinfo_key = TINFO_tensepsilon;
 }
@@ -93,6 +113,7 @@ void tensepsilon::copy(const tensepsilon & other)
        inherited::copy(other);
        minkowski = other.minkowski;
        pos_sig = other.pos_sig;
+       four_dim = other.four_dim;
 }
 
 //////////
@@ -101,9 +122,11 @@ void tensepsilon::copy(const tensepsilon & other)
 
 DEFAULT_ARCHIVING(tensor)
 DEFAULT_ARCHIVING(tensdelta)
+DEFAULT_ARCHIVING(tens4delta)
 DEFAULT_ARCHIVING(tensmetric)
 DEFAULT_ARCHIVING(spinmetric)
 DEFAULT_UNARCHIVE(minkmetric)
+DEFAULT_UNARCHIVE(mink4metric)
 DEFAULT_UNARCHIVE(tensepsilon)
 
 minkmetric::minkmetric(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
@@ -117,10 +140,22 @@ void minkmetric::archive(archive_node &n) const
        n.add_bool("pos_sig", pos_sig);
 }
 
+mink4metric::mink4metric(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+       n.find_bool("pos_sig", pos_sig);
+}
+
+void mink4metric::archive(archive_node &n) const
+{
+       inherited::archive(n);
+       n.add_bool("pos_sig", pos_sig);
+}
+
 tensepsilon::tensepsilon(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
 {
        n.find_bool("minkowski", minkowski);
        n.find_bool("pos_sig", pos_sig);
+       n.find_bool("4dim", four_dim);
 }
 
 void tensepsilon::archive(archive_node &n) const
@@ -128,6 +163,7 @@ void tensepsilon::archive(archive_node &n) const
        inherited::archive(n);
        n.add_bool("minkowski", minkowski);
        n.add_bool("pos_sig", pos_sig);
+       n.add_bool("4dim", four_dim);
 }
 
 //////////
@@ -136,6 +172,7 @@ void tensepsilon::archive(archive_node &n) const
 
 DEFAULT_COMPARE(tensor)
 DEFAULT_COMPARE(tensdelta)
+DEFAULT_COMPARE(tens4delta)
 DEFAULT_COMPARE(tensmetric)
 DEFAULT_COMPARE(spinmetric)
 
@@ -150,6 +187,17 @@ int minkmetric::compare_same_type(const basic & other) const
                return inherited::compare_same_type(other);
 }
 
+int mink4metric::compare_same_type(const basic & other) const
+{
+       GINAC_ASSERT(is_a<mink4metric>(other));
+       const mink4metric &o = static_cast<const mink4metric &>(other);
+
+       if (pos_sig != o.pos_sig)
+               return pos_sig ? -1 : 1;
+       else
+               return inherited::compare_same_type(other);
+}
+
 int tensepsilon::compare_same_type(const basic & other) const
 {
        GINAC_ASSERT(is_a<tensepsilon>(other));
@@ -159,13 +207,17 @@ int tensepsilon::compare_same_type(const basic & other) const
                return minkowski ? -1 : 1;
        else if (pos_sig != o.pos_sig)
                return pos_sig ? -1 : 1;
+       else if (four_dim != o.four_dim)
+               return four_dim ? -1 : 1;
        else
                return inherited::compare_same_type(other);
 }
 
 DEFAULT_PRINT_LATEX(tensdelta, "delta", "\\delta")
+DEFAULT_PRINT_LATEX(tens4delta, "delta4", "{\\delta^{(4)}}")
 DEFAULT_PRINT(tensmetric, "g")
 DEFAULT_PRINT_LATEX(minkmetric, "eta", "\\eta")
+DEFAULT_PRINT_LATEX(mink4metric, "eta4", "{\\eta^{(4)}}")
 DEFAULT_PRINT_LATEX(spinmetric, "eps", "\\varepsilon")
 DEFAULT_PRINT_LATEX(tensepsilon, "eps", "\\varepsilon")
 
@@ -196,6 +248,39 @@ ex tensdelta::eval_indexed(const basic & i) const
        return i.hold();
 }
 
+/** Automatic symbolic evaluation of an indexed 4-dimensional delta tensor. */
+ex tens4delta::eval_indexed(const basic & i) const
+{
+       GINAC_ASSERT(is_a<indexed>(i));
+       GINAC_ASSERT(i.nops() == 3);
+       GINAC_ASSERT(is_a<tens4delta>(i.op(0)));
+
+       const idx & i1 = ex_to<idx>(i.op(1));
+       const idx & i2 = ex_to<idx>(i.op(2));
+
+       // Trace of 4-dimensional delta tensor is four
+       if (is_dummy_pair(i1, i2))
+               return _ex4;
+
+       // 4-dimensional delta tensor with numeric index dimension of four or
+       // less gets replaced by ordinary delta tensor
+       if (i1.get_dim().is_equal(i2.get_dim()) && is_a<numeric>(i1.get_dim())
+        && ex_to<numeric>(i1.get_dim()).to_int() <= 4)
+               return indexed(tensdelta(), sy_symm(), i.op(1), i.op(2));
+
+       // Numeric evaluation
+       if (static_cast<const indexed &>(i).all_index_values_are(info_flags::integer)) {
+               int n1 = ex_to<numeric>(i1.get_value()).to_int(), n2 = ex_to<numeric>(i2.get_value()).to_int();
+               if (n1 == n2 && n1 < 4)
+                       return _ex1;
+               else
+                       return _ex0;
+       }
+
+       // No further simplifications
+       return i.hold();
+}
+
 /** Automatic symbolic evaluation of an indexed metric tensor. */
 ex tensmetric::eval_indexed(const basic & i) const
 {
@@ -244,6 +329,45 @@ ex minkmetric::eval_indexed(const basic & i) const
        return inherited::eval_indexed(i);
 }
 
+/** Automatic symbolic evaluation of an indexed 4-dimensional Lorentz metric
+ *  tensor. */
+ex mink4metric::eval_indexed(const basic & i) const
+{
+       GINAC_ASSERT(is_a<indexed>(i));
+       GINAC_ASSERT(i.nops() == 3);
+       GINAC_ASSERT(is_a<mink4metric>(i.op(0)));
+       GINAC_ASSERT(is_a<varidx>(i.op(1)));
+       GINAC_ASSERT(is_a<varidx>(i.op(2)));
+
+       const varidx & i1 = ex_to<varidx>(i.op(1));
+       const varidx & i2 = ex_to<varidx>(i.op(2));
+
+       // 4-dimensional Lorentz metric tensor with numeric index dimension of
+       // four or less gets replaced by ordinary Lorentz metric tensor
+       if (i1.get_dim().is_equal(i2.get_dim()) && is_a<numeric>(i1.get_dim())
+        && ex_to<numeric>(i1.get_dim()).to_int() <= 4)
+               return indexed(minkmetric(pos_sig), sy_symm(), i.op(1), i.op(2));
+
+       // A metric tensor with one covariant and one contravariant index gets
+       // replaced by a delta tensor
+       if (i1.is_covariant() != i2.is_covariant())
+               return indexed(tens4delta(), sy_symm(), i.op(1), i.op(2));
+
+       // Numeric evaluation
+       if (static_cast<const indexed &>(i).all_index_values_are(info_flags::nonnegint)) {
+               int n1 = ex_to<numeric>(i1.get_value()).to_int(), n2 = ex_to<numeric>(i2.get_value()).to_int();
+               if (n1 != n2 || n1 > 3)
+                       return _ex0;
+               else if (n1 == 0)
+                       return pos_sig ? _ex_1 : _ex1;
+               else
+                       return pos_sig ? _ex1 : _ex_1;
+       }
+
+       // No further simplifications
+       return i.hold();
+}
+
 /** Automatic symbolic evaluation of an indexed metric tensor. */
 ex spinmetric::eval_indexed(const basic & i) const
 {
@@ -358,6 +482,50 @@ again:
        return false;
 }
 
+/** Contraction of an indexed 4-dimensional delta tensor with something else. */
+bool tens4delta::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
+{
+       GINAC_ASSERT(is_a<indexed>(*self));
+       GINAC_ASSERT(is_a<indexed>(*other));
+       GINAC_ASSERT(self->nops() == 3);
+       GINAC_ASSERT(is_a<tens4delta>(self->op(0)));
+
+       // Only contract with 4-dimensional delta, metric and epsilon tensors
+       if (!(is_a<tens4delta>(other->op(0)) || is_a<mink4metric>(other->op(0)) || is_a<tensepsilon>(other->op(0))))
+               return false;
+
+       // Try to contract first index
+       const idx *self_idx = &ex_to<idx>(self->op(1));
+       const idx *free_idx = &ex_to<idx>(self->op(2));
+       bool first_index_tried = false;
+
+again:
+       if (self_idx->is_symbolic()) {
+               for (unsigned i=1; i<other->nops(); i++) {
+                       const idx &other_idx = ex_to<idx>(other->op(i));
+                       if (is_dummy_pair(*self_idx, other_idx)) {
+
+                               // Contraction found, remove delta tensor and substitute
+                               // index in second object
+                               *self = _ex1;
+                               *other = other->subs(other_idx == *free_idx);
+                               return true;
+                       }
+               }
+       }
+
+       if (!first_index_tried) {
+
+               // No contraction with first index found, try second index
+               self_idx = &ex_to<idx>(self->op(2));
+               free_idx = &ex_to<idx>(self->op(1));
+               first_index_tried = true;
+               goto again;
+       }
+
+       return false;
+}
+
 /** Contraction of an indexed metric tensor with something else. */
 bool tensmetric::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
 {
@@ -403,6 +571,51 @@ again:
        return false;
 }
 
+/** Contraction of an indexed 4-dimensional Lorentz metric tensor with something else. */
+bool mink4metric::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
+{
+       GINAC_ASSERT(is_a<indexed>(*self));
+       GINAC_ASSERT(is_a<indexed>(*other));
+       GINAC_ASSERT(self->nops() == 3);
+       GINAC_ASSERT(is_a<mink4metric>(self->op(0)));
+
+       // Only contract with 4-dimensional metric and epsilon tensors
+       if (!(is_a<mink4metric>(other->op(0)) || is_a<tensepsilon>(other->op(0))))
+               return false;
+
+       // Try to contract first index
+       const idx *self_idx = &ex_to<idx>(self->op(1));
+       const idx *free_idx = &ex_to<idx>(self->op(2));
+       bool first_index_tried = false;
+
+again:
+       if (self_idx->is_symbolic()) {
+               for (unsigned i=1; i<other->nops(); i++) {
+                       const idx &other_idx = ex_to<idx>(other->op(i));
+                       if (is_dummy_pair(*self_idx, other_idx)) {
+
+                               // Contraction found, remove metric tensor and substitute
+                               // index in second object
+                               *self = _ex1;
+                               *other = other->subs(other_idx == *free_idx);
+                               return true;
+                       }
+               }
+       }
+
+       if (!first_index_tried) {
+
+               // No contraction with first index found, try second index
+               self_idx = &ex_to<idx>(self->op(2));
+               free_idx = &ex_to<idx>(self->op(1));
+               first_index_tried = true;
+               goto again;
+       }
+
+       return false;
+}
+
+
 /** Contraction of an indexed spinor metric with something else. */
 bool spinmetric::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
 {
@@ -493,11 +706,12 @@ bool tensepsilon::contract_with(exvector::iterator self, exvector::iterator othe
        if (is_exactly_a<tensepsilon>(other->op(0)) && num+1 == other->nops()) {
 
                // Contraction of two epsilon tensors is a determinant
-               ex dim = ex_to<idx>(self->op(1)).get_dim();
                matrix M(num, num);
                for (int i=0; i<num; i++) {
                        for (int j=0; j<num; j++) {
-                               if (minkowski)
+                               if (four_dim)
+                                       M(i, j) = indexed(mink4metric(pos_sig), sy_symm(), self->op(i+1), other->op(j+1));
+                               else if (minkowski)
                                        M(i, j) = lorentz_g(self->op(i+1), other->op(j+1), pos_sig);
                                else
                                        M(i, j) = metric_tensor(self->op(i+1), other->op(j+1));
@@ -507,44 +721,6 @@ bool tensepsilon::contract_with(exvector::iterator self, exvector::iterator othe
                *self = sign * M.determinant().simplify_indexed();
                *other = _ex1;
                return true;
-
-       } else if (other->return_type() == return_types::commutative) {
-
-#if 0
-               // This handles eps.i.j.k * p.j * p.k = 0
-               // Maybe something like this should go to simplify_indexed() because
-               // such relations are true for any antisymmetric tensors...
-               exvector c;
-
-               // Handle all indices of the epsilon tensor
-               for (int i=0; i<num; i++) {
-                       ex idx = self->op(i+1);
-
-                       // Look whether there's a contraction with this index
-                       exvector::const_iterator ait, aitend = v.end();
-                       for (ait = v.begin(); ait != aitend; ait++) {
-                               if (ait == self)
-                                       continue;
-                               if (is_a<indexed>(*ait) && ait->return_type() == return_types::commutative && ex_to<indexed>(*ait).has_dummy_index_for(idx) && ait->nops() == 2) {
-
-                                       // Yes, did we already have another contraction with the same base expression?
-                                       ex base = ait->op(0);
-                                       if (std::find_if(c.begin(), c.end(), bind2nd(ex_is_equal(), base)) == c.end()) {
-
-                                               // No, add the base expression to the list
-                                               c.push_back(base);
-
-                                       } else {
-
-                                               // Yes, the contraction is zero
-                                               *self = _ex0;
-                                               *other = _ex0;
-                                               return true;
-                                       }
-                               }
-                       }
-               }
-#endif
        }
 
        return false;
@@ -633,7 +809,7 @@ ex lorentz_eps(const ex & i1, const ex & i2, const ex & i3, const ex & i4, bool
        if (!ex_to<idx>(i1).get_dim().is_equal(_ex4))
                throw(std::runtime_error("index dimension of epsilon tensor must match number of indices"));
 
-       return indexed(tensepsilon(true, pos_sig), sy_anti(), i1, i2, i3, i4);
+       return indexed(tensepsilon(true, pos_sig, false), sy_anti(), i1, i2, i3, i4);
 }
 
 ex eps0123(const ex & i1, const ex & i2, const ex & i3, const ex & i4, bool pos_sig)
@@ -645,7 +821,7 @@ ex eps0123(const ex & i1, const ex & i2, const ex & i3, const ex & i4, bool pos_
        if (dim.is_equal(4))
                return lorentz_eps(i1, i2, i3, i4, pos_sig);
        else
-               return indexed(tensepsilon(true, pos_sig), sy_anti(), i1, i2, i3, i4);
+               return indexed(tensepsilon(true, pos_sig, true), sy_anti(), i1, i2, i3, i4);
 }
 
 } // namespace GiNaC
index cbe0a44a315e4059b9fb4a6da99b3435de718b20..d3b3a136445c24945803a7122bf15a96204391ac 100644 (file)
@@ -113,6 +113,46 @@ public:
 };
 
 
+/** This class represents a 4-dimensional delta tensor embedded in a
+ *  higher-dimensional space. Its matrix representation is
+ *  diag(1,1,1,1,0,0...). */
+class tens4delta : public tensor
+{
+       GINAC_DECLARE_REGISTERED_CLASS(tens4delta, tensor)
+
+       // functions overriding virtual functions from base classes
+public:
+       void print(const print_context & c, unsigned level = 0) const;
+       ex eval_indexed(const basic & i) const;
+       bool contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const;
+};
+
+
+/** This class represents a 4-dimensional Minkowski tensor embedded in
+ *  a higher-dimensional space (so it's not really a metric for that space;
+ *  that's why this is not a subclass of tensmetric). Its matrix representation
+ *  is diag(1,-1,-1,-1,0,0,...) or diag(-1,1,1,1,0,0,...). */
+class mink4metric : public tensor
+{
+       GINAC_DECLARE_REGISTERED_CLASS(mink4metric, tensor)
+
+       // other constructors
+public:
+       /** Construct Lorentz metric tensor with given signature. */
+       mink4metric(bool pos_sig);
+
+       // functions overriding virtual functions from base classes
+public:
+       void print(const print_context & c, unsigned level = 0) const;
+       ex eval_indexed(const basic & i) const;
+       bool contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const;
+
+       // member variables
+private:
+       bool pos_sig; /**< If true, the metric is diag(-1,1,...). Otherwise it is diag(1,-1,...). */
+};
+
+
 /** This class represents the totally antisymmetric epsilon tensor. If
  *  indexed, all indices must be of the same type and their number must
  *  be equal to the dimension of the index space. */
@@ -122,7 +162,7 @@ class tensepsilon : public tensor
 
        // other constructors
 public:
-       tensepsilon(bool minkowski, bool pos_sig);
+       tensepsilon(bool minkowski, bool pos_sig, bool four_dim);
 
        // functions overriding virtual functions from base classes
 public:
@@ -133,7 +173,8 @@ public:
        // member variables
 private:
        bool minkowski; /**< If true, tensor is in Minkowski-type space. Otherwise it is in a Euclidean space. */
-       bool pos_sig;  /**< If true, the metric is assumed to be diag(-1,1,1...). Otherwise it is diag(1,-1,-1,...). This is only relevant if minkowski = true. */
+       bool pos_sig;   /**< If true, the metric is assumed to be diag(-1,1,1...). Otherwise it is diag(1,-1,-1,...). This is only relevant if minkowski = true. */
+       bool four_dim;  /**< If true, this is a four-dimensional object embedded in a higher-dimensional space */
 };
 
 
index 03b7315e0a2eab78ba4ab9a02062167015e9d004..d02caa83a96a910aaddde07321c7cd1571fed6ee 100644 (file)
@@ -75,6 +75,8 @@ const unsigned TINFO_tensmetric    = 0x000e1002U;
 const unsigned TINFO_minkmetric    = 0x000e2001U;
 const unsigned TINFO_spinmetric    = 0x000e2002U;
 const unsigned TINFO_tensepsilon   = 0x000e1003U;
+const unsigned TINFO_tens4delta    = 0x000e1004U;
+const unsigned TINFO_mink4metric   = 0x000e1005U;
 const unsigned TINFO_su3one        = 0x000e1008U;
 const unsigned TINFO_su3t          = 0x000e1009U;
 const unsigned TINFO_su3f          = 0x000e100aU;