78 clifford::
clifford() : representation_label(0), metric(0), commutator_sign(-1)
96 clifford::
clifford(const
ex & b,
unsigned char rl) : inherited(b), representation_label(rl), metric(0), commutator_sign(-1)
104 clifford::clifford(
const ex & b,
const ex & mu,
const ex & metr,
unsigned char rl,
int comm_sign) : inherited(b, mu), representation_label(rl), metric(metr), commutator_sign(comm_sign)
128 inherited::read_archive(
n, sym_lst);
130 n.find_unsigned(
"label", rl);
132 n.find_ex(
"metric",
metric, sym_lst);
133 n.find_unsigned(
"commutator_sign+1", rl);
139 inherited::archive(
n);
156 if (is_a<indexed>(
metric)) {
157 if (symmetrised && !(ex_to<symmetry>(ex_to<indexed>(
metric).
get_symmetry()).has_symmetry())) {
180 if (is_a<clifford>(other))
185 if (is_a<indexed>(metr))
189 return (indices.size() == 2)
216 return inherited::let_op(i);
222 if(is_a<clifford>(subsed)) {
223 ex prevmetric = ex_to<clifford>(subsed).
metric;
227 c.metric = newmetric;
244 return inherited::compare_same_type(other);
257 return !is_a<diracgamma5>(seq0) && !is_a<diracgammaL>(seq0) &&
258 !is_a<diracgammaR>(seq0) && !is_a<cliffordunit>(seq0) &&
259 !is_a<diracone>(seq0);
270 this->print_dispatch<inherited>(
c, level);
291 c.s <<
"\\hspace{-1.0ex}/}";
294 this->print_dispatch<inherited>(
c, level);
300 c.s << std::string(level,
' ') << class_name() <<
" @" <<
this 301 << std::hex <<
", hash=0x" <<
hashvalue <<
", flags=0x" <<
flags << std::dec
302 <<
", " <<
seq.size()-1 <<
" indices" 303 <<
", symmetry=" <<
symtree << std::endl;
305 seq[0].print(
c, level +
c.delta_indent);
320 DEFAULT_PRINT_LATEX(diracgammaL, "gammaL
", "{\\gamma_L}
") 321 DEFAULT_PRINT_LATEX(diracgammaR, "gammaR
", "{\\gamma_R}
") 324 static void base_and_index(const ex & c, ex & b, ex & i) 326 GINAC_ASSERT(is_a<clifford>(c)); 327 GINAC_ASSERT(c.nops() == 2+1); 329 if (is_a<cliffordunit>(c.op(0))) { // proper dirac gamma object or clifford unit 332 } else if (is_a<diracgamma5>(c.op(0)) || is_a<diracgammaL>(c.op(0)) || is_a<diracgammaR>(c.op(0))) { // gamma5/L/R 335 } else { // slash object, generate new dummy index 336 varidx ix(dynallocate<symbol>(), ex_to<idx>(c.op(1)).get_dim()); 337 b = indexed(c.op(0), ix.toggle_variance()); 343 struct is_not_a_clifford { 344 bool operator()(const ex & e) 346 return !is_a<clifford>(e); 351 bool diracgamma::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const 353 GINAC_ASSERT(is_a<clifford>(*self)); 354 GINAC_ASSERT(is_a<indexed>(*other)); 355 GINAC_ASSERT(is_a<diracgamma>(self->op(0))); 356 unsigned char rl = ex_to<clifford>(*self).get_representation_label(); 358 ex dim = ex_to<idx>(self->op(1)).get_dim(); 359 if (other->nops() > 1) 360 dim = minimal_dim(dim, ex_to<idx>(other->op(1)).get_dim()); 362 if (is_a<clifford>(*other)) { 364 // Contraction only makes sense if the representation labels are equal 365 if (ex_to<clifford>(*other).get_representation_label() != rl) 368 size_t num = other - self; 370 // gamma~mu gamma.mu = dim ONE 373 *other = dirac_ONE(rl); 376 // gamma~mu gamma~alpha gamma.mu = (2-dim) gamma~alpha 378 && is_a<clifford>(self[1])) { 383 // gamma~mu gamma~alpha gamma~beta gamma.mu = 4 g~alpha~beta + (dim-4) gamam~alpha gamma~beta 385 && is_a<clifford>(self[1]) 386 && is_a<clifford>(self[2])) { 388 base_and_index(self[1], b1, i1); 389 base_and_index(self[2], b2, i2); 390 *self = 4 * lorentz_g(i1, i2) * b1 * b2 * dirac_ONE(rl) + (dim - 4) * self[1] * self[2]; 396 // 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 398 && is_a<clifford>(self[1]) 399 && is_a<clifford>(self[2]) 400 && is_a<clifford>(self[3])) { 401 *self = -2 * self[3] * self[2] * self[1] - (dim - 4) * self[1] * self[2] * self[3]; 408 // gamma~mu Sodd gamma.mu = -2 Sodd_R 409 // (Chisholm identity in 4 dimensions) 410 } else if (!((other - self) & 1) && dim.is_equal(4)) { 411 if (std::find_if(self + 1, other, is_not_a_clifford()) != other) 414 *self = ncmul(exvector(std::reverse_iterator<exvector::const_iterator>(other), std::reverse_iterator<exvector::const_iterator>(self + 1))); 415 std::fill(self + 1, other, _ex1); 419 // gamma~mu Sodd gamma~alpha gamma.mu = 2 gamma~alpha Sodd + 2 Sodd_R gamma~alpha 420 // (commutate contracted indices towards each other, then use 421 // Chisholm identity in 4 dimensions) 422 } else if (((other - self) & 1) && dim.is_equal(4)) { 423 if (std::find_if(self + 1, other, is_not_a_clifford()) != other) 426 auto next_to_last = other - 1; 427 ex S = ncmul(exvector(self + 1, next_to_last)); 428 ex SR = ncmul(exvector(std::reverse_iterator<exvector::const_iterator>(next_to_last), std::reverse_iterator<exvector::const_iterator>(self + 1))); 430 *self = (*next_to_last) * S + SR * (*next_to_last); 431 std::fill(self + 1, other, _ex1); 435 // gamma~mu S gamma~alpha gamma.mu = 2 gamma~alpha S - gamma~mu S gamma.mu gamma~alpha 436 // (commutate contracted indices towards each other, simplify_indexed() 437 // will re-expand and re-run the simplification) 439 if (std::find_if(self + 1, other, is_not_a_clifford()) != other) 442 auto next_to_last = other - 1; 443 ex S = ncmul(exvector(self + 1, next_to_last)); 445 *self = 2 * (*next_to_last) * S - (*self) * S * (*other) * (*next_to_last); 446 std::fill(self + 1, other + 1, _ex1); 450 } else if (is_a<symbol>(other->op(0)) && other->nops() == 2) { 452 // x.mu gamma~mu -> x-slash 453 *self = dirac_slash(other->op(0), dim, rl); 462 bool cliffordunit::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const 464 GINAC_ASSERT(is_a<clifford>(*self)); 465 GINAC_ASSERT(is_a<indexed>(*other)); 466 GINAC_ASSERT(is_a<cliffordunit>(self->op(0))); 467 clifford unit = ex_to<clifford>(*self); 468 unsigned char rl = unit.get_representation_label(); 470 if (is_a<clifford>(*other)) { 471 // Contraction only makes sense if the representation labels are equal 472 // and the metrics are the same 473 if ((ex_to<clifford>(*other).get_representation_label() != rl) 474 && unit.same_metric(*other)) 477 auto before_other = other - 1; 479 ex mu_toggle = other->op(1); 480 ex alpha = before_other->op(1); 482 // e~mu e.mu = Tr ONE 483 if (other - self == 1) { 484 *self = unit.get_metric(mu, mu_toggle, true); 485 *other = dirac_ONE(rl); 488 } else if (other - self == 2) { 489 if (is_a<clifford>(*before_other) && ex_to<clifford>(*before_other).get_representation_label() == rl) { 490 // e~mu e~alpha e.mu = 2*e~mu B(alpha, mu.toggle_variance())-Tr(B) e~alpha 491 *self = 2 * (*self) * unit.get_metric(alpha, mu_toggle, true) - unit.get_metric(mu, mu_toggle, true) * (*before_other); 492 *before_other = _ex1; 497 // e~mu S e.mu = Tr S ONE 498 *self = unit.get_metric(mu, mu_toggle, true); 499 *other = dirac_ONE(rl); 503 // e~mu S e~alpha e.mu = 2 e~mu S B(alpha, mu.toggle_variance()) - e~mu S e.mu e~alpha 504 // (commutate contracted indices towards each other, simplify_indexed() 505 // will re-expand and re-run the simplification) 506 if (std::find_if(self + 1, other, is_not_a_clifford()) != other) { 510 ex S = ncmul(exvector(self + 1, before_other)); 512 if (is_a<clifford>(*before_other) && ex_to<clifford>(*before_other).get_representation_label() == rl) { 513 *self = 2 * (*self) * S * unit.get_metric(alpha, mu_toggle, true) - (*self) * S * (*other) * (*before_other); 516 *self = (*self) * S * (*other) * (*before_other); 519 std::fill(self + 1, other + 1, _ex1); 529 ex clifford::eval_ncmul(const exvector & v) const 534 // Remove superfluous ONEs 535 for (auto & it : v) { 536 if (!is_a<clifford>(it) || !is_a<diracone>(it.op(0))) 540 bool something_changed = false; 543 // Anticommutate gamma5/L/R's to the front 545 auto first = s.begin(), next_to_last = s.end() - 2; 547 auto it = next_to_last; 550 if (is_a<clifford>(*it) && is_a<clifford>(*it2)) { 551 ex e1 = it->op(0), e2 = it2->op(0); 553 if (is_a<diracgamma5>(e2)) { 555 if (is_a<diracgammaL>(e1) || is_a<diracgammaR>(e1)) { 557 // gammaL/R gamma5 -> gamma5 gammaL/R 559 something_changed = true; 561 } else if (!is_a<diracgamma5>(e1)) { 563 // gamma5 gamma5 -> gamma5 gamma5 (do nothing) 564 // x gamma5 -> -gamma5 x 567 something_changed = true; 570 } else if (is_a<diracgammaL>(e2)) { 572 if (is_a<diracgammaR>(e1)) { 574 // gammaR gammaL -> 0 577 } else if (!is_a<diracgammaL>(e1) && !is_a<diracgamma5>(e1)) { 579 // gammaL gammaL -> gammaL gammaL (do nothing) 580 // gamma5 gammaL -> gamma5 gammaL (do nothing) 581 // x gammaL -> gammaR x 583 *it = clifford(diracgammaR(), ex_to<clifford>(*it).get_representation_label()); 584 something_changed = true; 587 } else if (is_a<diracgammaR>(e2)) { 589 if (is_a<diracgammaL>(e1)) { 591 // gammaL gammaR -> 0 594 } else if (!is_a<diracgammaR>(e1) && !is_a<diracgamma5>(e1)) { 596 // gammaR gammaR -> gammaR gammaR (do nothing) 597 // gamma5 gammaR -> gamma5 gammaR (do nothing) 598 // x gammaR -> gammaL x 600 *it = clifford(diracgammaL(), ex_to<clifford>(*it).get_representation_label()); 601 something_changed = true; 609 if (next_to_last == first) 615 // Remove equal adjacent gammas 617 exvector::iterator it, itend = s.end() - 1; 618 for (it = s.begin(); it != itend; ++it) { 621 if (!is_a<clifford>(a) || !is_a<clifford>(b)) 624 const ex & ag = a.op(0); 625 const ex & bg = b.op(0); 626 bool a_is_cliffordunit = is_a<cliffordunit>(ag); 627 bool b_is_cliffordunit = is_a<cliffordunit>(bg); 629 if (a_is_cliffordunit && b_is_cliffordunit && ex_to<clifford>(a).same_metric(b) 630 && (ex_to<clifford>(a).get_commutator_sign() == -1)) { 631 // This is done only for Clifford algebras 633 const ex & ia = a.op(1); 634 const ex & ib = b.op(1); 635 if (ia.is_equal(ib)) { // gamma~alpha gamma~alpha -> g~alpha~alpha 636 a = ex_to<clifford>(a).get_metric(ia, ib, true); 637 b = dirac_ONE(representation_label); 638 something_changed = true; 641 } else if ((is_a<diracgamma5>(ag) && is_a<diracgamma5>(bg))) { 643 // Remove squares of gamma5 644 a = dirac_ONE(representation_label); 645 b = dirac_ONE(representation_label); 646 something_changed = true; 648 } else if ((is_a<diracgammaL>(ag) && is_a<diracgammaL>(bg)) 649 || (is_a<diracgammaR>(ag) && is_a<diracgammaR>(bg))) { 651 // Remove squares of gammaL/R 652 b = dirac_ONE(representation_label); 653 something_changed = true; 655 } else if (is_a<diracgammaL>(ag) && is_a<diracgammaR>(bg)) { 657 // gammaL and gammaR are orthogonal 660 } else if (is_a<diracgamma5>(ag) && is_a<diracgammaL>(bg)) { 662 // gamma5 gammaL -> -gammaL 663 a = dirac_ONE(representation_label); 665 something_changed = true; 667 } else if (is_a<diracgamma5>(ag) && is_a<diracgammaR>(bg)) { 669 // gamma5 gammaR -> gammaR 670 a = dirac_ONE(representation_label); 671 something_changed = true; 673 } else if (!a_is_cliffordunit && !b_is_cliffordunit && ag.is_equal(bg)) { 676 varidx ix(dynallocate<symbol>(), ex_to<idx>(a.op(1)).minimal_dim(ex_to<idx>(b.op(1)))); 678 a = indexed(ag, ix) * indexed(ag, ix.toggle_variance()); 679 b = dirac_ONE(representation_label); 680 something_changed = true; 686 return dirac_ONE(representation_label) * sign; 687 if (something_changed) 688 return reeval_ncmul(s) * sign; 690 return hold_ncmul(s) * sign; 693 ex clifford::thiscontainer(const exvector & v) const 695 return clifford(representation_label, metric, commutator_sign, v); 698 ex clifford::thiscontainer(exvector && v) const 700 return clifford(representation_label, metric, commutator_sign, std::move(v)); 703 ex diracgamma5::conjugate() const 705 return _ex_1 * (*this); 708 ex diracgammaL::conjugate() const 710 return dynallocate<diracgammaR>(); 713 ex diracgammaR::conjugate() const 715 return dynallocate<diracgammaL>(); 722 ex dirac_ONE(unsigned char rl) 724 static ex ONE = dynallocate<diracone>(); 725 return clifford(ONE, rl); 728 static unsigned get_dim_uint(const ex& e) 731 throw std::invalid_argument("get_dim_uint: argument is not an index
"); 732 ex dim = ex_to<idx>(e).get_dim(); 733 if (!dim.info(info_flags::posint)) 734 throw std::invalid_argument("get_dim_uint: dimension of index should be a positive integer
"); 735 unsigned d = ex_to<numeric>(dim).to_int(); 739 ex clifford_unit(const ex & mu, const ex & metr, unsigned char rl) 741 ex unit = dynallocate<cliffordunit>(); 746 exvector indices = metr.get_free_indices(); 748 if (indices.size() == 2) { 749 return clifford(unit, mu, metr, rl); 750 } else if (is_a<matrix>(metr)) { 751 matrix M = ex_to<matrix>(metr); 752 unsigned n = M.rows(); 753 bool symmetric = true; 755 //static idx xi(dynallocate<symbol>(), n), 756 // chi(dynallocate<symbol>(), n); 757 idx xi(dynallocate<symbol>(), n), 758 chi(dynallocate<symbol>(), n); 759 if ((n == M.cols()) && (n == get_dim_uint(mu))) { 760 for (unsigned i = 0; i < n; i++) { 761 for (unsigned j = i+1; j < n; j++) { 762 if (!M(i, j).is_equal(M(j, i))) { 767 return clifford(unit, mu, indexed(metr, symmetric?symmetric2():not_symmetric(), xi, chi), rl); 769 throw(std::invalid_argument("clifford_unit(): metric for Clifford unit must be a square
matrix with the same dimensions as index
")); 771 } else if (indices.size() == 0) { // a tensor or other expression without indices 772 //static varidx xi(dynallocate<symbol>(), ex_to<idx>(mu).get_dim()), 773 // chi(dynallocate<symbol>(), ex_to<idx>(mu).get_dim()); 774 varidx xi(dynallocate<symbol>(), ex_to<idx>(mu).get_dim()), 775 chi(dynallocate<symbol>(), ex_to<idx>(mu).get_dim()); 776 return clifford(unit, mu, indexed(metr, xi, chi), rl); 778 throw(std::invalid_argument("clifford_unit(): metric for Clifford unit must be of type
tensor,
matrix or an expression with two free indices
")); 781 ex dirac_gamma(const ex & mu, unsigned char rl) 783 static ex gamma = dynallocate<diracgamma>(); 785 if (!is_a<varidx>(mu)) 786 throw(std::invalid_argument("dirac_gamma(): index of Dirac gamma must be of type
varidx")); 788 static varidx xi(dynallocate<symbol>(), ex_to<varidx>(mu).get_dim()), 789 chi(dynallocate<symbol>(), ex_to<varidx>(mu).get_dim()); 790 return clifford(gamma, mu, indexed(dynallocate<minkmetric>(), symmetric2(), xi, chi), rl); 793 ex dirac_gamma5(unsigned char rl) 795 static ex gamma5 = dynallocate<diracgamma5>(); 796 return clifford(gamma5, rl); 799 ex dirac_gammaL(unsigned char rl) 801 static ex gammaL = dynallocate<diracgammaL>(); 802 return clifford(gammaL, rl); 805 ex dirac_gammaR(unsigned char rl) 807 static ex gammaR = dynallocate<diracgammaR>(); 808 return clifford(gammaR, rl); 811 ex dirac_slash(const ex & e, const ex & dim, unsigned char rl) 813 // Slashed vectors are actually stored as a clifford object with the 814 // vector as its base expression and a (dummy) index that just serves 815 // for storing the space dimensionality 817 static varidx xi(dynallocate<symbol>(), dim), 818 chi(dynallocate<symbol>(), dim); 819 return clifford(e, varidx(0, dim), indexed(dynallocate<minkmetric>(), symmetric2(), xi, chi), rl); 824 static unsigned char get_representation_label(const return_type_t& ti) 826 return (unsigned char)ti.rl; 831 static ex trace_string(exvector::const_iterator ix, size_t num) 833 // Tr gamma.mu gamma.nu = 4 g.mu.nu 835 return lorentz_g(ix[0], ix[1]); 837 // Tr gamma.mu gamma.nu gamma.rho gamma.sig = 4 (g.mu.nu g.rho.sig + g.nu.rho g.mu.sig - g.mu.rho g.nu.sig ) 839 return lorentz_g(ix[0], ix[1]) * lorentz_g(ix[2], ix[3]) 840 + lorentz_g(ix[1], ix[2]) * lorentz_g(ix[0], ix[3]) 841 - lorentz_g(ix[0], ix[2]) * lorentz_g(ix[1], ix[3]); 843 // Traces of 6 or more gammas are computed recursively: 844 // Tr gamma.mu1 gamma.mu2 ... gamma.mun = 845 // + g.mu1.mu2 * Tr gamma.mu3 ... gamma.mun 846 // - g.mu1.mu3 * Tr gamma.mu2 gamma.mu4 ... gamma.mun 847 // + g.mu1.mu4 * Tr gamma.mu3 gamma.mu3 gamma.mu5 ... gamma.mun 849 // + g.mu1.mun * Tr gamma.mu2 ... gamma.mu(n-1) 853 for (size_t i=1; i<num; i++) { 854 for (size_t n=1, j=0; n<num; n++) { 859 result += sign * lorentz_g(ix[0], ix[i]) * trace_string(v.begin(), num-2); 865 ex dirac_trace(const ex & e, const std::set<unsigned char> & rls, const ex & trONE) 867 if (is_a<clifford>(e)) { 869 unsigned char rl = ex_to<clifford>(e).get_representation_label(); 871 // Are we taking the trace over this object's representation label? 872 if (rls.find(rl) == rls.end()) 875 // Yes, all elements are traceless, except for dirac_ONE and dirac_L/R 876 const ex & g = e.op(0); 877 if (is_a<diracone>(g)) 879 else if (is_a<diracgammaL>(g) || is_a<diracgammaR>(g)) 884 } else if (is_exactly_a<mul>(e)) { 886 // Trace of product: pull out non-clifford factors 888 for (size_t i=0; i<e.nops(); i++) { 889 const ex &o = e.op(i); 890 if (is_clifford_tinfo(o.return_type_tinfo())) 891 prod *= dirac_trace(o, rls, trONE); 897 } else if (is_exactly_a<ncmul>(e)) { 899 unsigned char rl = get_representation_label(e.return_type_tinfo()); 901 // Are we taking the trace over this string's representation label? 902 if (rls.find(rl) == rls.end()) 905 // Substitute gammaL/R and expand product, if necessary 906 ex e_expanded = e.subs(lst{ 907 dirac_gammaL(rl) == (dirac_ONE(rl)-dirac_gamma5(rl))/2, 908 dirac_gammaR(rl) == (dirac_ONE(rl)+dirac_gamma5(rl))/2 909 }, subs_options::no_pattern).expand(); 910 if (!is_a<ncmul>(e_expanded)) 911 return dirac_trace(e_expanded, rls, trONE); 913 // gamma5 gets moved to the front so this check is enough 914 bool has_gamma5 = is_a<diracgamma5>(e.op(0).op(0)); 915 size_t num = e.nops(); 919 // Trace of gamma5 * odd number of gammas and trace of 920 // gamma5 * gamma.mu * gamma.nu are zero 921 if ((num & 1) == 0 || num == 3) 924 // Tr gamma5 gamma.mu gamma.nu gamma.rho gamma.sigma = 4I * epsilon(mu, nu, rho, sigma) 925 // (the epsilon is always 4-dimensional) 927 ex b1, i1, b2, i2, b3, i3, b4, i4; 928 base_and_index(e.op(1), b1, i1); 929 base_and_index(e.op(2), b2, i2); 930 base_and_index(e.op(3), b3, i3); 931 base_and_index(e.op(4), b4, i4); 932 return trONE * I * (lorentz_eps(ex_to<idx>(i1).replace_dim(_ex4), ex_to<idx>(i2).replace_dim(_ex4), ex_to<idx>(i3).replace_dim(_ex4), ex_to<idx>(i4).replace_dim(_ex4)) * b1 * b2 * b3 * b4).simplify_indexed(); 936 // I/4! * epsilon0123.mu1.mu2.mu3.mu4 * Tr gamma.mu1 gamma.mu2 gamma.mu3 gamma.mu4 S_2k 937 // (the epsilon is always 4-dimensional) 938 exvector ix(num-1), bv(num-1); 939 for (size_t i=1; i<num; i++) 940 base_and_index(e.op(i), bv[i-1], ix[i-1]); 942 int *iv = new int[num]; 944 for (size_t i=0; i<num-3; i++) { 946 for (size_t j=i+1; j<num-2; j++) { 948 for (size_t k=j+1; k<num-1; k++) { 950 for (size_t l=k+1; l<num; l++) { 952 iv[0] = i; iv[1] = j; iv[2] = k; iv[3] = l; 955 for (size_t n=0, t=4; n<num; n++) { 956 if (n == i || n == j || n == k || n == l) 961 int sign = permutation_sign(iv, iv + num); 962 result += sign * lorentz_eps(ex_to<idx>(idx1).replace_dim(_ex4), ex_to<idx>(idx2).replace_dim(_ex4), ex_to<idx>(idx3).replace_dim(_ex4), ex_to<idx>(idx4).replace_dim(_ex4)) 963 * trace_string(v.begin(), num - 4); 969 return trONE * I * result * mul(bv); 971 } else { // no gamma5 973 // Trace of odd number of gammas is zero 977 // Tr gamma.mu gamma.nu = 4 g.mu.nu 980 base_and_index(e.op(0), b1, i1); 981 base_and_index(e.op(1), b2, i2); 982 return trONE * (lorentz_g(i1, i2) * b1 * b2).simplify_indexed(); 985 exvector iv(num), bv(num); 986 for (size_t i=0; i<num; i++) 987 base_and_index(e.op(i), bv[i], iv[i]); 989 return trONE * (trace_string(iv.begin(), num) * mul(bv)).simplify_indexed(); 992 } else if (e.nops() > 0) { 994 // Trace maps to all other container classes (this includes sums) 995 pointer_to_map_function_2args<const std::set<unsigned char> &, const ex &> fcn(dirac_trace, rls, trONE); 1002 ex dirac_trace(const ex & e, const lst & rll, const ex & trONE) 1004 // Convert list to set 1005 std::set<unsigned char> rls; 1006 for (const auto & i : rll) { 1007 if (i.info(info_flags::nonnegint)) 1008 rls.insert(ex_to<numeric>(i).to_int()); 1011 return dirac_trace(e, rls, trONE); 1014 ex dirac_trace(const ex & e, unsigned char rl, const ex & trONE) 1016 // Convert label to set 1017 std::set<unsigned char> rls; 1020 return dirac_trace(e, rls, trONE); 1024 ex canonicalize_clifford(const ex & e_) 1026 pointer_to_map_function fcn(canonicalize_clifford); 1028 if (is_a<matrix>(e_) // || is_a<pseries>(e) || is_a<integral>(e) 1029 || e_.info(info_flags::list)) { 1032 ex e=simplify_indexed(e_); 1033 // Scan for any ncmul objects 1035 ex aux = e.to_rational(srl); 1036 for (auto & i : srl) { 1041 if (is_exactly_a<ncmul>(rhs) 1042 && rhs.return_type() == return_types::noncommutative 1043 && is_clifford_tinfo(rhs.return_type_tinfo())) { 1045 // Expand product, if necessary 1046 ex rhs_expanded = rhs.expand(); 1047 if (!is_a<ncmul>(rhs_expanded)) { 1048 i.second = canonicalize_clifford(rhs_expanded); 1051 } else if (!is_a<clifford>(rhs.op(0))) 1055 v.reserve(rhs.nops()); 1056 for (size_t j=0; j<rhs.nops(); j++) 1057 v.push_back(rhs.op(j)); 1059 // Stupid recursive bubble sort because we only want to swap adjacent gammas 1060 auto it = v.begin(), next_to_last = v.end() - 1; 1061 if (is_a<diracgamma5>(it->op(0)) || is_a<diracgammaL>(it->op(0)) || is_a<diracgammaR>(it->op(0))) 1064 while (it != next_to_last) { 1065 if (it[0].compare(it[1]) > 0) { 1067 ex save0 = it[0], save1 = it[1]; 1069 base_and_index(it[0], b1, i1); 1070 base_and_index(it[1], b2, i2); 1071 // for Clifford algebras (commutator_sign == -1) metric should be symmetrised 1072 it[0] = (ex_to<clifford>(save0).get_metric(i1, i2, ex_to<clifford>(save0).get_commutator_sign() == -1) * b1 * b2).simplify_indexed(); 1073 it[1] = v.size() ? _ex2 * dirac_ONE(ex_to<clifford>(save0).get_representation_label()) : _ex2; 1077 sum += ex_to<clifford>(save0).get_commutator_sign() * ncmul(std::move(v)); 1078 i.second = canonicalize_clifford(sum); 1086 return aux.subs(srl, subs_options::no_pattern).simplify_indexed(); 1090 ex clifford_star_bar(const ex & e, bool do_bar, unsigned options) 1092 pointer_to_map_function_2args<bool, unsigned> fcn(clifford_star_bar, do_bar, options | 1); 1094 // is a child, no need to expand 1095 ex e1= (options & 1 ? e : e.expand()); 1097 if (is_a<ncmul>(e1) ) { // reversing order of clifford units 1099 ev.reserve(e1.nops()); 1100 cv.reserve(e1.nops()); 1101 // separate clifford and non-clifford entries 1102 for (int i= 0; i < e1.nops(); ++i) { 1103 if (is_a<clifford>(e1.op(i)) && is_a<cliffordunit>(e1.op(i).op(0))) 1104 cv.push_back(e1.op(i)); 1106 ev.push_back(e1.op(i)); 1108 for (auto i=cv.rbegin(); i!=cv.rend(); ++i) { // reverse order of Clifford units 1109 ev.push_back(i->conjugate()); 1111 // For clifford_bar an odd number of clifford units reverts the sign 1112 if (do_bar && (cv.size() % 2 == 1)) 1113 return -dynallocate<ncmul>(std::move(ev)); 1115 return dynallocate<ncmul>(std::move(ev)); 1116 } else if (is_a<clifford>(e1) && is_a<cliffordunit>(e1.op(0))) { 1121 } else if (is_a<power>(e1)) { 1122 // apply the procedure to the base of a power 1123 return pow(clifford_star_bar(e1.op(0), do_bar, 0), e1.op(1)); 1124 } else if (is_a<add>(e1) || is_a<mul>(e1) || e.info(info_flags::list)) { 1125 // recurse into subexpressions 1127 } else // nothing meaningful can be done 1131 ex clifford_prime(const ex & e) 1133 pointer_to_map_function fcn(clifford_prime); 1134 if (is_a<clifford>(e) && is_a<cliffordunit>(e.op(0))) { 1136 } else if (is_a<add>(e) || is_a<ncmul>(e) || is_a<mul>(e) //|| is_a<pseries>(e) || is_a<integral>(e) 1137 || is_a<matrix>(e) || e.info(info_flags::list)) { 1139 } else if (is_a<power>(e)) { 1140 return pow(clifford_prime(e.op(0)), e.op(1)); 1145 ex remove_dirac_ONE(const ex & e, unsigned char rl, unsigned options) 1147 pointer_to_map_function_2args<unsigned char, unsigned> fcn(remove_dirac_ONE, rl, options | 1); 1148 bool need_reevaluation = false; 1150 if (! (options & 1) ) { // is not a child 1152 e1 = expand_dummy_sum(e, true); 1153 e1 = canonicalize_clifford(e1); 1156 if (is_a<clifford>(e1) && ex_to<clifford>(e1).get_representation_label() >= rl) { 1157 if (is_a<diracone>(e1.op(0))) 1160 throw(std::invalid_argument("remove_dirac_ONE(): expression is a non-scalar Clifford number!
")); 1161 } else if (is_a<add>(e1) || is_a<ncmul>(e1) || is_a<mul>(e1) 1162 || is_a<matrix>(e1) || e1.info(info_flags::list)) { 1163 if (options & 3) // is a child or was already expanded 1168 } catch (std::exception &p) { 1169 need_reevaluation = true; 1171 } else if (is_a<power>(e1)) { 1172 if (options & 3) // is a child or was already expanded 1173 return pow(remove_dirac_ONE(e1.op(0), rl, options | 1), e1.op(1)); 1176 return pow(remove_dirac_ONE(e1.op(0), rl, options | 1), e1.op(1)); 1177 } catch (std::exception &p) { 1178 need_reevaluation = true; 1181 if (need_reevaluation) 1182 return remove_dirac_ONE(e, rl, options | 2); 1186 int clifford_max_label(const ex & e, bool ignore_ONE) 1188 if (is_a<clifford>(e)) 1189 if (ignore_ONE && is_a<diracone>(e.op(0))) 1192 return ex_to<clifford>(e).get_representation_label(); 1195 for (size_t i=0; i < e.nops(); i++) 1196 rl = (rl > clifford_max_label(e.op(i), ignore_ONE)) ? rl : clifford_max_label(e.op(i), ignore_ONE); 1201 ex clifford_norm(const ex & e) 1203 return sqrt(remove_dirac_ONE(e * clifford_bar(e))); 1206 ex clifford_inverse(const ex & e) 1208 ex norm = clifford_norm(e); 1209 if (!norm.is_zero()) 1210 return clifford_bar(e) / pow(norm, 2); 1215 ex lst_to_clifford(const ex & v, const ex & mu, const ex & metr, unsigned char rl) 1217 if (!ex_to<idx>(mu).is_dim_numeric()) 1219 ex e = clifford_unit(mu, metr, rl); 1220 return lst_to_clifford(v, e); 1223 ex lst_to_clifford(const ex & v, const ex & e) { 1226 if (is_a<clifford>(e)) { 1229 = is_a<varidx>(mu) ? ex_to<varidx>(mu).toggle_variance() : mu; 1230 unsigned dim = get_dim_uint(mu); 1232 if (is_a<matrix>(v)) { 1233 if (ex_to<matrix>(v).cols() > ex_to<matrix>(v).rows()) { 1234 min = ex_to<matrix>(v).rows(); 1235 max = ex_to<matrix>(v).cols(); 1237 min = ex_to<matrix>(v).cols(); 1238 max = ex_to<matrix>(v).rows(); 1242 return indexed(v, mu_toggle) * e; 1243 else if (max - dim == 1) { 1244 if (ex_to<matrix>(v).cols() > ex_to<matrix>(v).rows()) 1245 return v.op(0) * dirac_ONE(ex_to<clifford>(e).get_representation_label()) + indexed(sub_matrix(ex_to<matrix>(v), 0, 1, 1, dim), mu_toggle) * e; 1247 return v.op(0) * dirac_ONE(ex_to<clifford>(e).get_representation_label()) + indexed(sub_matrix(ex_to<matrix>(v), 1, dim, 0, 1), mu_toggle) * e; 1251 throw(std::invalid_argument("lst_to_clifford(): first argument should be a vector (nx1 or 1xn
matrix)
")); 1252 } else if (v.info(info_flags::list)) { 1253 if (dim == ex_to<lst>(v).nops()) 1254 return indexed(matrix(dim, 1, ex_to<lst>(v)), mu_toggle) * e; 1255 else if (ex_to<lst>(v).nops() - dim == 1) 1256 return v.op(0) * dirac_ONE(ex_to<clifford>(e).get_representation_label()) + indexed(sub_matrix(matrix(dim+1, 1, ex_to<lst>(v)), 1, dim, 0, 1), mu_toggle) * e; 1260 throw(std::invalid_argument("lst_to_clifford(): cannot construct from anything but list or vector
")); 1262 throw(std::invalid_argument("lst_to_clifford(): the second argument should be a Clifford unit
")); 1267 static ex get_clifford_comp(const ex & e, const ex & c, bool root=true) 1269 // make expansion on the top-level call only 1270 ex e1=(root? e.expand() : e); 1272 pointer_to_map_function_2args<const ex &, bool> fcn(get_clifford_comp, c, false); 1273 int ival = ex_to<numeric>(ex_to<idx>(c.op(1)).get_value()).to_int(); 1274 int rl=ex_to<clifford>(c).get_representation_label(); 1276 if ( (is_a<add>(e1) || e1.info(info_flags::list) || is_a<matrix>(e1))) { 1278 } else if (is_a<ncmul>(e1) || is_a<mul>(e1)) { 1279 // searches are done within products only 1280 exvector ev, all_dummy=get_all_dummy_indices(e1); 1281 bool found=false, same_value_found=false; 1283 ev.reserve(e1.nops()); 1284 for (int i=0; i < e1.nops();++i) { 1285 // look for a Clifford unit with the same metric and representation label, 1286 // if found remember its index 1287 if (is_a<clifford>(e1.op(i)) && ex_to<clifford>(e1.op(i)).get_representation_label() == rl 1288 && is_a<cliffordunit>(e1.op(i).op(0)) && ex_to<clifford>(e1.op(i)).same_metric(c)) { // same Clifford unit 1290 throw(std::invalid_argument("get_clifford_comp(): expression is a Clifford multi-vector
")); 1292 if (ex_to<idx>(e1.op(i).op(1)).is_numeric() && 1293 (ival == ex_to<numeric>(ex_to<idx>(e1.op(i).op(1)).get_value()).to_int())) { 1294 same_value_found = true; // desired index value is found 1295 } else if ((std::find(all_dummy.begin(), all_dummy.end(), e1.op(i).op(1)) != all_dummy.end()) 1296 || (is_a<varidx>(e1.op(i).op(1)) 1297 && std::find(all_dummy.begin(), all_dummy.end(), 1298 ex_to<varidx>(e1.op(i).op(1)).toggle_variance()) != all_dummy.end())) { 1299 dummy_ind=(e1.op(i).op(1)); // suitable dummy index found 1301 ev.push_back(e.op(i)); // another index value 1303 ev.push_back(e1.op(i)); 1306 if (! found) // no Clifford units found at all 1307 throw(std::invalid_argument("get_clifford_comp(): expression is not a Clifford vector to the given units
")); 1309 ex res=dynallocate<ncmul>(std::move(ev)); 1310 if (same_value_found) { 1312 } else if (! dummy_ind.is_zero()) { // a dummy index was found 1313 if (is_a<varidx>(dummy_ind)) 1314 dummy_ind = ex_to<varidx>(dummy_ind).toggle_variance(); 1315 return res.subs(dummy_ind==ival, subs_options::no_pattern); 1316 } else // found a Clifford unit with another index 1318 } else if (e1.is_zero()) { 1320 } else if (is_a<clifford>(e1) && is_a<cliffordunit>(e1.op(0)) && ex_to<clifford>(e1).same_metric(c)) { 1321 if (ex_to<idx>(e1.op(1)).is_numeric() && 1322 (ival == ex_to<numeric>(ex_to<idx>(e1.op(1)).get_value()).to_int()) ) 1327 throw(std::invalid_argument("get_clifford_comp(): expression is not usable as a Clifford vector
")); 1330 lst clifford_to_lst(const ex & e, const ex & c, bool algebraic) 1332 GINAC_ASSERT(is_a<clifford>(c)); 1334 if (! ex_to<idx>(mu).is_dim_numeric()) 1336 unsigned int D = ex_to<numeric>(ex_to<idx>(mu).get_dim()).to_int(); 1338 if (algebraic) // check if algebraic method is applicable 1339 for (unsigned int i = 0; i < D; i++) 1340 if (pow(c.subs(mu == i, subs_options::no_pattern), 2).is_zero() 1341 || (! is_a<numeric>(pow(c.subs(mu == i, subs_options::no_pattern), 2)))) 1344 ex v0 = remove_dirac_ONE(canonicalize_clifford(e+clifford_prime(e)))/2; 1347 ex e1 = canonicalize_clifford(e - v0 * dirac_ONE(ex_to<clifford>(c).get_representation_label())); 1349 for (unsigned int i = 0; i < D; i++) 1350 V.append(remove_dirac_ONE( 1351 simplify_indexed(canonicalize_clifford(e1 * c.subs(mu == i, subs_options::no_pattern) + c.subs(mu == i, subs_options::no_pattern) * e1)) 1352 / (2*pow(c.subs(mu == i, subs_options::no_pattern), 2)))); 1355 for (unsigned int i = 0; i < D; i++) 1356 V.append(get_clifford_comp(e1, c.subs(c.op(1) == i, subs_options::no_pattern))); 1357 } catch (std::exception &p) { 1358 /* Try to expand dummy summations to simplify the expression*/ 1359 e1 = canonicalize_clifford(expand_dummy_sum(e, true)); 1361 v0 = remove_dirac_ONE(canonicalize_clifford(e1+clifford_prime(e1)))/2; 1362 if (! v0.is_zero()) { 1364 e1 = canonicalize_clifford(e1 - v0 * dirac_ONE(ex_to<clifford>(c).get_representation_label())); 1366 for (unsigned int i = 0; i < D; i++) 1367 V.append(get_clifford_comp(e1, c.subs(c.op(1) == i, subs_options::no_pattern))); 1374 ex clifford_moebius_map(const ex & a, const ex & b, const ex & c, const ex & d, const ex & v, const ex & G, unsigned char rl) 1378 if (! is_a<matrix>(v) && ! v.info(info_flags::list)) 1379 throw(std::invalid_argument("clifford_moebius_map(): parameter v should be either vector or list
")); 1381 if (is_a<clifford>(G)) { 1384 if (is_a<indexed>(G)) { 1385 D = ex_to<idx>(G.op(1)).get_dim(); 1386 varidx mu(dynallocate<symbol>(), D); 1387 cu = clifford_unit(mu, G, rl); 1388 } else if (is_a<matrix>(G)) { 1389 D = ex_to<matrix>(G).rows(); 1390 idx mu(dynallocate<symbol>(), D); 1391 cu = clifford_unit(mu, G, rl); 1396 x = lst_to_clifford(v, cu); 1397 ex e = clifford_to_lst(simplify_indexed(canonicalize_clifford((a * x + b) * clifford_inverse(c * x + d))), cu, false); 1398 return (is_a<matrix>(v) ? matrix(ex_to<matrix>(v).rows(), ex_to<matrix>(v).cols(), ex_to<lst>(e)) : e); 1401 ex clifford_moebius_map(const ex & M, const ex & v, const ex & G, unsigned char rl) 1403 if (is_a<matrix>(M) && (ex_to<matrix>(M).rows() == 2) && (ex_to<matrix>(M).cols() == 2)) 1404 return clifford_moebius_map(M.op(0), M.op(1), M.op(2), M.op(3), v, G, rl); 1409 } // namespace GiNaC This class represents the Dirac gammaL object which behaves like 1/2 (1+gamma5).
Interface to GiNaC's symbolic exponentiation (basis^exponent).
bool find(const ex &thisex, const ex &pattern, exset &found)
Interface to GiNaC's symbolic objects.
unsigned hashvalue
hash value
This class holds an object representing an element of the Clifford algebra (the Dirac gamma matrices)...
print_func< print_dflt >(&diracone::do_print). print_func< print_latex >(&diracone
Interface to GiNaC's symmetry definitions.
ex subs(const exmap &m, unsigned options=0) const
matrix transpose(const matrix &m)
static ex get_clifford_comp(const ex &e, const ex &c, bool root=true)
Auxiliary structure to define a function for striping one Clifford unit from vectors.
Interface to GiNaC's clifford algebra (Dirac gamma) objects.
void read_archive(const archive_node &n, lst &sym_lst) override
Load (deserialize) the object from an archive node.
bool is_equal(const ex &other) const
Archiving of GiNaC expressions.
Interface to GiNaC's sums of expressions.
ex get_symmetry() const
Return symmetry properties.
This class is the ABC (abstract base class) of GiNaC's class hierarchy.
bool same_metric(const ex &other) const
This class holds one of GiNaC's predefined special tensors such as the delta and the metric tensors...
This class represents the Clifford algebra generators (units).
bool are_ex_trivially_equal(const ex &e1, const ex &e2)
Compare two objects of class quickly without doing a deep tree traversal.
ex dirac_gamma(const ex &mu, unsigned char rl)
Create a Dirac gamma object.
Interface to GiNaC's products of expressions.
ex metric
Metric of the space, all constructors make it an indexed object.
This class represents the Dirac gammaL object which behaves like 1/2 (1-gamma5).
Interface to GiNaC's indices.
void archive(archive_node &n) const override
Save (serialize) the object into archive node.
Interface to several small and furry utilities needed within GiNaC but not of any interest to the use...
void do_print_dflt(const print_dflt &c, unsigned level) const
bool is_zero(const ex &thisex)
Context for default (ginsh-parsable) output.
This class is a wrapper around CLN-numbers within the GiNaC class hierarchy.
Context for latex-parsable output.
ex subs(const exmap &m, unsigned options=0) const override
Substitute a set of objects by arbitrary expressions.
ex remove_dirac_ONE(const ex &e, unsigned char rl, unsigned options)
Replaces dirac_ONE's (with a representation_label no less than rl) in e with 1.
friend ex simplify_indexed(const ex &e, exvector &free_indices, exvector &dummy_indices, const scalar_products &sp)
Simplify indexed expression, return list of free indices.
This class holds an indexed expression.
#define DEFAULT_PRINT_LATEX(classname, text, latex)
int commutator_sign
It is the sign in the definition e~i e~j +/- e~j e~i = B(i, j) + B(j, i)
#define GINAC_ASSERT(X)
Assertion macro for checking invariances.
void do_print_latex(const print_latex &c, unsigned level) const
ex clifford_moebius_map(const ex &a, const ex &b, const ex &c, const ex &d, const ex &v, const ex &G, unsigned char rl)
Calculations of Moebius transformations (conformal map) defined by a 2x2 Clifford matrix (a b\c d) in...
ex & let_op(size_t i) override
Return modifiable operand/member at position i.
GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(add, expairseq, print_func< print_context >(&add::do_print). print_func< print_latex >(&add::do_print_latex). print_func< print_csrc >(&add::do_print_csrc). print_func< print_tree >(&add::do_print_tree). print_func< print_python_repr >(&add::do_print_python_repr)) add
To distinguish between different kinds of non-commutative objects.
ex op(const ex &thisex, size_t i)
Interface to symbolic matrices.
std::vector< ex > exvector
std::map< ex, ex, ex_is_less > exmap
clifford(const ex &b, unsigned char rl=0)
Construct object without any indices.
Interface to GiNaC's overloaded operators.
void printindices(const print_context &c, unsigned level) const
This class represents the Dirac gamma Lorentz vector.
Interface to GiNaC's light-weight expression handles.
This class represents the Clifford algebra unity element.
Base class for print_contexts.
Definition of GiNaC's lst.
static unsigned get_dim_uint(const ex &e)
void ensure_if_modifiable() const
Ensure the object may be modified without hurting others, throws if this is not the case...
indexed(const ex &b)
Construct indexed object with no index.
int get_commutator_sign() const
size_t nops() const override
Number of operands/members.
This class holds an index with a variance (co- or contravariant).
void print(const print_context &c, unsigned level=0) const
Print expression to stream.
This class stores all properties needed to record/retrieve the state of one object of class basic (or...
Lightweight wrapper for GiNaC's symbolic objects.
unsigned precedence() const override
Return relative operator precedence (for parenthezing output).
ex lst_to_clifford(const ex &v, const ex &mu, const ex &metr, unsigned char rl)
List or vector conversion into the Clifford vector.
bool match_same_type(const basic &other) const override
Returns true if the attributes of two objects are similar enough for a match.
ex op(size_t i) const override
Return operand/member at position i.
Interface to GiNaC's non-commutative products of expressions.
const symmetry & symmetric2()
void do_print_tree(const print_tree &c, unsigned level) const
virtual int compare_same_type(const basic &other) const
Returns order relation between two objects of same type.
This class represents the Dirac gamma5 object which anticommutates with all other gammas...
Wrapper template for making GiNaC classes out of STL containers.
This class holds one index of an indexed object.
Interface to relations between expressions.
Makes the interface to the underlying bignum package available.
unsigned char representation_label
Representation label to distinguish independent spin lines.
#define DEFAULT_COMPARE(classname)
#define DEFAULT_CTOR(classname)
const symmetry & not_symmetric()
static bool is_dirac_slash(const ex &seq0)
lst clifford_to_lst(const ex &e, const ex &c, bool algebraic)
An inverse function to lst_to_clifford().
matrix inverse(const matrix &m)
Context for tree-like output for debugging.
ex symtree
Index symmetry (tree of symmetry objects)
ex subs(const ex &thisex, const exmap &m, unsigned options=0)
ex clifford_unit(const ex &mu, const ex &metr, unsigned char rl)
Create a Clifford unit object.
unsigned flags
of type status_flags
ex clifford_inverse(const ex &e)
Calculation of the inverse in the Clifford algebra.
return_type_t return_type_tinfo() const override
GINAC_BIND_UNARCHIVER(add)
exvector get_free_indices() const