GiNaC  1.6.2
color.cpp
Go to the documentation of this file.
00001 
00005 /*
00006  *  GiNaC Copyright (C) 1999-2011 Johannes Gutenberg University Mainz, Germany
00007  *
00008  *  This program is free software; you can redistribute it and/or modify
00009  *  it under the terms of the GNU General Public License as published by
00010  *  the Free Software Foundation; either version 2 of the License, or
00011  *  (at your option) any later version.
00012  *
00013  *  This program is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *  GNU General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU General Public License
00019  *  along with this program; if not, write to the Free Software
00020  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  */
00022 
00023 #include "color.h"
00024 #include "idx.h"
00025 #include "ncmul.h"
00026 #include "symmetry.h"
00027 #include "operators.h"
00028 #include "numeric.h"
00029 #include "mul.h"
00030 #include "power.h" // for sqrt()
00031 #include "symbol.h"
00032 #include "archive.h"
00033 #include "utils.h"
00034 
00035 #include <iostream>
00036 #include <stdexcept>
00037 
00038 namespace GiNaC {
00039 
00040 GINAC_IMPLEMENT_REGISTERED_CLASS(color, indexed)
00041 
00042 GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(su3one, tensor,
00043   print_func<print_dflt>(&su3one::do_print).
00044   print_func<print_latex>(&su3one::do_print_latex))
00045 
00046 GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(su3t, tensor,
00047   print_func<print_dflt>(&su3t::do_print).
00048   print_func<print_latex>(&su3t::do_print))
00049 
00050 GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(su3f, tensor,
00051   print_func<print_dflt>(&su3f::do_print).
00052   print_func<print_latex>(&su3f::do_print))
00053 
00054 GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(su3d, tensor,
00055   print_func<print_dflt>(&su3d::do_print).
00056   print_func<print_latex>(&su3d::do_print))
00057 
00059 // default constructors
00061 
00062 color::color() : representation_label(0)
00063 {
00064 }
00065 
00066 DEFAULT_CTOR(su3one)
00067 DEFAULT_CTOR(su3t)
00068 DEFAULT_CTOR(su3f)
00069 DEFAULT_CTOR(su3d)
00070 
00072 // other constructors
00074 
00078 color::color(const ex & b, unsigned char rl) : inherited(b), representation_label(rl)
00079 {
00080 }
00081 
00085 color::color(const ex & b, const ex & i1, unsigned char rl) : inherited(b, i1), representation_label(rl)
00086 {
00087 }
00088 
00089 color::color(unsigned char rl, const exvector & v, bool discardable) : inherited(not_symmetric(), v, discardable), representation_label(rl)
00090 {
00091 }
00092 
00093 color::color(unsigned char rl, std::auto_ptr<exvector> vp) : inherited(not_symmetric(), vp), representation_label(rl)
00094 {
00095 }
00096 
00097 return_type_t color::return_type_tinfo() const
00098 {
00099     return make_return_type_t<color>(representation_label);
00100 }
00101 
00103 // archiving
00105 
00106 void color::read_archive(const archive_node& n, lst& sym_lst)
00107 {
00108     inherited::read_archive(n, sym_lst);
00109     unsigned rl;
00110     n.find_unsigned("label", rl);
00111     representation_label = rl;
00112 }
00113 
00114 void color::archive(archive_node &n) const
00115 {
00116     inherited::archive(n);
00117     n.add_unsigned("label", representation_label);
00118 }
00119 
00120 GINAC_BIND_UNARCHIVER(color);
00121 GINAC_BIND_UNARCHIVER(su3one);
00122 GINAC_BIND_UNARCHIVER(su3t);
00123 GINAC_BIND_UNARCHIVER(su3f);
00124 GINAC_BIND_UNARCHIVER(su3d);
00125 
00127 // functions overriding virtual functions from base classes
00129 
00130 int color::compare_same_type(const basic & other) const
00131 {
00132     GINAC_ASSERT(is_a<color>(other));
00133     const color &o = static_cast<const color &>(other);
00134 
00135     if (representation_label != o.representation_label) {
00136         // different representation label
00137         return representation_label < o.representation_label ? -1 : 1;
00138     }
00139 
00140     return inherited::compare_same_type(other);
00141 }
00142 
00143 bool color::match_same_type(const basic & other) const
00144 {
00145     GINAC_ASSERT(is_a<color>(other));
00146     const color &o = static_cast<const color &>(other);
00147 
00148     return representation_label == o.representation_label;
00149 }
00150 
00151 DEFAULT_COMPARE(su3one)
00152 DEFAULT_COMPARE(su3t)
00153 DEFAULT_COMPARE(su3f)
00154 DEFAULT_COMPARE(su3d)
00155 
00156 DEFAULT_PRINT_LATEX(su3one, "ONE", "\\mathbb{1}")
00157 DEFAULT_PRINT(su3t, "T")
00158 DEFAULT_PRINT(su3f, "f")
00159 DEFAULT_PRINT(su3d, "d")
00160 
00163 ex color::eval_ncmul(const exvector & v) const
00164 {
00165     exvector s;
00166     s.reserve(v.size());
00167 
00168     // Remove superfluous ONEs
00169     exvector::const_iterator it = v.begin(), itend = v.end();
00170     while (it != itend) {
00171         if (!is_a<su3one>(it->op(0)))
00172             s.push_back(*it);
00173         it++;
00174     }
00175 
00176     if (s.empty())
00177         return color(su3one(), representation_label);
00178     else
00179         return hold_ncmul(s);
00180 }
00181 
00182 ex color::thiscontainer(const exvector & v) const
00183 {
00184     return color(representation_label, v);
00185 }
00186 
00187 ex color::thiscontainer(std::auto_ptr<exvector> vp) const
00188 {
00189     return color(representation_label, vp);
00190 }
00191 
00200 static ex permute_free_index_to_front(const exvector & iv3, const exvector & iv2, int & sig)
00201 {
00202     GINAC_ASSERT(iv3.size() == 3);
00203     GINAC_ASSERT(iv2.size() == 2);
00204 
00205     sig = 1;
00206 
00207 #define TEST_PERMUTATION(A,B,C,P) \
00208     if (iv3[B].is_equal(iv2[0]) && iv3[C].is_equal(iv2[1])) { \
00209         sig = P; \
00210         return iv3[A]; \
00211     }
00212     
00213     TEST_PERMUTATION(0,1,2,  1);
00214     TEST_PERMUTATION(0,2,1, -1);
00215     TEST_PERMUTATION(1,0,2, -1);
00216     TEST_PERMUTATION(1,2,0,  1);
00217     TEST_PERMUTATION(2,0,1,  1);
00218     TEST_PERMUTATION(2,1,0, -1);
00219 
00220     throw(std::logic_error("permute_free_index_to_front(): no valid permutation found"));
00221 }
00222 
00224 ex su3d::eval_indexed(const basic & i) const
00225 {
00226     GINAC_ASSERT(is_a<indexed>(i));
00227     GINAC_ASSERT(i.nops() == 4);
00228     GINAC_ASSERT(is_a<su3d>(i.op(0)));
00229 
00230     // Convolutions are zero
00231     if (!(static_cast<const indexed &>(i).get_dummy_indices().empty()))
00232         return _ex0;
00233 
00234     // Numeric evaluation
00235     if (static_cast<const indexed &>(i).all_index_values_are(info_flags::nonnegint)) {
00236 
00237         // Sort indices
00238         int v[3];
00239         for (unsigned j=0; j<3; j++)
00240             v[j] = ex_to<numeric>(ex_to<idx>(i.op(j + 1)).get_value()).to_int();
00241         if (v[0] > v[1]) std::swap(v[0], v[1]);
00242         if (v[0] > v[2]) std::swap(v[0], v[2]);
00243         if (v[1] > v[2]) std::swap(v[1], v[2]);
00244 
00245 #define CMPINDICES(A,B,C) ((v[0] == (A)) && (v[1] == (B)) && (v[2] == (C)))
00246 
00247         // Check for non-zero elements
00248         if (CMPINDICES(1,4,6) || CMPINDICES(1,5,7) || CMPINDICES(2,5,6)
00249          || CMPINDICES(3,4,4) || CMPINDICES(3,5,5))
00250             return _ex1_2;
00251         else if (CMPINDICES(2,4,7) || CMPINDICES(3,6,6) || CMPINDICES(3,7,7))
00252             return _ex_1_2;
00253         else if (CMPINDICES(1,1,8) || CMPINDICES(2,2,8) || CMPINDICES(3,3,8))
00254             return sqrt(_ex3)*_ex1_3;
00255         else if (CMPINDICES(8,8,8))
00256             return sqrt(_ex3)*_ex_1_3;
00257         else if (CMPINDICES(4,4,8) || CMPINDICES(5,5,8)
00258               || CMPINDICES(6,6,8) || CMPINDICES(7,7,8))
00259             return sqrt(_ex3)/_ex_6;
00260         else
00261             return _ex0;
00262     }
00263 
00264     // No further simplifications
00265     return i.hold();
00266 }
00267 
00269 ex su3f::eval_indexed(const basic & i) const
00270 {
00271     GINAC_ASSERT(is_a<indexed>(i));
00272     GINAC_ASSERT(i.nops() == 4);
00273     GINAC_ASSERT(is_a<su3f>(i.op(0)));
00274 
00275     // Numeric evaluation
00276     if (static_cast<const indexed &>(i).all_index_values_are(info_flags::nonnegint)) {
00277 
00278         // Sort indices, remember permutation sign
00279         int v[3];
00280         for (unsigned j=0; j<3; j++)
00281             v[j] = ex_to<numeric>(ex_to<idx>(i.op(j + 1)).get_value()).to_int();
00282         int sign = 1;
00283         if (v[0] > v[1]) { std::swap(v[0], v[1]); sign = -sign; }
00284         if (v[0] > v[2]) { std::swap(v[0], v[2]); sign = -sign; }
00285         if (v[1] > v[2]) { std::swap(v[1], v[2]); sign = -sign; }
00286 
00287         // Check for non-zero elements
00288         if (CMPINDICES(1,2,3))
00289             return sign;
00290         else if (CMPINDICES(1,4,7) || CMPINDICES(2,4,6)
00291               || CMPINDICES(2,5,7) || CMPINDICES(3,4,5))
00292             return _ex1_2 * sign;
00293         else if (CMPINDICES(1,5,6) || CMPINDICES(3,6,7))
00294             return _ex_1_2 * sign;
00295         else if (CMPINDICES(4,5,8) || CMPINDICES(6,7,8))
00296             return sqrt(_ex3)/2 * sign;
00297         else
00298             return _ex0;
00299     }
00300 
00301     // No further simplifications
00302     return i.hold();
00303 }
00304 
00305 
00307 bool su3t::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
00308 {
00309     GINAC_ASSERT(is_a<indexed>(*self));
00310     GINAC_ASSERT(is_a<indexed>(*other));
00311     GINAC_ASSERT(self->nops() == 2);
00312     GINAC_ASSERT(is_a<su3t>(self->op(0)));
00313     unsigned char rl = ex_to<color>(*self).get_representation_label();
00314 
00315     if (is_exactly_a<su3t>(other->op(0))) {
00316 
00317         // Contraction only makes sense if the represenation labels are equal
00318         GINAC_ASSERT(is_a<color>(*other));
00319         if (ex_to<color>(*other).get_representation_label() != rl)
00320             return false;
00321 
00322         // T.a T.a = 4/3 ONE
00323         if (other - self == 1) {
00324             *self = numeric(4, 3);
00325             *other = color_ONE(rl);
00326             return true;
00327 
00328         // T.a T.b T.a = -1/6 T.b
00329         } else if (other - self == 2
00330                 && is_a<color>(self[1])) {
00331             *self = numeric(-1, 6);
00332             *other = _ex1;
00333             return true;
00334 
00335         // T.a S T.a = 1/2 Tr(S) - 1/6 S
00336         } else {
00337             exvector::iterator it = self + 1;
00338             while (it != other) {
00339                 if (!is_a<color>(*it)) {
00340                     return false;
00341                 }
00342                 it++;
00343             }
00344 
00345             it = self + 1;
00346             ex S = _ex1;
00347             while (it != other) {
00348                 S *= *it;
00349                 *it++ = _ex1;
00350             }
00351 
00352             *self = color_trace(S, rl) * color_ONE(rl) / 2 - S / 6;
00353             *other = _ex1;
00354             return true;
00355         }
00356     }
00357 
00358     return false;
00359 }
00360 
00362 bool su3d::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
00363 {
00364     GINAC_ASSERT(is_a<indexed>(*self));
00365     GINAC_ASSERT(is_a<indexed>(*other));
00366     GINAC_ASSERT(self->nops() == 4);
00367     GINAC_ASSERT(is_a<su3d>(self->op(0)));
00368 
00369     if (is_exactly_a<su3d>(other->op(0))) {
00370 
00371         // Find the dummy indices of the contraction
00372         exvector self_indices = ex_to<indexed>(*self).get_indices();
00373         exvector other_indices = ex_to<indexed>(*other).get_indices();
00374         exvector all_indices = self_indices;
00375         all_indices.insert(all_indices.end(), other_indices.begin(), other_indices.end());
00376         exvector free_indices, dummy_indices;
00377         find_free_and_dummy(all_indices, free_indices, dummy_indices);
00378 
00379         // d.abc d.abc = 40/3
00380         if (dummy_indices.size() == 3) {
00381             *self = numeric(40, 3);
00382             *other = _ex1;
00383             return true;
00384 
00385         // d.akl d.bkl = 5/3 delta.ab
00386         } else if (dummy_indices.size() == 2) {
00387             exvector a;
00388             std::back_insert_iterator<exvector> ita(a);
00389             ita = set_difference(self_indices.begin(), self_indices.end(), dummy_indices.begin(), dummy_indices.end(), ita, ex_is_less());
00390             ita = set_difference(other_indices.begin(), other_indices.end(), dummy_indices.begin(), dummy_indices.end(), ita, ex_is_less());
00391             GINAC_ASSERT(a.size() == 2);
00392             *self = numeric(5, 3) * delta_tensor(a[0], a[1]);
00393             *other = _ex1;
00394             return true;
00395         }
00396 
00397     } else if (is_exactly_a<su3t>(other->op(0))) {
00398 
00399         // d.abc T.b T.c = 5/6 T.a
00400         if (other+1 != v.end()
00401          && is_exactly_a<su3t>(other[1].op(0))
00402          && ex_to<indexed>(*self).has_dummy_index_for(other[1].op(1))) {
00403 
00404             exvector self_indices = ex_to<indexed>(*self).get_indices();
00405             exvector dummy_indices;
00406             dummy_indices.push_back(other[0].op(1));
00407             dummy_indices.push_back(other[1].op(1));
00408             int sig;
00409             ex a = permute_free_index_to_front(self_indices, dummy_indices, sig);
00410             *self = numeric(5, 6);
00411             other[0] = color_T(a, ex_to<color>(other[0]).get_representation_label());
00412             other[1] = _ex1;
00413             return true;
00414         }
00415     }
00416 
00417     return false;
00418 }
00419 
00421 bool su3f::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
00422 {
00423     GINAC_ASSERT(is_a<indexed>(*self));
00424     GINAC_ASSERT(is_a<indexed>(*other));
00425     GINAC_ASSERT(self->nops() == 4);
00426     GINAC_ASSERT(is_a<su3f>(self->op(0)));
00427 
00428     if (is_exactly_a<su3f>(other->op(0))) { // f*d is handled by su3d class
00429 
00430         // Find the dummy indices of the contraction
00431         exvector dummy_indices;
00432         dummy_indices = ex_to<indexed>(*self).get_dummy_indices(ex_to<indexed>(*other));
00433 
00434         // f.abc f.abc = 24
00435         if (dummy_indices.size() == 3) {
00436             *self = 24;
00437             *other = _ex1;
00438             return true;
00439 
00440         // f.akl f.bkl = 3 delta.ab
00441         } else if (dummy_indices.size() == 2) {
00442             int sign1, sign2;
00443             ex a = permute_free_index_to_front(ex_to<indexed>(*self).get_indices(), dummy_indices, sign1);
00444             ex b = permute_free_index_to_front(ex_to<indexed>(*other).get_indices(), dummy_indices, sign2);
00445             *self = sign1 * sign2 * 3 * delta_tensor(a, b);
00446             *other = _ex1;
00447             return true;
00448         }
00449 
00450     } else if (is_exactly_a<su3t>(other->op(0))) {
00451 
00452         // f.abc T.b T.c = 3/2 I T.a
00453         if (other+1 != v.end()
00454          && is_exactly_a<su3t>(other[1].op(0))
00455          && ex_to<indexed>(*self).has_dummy_index_for(other[1].op(1))) {
00456 
00457             exvector self_indices = ex_to<indexed>(*self).get_indices();
00458             exvector dummy_indices;
00459             dummy_indices.push_back(other[0].op(1));
00460             dummy_indices.push_back(other[1].op(1));
00461             int sig;
00462             ex a = permute_free_index_to_front(self_indices, dummy_indices, sig);
00463             *self = numeric(3, 2) * sig * I;
00464             other[0] = color_T(a, ex_to<color>(other[0]).get_representation_label());
00465             other[1] = _ex1;
00466             return true;
00467         }
00468     }
00469 
00470     return false;
00471 }
00472 
00474 // global functions
00476 
00477 ex color_ONE(unsigned char rl)
00478 {
00479     static ex ONE = (new su3one)->setflag(status_flags::dynallocated);
00480     return color(ONE, rl);
00481 }
00482 
00483 ex color_T(const ex & a, unsigned char rl)
00484 {
00485     static ex t = (new su3t)->setflag(status_flags::dynallocated);
00486 
00487     if (!is_a<idx>(a))
00488         throw(std::invalid_argument("indices of color_T must be of type idx"));
00489     if (!ex_to<idx>(a).get_dim().is_equal(8))
00490         throw(std::invalid_argument("index dimension for color_T must be 8"));
00491 
00492     return color(t, a, rl);
00493 }
00494 
00495 ex color_f(const ex & a, const ex & b, const ex & c)
00496 {
00497     static ex f = (new su3f)->setflag(status_flags::dynallocated);
00498 
00499     if (!is_a<idx>(a) || !is_a<idx>(b) || !is_a<idx>(c))
00500         throw(std::invalid_argument("indices of color_f must be of type idx"));
00501     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))
00502         throw(std::invalid_argument("index dimension for color_f must be 8"));
00503 
00504     return indexed(f, antisymmetric3(), a, b, c);
00505 }
00506 
00507 ex color_d(const ex & a, const ex & b, const ex & c)
00508 {
00509     static ex d = (new su3d)->setflag(status_flags::dynallocated);
00510 
00511     if (!is_a<idx>(a) || !is_a<idx>(b) || !is_a<idx>(c))
00512         throw(std::invalid_argument("indices of color_d must be of type idx"));
00513     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))
00514         throw(std::invalid_argument("index dimension for color_d must be 8"));
00515 
00516     return indexed(d, symmetric3(), a, b, c);
00517 }
00518 
00519 ex color_h(const ex & a, const ex & b, const ex & c)
00520 {
00521     return color_d(a, b, c) + I * color_f(a, b, c);
00522 }
00523 
00526 static bool is_color_tinfo(const return_type_t& ti)
00527 {
00528     return *(ti.tinfo) == typeid(color);
00529 }
00530 
00533 static unsigned char get_representation_label(const return_type_t& ti)
00534 {
00535     return (unsigned char)ti.rl;
00536 }
00537 
00538 ex color_trace(const ex & e, const std::set<unsigned char> & rls)
00539 {
00540     if (is_a<color>(e)) {
00541 
00542         unsigned char rl = ex_to<color>(e).get_representation_label();
00543 
00544         // Are we taking the trace over this object's representation label?
00545         if (rls.find(rl) == rls.end())
00546             return e;
00547 
00548         // Yes, all generators are traceless, except for color_ONE
00549         if (is_a<su3one>(e.op(0)))
00550             return _ex3;
00551         else
00552             return _ex0;
00553 
00554     } else if (is_exactly_a<mul>(e)) {
00555 
00556         // Trace of product: pull out non-color factors
00557         ex prod = _ex1;
00558         for (size_t i=0; i<e.nops(); i++) {
00559             const ex &o = e.op(i);
00560             if (is_color_tinfo(o.return_type_tinfo()))
00561                 prod *= color_trace(o, rls);
00562             else
00563                 prod *= o;
00564         }
00565         return prod;
00566 
00567     } else if (is_exactly_a<ncmul>(e)) {
00568 
00569         unsigned char rl = get_representation_label(e.return_type_tinfo());
00570 
00571         // Are we taking the trace over this string's representation label?
00572         if (rls.find(rl) == rls.end())
00573             return e;
00574 
00575         // Yes, expand product if necessary
00576         ex e_expanded = e.expand();
00577         if (!is_a<ncmul>(e_expanded))
00578             return color_trace(e_expanded, rls);
00579 
00580         size_t num = e.nops();
00581 
00582         if (num == 2) {
00583 
00584             // Tr T_a T_b = 1/2 delta_a_b
00585             return delta_tensor(e.op(0).op(1), e.op(1).op(1)) / 2;
00586 
00587         } else if (num == 3) {
00588 
00589             // Tr T_a T_b T_c = 1/4 h_a_b_c
00590             return color_h(e.op(0).op(1), e.op(1).op(1), e.op(2).op(1)) / 4;
00591 
00592         } else {
00593 
00594             // Traces of 4 or more generators are computed recursively:
00595             // Tr T_a1 .. T_an =
00596             //     1/6 delta_a(n-1)_an Tr T_a1 .. T_a(n-2)
00597             //   + 1/2 h_a(n-1)_an_k Tr T_a1 .. T_a(n-2) T_k
00598             const ex &last_index = e.op(num - 1).op(1);
00599             const ex &next_to_last_index = e.op(num - 2).op(1);
00600             idx summation_index((new symbol)->setflag(status_flags::dynallocated), 8);
00601 
00602             exvector v1;
00603             v1.reserve(num - 2);
00604             for (size_t i=0; i<num-2; i++)
00605                 v1.push_back(e.op(i));
00606 
00607             exvector v2 = v1;
00608             v2.push_back(color_T(summation_index, rl));
00609 
00610             return delta_tensor(next_to_last_index, last_index) * color_trace(ncmul(v1), rl) / 6
00611                    + color_h(next_to_last_index, last_index, summation_index) * color_trace(ncmul(v2), rl) / 2;
00612         }
00613 
00614     } else if (e.nops() > 0) {
00615 
00616         // Trace maps to all other container classes (this includes sums)
00617         pointer_to_map_function_1arg<const std::set<unsigned char> &> fcn(color_trace, rls);
00618         return e.map(fcn);
00619 
00620     } else
00621         return _ex0;
00622 }
00623 
00624 ex color_trace(const ex & e, const lst & rll)
00625 {
00626     // Convert list to set
00627     std::set<unsigned char> rls;
00628     for (lst::const_iterator i = rll.begin(); i != rll.end(); ++i) {
00629         if (i->info(info_flags::nonnegint))
00630             rls.insert(ex_to<numeric>(*i).to_int());
00631     }
00632 
00633     return color_trace(e, rls);
00634 }
00635 
00636 ex color_trace(const ex & e, unsigned char rl)
00637 {
00638     // Convert label to set
00639     std::set<unsigned char> rls;
00640     rls.insert(rl);
00641 
00642     return color_trace(e, rls);
00643 }
00644 
00645 } // namespace GiNaC

This page is part of the GiNaC developer's reference. It was generated automatically by doxygen. For an introduction, see the tutorial.