- color/clifford objects have representation label to distinguish elements
[ginac.git] / ginac / clifford.cpp
1 /** @file clifford.cpp
2  *
3  *  Implementation of GiNaC's clifford algebra (Dirac gamma) objects. */
4
5 /*
6  *  GiNaC Copyright (C) 1999-2001 Johannes Gutenberg University Mainz, Germany
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "clifford.h"
24 #include "ex.h"
25 #include "idx.h"
26 #include "ncmul.h"
27 #include "print.h"
28 #include "archive.h"
29 #include "debugmsg.h"
30 #include "utils.h"
31
32 #include <stdexcept>
33
34 namespace GiNaC {
35
36 GINAC_IMPLEMENT_REGISTERED_CLASS(clifford, indexed)
37 GINAC_IMPLEMENT_REGISTERED_CLASS(diracone, tensor)
38 GINAC_IMPLEMENT_REGISTERED_CLASS(diracgamma, tensor)
39 GINAC_IMPLEMENT_REGISTERED_CLASS(diracgamma5, tensor)
40
41 //////////
42 // default constructor, destructor, copy constructor assignment operator and helpers
43 //////////
44
45 clifford::clifford() : representation_label(0)
46 {
47         debugmsg("clifford default constructor", LOGLEVEL_CONSTRUCT);
48         tinfo_key = TINFO_clifford;
49 }
50
51 void clifford::copy(const clifford & other)
52 {
53         inherited::copy(other);
54         representation_label = other.representation_label;
55 }
56
57 DEFAULT_DESTROY(clifford)
58 DEFAULT_CTORS(diracone)
59 DEFAULT_CTORS(diracgamma)
60 DEFAULT_CTORS(diracgamma5)
61
62 //////////
63 // other constructors
64 //////////
65
66 /** Construct object without any indices. This constructor is for internal
67  *  use only. Use the dirac_ONE() function instead.
68  *  @see dirac_ONE */
69 clifford::clifford(const ex & b, unsigned char rl) : inherited(b), representation_label(rl)
70 {
71         debugmsg("clifford constructor from ex", LOGLEVEL_CONSTRUCT);
72         tinfo_key = TINFO_clifford;
73 }
74
75 /** Construct object with one Lorentz index. This constructor is for internal
76  *  use only. Use the dirac_gamma() function instead.
77  *  @see dirac_gamma */
78 clifford::clifford(const ex & b, const ex & mu, unsigned char rl) : inherited(b, mu), representation_label(rl)
79 {
80         debugmsg("clifford constructor from ex,ex", LOGLEVEL_CONSTRUCT);
81         GINAC_ASSERT(is_ex_of_type(mu, varidx));
82         tinfo_key = TINFO_clifford;
83 }
84
85 clifford::clifford(unsigned char rl, const exvector & v, bool discardable) : inherited(indexed::unknown, v, discardable), representation_label(rl)
86 {
87         debugmsg("clifford constructor from unsigned char,exvector", LOGLEVEL_CONSTRUCT);
88         tinfo_key = TINFO_clifford;
89 }
90
91 clifford::clifford(unsigned char rl, exvector * vp) : inherited(indexed::unknown, vp), representation_label(rl)
92 {
93         debugmsg("clifford constructor from unsigned char,exvector *", LOGLEVEL_CONSTRUCT);
94         tinfo_key = TINFO_clifford;
95 }
96
97 //////////
98 // archiving
99 //////////
100
101 clifford::clifford(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
102 {
103         debugmsg("clifford constructor from archive_node", LOGLEVEL_CONSTRUCT);
104         unsigned rl;
105         n.find_unsigned("label", rl);
106         representation_label = rl;
107 }
108
109 void clifford::archive(archive_node &n) const
110 {
111         inherited::archive(n);
112         n.add_unsigned("label", representation_label);
113 }
114
115 DEFAULT_UNARCHIVE(clifford)
116 DEFAULT_ARCHIVING(diracone)
117 DEFAULT_ARCHIVING(diracgamma)
118 DEFAULT_ARCHIVING(diracgamma5)
119
120 //////////
121 // functions overriding virtual functions from bases classes
122 //////////
123
124 int clifford::compare_same_type(const basic & other) const
125 {
126         GINAC_ASSERT(other.tinfo() == TINFO_clifford);
127         const clifford &o = static_cast<const clifford &>(other);
128
129         if (representation_label != o.representation_label) {
130                 // different representation label
131                 return representation_label < o.representation_label ? -1 : 1;
132         }
133
134         return inherited::compare_same_type(other);
135 }
136
137 DEFAULT_COMPARE(diracone)
138 DEFAULT_COMPARE(diracgamma)
139 DEFAULT_COMPARE(diracgamma5)
140
141 DEFAULT_PRINT(diracone, "ONE")
142 DEFAULT_PRINT(diracgamma, "gamma")
143 DEFAULT_PRINT(diracgamma5, "gamma5")
144
145 /** Contraction of a gamma matrix with something else. */
146 bool diracgamma::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
147 {
148         GINAC_ASSERT(is_ex_of_type(*self, indexed));
149         GINAC_ASSERT(is_ex_of_type(*other, indexed));
150         GINAC_ASSERT(is_ex_of_type(self->op(0), diracgamma));
151
152         if (is_ex_of_type(other->op(0), diracgamma)) {
153
154                 ex dim = ex_to_idx(self->op(1)).get_dim();
155
156                 // gamma~mu*gamma.mu = dim*ONE
157                 if (other - self == 1) {
158                         *self = dim;
159                         *other = dirac_ONE();
160                         return true;
161
162                 // gamma~mu*gamma~alpha*gamma.mu = (2-dim)*gamma~alpha
163                 } else if (other - self == 2
164                         && is_ex_of_type(self[1], clifford)) {
165                         *self = 2 - dim;
166                         *other = _ex1();
167                         return true;
168
169                 // gamma~mu*gamma~alpha*gamma~beta*gamma.mu = 4*g~alpha~beta+(dim-4)*gamam~alpha*gamma~beta
170                 } else if (other - self == 3
171                         && is_ex_of_type(self[1], clifford)
172                         && is_ex_of_type(self[2], clifford)) {
173                         *self = 4 * metric_tensor(self[1].op(1), self[2].op(1)) * dirac_ONE() + (dim - 4) * self[1] * self[2];
174                         self[1] = _ex1();
175                         self[2] = _ex1();
176                         *other = _ex1();
177                         return true;
178
179                 // gamma~mu*gamma~alpha*gamma~beta*gamma~delta*gamma.mu = -2*gamma~delta*gamma~beta*gamma~alpha+(4-dim)*gamma~alpha*gamma~beta*gamma~delta
180                 } else if (other - self == 4
181                         && is_ex_of_type(self[1], clifford)
182                         && is_ex_of_type(self[2], clifford)
183                         && is_ex_of_type(self[3], clifford)) {
184                         *self = -2 * self[3] * self[2] * self[1] + (4 - dim) * self[1] * self[2] * self[3];
185                         self[1] = _ex1();
186                         self[2] = _ex1();
187                         self[3] = _ex1();
188                         *other = _ex1();
189                         return true;
190                 }
191         }
192
193         return false;
194 }
195
196 /** Perform automatic simplification on noncommutative product of clifford
197  *  objects. This removes superfluous ONEs, permutes gamma5's to the front
198  *  and removes squares of gamma objects. */
199 ex clifford::simplify_ncmul(const exvector & v) const
200 {
201         exvector s;
202         s.reserve(v.size());
203
204         // Remove superfluous ONEs
205         exvector::const_iterator cit = v.begin(), citend = v.end();
206         while (cit != citend) {
207                 if (!is_ex_of_type(cit->op(0), diracone))
208                         s.push_back(*cit);
209                 cit++;
210         }
211
212         bool something_changed = false;
213         int sign = 1;
214
215         // Anticommute gamma5's to the front
216         if (s.size() >= 2) {
217                 exvector::iterator first = s.begin(), next_to_last = s.end() - 2;
218                 while (true) {
219                         exvector::iterator it = next_to_last;
220                         while (true) {
221                                 exvector::iterator it2 = it + 1;
222                                 if (!is_ex_of_type(it->op(0), diracgamma5) && is_ex_of_type(it2->op(0), diracgamma5)) {
223                                         it->swap(*it2);
224                                         sign = -sign;
225                                         something_changed = true;
226                                 }
227                                 if (it == first)
228                                         break;
229                                 it--;
230                         }
231                         if (next_to_last == first)
232                                 break;
233                         next_to_last--;
234                 }
235         }
236
237         // Remove squares of gamma5
238         while (s.size() >= 2 && is_ex_of_type(s[0].op(0), diracgamma5) && is_ex_of_type(s[1].op(0), diracgamma5)) {
239                 s.erase(s.begin(), s.begin() + 2);
240                 something_changed = true;
241         }
242
243         // Remove equal adjacent gammas
244         if (s.size() >= 2) {
245                 exvector::iterator it = s.begin(), itend = s.end() - 1;
246                 while (it != itend) {
247                         ex & a = it[0];
248                         ex & b = it[1];
249                         if (is_ex_of_type(a.op(0), diracgamma) && is_ex_of_type(b.op(0), diracgamma)) {
250                                 const ex & ia = a.op(1);
251                                 const ex & ib = b.op(1);
252                                 if (ia.is_equal(ib)) {
253                                         a = lorentz_g(ia, ib);
254                                         b = dirac_ONE();
255                                         something_changed = true;
256                                 }
257                         }
258                         it++;
259                 }
260         }
261
262         if (s.size() == 0)
263                 return clifford(diracone()) * sign;
264         if (something_changed)
265                 return nonsimplified_ncmul(s) * sign;
266         else
267                 return simplified_ncmul(s) * sign;
268 }
269
270 ex clifford::thisexprseq(const exvector & v) const
271 {
272         return clifford(representation_label, v);
273 }
274
275 ex clifford::thisexprseq(exvector * vp) const
276 {
277         return clifford(representation_label, vp);
278 }
279
280 //////////
281 // global functions
282 //////////
283
284 ex dirac_ONE(unsigned char rl)
285 {
286         return clifford(diracone(), rl);
287 }
288
289 ex dirac_gamma(const ex & mu, unsigned char rl)
290 {
291         if (!is_ex_of_type(mu, varidx))
292                 throw(std::invalid_argument("index of Dirac gamma must be of type varidx"));
293
294         return clifford(diracgamma(), mu, rl);
295 }
296
297 ex dirac_gamma5(unsigned char rl)
298 {
299         return clifford(diracgamma5(), rl);
300 }
301
302 } // namespace GiNaC