|
GiNaC
1.6.2
|
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