X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fcolor.cpp;h=adcd8740f2ab7686a7babde2ca6a493cfa998394;hp=f905693e18947c1f0df3ccead73215318fec3d30;hb=1c366ae20b00440baee6c3a11b2a109294f236b9;hpb=66c0f31c678e6c1938d637636b230ea376c157c1 diff --git a/ginac/color.cpp b/ginac/color.cpp index f905693e..adcd8740 100644 --- a/ginac/color.cpp +++ b/ginac/color.cpp @@ -1,9 +1,9 @@ /** @file color.cpp * - * Implementation of GiNaC's color objects. - * No real implementation yet, to be done. - * - * GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany + * Implementation of GiNaC's color (SU(3) Lie algebra) objects. */ + +/* + * GiNaC Copyright (C) 1999-2001 Johannes Gutenberg University Mainz, Germany * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,956 +20,570 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include #include -#include #include #include "color.h" -#include "ex.h" -#include "coloridx.h" +#include "idx.h" #include "ncmul.h" #include "numeric.h" -#include "relational.h" +#include "power.h" // for sqrt() +#include "symbol.h" +#include "print.h" +#include "archive.h" +#include "debugmsg.h" +#include "utils.h" + +namespace GiNaC { + +GINAC_IMPLEMENT_REGISTERED_CLASS(color, indexed) +GINAC_IMPLEMENT_REGISTERED_CLASS(su3one, tensor) +GINAC_IMPLEMENT_REGISTERED_CLASS(su3t, tensor) +GINAC_IMPLEMENT_REGISTERED_CLASS(su3f, tensor) +GINAC_IMPLEMENT_REGISTERED_CLASS(su3d, tensor) ////////// // default constructor, destructor, copy constructor assignment operator and helpers ////////// -// public - -color::color() : type(invalid), representation_label(0) -{ - debugmsg("color default constructor",LOGLEVEL_CONSTRUCT); - tinfo_key=TINFO_color; -} - -color::~color() -{ - debugmsg("color destructor",LOGLEVEL_DESTRUCT); - destroy(0); -} - -color::color(color const & other) +color::color() : representation_label(0) { - debugmsg("color copy constructor",LOGLEVEL_CONSTRUCT); - copy (other); + debugmsg("color default constructor", LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_color; } -color const & color::operator=(color const & other) +void color::copy(const color & other) { - debugmsg("color operator=",LOGLEVEL_ASSIGNMENT); - if (this != &other) { - destroy(1); - copy(other); - } - return *this; + inherited::copy(other); + representation_label = other.representation_label; } -// protected - -void color::copy(color const & other) -{ - indexed::copy(other); - type=other.type; - representation_label=other.representation_label; -} - -void color::destroy(bool call_parent) -{ - if (call_parent) { - indexed::destroy(call_parent); - } -} +DEFAULT_DESTROY(color) +DEFAULT_CTORS(su3one) +DEFAULT_CTORS(su3t) +DEFAULT_CTORS(su3f) +DEFAULT_CTORS(su3d) ////////// // other constructors ////////// -// protected - -color::color(color_types const t, unsigned const rl) : type(t), representation_label(rl) +/** Construct object without any color index. This constructor is for + * internal use only. Use the color_ONE() function instead. + * @see color_ONE */ +color::color(const ex & b, unsigned char rl) : inherited(b), representation_label(rl) { - debugmsg("color constructor from color_types,unsigned",LOGLEVEL_CONSTRUCT); - ASSERT(representation_label(other); -void color::printraw(ostream & os) const -{ - debugmsg("color printraw",LOGLEVEL_PRINT); - os << "color(type=" << (unsigned)type - << ",representation_label=" << representation_label - << ",indices="; - printrawindices(os); - os << ",hash=" << hashvalue << ",flags=" << flags << ")"; -} + if (representation_label != o.representation_label) { + // different representation label + return representation_label < o.representation_label ? -1 : 1; + } -void color::printtree(ostream & os, unsigned indent) const -{ - debugmsg("color printtree",LOGLEVEL_PRINT); - os << string(indent,' ') << "color object: " - << "type=" << (unsigned)type - << ",representation_label=" << representation_label << ", "; - os << seq.size() << " indices" << endl; - printtreeindices(os,indent); - os << string(indent,' ') << "hash=" << hashvalue - << " (0x" << hex << hashvalue << dec << ")" - << ", flags=" << flags << endl; + return inherited::compare_same_type(other); } -void color::print(ostream & os, unsigned upper_precedence) const -{ - debugmsg("color print",LOGLEVEL_PRINT); - switch (type) { - case color_T: - os << "T"; - if (representation_label!=0) { - os << "^(" << representation_label << ")"; - } - break; - case color_f: - os << "f"; - break; - case color_d: - os << "d"; - break; - case color_delta8: - os << "delta8"; - break; - case color_ONE: - os << "color_ONE"; - break; - case invalid: - default: - os << "INVALID_COLOR_OBJECT"; - break; - } - printindices(os); -} +DEFAULT_COMPARE(su3one) +DEFAULT_COMPARE(su3t) +DEFAULT_COMPARE(su3f) +DEFAULT_COMPARE(su3d) -void color::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const -{ - debugmsg("color print csrc",LOGLEVEL_PRINT); - print(os,upper_precedence); -} +DEFAULT_PRINT_LATEX(su3one, "ONE", "\\mathbb{1}") +DEFAULT_PRINT(su3t, "T") +DEFAULT_PRINT(su3f, "f") +DEFAULT_PRINT(su3d, "d") -bool color::info(unsigned inf) const +/** Perform automatic simplification on noncommutative product of color + * objects. This removes superfluous ONEs. */ +ex color::simplify_ncmul(const exvector & v) const { - return indexed::info(inf); -} - -#define CMPINDICES(A,B,C) ((idx1.get_value()==(A))&&(idx2.get_value()==(B))&&(idx3.get_value()==(C))) + exvector s; + s.reserve(v.size()); -ex color::eval(int level) const -{ - // canonicalize indices - - bool antisymmetric=false; - - switch (type) { - case color_f: - antisymmetric=true; // no break here! - case color_d: - case color_delta8: - { - exvector iv=seq; - int sig=canonicalize_indices(iv,antisymmetric); - if (sig!=INT_MAX) { - // something has changed while sorting indices, more evaluations later - if (sig==0) return exZERO(); - return ex(sig)*color(type,iv,representation_label); - } - } - break; - default: - // nothing to canonicalize - break; - } - - switch (type) { - case color_delta8: - { - ASSERT(seq.size()==2); - coloridx const & idx1=ex_to_coloridx(seq[0]); - coloridx const & idx2=ex_to_coloridx(seq[1]); - - // check for delta8_{a,a} where a is a symbolic index, replace by 8 - if ((idx1.is_symbolic())&&(idx1.is_equal_same_type(idx2))) { - return ex(COLOR_EIGHT); - } - - // check for delta8_{a,b} where a and b are numeric indices, replace by 0 or 1 - if ((!idx1.is_symbolic())&&(!idx2.is_symbolic())) { - if ((idx1.get_value()!=idx2.get_value())) { - return exONE(); - } else { - return exZERO(); - } - } + // Remove superfluous ONEs + exvector::const_iterator it = v.begin(), itend = v.end(); + while (it != itend) { + if (!is_ex_of_type(it->op(0), su3one)) + s.push_back(*it); + it++; } - break; - case color_d: - // check for d_{a,a,c} (=0) when a is symbolic - { - ASSERT(seq.size()==3); - coloridx const & idx1=ex_to_coloridx(seq[0]); - coloridx const & idx2=ex_to_coloridx(seq[1]); - coloridx const & idx3=ex_to_coloridx(seq[2]); - - if (idx1.is_equal_same_type(idx2) && idx1.is_symbolic()) { - return exZERO(); - } else if (idx2.is_equal_same_type(idx3) && idx2.is_symbolic()) { - return exZERO(); - } - - // check for three numeric indices - if (!(idx1.is_symbolic()||idx2.is_symbolic()||idx3.is_symbolic())) { - ASSERT(idx1.get_value()<=idx2.get_value()); - ASSERT(idx2.get_value()<=idx3.get_value()); - if (CMPINDICES(1,4,6)||CMPINDICES(1,5,7)||CMPINDICES(2,5,6)|| - CMPINDICES(3,4,4)||CMPINDICES(3,5,5)) { - return exHALF(); - } else if (CMPINDICES(2,4,7)||CMPINDICES(3,6,6)||CMPINDICES(3,7,7)) { - return -exHALF(); - } else if (CMPINDICES(1,1,8)||CMPINDICES(2,2,8)||CMPINDICES(3,3,8)) { - return 1/sqrt(numeric(3)); - } else if (CMPINDICES(8,8,8)) { - return -1/sqrt(numeric(3)); - } else if (CMPINDICES(4,4,8)||CMPINDICES(5,5,8)||CMPINDICES(6,6,8)||CMPINDICES(7,7,8)) { - return -1/(2*sqrt(numeric(3))); - } - return exZERO(); - } - } - break; - case color_f: - { - ASSERT(seq.size()==3); - coloridx const & idx1=ex_to_coloridx(seq[0]); - coloridx const & idx2=ex_to_coloridx(seq[1]); - coloridx const & idx3=ex_to_coloridx(seq[2]); - - // check for three numeric indices - if (!(idx1.is_symbolic()||idx2.is_symbolic()||idx3.is_symbolic())) { - ASSERT(idx1.get_value()<=idx2.get_value()); - ASSERT(idx2.get_value()<=idx3.get_value()); - if (CMPINDICES(1,2,3)) { - return exONE(); - } else if (CMPINDICES(1,4,7)||CMPINDICES(2,4,6)|| - CMPINDICES(2,5,7)||CMPINDICES(3,4,5)) { - return exHALF(); - } else if (CMPINDICES(1,5,6)||CMPINDICES(3,6,7)) { - return -exHALF(); - } else if (CMPINDICES(4,5,8)||CMPINDICES(6,7,8)) { - return sqrt(numeric(3))/2; - } else if (CMPINDICES(8,8,8)) { - return -1/sqrt(numeric(3)); - } else if (CMPINDICES(4,4,8)||CMPINDICES(5,5,8)||CMPINDICES(6,6,8)||CMPINDICES(7,7,8)) { - return -1/(2*sqrt(numeric(3))); - } - return exZERO(); - } - break; - } - default: - // nothing to evaluate - break; - } - - return this->hold(); -} - -// protected - -int color::compare_same_type(basic const & other) const -{ - ASSERT(other.tinfo() == TINFO_color); - const color *o = static_cast(&other); - if (type==o->type) { - if (representation_label==o->representation_label) { - return indexed::compare_same_type(other); - } - return representation_label < o->representation_label ? -1 : 1; - } - return type < o->type ? -1 : 1; -} - -bool color::is_equal_same_type(basic const & other) const -{ - ASSERT(other.tinfo() == TINFO_color); - const color *o = static_cast(&other); - if (type!=o->type) return false; - if (representation_label!=o->representation_label) return false; - return indexed::is_equal_same_type(other); -} - -#include -ex color::simplify_ncmul(exvector const & v) const -{ - // simplifications: contract delta8_{a,b} where possible - // sort delta8,f,d,T(rl=0),T(rl=1),...,ONE(rl=0),ONE(rl=1),... - // remove superfluous ONEs - - // contract indices of delta8_{a,b} if they are different and symbolic - - exvector v_contracted=v; - unsigned replacements; - bool something_changed=false; - - exvector::iterator it=v_contracted.begin(); - while (it!=v_contracted.end()) { - // process only delta8 objects - if (is_ex_exactly_of_type(*it,color) && (ex_to_color(*it).type==color_delta8)) { - color & d8=ex_to_nonconst_color(*it); - ASSERT(d8.seq.size()==2); - coloridx const & first_idx=ex_to_coloridx(d8.seq[0]); - coloridx const & second_idx=ex_to_coloridx(d8.seq[1]); - // delta8_{a,a} should have been contracted in color::eval() - ASSERT((!first_idx.is_equal(second_idx))||(!first_idx.is_symbolic())); - ex saved_delta8=*it; // save to restore it later - - // try to contract first index - replacements=1; - if (first_idx.is_symbolic()) { - replacements = subs_index_in_exvector(v_contracted,first_idx,second_idx); - if (replacements==1) { - // not contracted except in itself, restore delta8 object - *it=saved_delta8; - } else { - // a contracted index should occur exactly twice - ASSERT(replacements==2); - *it=exONE(); - something_changed=true; - } - } - - // try second index only if first was not contracted - if ((replacements==1)&&(second_idx.is_symbolic())) { - // first index not contracted, *it is guaranteed to be the original delta8 object - replacements = subs_index_in_exvector(v_contracted,second_idx,first_idx); - if (replacements==1) { - // not contracted except in itself, restore delta8 object - *it=saved_delta8; - } else { - // a contracted index should occur exactly twice - ASSERT(replacements==2); - *it=exONE(); - something_changed=true; - } - } - } - ++it; - } - - if (something_changed) { - // do more simplifications later - return nonsimplified_ncmul(v_contracted); - } - - // there were no indices to contract - // sort delta8,f,d,T(rl=0),T(rl=1),...,ONE(rl=0),ONE(rl=1),...,unknown - // (if there is at least one unknown object, all Ts will be unknown to not change the order) - - exvector delta8vec; - exvector fvec; - exvector dvec; - vector Tvecs; - Tvecs.resize(MAX_REPRESENTATION_LABELS); - vector ONEvecs; - ONEvecs.resize(MAX_REPRESENTATION_LABELS); - exvector unknownvec; - - split_color_string_in_parts(v,delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec); - - // d_{a,k,l} f_{b,k,l}=0 (includes case a=b) - if ((dvec.size()>=1)&&(fvec.size()>=1)) { - for (exvector::iterator it1=dvec.begin(); it1!=dvec.end(); ++it1) { - for (exvector::iterator it2=fvec.begin(); it2!=fvec.end(); ++it2) { - ASSERT(is_ex_exactly_of_type(*it1,color)); - ASSERT(is_ex_exactly_of_type(*it2,color)); - color const & col1=ex_to_color(*it1); - color const & col2=ex_to_color(*it2); - exvector iv_intersect=idx_intersect(col1.seq,col2.seq); - if (iv_intersect.size()>=2) return exZERO(); - } - } - } - - // d_{a,k,l} d_{b,k,l}=5/3 delta8_{a,b} (includes case a=b) - if (dvec.size()>=2) { - for (exvector::iterator it1=dvec.begin(); it1!=dvec.end()-1; ++it1) { - for (exvector::iterator it2=it1+1; it2!=dvec.end(); ++it2) { - ASSERT(is_ex_exactly_of_type(*it1,color)); - ASSERT(is_ex_exactly_of_type(*it2,color)); - color const & col1=ex_to_color(*it1); - color const & col2=ex_to_color(*it2); - exvector iv_intersect=idx_intersect(col1.seq,col2.seq); - if (iv_intersect.size()>=2) { - if (iv_intersect.size()==3) { - *it1=numeric(40)/numeric(3); - *it2=exONE(); - } else { - int sig1, sig2; // unimportant, since symmetric - ex idx1=permute_free_index_to_front(col1.seq,iv_intersect,false,&sig1); - ex idx2=permute_free_index_to_front(col2.seq,iv_intersect,false,&sig2); - *it1=numeric(5)/numeric(3)*color(color_delta8,idx1,idx2); - *it2=exONE(); - } - return nonsimplified_ncmul(recombine_color_string( - delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec)); - } - } - } - } - - // f_{a,k,l} f_{b,k,l}=3 delta8_{a,b} (includes case a=b) - if (fvec.size()>=2) { - for (exvector::iterator it1=fvec.begin(); it1!=fvec.end()-1; ++it1) { - for (exvector::iterator it2=it1+1; it2!=fvec.end(); ++it2) { - ASSERT(is_ex_exactly_of_type(*it1,color)); - ASSERT(is_ex_exactly_of_type(*it2,color)); - color const & col1=ex_to_color(*it1); - color const & col2=ex_to_color(*it2); - exvector iv_intersect=idx_intersect(col1.seq,col2.seq); - if (iv_intersect.size()>=2) { - if (iv_intersect.size()==3) { - *it1=numeric(24); - *it2=exONE(); - } else { - int sig1, sig2; - ex idx1=permute_free_index_to_front(col1.seq,iv_intersect,true,&sig1); - ex idx2=permute_free_index_to_front(col2.seq,iv_intersect,true,&sig2); - *it1=numeric(sig1*sig2*5)/numeric(3)*color(color_delta8,idx1,idx2); - *it2=exONE(); - } - return nonsimplified_ncmul(recombine_color_string( - delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec)); - } - } - } - } - - // d_{a,b,c} T_b T_c = 5/6 T_a - // f_{a,b,c} T_b T_c = 3/2 I T_a - for (unsigned rl=0; rl=2)&&((dvec.size()>=1)||(fvec.size()>=1))) { - for (exvector::iterator it1=Tvecs[rl].begin(); it1!=Tvecs[rl].end()-1; ++it1) { - exvector iv; - ASSERT(is_ex_exactly_of_type(*it1,color)&&ex_to_color(*it1).type==color_T); - ASSERT(is_ex_exactly_of_type(*(it1+1),color)&&ex_to_color(*(it1+1)).type==color_T); - iv.push_back(ex_to_color(*it1).seq[0]); - iv.push_back(ex_to_color(*(it1+1)).seq[0]); - - // d_{a,b,c} T_b T_c = 5/6 T_a - for (exvector::iterator it2=dvec.begin(); it2!=dvec.end(); ++it2) { - ASSERT(is_ex_exactly_of_type(*it2,color)&&ex_to_color(*it2).type==color_d); - color const & dref=ex_to_color(*it2); - exvector iv_intersect=idx_intersect(dref.seq,iv); - if (iv_intersect.size()==2) { - int sig; // unimportant, since symmetric - ex free_idx=permute_free_index_to_front(dref.seq,iv,false,&sig); - *it1=color(color_T,free_idx,rl); - *(it1+1)=color(color_ONE,rl); - *it2=numeric(5)/numeric(6); - return nonsimplified_ncmul(recombine_color_string( - delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec)); - } - } - - // f_{a,b,c} T_b T_c = 3/2 I T_a - for (exvector::iterator it2=fvec.begin(); it2!=fvec.end(); ++it2) { - ASSERT(is_ex_exactly_of_type(*it2,color)&&ex_to_color(*it2).type==color_f); - color const & fref=ex_to_color(*it2); - exvector iv_intersect=idx_intersect(fref.seq,iv); - if (iv_intersect.size()==2) { - int sig; - ex free_idx=permute_free_index_to_front(fref.seq,iv,true,&sig); - *it1=color(color_T,free_idx,rl); - *(it1+1)=color(color_ONE,rl); - *it2=numeric(sig*3)/numeric(2)*I; - return nonsimplified_ncmul(recombine_color_string( - delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec)); - } - } - } - } - } - - // clear all ONEs when there is at least one corresponding color_T - // in this representation, retain one ONE otherwise - for (unsigned rl=0; rl(i).get_dummy_indices().size() != 0) + return _ex0(); + + // Numeric evaluation + if (static_cast(i).all_index_values_are(info_flags::nonnegint)) { + + // Sort indices + int v[3]; + for (unsigned j=0; j<3; j++) + v[j] = ex_to_numeric(ex_to_idx(i.op(j + 1)).get_value()).to_int(); + if (v[0] > v[1]) std::swap(v[0], v[1]); + if (v[0] > v[2]) std::swap(v[0], v[2]); + if (v[1] > v[2]) std::swap(v[1], v[2]); + +#define CMPINDICES(A,B,C) ((v[0] == (A)) && (v[1] == (B)) && (v[2] == (C))) + + // Check for non-zero elements + if (CMPINDICES(1,4,6) || CMPINDICES(1,5,7) || CMPINDICES(2,5,6) + || CMPINDICES(3,4,4) || CMPINDICES(3,5,5)) + return _ex1_2(); + else if (CMPINDICES(2,4,7) || CMPINDICES(3,6,6) || CMPINDICES(3,7,7)) + return _ex_1_2(); + else if (CMPINDICES(1,1,8) || CMPINDICES(2,2,8) || CMPINDICES(3,3,8)) + return sqrt(_ex3())/3; + else if (CMPINDICES(8,8,8)) + return -sqrt(_ex3())/3; + else if (CMPINDICES(4,4,8) || CMPINDICES(5,5,8) + || CMPINDICES(6,6,8) || CMPINDICES(7,7,8)) + return -sqrt(_ex3())/6; + else + return _ex0(); + } -////////// -// non-virtual functions in this class -////////// + // No further simplifications + return i.hold(); +} + +/** Automatic symbolic evaluation of indexed antisymmetric structure constant. */ +ex su3f::eval_indexed(const basic & i) const +{ + GINAC_ASSERT(is_of_type(i, indexed)); + GINAC_ASSERT(i.nops() == 4); + GINAC_ASSERT(is_ex_of_type(i.op(0), su3f)); + + // Numeric evaluation + if (static_cast(i).all_index_values_are(info_flags::nonnegint)) { + + // Sort indices, remember permutation sign + int v[3]; + for (unsigned j=0; j<3; j++) + v[j] = ex_to_numeric(ex_to_idx(i.op(j + 1)).get_value()).to_int(); + int sign = 1; + if (v[0] > v[1]) { std::swap(v[0], v[1]); sign = -sign; } + if (v[0] > v[2]) { std::swap(v[0], v[2]); sign = -sign; } + if (v[1] > v[2]) { std::swap(v[1], v[2]); sign = -sign; } + + // Check for non-zero elements + if (CMPINDICES(1,2,3)) + return sign; + else if (CMPINDICES(1,4,7) || CMPINDICES(2,4,6) + || CMPINDICES(2,5,7) || CMPINDICES(3,4,5)) + return _ex1_2() * sign; + else if (CMPINDICES(1,5,6) || CMPINDICES(3,6,7)) + return _ex_1_2() * sign; + else if (CMPINDICES(4,5,8) || CMPINDICES(6,7,8)) + return sqrt(_ex3())/2 * sign; + else + return _ex0(); + } -////////// -// static member variables -////////// + // No further simplifications + return i.hold(); +} + + +/** 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; + } + } -// none + 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 +{ + GINAC_ASSERT(is_ex_of_type(*self, indexed)); + GINAC_ASSERT(is_ex_of_type(*other, indexed)); + GINAC_ASSERT(self->nops() == 4); + GINAC_ASSERT(is_ex_of_type(self->op(0), su3d)); + + if (is_ex_exactly_of_type(other->op(0), su3d)) { + + // Find the dummy indices of the contraction + exvector self_indices = ex_to_indexed(*self).get_indices(); + exvector other_indices = ex_to_indexed(*other).get_indices(); + exvector all_indices = self_indices; + all_indices.insert(all_indices.end(), other_indices.begin(), other_indices.end()); + exvector free_indices, dummy_indices; + find_free_and_dummy(all_indices, free_indices, dummy_indices); + + // d.abc d.abc = 40/3 + if (dummy_indices.size() == 3) { + *self = numeric(40, 3); + *other = _ex1(); + return true; + + // d.akl d.bkl = 5/3 delta.ab + } else if (dummy_indices.size() == 2) { + exvector a; + std::back_insert_iterator ita(a); + ita = set_difference(self_indices.begin(), self_indices.end(), dummy_indices.begin(), dummy_indices.end(), ita, ex_is_less()); + ita = set_difference(other_indices.begin(), other_indices.end(), dummy_indices.begin(), dummy_indices.end(), ita, ex_is_less()); + GINAC_ASSERT(a.size() == 2); + *self = numeric(5, 3) * delta_tensor(a[0], a[1]); + *other = _ex1(); + return true; + } + + } else if (is_ex_exactly_of_type(other->op(0), su3t)) { + + // d.abc T.b T.c = 5/6 T.a + if (other+1 != v.end() + && is_ex_exactly_of_type(other[1].op(0), su3t) + && ex_to_indexed(*self).has_dummy_index_for(other[1].op(1))) { + + exvector self_indices = ex_to_indexed(*self).get_indices(); + exvector dummy_indices; + dummy_indices.push_back(other[0].op(1)); + dummy_indices.push_back(other[1].op(1)); + int sig; + ex a = permute_free_index_to_front(self_indices, dummy_indices, sig); + *self = numeric(5, 6); + other[0] = color_T(a, ex_to_color(other[0]).get_representation_label()); + other[1] = _ex1(); + return true; + } + } -////////// -// global constants -////////// + return false; +} + +/** Contraction of an indexed antisymmetric structure constant with something else. */ +bool su3f::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() == 4); + GINAC_ASSERT(is_ex_of_type(self->op(0), su3f)); + + if (is_ex_exactly_of_type(other->op(0), su3f)) { // f*d is handled by su3d class + + // Find the dummy indices of the contraction + exvector dummy_indices; + dummy_indices = ex_to_indexed(*self).get_dummy_indices(ex_to_indexed(*other)); + + // f.abc f.abc = 24 + if (dummy_indices.size() == 3) { + *self = 24; + *other = _ex1(); + return true; + + // f.akl f.bkl = 3 delta.ab + } else if (dummy_indices.size() == 2) { + int sign1, sign2; + ex a = permute_free_index_to_front(ex_to_indexed(*self).get_indices(), dummy_indices, sign1); + ex b = permute_free_index_to_front(ex_to_indexed(*other).get_indices(), dummy_indices, sign2); + *self = sign1 * sign2 * 3 * delta_tensor(a, b); + *other = _ex1(); + return true; + } + + } else if (is_ex_exactly_of_type(other->op(0), su3t)) { + + // f.abc T.b T.c = 3/2 I T.a + if (other+1 != v.end() + && is_ex_exactly_of_type(other[1].op(0), su3t) + && ex_to_indexed(*self).has_dummy_index_for(other[1].op(1))) { + + exvector self_indices = ex_to_indexed(*self).get_indices(); + exvector dummy_indices; + dummy_indices.push_back(other[0].op(1)); + dummy_indices.push_back(other[1].op(1)); + int sig; + ex a = permute_free_index_to_front(self_indices, dummy_indices, sig); + *self = numeric(3, 2) * sig * I; + other[0] = color_T(a, ex_to_color(other[0]).get_representation_label()); + other[1] = _ex1(); + return true; + } + } -const color some_color; -type_info const & typeid_color=typeid(some_color); + return false; +} ////////// -// friend functions +// global functions ////////// -color color_ONE(unsigned const rl) +ex color_ONE(unsigned char rl) { - return color(color::color_ONE,rl); + return color(su3one(), rl); } -color color_T(ex const & a, unsigned const rl) +ex color_T(const ex & a, unsigned char rl) { - return color(color::color_T,a,rl); -} + if (!is_ex_of_type(a, idx)) + throw(std::invalid_argument("indices of color_T must be of type idx")); + if (!ex_to_idx(a).get_dim().is_equal(8)) + throw(std::invalid_argument("index dimension for color_T must be 8")); -color color_f(ex const & a, ex const & b, ex const & c) -{ - return color(color::color_f,a,b,c); + return color(su3t(), a, rl); } -color color_d(ex const & a, ex const & b, ex const & c) +ex color_f(const ex & a, const ex & b, const ex & c) { - return color(color::color_d,a,b,c); -} + if (!is_ex_of_type(a, idx) || !is_ex_of_type(b, idx) || !is_ex_of_type(c, idx)) + throw(std::invalid_argument("indices of color_f must be of type idx")); + if (!ex_to_idx(a).get_dim().is_equal(8) || !ex_to_idx(b).get_dim().is_equal(8) || !ex_to_idx(c).get_dim().is_equal(8)) + throw(std::invalid_argument("index dimension for color_f must be 8")); -ex color_h(ex const & a, ex const & b, ex const & c) -{ - return color(color::color_d,a,b,c)+I*color(color::color_f,a,b,c); + return indexed(su3f(), indexed::antisymmetric, a, b, c); } -color color_delta8(ex const & a, ex const & b) +ex color_d(const ex & a, const ex & b, const ex & c) { - return color(color::color_delta8,a,b); -} + if (!is_ex_of_type(a, idx) || !is_ex_of_type(b, idx) || !is_ex_of_type(c, idx)) + throw(std::invalid_argument("indices of color_d must be of type idx")); + if (!ex_to_idx(a).get_dim().is_equal(8) || !ex_to_idx(b).get_dim().is_equal(8) || !ex_to_idx(c).get_dim().is_equal(8)) + throw(std::invalid_argument("index dimension for color_d must be 8")); -void split_color_string_in_parts(exvector const & v, exvector & delta8vec, - exvector & fvec, exvector & dvec, - vector & Tvecs, - vector & ONEvecs, - exvector & unknownvec) -{ - // if not all elements are of type color, put all Ts in unknownvec to - // retain the ordering - bool all_color=true; - for (exvector::const_iterator cit=v.begin(); cit!=v.end(); ++cit) { - if (!is_ex_exactly_of_type(*cit,color)) { - all_color=false; - break; - } - } - - for (exvector::const_iterator cit=v.begin(); cit!=v.end(); ++cit) { - if (is_ex_exactly_of_type(*cit,color)) { - switch (ex_to_color(*cit).type) { - case color::color_delta8: - delta8vec.push_back(*cit); - break; - case color::color_f: - fvec.push_back(*cit); - break; - case color::color_d: - dvec.push_back(*cit); - break; - case color::color_T: - ASSERT(ex_to_color(*cit).representation_label & Tvecs, - vector & ONEvecs, exvector & unknownvec) -{ - unsigned sz=delta8vec.size()+fvec.size()+dvec.size()+unknownvec.size(); - for (unsigned rl=0; rl Tvecs; - Tvecs.resize(MAX_REPRESENTATION_LABELS); - vector ONEvecs; - ONEvecs.resize(MAX_REPRESENTATION_LABELS); - exvector unknownvec; - - split_color_string_in_parts(ex_to_ncmul(e).get_factors(),delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec); - - // search for T_k S T_k (=1/2 Tr(S) - 1/6 S) - for (unsigned rl=0; rl=2) { - for (unsigned i=0; i counter; - counter.resize(iv_double.size()); - int l; - for (l=0; unsigned(l)=0)&&((++counter[l])>COLOR_EIGHT)) { - counter[l]=1; - l--; - } - if (l<2) { cout << counter[0] << counter[1] << endl; } - if (l<0) break; - } - - return sum; -} + if (ex_to_color(e).get_representation_label() == rl + && is_ex_of_type(e.op(0), su3one)) + return _ex3(); + else + return _ex0(); -void append_exvector_to_exvector(exvector & dest, exvector const & source) -{ - for (exvector::const_iterator cit=source.begin(); cit!=source.end(); ++cit) { - dest.push_back(*cit); - } -} + } else if (is_ex_exactly_of_type(e, add)) { + + // Trace of sum = sum of traces + ex sum = _ex0(); + for (unsigned i=0; isetflag(status_flags::dynallocated), 8); + exvector v1; + v1.reserve(num - 2); + for (int i=0; i