#include <stdexcept>
#include "color.h"
-#include "ex.h"
#include "idx.h"
#include "ncmul.h"
#include "numeric.h"
#include "power.h" // for sqrt()
+#include "symbol.h"
#include "print.h"
#include "archive.h"
#include "debugmsg.h"
DEFAULT_COMPARE(su3f)
DEFAULT_COMPARE(su3d)
-DEFAULT_PRINT(su3one, "ONE")
+DEFAULT_PRINT_LATEX(su3one, "ONE", "\\mathbb{1}")
DEFAULT_PRINT(su3t, "T")
DEFAULT_PRINT(su3f, "f")
DEFAULT_PRINT(su3d, "d")
* objects. This removes superfluous ONEs. */
ex color::simplify_ncmul(const exvector & v) const
{
- //!! TODO: sort by representation label
exvector s;
s.reserve(v.size());
+ // Remove superfluous ONEs
exvector::const_iterator it = v.begin(), itend = v.end();
while (it != itend) {
if (!is_ex_of_type(it->op(0), su3one))
}
if (s.size() == 0)
- return color(su3one());
- else if (s.size() == v.size())
- return simplified_ncmul(v);
+ return color(su3one(), representation_label);
else
return simplified_ncmul(s);
}
}
+/** Contraction of generator with something else. */
+bool su3t::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
+{
+ GINAC_ASSERT(is_ex_of_type(*self, indexed));
+ GINAC_ASSERT(is_ex_of_type(*other, indexed));
+ GINAC_ASSERT(self->nops() == 2);
+ GINAC_ASSERT(is_ex_of_type(self->op(0), su3t));
+ unsigned char rl = ex_to_color(*self).get_representation_label();
+
+ if (is_ex_exactly_of_type(other->op(0), su3t)) {
+
+ // T.a T.a = 4/3 ONE
+ if (other - self == 1) {
+ *self = numeric(4, 3);
+ *other = color_ONE(rl);
+ return true;
+
+ // T.a T.b T.a = -1/6 T.b
+ } else if (other - self == 2
+ && is_ex_of_type(self[1], color)) {
+ *self = numeric(-1, 6);
+ *other = _ex1();
+ return true;
+
+ // T.a S T.a = 1/2 Tr(S) - 1/6 S
+ } else {
+ exvector::iterator it = self + 1;
+ while (it != other) {
+ if (!is_ex_of_type(*it, color)) {
+ return false;
+ }
+ it++;
+ }
+
+ it = self + 1;
+ ex S = _ex1();
+ while (it != other) {
+ S *= *it;
+ *it++ = _ex1();
+ }
+
+ *self = color_trace(S, rl) * color_ONE(rl) / 2 - S / 6;
+ *other = _ex1();
+ return true;
+ }
+ }
+
+ return false;
+}
+
/** Contraction of an indexed symmetric structure constant with something else. */
bool su3d::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
{
if (is_ex_exactly_of_type(other->op(0), su3d)) {
// Find the dummy indices of the contraction
- exvector dummy_indices;
- dummy_indices = ex_to_indexed(*self).get_dummy_indices(ex_to_indexed(*other));
-
- // d.abc*d.abc=40/3
+ 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
+ // d.akl d.bkl = 5/3 delta.ab
} else if (dummy_indices.size() == 2) {
- exvector a = index_set_difference(ex_to_indexed(*self).get_indices(), dummy_indices);
- exvector b = index_set_difference(ex_to_indexed(*other).get_indices(), dummy_indices);
- GINAC_ASSERT(a.size() > 0);
- GINAC_ASSERT(b.size() > 0);
- *self = numeric(5, 3) * delta_tensor(a[0], b[0]);
+ exvector a;
+ std::back_insert_iterator<exvector> 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;
+ }
}
return false;
exvector dummy_indices;
dummy_indices = ex_to_indexed(*self).get_dummy_indices(ex_to_indexed(*other));
- // f.abc*f.abc=24
+ // f.abc f.abc = 24
if (dummy_indices.size() == 3) {
*self = 24;
*other = _ex1();
return true;
- // f.akl*f.bkl=3*delta.ab
+ // 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);
*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;
+ }
}
return false;
return color_d(a, b, c) + I * color_f(a, b, c);
}
+/** Check whether a given tinfo key (as returned by return_type_tinfo()
+ * is that of a color object with the specified representation label. */
+static bool is_color_tinfo(unsigned ti, unsigned char rl)
+{
+ return ti == (TINFO_color + rl);
+}
+
+ex color_trace(const ex & e, unsigned char rl)
+{
+ if (is_ex_of_type(e, color)) {
+
+ if (ex_to_color(e).get_representation_label() == rl
+ && is_ex_of_type(e.op(0), su3one))
+ return _ex3();
+ else
+ return _ex0();
+
+ } else if (is_ex_exactly_of_type(e, add)) {
+
+ // Trace of sum = sum of traces
+ ex sum = _ex0();
+ for (unsigned i=0; i<e.nops(); i++)
+ sum += color_trace(e.op(i), rl);
+ return sum;
+
+ } else if (is_ex_exactly_of_type(e, mul)) {
+
+ // Trace of product: pull out non-color factors
+ ex prod = _ex1();
+ for (unsigned i=0; i<e.nops(); i++) {
+ const ex &o = e.op(i);
+ if (is_color_tinfo(o.return_type_tinfo(), rl))
+ prod *= color_trace(o, rl);
+ else
+ prod *= o;
+ }
+ return prod;
+
+ } else if (is_ex_exactly_of_type(e, ncmul)) {
+
+ if (!is_color_tinfo(e.return_type_tinfo(), rl))
+ return _ex0();
+
+ // Expand product, if necessary
+ ex e_expanded = e.expand();
+ if (!is_ex_of_type(e_expanded, ncmul))
+ return color_trace(e_expanded, rl);
+
+ unsigned num = e.nops();
+
+ if (num == 2) {
+
+ // Tr T_a T_b = 1/2 delta_a_b
+ return delta_tensor(e.op(0).op(1), e.op(1).op(1)) / 2;
+
+ } else if (num == 3) {
+
+ // Tr T_a T_b T_c = 1/4 h_a_b_c
+ return color_h(e.op(0).op(1), e.op(1).op(1), e.op(2).op(1)) / 4;
+
+ } else {
+
+ // Traces of 4 or more generators are computed recursively:
+ // Tr T_a1 .. T_an =
+ // 1/6 delta_a(n-1)_an Tr T_a1 .. T_a(n-2)
+ // + 1/2 h_a(n-1)_an_k Tr T_a1 .. T_a(n-2) T_k
+ const ex &last_index = e.op(num - 1).op(1);
+ const ex &next_to_last_index = e.op(num - 2).op(1);
+ idx summation_index((new symbol)->setflag(status_flags::dynallocated), 8);
+
+ exvector v1;
+ v1.reserve(num - 2);
+ for (int i=0; i<num-2; i++)
+ v1.push_back(e.op(i));
+
+ exvector v2 = v1;
+ v2.push_back(color_T(summation_index, rl));
+
+ return delta_tensor(next_to_last_index, last_index) * color_trace(ncmul(v1), rl) / 6
+ + color_h(next_to_last_index, last_index, summation_index) * color_trace(ncmul(v2), rl) / 2;
+ }
+ }
+
+ return _ex0();
+}
+
} // namespace GiNaC