From 6c9a7dfd6b92368b21a2fe5aaf3638bc849099ba Mon Sep 17 00:00:00 2001 From: Christian Bauer Date: Thu, 10 May 2001 20:41:24 +0000 Subject: [PATCH] - color and clifford classes are quite functional now - new "spinidx" class for dotted/undotted indices - predefined spinor metric tensor (created by spinor_metric()) --- ginac/clifford.cpp | 24 ++++---- ginac/clifford.h | 6 ++ ginac/color.cpp | 57 +++++++++++++++++-- ginac/color.h | 1 + ginac/idx.cpp | 121 ++++++++++++++++++++++++++++++++++++++++ ginac/idx.h | 52 ++++++++++++++++++ ginac/indexed.cpp | 19 ++++++- ginac/indexed.h | 5 ++ ginac/tensor.cpp | 134 ++++++++++++++++++++++++++++++++++++++++++++- ginac/tensor.h | 26 +++++++++ ginac/tinfos.h | 2 + 11 files changed, 427 insertions(+), 20 deletions(-) diff --git a/ginac/clifford.cpp b/ginac/clifford.cpp index 5a69cfd5..32096410 100644 --- a/ginac/clifford.cpp +++ b/ginac/clifford.cpp @@ -178,20 +178,6 @@ bool diracgamma::contract_with(exvector::iterator self, exvector::iterator other *other = _ex1(); return true; -#if 0 - // gamma~mu gamma~alpha gamma~beta gamma~delta gamma.mu = -2 gamma~delta gamma~beta gamma~alpha + (4-dim) gamma~alpha gamma~beta gamma~delta - } else if (other - self == 4 - && is_ex_of_type(self[1], clifford) - && is_ex_of_type(self[2], clifford) - && is_ex_of_type(self[3], clifford)) { - *self = -2 * self[3] * self[2] * self[1] + (4 - dim) * self[1] * self[2] * self[3]; - self[1] = _ex1(); - self[2] = _ex1(); - self[3] = _ex1(); - *other = _ex1(); - return true; -#endif - // gamma~mu S gamma~alpha gamma.mu = 2 gamma~alpha S - gamma~mu S gamma.mu gamma~alpha // (commutate contracted indices towards each other, simplify_indexed() // will re-expand and re-run the simplification) @@ -327,6 +313,16 @@ ex dirac_gamma5(unsigned char rl) return clifford(diracgamma5(), rl); } +ex dirac_gamma6(unsigned char rl) +{ + return clifford(diracone(), rl) + clifford(diracgamma5(), rl); +} + +ex dirac_gamma7(unsigned char rl) +{ + return clifford(diracone(), rl) - clifford(diracgamma5(), rl); +} + ex dirac_slash(const ex & e, const ex & dim, unsigned char rl) { varidx mu((new symbol)->setflag(status_flags::dynallocated), dim); diff --git a/ginac/clifford.h b/ginac/clifford.h index af3cb788..69c9e23a 100644 --- a/ginac/clifford.h +++ b/ginac/clifford.h @@ -126,6 +126,12 @@ ex dirac_gamma(const ex & mu, unsigned char rl = 0); * @return newly constructed object */ ex dirac_gamma5(unsigned char rl = 0); +/** This returns (dirac_ONE(rl) + dirac_gamma5(rl)). */ +ex dirac_gamma6(unsigned char rl = 0); + +/** This returns (dirac_ONE(rl) - dirac_gamma5(rl)). */ +ex dirac_gamma7(unsigned char rl = 0); + /** Create a term of the form e_mu * gamma~mu with a unique index mu. * * @param dim Dimension of index diff --git a/ginac/color.cpp b/ginac/color.cpp index 77cf89c4..9e719ec0 100644 --- a/ginac/color.cpp +++ b/ginac/color.cpp @@ -154,10 +154,11 @@ DEFAULT_PRINT(su3d, "d") * objects. This removes superfluous ONEs. */ ex color::simplify_ncmul(const exvector & v) const { - //!! TODO: sort by representation label exvector s; s.reserve(v.size()); + unsigned rl = ex_to_color(v[0]).get_representation_label(); + // Remove superfluous ONEs exvector::const_iterator it = v.begin(), itend = v.end(); while (it != itend) { if (!is_ex_of_type(it->op(0), su3one)) @@ -166,9 +167,7 @@ ex color::simplify_ncmul(const exvector & v) const } if (s.size() == 0) - return color(su3one()); - else if (s.size() == v.size()) - return simplified_ncmul(v); + return color(su3one(), rl); else return simplified_ncmul(s); } @@ -297,6 +296,56 @@ ex su3f::eval_indexed(const basic & i) const } +/** Contraction of generator with something else. */ +bool su3t::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const +{ + GINAC_ASSERT(is_ex_of_type(*self, indexed)); + GINAC_ASSERT(is_ex_of_type(*other, indexed)); + GINAC_ASSERT(self->nops() == 2); + GINAC_ASSERT(is_ex_of_type(self->op(0), su3t)); + unsigned char rl = ex_to_color(*self).get_representation_label(); + + if (is_ex_exactly_of_type(other->op(0), su3t)) { + + // T.a T.a = 4/3 ONE + if (other - self == 1) { + *self = numeric(4, 3); + *other = color_ONE(rl); + return true; + + // T.a T.b T.a = -1/6 T.b + } else if (other - self == 2 + && is_ex_of_type(self[1], color)) { + *self = numeric(-1, 6); + *other = _ex1(); + return true; + + // T.a S T.a = 1/2 Tr(S) - 1/6 S + } else { + exvector::iterator it = self + 1; + while (it != other) { + if (!is_ex_of_type(*it, color)) { + return false; + } + it++; + } + + it = self + 1; + ex S = _ex1(); + while (it != other) { + S *= *it; + *it++ = _ex1(); + } + + *self = color_trace(S, rl) * color_ONE(rl) / 2 - S / 6; + *other = _ex1(); + return true; + } + } + + return false; +} + /** Contraction of an indexed symmetric structure constant with something else. */ bool su3d::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const { diff --git a/ginac/color.h b/ginac/color.h index 70049325..48903e45 100644 --- a/ginac/color.h +++ b/ginac/color.h @@ -85,6 +85,7 @@ class su3t : public tensor // functions overriding virtual functions from bases classes public: void print(const print_context & c, unsigned level = 0) const; + bool contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const; }; /** This class represents the tensor of antisymmetric su(3) structure diff --git a/ginac/idx.cpp b/ginac/idx.cpp index 44427a6a..90ac3a42 100644 --- a/ginac/idx.cpp +++ b/ginac/idx.cpp @@ -34,6 +34,7 @@ namespace GiNaC { GINAC_IMPLEMENT_REGISTERED_CLASS(idx, basic) GINAC_IMPLEMENT_REGISTERED_CLASS(varidx, idx) +GINAC_IMPLEMENT_REGISTERED_CLASS(spinidx, varidx) ////////// // default constructor, destructor, copy constructor assignment operator and helpers @@ -50,6 +51,12 @@ varidx::varidx() : covariant(false) tinfo_key = TINFO_varidx; } +spinidx::spinidx() : dotted(false) +{ + debugmsg("spinidx default constructor", LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_spinidx; +} + void idx::copy(const idx & other) { inherited::copy(other); @@ -63,8 +70,15 @@ void varidx::copy(const varidx & other) covariant = other.covariant; } +void spinidx::copy(const spinidx & other) +{ + inherited::copy(other); + dotted = other.dotted; +} + DEFAULT_DESTROY(idx) DEFAULT_DESTROY(varidx) +DEFAULT_DESTROY(spinidx) ////////// // other constructors @@ -84,6 +98,12 @@ varidx::varidx(const ex & v, const ex & d, bool cov) : inherited(v, d), covarian tinfo_key = TINFO_varidx; } +spinidx::spinidx(const ex & v, const ex & d, bool cov, bool dot) : inherited(v, d, cov), dotted(dot) +{ + debugmsg("spinidx constructor from ex,ex,bool,bool", LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_spinidx; +} + ////////// // archiving ////////// @@ -101,6 +121,12 @@ varidx::varidx(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst n.find_bool("covariant", covariant); } +spinidx::spinidx(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) +{ + debugmsg("spinidx constructor from archive_node", LOGLEVEL_CONSTRUCT); + n.find_bool("dotted", dotted); +} + void idx::archive(archive_node &n) const { inherited::archive(n); @@ -114,8 +140,15 @@ void varidx::archive(archive_node &n) const n.add_bool("covariant", covariant); } +void spinidx::archive(archive_node &n) const +{ + inherited::archive(n); + n.add_bool("dotted", dotted); +} + DEFAULT_UNARCHIVE(idx) DEFAULT_UNARCHIVE(varidx) +DEFAULT_UNARCHIVE(spinidx) ////////// // functions overriding virtual functions from bases classes @@ -178,6 +211,47 @@ void varidx::print(const print_context & c, unsigned level) const } } +void spinidx::print(const print_context & c, unsigned level) const +{ + debugmsg("spinidx print", LOGLEVEL_PRINT); + + if (is_of_type(c, print_tree)) { + + c.s << std::string(level, ' ') << class_name() + << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec + << (covariant ? ", covariant" : ", contravariant") + << (dotted ? ", dotted" : ", undotted") + << std::endl; + unsigned delta_indent = static_cast(c).delta_indent; + value.print(c, level + delta_indent); + dim.print(c, level + delta_indent); + + } else { + + bool is_tex = is_of_type(c, print_latex); + if (!is_tex) { + if (covariant) + c.s << "."; + else + c.s << "~"; + } + if (dotted) { + if (is_tex) + c.s << "\\dot{"; + else + c.s << "*"; + } + bool need_parens = !(is_ex_exactly_of_type(value, numeric) || is_ex_of_type(value, symbol)); + if (need_parens) + c.s << "("; + value.print(c); + if (need_parens) + c.s << ")"; + if (is_tex && dotted) + c.s << "}"; + } +} + bool idx::info(unsigned inf) const { if (inf == info_flags::idx) @@ -225,6 +299,24 @@ int varidx::compare_same_type(const basic & other) const return 0; } +int spinidx::compare_same_type(const basic & other) const +{ + GINAC_ASSERT(is_of_type(other, spinidx)); + const spinidx &o = static_cast(other); + + int cmpval = inherited::compare_same_type(other); + if (cmpval) + return cmpval; + + // Check variance and dottedness last so dummy indices will end up next to each other + if (covariant != o.covariant) + return covariant ? -1 : 1; + if (dotted != o.dotted) + return dotted ? -1 : 1; + + return 0; +} + ex idx::subs(const lst & ls, const lst & lr) const { GINAC_ASSERT(ls.nops() == lr.nops()); @@ -287,6 +379,18 @@ bool varidx::is_dummy_pair_same_type(const basic & other) const return inherited::is_dummy_pair_same_type(other); } +bool spinidx::is_dummy_pair_same_type(const basic & other) const +{ + const spinidx &o = static_cast(other); + + // Dottedness must be the same + if (dotted != o.dotted) + return false; + + return inherited::is_dummy_pair_same_type(other); +} + + ////////// // non-virtual functions ////////// @@ -299,6 +403,23 @@ ex varidx::toggle_variance(void) const return i_copy->setflag(status_flags::dynallocated); } +ex spinidx::toggle_dot(void) const +{ + spinidx *i_copy = static_cast(duplicate()); + i_copy->dotted = !i_copy->dotted; + i_copy->clearflag(status_flags::hash_calculated); + return i_copy->setflag(status_flags::dynallocated); +} + +ex spinidx::toggle_variance_dot(void) const +{ + spinidx *i_copy = static_cast(duplicate()); + i_copy->covariant = !i_copy->covariant; + i_copy->dotted = !i_copy->dotted; + i_copy->clearflag(status_flags::hash_calculated); + return i_copy->setflag(status_flags::dynallocated); +} + ////////// // global functions ////////// diff --git a/ginac/idx.h b/ginac/idx.h index 4981fefc..07ff8392 100644 --- a/ginac/idx.h +++ b/ginac/idx.h @@ -124,6 +124,53 @@ protected: }; +/** This class holds a spinor index that can be dotted or undotted and that + * also has a variance. This is used in the Weyl-van-der-Waerden formalism + * where the dot indicates complex conjugation. There is an associated + * (asymmetric) metric tensor that can be used to raise/lower spinor + * indices. */ +class spinidx : public varidx +{ + GINAC_DECLARE_REGISTERED_CLASS(spinidx, varidx) + + // other constructors +public: + /** Construct index with given value, dimension, variance and dot. + * + * @param v Value of index (numeric or symbolic) + * @param dim Dimension of index space (numeric or symbolic) + * @param covariant Make covariant index (default is contravariant) + * @param dotted Make covariant dotted (default is undotted) + * @return newly constructed index */ + spinidx(const ex & v, const ex & dim = 2, bool covariant = false, bool dotted = false); + + // functions overriding virtual functions from bases classes +public: + void print(const print_context & c, unsigned level = 0) const; + bool is_dummy_pair_same_type(const basic & other) const; + + // non-virtual functions in this class +public: + /** Check whether the index is dotted. */ + bool is_dotted(void) const {return dotted;} + + /** Check whether the index is not dotted. */ + bool is_undotted(void) const {return !dotted;} + + /** Make a new index with the same value and variance but the opposite + * dottedness. */ + ex toggle_dot(void) const; + + /** Make a new index with the same value but opposite variance and + * dottedness. */ + ex toggle_variance_dot(void) const; + + // member variables +protected: + bool dotted; +}; + + // utility functions inline const idx &ex_to_idx(const ex & e) { @@ -135,6 +182,11 @@ inline const varidx &ex_to_varidx(const ex & e) return static_cast(*e.bp); } +inline const spinidx &ex_to_spinidx(const ex & e) +{ + return static_cast(*e.bp); +} + /** Check whether two indices form a dummy pair. */ bool is_dummy_pair(const idx & i1, const idx & i2); diff --git a/ginac/indexed.cpp b/ginac/indexed.cpp index 3c7005e2..3240c8dd 100644 --- a/ginac/indexed.cpp +++ b/ginac/indexed.cpp @@ -666,12 +666,16 @@ try_again: } if (contracted) { contraction_done: - if (is_ex_exactly_of_type(*it1, add) || is_ex_exactly_of_type(*it2, add) + if (non_commutative + || is_ex_exactly_of_type(*it1, add) || is_ex_exactly_of_type(*it2, add) || is_ex_exactly_of_type(*it1, mul) || is_ex_exactly_of_type(*it2, mul) || is_ex_exactly_of_type(*it1, ncmul) || is_ex_exactly_of_type(*it2, ncmul)) { // One of the factors became a sum or product: // re-expand expression and run again + // Non-commutative products are always re-expanded to give + // simplify_ncmul() the chance to re-order and canonicalize + // the product ex r = (non_commutative ? ex(ncmul(v)) : ex(mul(v))); return simplify_indexed(r, free_indices, sp); } @@ -785,6 +789,19 @@ void scalar_products::add(const ex & v1, const ex & v2, const ex & sp) spm[make_key(v1, v2)] = sp; } +void scalar_products::add_vectors(const lst & l) +{ + // Add all possible pairs of products + unsigned num = l.nops(); + for (unsigned i=0; i(i).get_dummy_indices().size() != 0) + return _ex0(); + + // Numeric evaluation + if (static_cast(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) + return _ex0(); + else if (n1 < n2) + return _ex1(); + else + return _ex_1(); + } + + // No further simplifications + return i.hold(); +} + /** Automatic symbolic evaluation of an indexed epsilon tensor. */ ex tensepsilon::eval_indexed(const basic & i) const { @@ -370,6 +413,85 @@ 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 +{ + GINAC_ASSERT(is_ex_of_type(*self, indexed)); + GINAC_ASSERT(is_ex_of_type(*other, indexed)); + GINAC_ASSERT(self->nops() == 3); + GINAC_ASSERT(is_ex_of_type(self->op(0), spinmetric)); + + // Contractions between spinor metrics + if (is_ex_of_type(other->op(0), spinmetric)) { + const idx &self_i1 = ex_to_idx(self->op(1)); + const idx &self_i2 = ex_to_idx(self->op(2)); + const idx &other_i1 = ex_to_idx(other->op(1)); + const idx &other_i2 = ex_to_idx(other->op(2)); + + if (is_dummy_pair(self_i1, other_i1)) { + if (is_dummy_pair(self_i2, other_i2)) + *self = _ex2(); + else + *self = delta_tensor(self_i2, other_i2); + *other = _ex1(); + return true; + } else if (is_dummy_pair(self_i1, other_i2)) { + if (is_dummy_pair(self_i2, other_i1)) + *self = _ex_2(); + else + *self = -delta_tensor(self_i2, other_i1); + *other = _ex1(); + return true; + } else if (is_dummy_pair(self_i2, other_i1)) { + *self = -delta_tensor(self_i1, other_i2); + *other = _ex1(); + return true; + } else if (is_dummy_pair(self_i2, other_i2)) { + *self = delta_tensor(self_i1, other_i1); + *other = _ex1(); + return true; + } + } + + // If contracting with the delta tensor, let the delta do it + // (don't raise/lower delta indices) + if (is_ex_of_type(other->op(0), tensdelta)) + 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; + int sign = 1; + +again: + if (self_idx->is_symbolic()) { + for (int i=1; inops(); 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 = (static_cast(self_idx)->is_covariant() ? sign : -sign); + *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; + sign = -sign; + goto again; + } + + return false; +} + ////////// // global functions ////////// @@ -398,6 +520,16 @@ ex lorentz_g(const ex & i1, const ex & i2, bool pos_sig) return indexed(minkmetric(pos_sig), indexed::symmetric, i1, i2); } +ex spinor_metric(const ex & i1, const ex & i2) +{ + if (!is_ex_of_type(i1, spinidx) || !is_ex_of_type(i2, spinidx)) + throw(std::invalid_argument("indices of spinor metric must be of type spinidx")); + if (!ex_to_idx(i1).get_dim().is_equal(2) || !ex_to_idx(i2).get_dim().is_equal(2)) + throw(std::runtime_error("index dimension for spinor metric must be 2")); + + return indexed(spinmetric(), indexed::antisymmetric, i1, i2); +} + ex epsilon_tensor(const ex & i1, const ex & i2) { if (!is_ex_of_type(i1, idx) || !is_ex_of_type(i2, idx)) diff --git a/ginac/tensor.h b/ginac/tensor.h index b077ee4d..5698b9b9 100644 --- a/ginac/tensor.h +++ b/ginac/tensor.h @@ -97,6 +97,22 @@ private: }; +/** This class represents an antisymmetric spinor metric tensor which + * can be used to raise/lower indices of 2-component Weyl spinors. If + * indexed, it must have exactly two indices of the same type which + * must be of class spinidx or a subclass and have dimension 2. */ +class spinmetric : public tensmetric +{ + GINAC_DECLARE_REGISTERED_CLASS(spinmetric, tensmetric) + + // functions overriding virtual functions from bases 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 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. */ @@ -155,6 +171,16 @@ ex metric_tensor(const ex & i1, const ex & i2); * @return newly constructed Lorentz metric tensor */ ex lorentz_g(const ex & i1, const ex & i2, bool pos_sig = false); +/** Create a spinor metric tensor with specified indices. The indices must be + * of class spinidx or a subclass and have a dimension of 2. The spinor + * metric is an antisymmetric tensor with a matrix representation of + * [[ [[ 0, 1 ]], [[ -1, 0 ]] ]]. + * + * @param i1 First index + * @param i2 Second index + * @return newly constructed spinor metric tensor */ +ex spinor_metric(const ex & i1, const ex & i2); + /** Create an epsilon tensor in a Euclidean space with two indices. The * indices must be of class idx or a subclass, and have a dimension of 2. * diff --git a/ginac/tinfos.h b/ginac/tinfos.h index 7c6994d2..2a5fad61 100644 --- a/ginac/tinfos.h +++ b/ginac/tinfos.h @@ -66,11 +66,13 @@ const unsigned TINFO_structure = 0x000c0001U; const unsigned TINFO_idx = 0x000d0001U; const unsigned TINFO_varidx = 0x000d1001U; +const unsigned TINFO_spinidx = 0x000d2001U; const unsigned TINFO_tensor = 0x000e0001U; const unsigned TINFO_tensdelta = 0x000e1001U; const unsigned TINFO_tensmetric = 0x000e1002U; const unsigned TINFO_minkmetric = 0x000e2001U; +const unsigned TINFO_spinmetric = 0x000e2002U; const unsigned TINFO_tensepsilon = 0x000e1003U; const unsigned TINFO_su3one = 0x000e1008U; const unsigned TINFO_su3t = 0x000e1009U; -- 2.44.0