From df4cdb81dff6ef947e933d3f0abc4b5bbf5a25cc Mon Sep 17 00:00:00 2001 From: Christian Bauer Date: Thu, 5 Aug 2004 21:39:18 +0000 Subject: [PATCH] synced to head (dirac_trace()/color_trace()) --- check/exam_clifford.cpp | 13 +++++ check/exam_color.cpp | 14 ++++- doc/tutorial/ginac.texi | 34 +++++++----- ginac/clifford.cpp | 119 +++++++++++++++++++++++++++++++--------- ginac/clifford.h | 22 ++++++++ ginac/color.cpp | 64 +++++++++++++++++---- ginac/color.h | 14 +++++ ginac/indexed.cpp | 2 + 8 files changed, 231 insertions(+), 51 deletions(-) diff --git a/check/exam_clifford.cpp b/check/exam_clifford.cpp index b6ec71e4..9fab7543 100644 --- a/check/exam_clifford.cpp +++ b/check/exam_clifford.cpp @@ -184,6 +184,19 @@ static unsigned clifford_check3() e = dirac_trace(e); result += check_equal(e, 4); + // traces with multiple representation labels + e = dirac_ONE(0) * dirac_ONE(1) / 16; + result += check_equal(dirac_trace(e, 0), dirac_ONE(1) / 4); + result += check_equal(dirac_trace(e, 1), dirac_ONE(0) / 4); + result += check_equal(dirac_trace(e, 2), e); + result += check_equal(dirac_trace(e, lst(0, 1)), 1); + + e = dirac_gamma(mu, 0) * dirac_gamma(mu.toggle_variance(), 1) * dirac_gamma(nu, 0) * dirac_gamma(nu.toggle_variance(), 1); + result += check_equal_simplify(dirac_trace(e, 0), 4 * dim * dirac_ONE(1)); + result += check_equal_simplify(dirac_trace(e, 1), 4 * dim * dirac_ONE(0)); + result += check_equal_simplify(dirac_trace(e, 2), e); + result += check_equal_simplify(dirac_trace(e, lst(0, 1)), 16 * dim); + return result; } diff --git a/check/exam_color.cpp b/check/exam_color.cpp index 4d26a1e4..a3e972ad 100644 --- a/check/exam_color.cpp +++ b/check/exam_color.cpp @@ -113,7 +113,7 @@ static unsigned color_check3() unsigned result = 0; - idx a(symbol("a"), 8), b(symbol("b"), 8), c(symbol("c"), 8), k(symbol("k"), 8); + idx a(symbol("a"), 8), b(symbol("b"), 8), c(symbol("c"), 8); ex e; e = color_ONE(); @@ -125,6 +125,18 @@ static unsigned color_check3() e = color_T(a) * color_T(b) * color_T(c); result += check_equal(color_trace(e), color_h(a, b, c) / 4); + e = color_ONE(0) * color_ONE(1) / 9; + result += check_equal(color_trace(e, 0), color_ONE(1) / 3); + result += check_equal(color_trace(e, 1), color_ONE(0) / 3); + result += check_equal(color_trace(e, 2), e); + result += check_equal(color_trace(e, lst(0, 1)), 1); + + e = color_T(a, 0) * color_T(a, 1) * color_T(b, 0) * color_T(b, 1); + result += check_equal_simplify(color_trace(e, 0), 2 * color_ONE(1) / 3); + result += check_equal_simplify(color_trace(e, 1), 2 * color_ONE(0) / 3); + result += check_equal_simplify(color_trace(e, 2), e); + result += check_equal_simplify(color_trace(e, lst(0, 1)), 2); + return result; } diff --git a/doc/tutorial/ginac.texi b/doc/tutorial/ginac.texi index 9c4d15ee..50e95ae9 100644 --- a/doc/tutorial/ginac.texi +++ b/doc/tutorial/ginac.texi @@ -3002,20 +3002,25 @@ for example @cindex @code{dirac_trace()} To calculate the trace of an expression containing strings of Dirac gammas -you use the function +you use one of the functions @example +ex dirac_trace(const ex & e, const std::set & rls, const ex & trONE = 4); +ex dirac_trace(const ex & e, const lst & rll, const ex & trONE = 4); ex dirac_trace(const ex & e, unsigned char rl = 0, const ex & trONE = 4); @end example -This function takes the trace of all gammas with the specified representation -label; gammas with other labels are left standing. The last argument to +These functions take the trace over all gammas in the specified set @code{rls} +or list @code{rll} of representation labels, or the single label @code{rl}; +gammas with other labels are left standing. The last argument to @code{dirac_trace()} is the value to be returned for the trace of the unity -element, which defaults to 4. The @code{dirac_trace()} function is a linear -functional that is equal to the usual trace only in @math{D = 4} dimensions. -In particular, the functional is not cyclic in @math{D != 4} dimensions when -acting on expressions containing @samp{gamma5}, so it's not a proper trace. -This @samp{gamma5} scheme is described in greater detail in +element, which defaults to 4. + +The @code{dirac_trace()} function is a linear functional that is equal to the +ordinary matrix trace only in @math{D = 4} dimensions. In particular, the +functional is not cyclic in @math{D != 4} dimensions when acting on +expressions containing @samp{gamma5}, so it's not a proper trace. This +@samp{gamma5} scheme is described in greater detail in @cite{The Role of gamma5 in Dimensional Regularization}. The value of the trace itself is also usually different in 4 and in @@ -3177,16 +3182,19 @@ expressions containing color objects: @end example @cindex @code{color_trace()} -To calculate the trace of an expression containing color objects you use the -function +To calculate the trace of an expression containing color objects you use one +of the functions @example +ex color_trace(const ex & e, const std::set & rls); +ex color_trace(const ex & e, const lst & rll); ex color_trace(const ex & e, unsigned char rl = 0); @end example -This function takes the trace of all color @samp{T} objects with the -specified representation label; @samp{T}s with other labels are left -standing. For example: +These functions take the trace over all color @samp{T} objects in the +specified set @code{rls} or list @code{rll} of representation labels, or the +single label @code{rl}; @samp{T}s with other labels are left standing. For +example: @example ... diff --git a/ginac/clifford.cpp b/ginac/clifford.cpp index 591d0ff9..e5b6f5e9 100644 --- a/ginac/clifford.cpp +++ b/ginac/clifford.cpp @@ -217,6 +217,14 @@ static void base_and_index(const ex & c, ex & b, ex & i) } } +/** Predicate for finding non-clifford objects. */ +struct is_not_a_clifford : public std::unary_function { + bool operator()(const ex & e) + { + return !is_a(e); + } +}; + /** Contraction of a gamma matrix with something else. */ bool diracgamma::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const { @@ -235,21 +243,23 @@ bool diracgamma::contract_with(exvector::iterator self, exvector::iterator other if (ex_to(*other).get_representation_label() != rl) return false; + size_t num = other - self; + // gamma~mu gamma.mu = dim ONE - if (other - self == 1) { + if (num == 1) { *self = dim; *other = dirac_ONE(rl); return true; // gamma~mu gamma~alpha gamma.mu = (2-dim) gamma~alpha - } else if (other - self == 2 + } else if (num == 2 && is_a(self[1])) { *self = 2 - dim; *other = _ex1; return true; // gamma~mu gamma~alpha gamma~beta gamma.mu = 4 g~alpha~beta + (dim-4) gamam~alpha gamma~beta - } else if (other - self == 3 + } else if (num == 3 && is_a(self[1]) && is_a(self[2])) { ex b1, i1, b2, i2; @@ -262,7 +272,7 @@ bool diracgamma::contract_with(exvector::iterator self, exvector::iterator other return true; // gamma~mu gamma~alpha gamma~beta gamma~delta gamma.mu = -2 gamma~delta gamma~beta gamma~alpha - (dim-4) gamam~alpha gamma~beta gamma~delta - } else if (other - self == 4 + } else if (num == 4 && is_a(self[1]) && is_a(self[2]) && is_a(self[3])) { @@ -273,27 +283,45 @@ bool diracgamma::contract_with(exvector::iterator self, exvector::iterator other *other = _ex1; return true; + // gamma~mu Sodd gamma.mu = -2 Sodd_R + // (Chisholm identity in 4 dimensions) + } else if (!((other - self) & 1) && dim.is_equal(4)) { + if (std::find_if(self + 1, other, is_not_a_clifford()) != other) + return false; + + *self = ncmul(exvector(std::reverse_iterator(other), std::reverse_iterator(self + 1)), true); + std::fill(self + 1, other, _ex1); + *other = _ex_2; + return true; + + // gamma~mu Sodd gamma~alpha gamma.mu = 2 gamma~alpha Sodd + 2 Sodd_R gamma~alpha + // (commutate contracted indices towards each other, then use + // Chisholm identity in 4 dimensions) + } else if (((other - self) & 1) && dim.is_equal(4)) { + if (std::find_if(self + 1, other, is_not_a_clifford()) != other) + return false; + + exvector::iterator next_to_last = other - 1; + ex S = ncmul(exvector(self + 1, next_to_last), true); + ex SR = ncmul(exvector(std::reverse_iterator(next_to_last), std::reverse_iterator(self + 1)), true); + + *self = (*next_to_last) * S + SR * (*next_to_last); + std::fill(self + 1, other, _ex1); + *other = _ex2; + return true; + // 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) } else { - exvector::iterator it = self + 1, next_to_last = other - 1; - while (it != other) { - if (!is_a(*it)) - return false; - ++it; - } + if (std::find_if(self + 1, other, is_not_a_clifford()) != other) + return false; - it = self + 1; - ex S = _ex1; - while (it != next_to_last) { - S *= *it; - *it++ = _ex1; - } + exvector::iterator next_to_last = other - 1; + ex S = ncmul(exvector(self + 1, next_to_last), true); *self = 2 * (*next_to_last) * S - (*self) * S * (*other) * (*next_to_last); - *next_to_last = _ex1; - *other = _ex1; + std::fill(self + 1, other + 1, _ex1); return true; } @@ -559,6 +587,13 @@ static bool is_clifford_tinfo(unsigned ti) return (ti & ~0xff) == TINFO_clifford; } +/** Extract representation label from tinfo key (as returned by + * return_type_tinfo()). */ +static unsigned char get_representation_label(unsigned ti) +{ + return ti & 0xff; +} + /** Take trace of a string of an even number of Dirac gammas given a vector * of indices. */ static ex trace_string(exvector::const_iterator ix, size_t num) @@ -595,12 +630,17 @@ static ex trace_string(exvector::const_iterator ix, size_t num) return result; } -ex dirac_trace(const ex & e, unsigned char rl, const ex & trONE) +ex dirac_trace(const ex & e, const std::set & rls, const ex & trONE) { if (is_a(e)) { - if (!ex_to(e).get_representation_label() == rl) - return _ex0; + unsigned char rl = ex_to(e).get_representation_label(); + + // Are we taking the trace over this object's representation label? + if (rls.find(rl) == rls.end()) + return e; + + // Yes, all elements are traceless, except for dirac_ONE and dirac_L/R const ex & g = e.op(0); if (is_a(g)) return trONE; @@ -615,8 +655,8 @@ ex dirac_trace(const ex & e, unsigned char rl, const ex & trONE) ex prod = _ex1; for (size_t i=0; i(e)) { - if (!is_clifford_tinfo(e.return_type_tinfo(), rl)) - return _ex0; + unsigned char rl = get_representation_label(e.return_type_tinfo()); + + // Are we taking the trace over this string's representation label? + if (rls.find(rl) == rls.end()) + return e; // Substitute gammaL/R and expand product, if necessary ex e_expanded = e.subs(lst( @@ -633,7 +676,7 @@ ex dirac_trace(const ex & e, unsigned char rl, const ex & trONE) dirac_gammaR(rl) == (dirac_ONE(rl)+dirac_gamma5(rl))/2 ), subs_options::no_pattern).expand(); if (!is_a(e_expanded)) - return dirac_trace(e_expanded, rl, trONE); + return dirac_trace(e_expanded, rls, trONE); // gamma5 gets moved to the front so this check is enough bool has_gamma5 = is_a(e.op(0).op(0)); @@ -717,13 +760,35 @@ ex dirac_trace(const ex & e, unsigned char rl, const ex & trONE) } else if (e.nops() > 0) { // Trace maps to all other container classes (this includes sums) - pointer_to_map_function_2args fcn(dirac_trace, rl, trONE); + pointer_to_map_function_2args &, const ex &> fcn(dirac_trace, rls, trONE); return e.map(fcn); } else return _ex0; } +ex dirac_trace(const ex & e, const lst & rll, const ex & trONE) +{ + // Convert list to set + std::set rls; + for (lst::const_iterator i = rll.begin(); i != rll.end(); ++i) { + if (i->info(info_flags::nonnegint)) + rls.insert(ex_to(*i).to_int()); + } + + return dirac_trace(e, rls, trONE); +} + +ex dirac_trace(const ex & e, unsigned char rl, const ex & trONE) +{ + // Convert label to set + std::set rls; + rls.insert(rl); + + return dirac_trace(e, rls, trONE); +} + + ex canonicalize_clifford(const ex & e) { // Scan for any ncmul objects diff --git a/ginac/clifford.h b/ginac/clifford.h index 2959a0f7..996a844e 100644 --- a/ginac/clifford.h +++ b/ginac/clifford.h @@ -26,6 +26,8 @@ #include "indexed.h" #include "tensor.h" +#include + namespace GiNaC { @@ -192,6 +194,26 @@ ex dirac_gammaR(unsigned char rl = 0); * @param rl Representation label */ ex dirac_slash(const ex & e, const ex & dim, unsigned char rl = 0); +/** Calculate dirac traces over the specified set of representation labels. + * The computed trace is a linear functional that is equal to the usual + * trace only in D = 4 dimensions. In particular, the functional is not + * always cyclic in D != 4 dimensions when gamma5 is involved. + * + * @param e Expression to take the trace of + * @param rls Set of representation labels + * @param trONE Expression to be returned as the trace of the unit matrix */ +ex dirac_trace(const ex & e, const std::set & rls, const ex & trONE = 4); + +/** Calculate dirac traces over the specified list of representation labels. + * The computed trace is a linear functional that is equal to the usual + * trace only in D = 4 dimensions. In particular, the functional is not + * always cyclic in D != 4 dimensions when gamma5 is involved. + * + * @param e Expression to take the trace of + * @param rll List of representation labels + * @param trONE Expression to be returned as the trace of the unit matrix */ +ex dirac_trace(const ex & e, const lst & rll, const ex & trONE = 4); + /** Calculate the trace of an expression containing gamma objects with * a specified representation label. The computed trace is a linear * functional that is equal to the usual trace only in D = 4 dimensions. diff --git a/ginac/color.cpp b/ginac/color.cpp index e06eff44..3f45bba5 100644 --- a/ginac/color.cpp +++ b/ginac/color.cpp @@ -527,12 +527,32 @@ static bool is_color_tinfo(unsigned ti, unsigned char rl) return ti == (TINFO_color + rl); } -ex color_trace(const ex & e, unsigned char rl) +/** Check whether a given tinfo key (as returned by return_type_tinfo() + * is that of a color object (with an arbitrary representation label). */ +static bool is_color_tinfo(unsigned ti) +{ + return (ti & ~0xff) == TINFO_color; +} + +/** Extract representation label from tinfo key (as returned by + * return_type_tinfo()). */ +static unsigned char get_representation_label(unsigned ti) +{ + return ti & 0xff; +} + +ex color_trace(const ex & e, const std::set & rls) { if (is_a(e)) { - if (ex_to(e).get_representation_label() == rl - && is_a(e.op(0))) + unsigned char rl = ex_to(e).get_representation_label(); + + // Are we taking the trace over this object's representation label? + if (rls.find(rl) == rls.end()) + return e; + + // Yes, all generators are traceless, except for color_ONE + if (is_a(e.op(0))) return _ex3; else return _ex0; @@ -543,8 +563,8 @@ ex color_trace(const ex & e, unsigned char rl) ex prod = _ex1; for (size_t i=0; i(e)) { - if (!is_color_tinfo(e.return_type_tinfo(), rl)) - return _ex0; + unsigned char rl = get_representation_label(e.return_type_tinfo()); - // Expand product, if necessary + // Are we taking the trace over this string's representation label? + if (rls.find(rl) == rls.end()) + return e; + + // Yes, expand product if necessary ex e_expanded = e.expand(); if (!is_a(e_expanded)) - return color_trace(e_expanded, rl); + return color_trace(e_expanded, rls); size_t num = e.nops(); @@ -597,11 +620,32 @@ ex color_trace(const ex & e, unsigned char rl) } else if (e.nops() > 0) { // Trace maps to all other container classes (this includes sums) - pointer_to_map_function_1arg fcn(color_trace, rl); + pointer_to_map_function_1arg &> fcn(color_trace, rls); return e.map(fcn); } else return _ex0; } +ex color_trace(const ex & e, const lst & rll) +{ + // Convert list to set + std::set rls; + for (lst::const_iterator i = rll.begin(); i != rll.end(); ++i) { + if (i->info(info_flags::nonnegint)) + rls.insert(ex_to(*i).to_int()); + } + + return color_trace(e, rls); +} + +ex color_trace(const ex & e, unsigned char rl) +{ + // Convert label to set + std::set rls; + rls.insert(rl); + + return color_trace(e, rls); +} + } // namespace GiNaC diff --git a/ginac/color.h b/ginac/color.h index 2086909e..826b4c7f 100644 --- a/ginac/color.h +++ b/ginac/color.h @@ -26,6 +26,8 @@ #include "indexed.h" #include "tensor.h" +#include + namespace GiNaC { @@ -169,6 +171,18 @@ ex color_d(const ex & a, const ex & b, const ex & c); /** This returns the linear combination d.a.b.c+I*f.a.b.c. */ ex color_h(const ex & a, const ex & b, const ex & c); +/** Calculate color traces over the specified set of representation labels. + * + * @param e Expression to take the trace of + * @param rls Set of representation labels */ +ex color_trace(const ex & e, const std::set & rls); + +/** Calculate color traces over the specified list of representation labels. + * + * @param e Expression to take the trace of + * @param rll List of representation labels */ +ex color_trace(const ex & e, const lst & rll); + /** Calculate the trace of an expression containing color objects with a * specified representation label. * diff --git a/ginac/indexed.cpp b/ginac/indexed.cpp index ad17a497..d693373c 100644 --- a/ginac/indexed.cpp +++ b/ginac/indexed.cpp @@ -1128,6 +1128,7 @@ ex simplify_indexed(const ex & e, exvector & free_indices, exvector & dummy_indi * performs contraction of dummy indices where possible and checks whether * the free indices in sums are consistent. * + * @param options Simplification options (currently unused) * @return simplified expression */ ex ex::simplify_indexed(unsigned options) const { @@ -1142,6 +1143,7 @@ ex ex::simplify_indexed(unsigned options) const * scalar products by known values if desired. * * @param sp Scalar products to be replaced automatically + * @param options Simplification options (currently unused) * @return simplified expression */ ex ex::simplify_indexed(const scalar_products & sp, unsigned options) const { -- 2.47.0