1 /** @file lortensor.cpp
3 * Implementation of GiNaCĀ“s lortensor objects.
4 * No real implementation yet, do be done. */
7 * GiNaC Copyright (C) 1999-2001 Johannes Gutenberg University Mainz, Germany
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37 #include "lortensor.h"
38 #include "operators.h"
45 #ifndef NO_NAMESPACE_GINAC
47 #endif // ndef NO_NAMESPACE_GINAC
49 GINAC_IMPLEMENT_REGISTERED_CLASS(lortensor, indexed)
52 // default constructor, destructor, copy constructor assignment operator and helpers
57 lortensor::lortensor() : inherited(TINFO_lortensor), type(invalid)
59 debugmsg("lortensor default constructor",LOGLEVEL_CONSTRUCT);
61 name=autoname_prefix()+ToString(serial);
64 lortensor::~lortensor()
66 debugmsg("lortensor destructor",LOGLEVEL_DESTRUCT);
70 lortensor::lortensor(const lortensor & other)
72 debugmsg("lortensor copy constructor",LOGLEVEL_CONSTRUCT);
76 const lortensor & lortensor::operator=(const lortensor & other)
78 debugmsg("lortensor operator=",LOGLEVEL_ASSIGNMENT);
79 if (this != & other) {
88 void lortensor::copy(const lortensor & other)
90 inherited::copy(other);
96 void lortensor::destroy(bool call_parent)
98 if (call_parent) inherited::destroy(call_parent);
102 // other constructors
107 /** Construct object without any Lorentz index. This constructor is for
108 * internal use only. */
109 lortensor::lortensor(lortensor_types const lt, const std::string & n) : type(lt), name(n)
111 debugmsg("lortensor constructor from lortensor_types,string",LOGLEVEL_CONSTRUCT);
112 if (lt == lortensor_symbolic)
113 serial = next_serial++;
116 tinfo_key = TINFO_lortensor;
119 /** Construct object with one Lorentz index. This constructor is for
120 * internal use only. Use the lortensor_vector() or lortensor_symbolic()
122 * @see lortensor_vector
123 * @see lortensor_symbolic */
124 lortensor::lortensor(lortensor_types const lt, const std::string & n, const ex & mu) : inherited(mu), type(lt), name(n)
126 debugmsg("lortensor constructor from lortensor_types,string,ex",LOGLEVEL_CONSTRUCT);
127 GINAC_ASSERT(all_of_type_lorentzidx());
128 if (lt == lortensor_symbolic)
129 serial = next_serial++;
132 tinfo_key=TINFO_lortensor;
135 /** Construct object with two Lorentz indices. This constructor is for
136 * internal use only. Use the lortensor_g(), lortensor_delta() or
137 * lortensor_symbolic() functions instead.
139 * @see lortensor_delta
140 * @see lortensor_symbolic */
141 lortensor::lortensor(lortensor_types const lt, const std::string & n, const ex & mu, const ex & nu) : inherited(mu,nu), type(lt), name(n)
143 debugmsg("lortensor constructor from lortensor_types,string,ex,ex",LOGLEVEL_CONSTRUCT);
144 GINAC_ASSERT(all_of_type_lorentzidx());
145 if (lt == lortensor_symbolic)
146 serial = next_serial++;
149 tinfo_key=TINFO_lortensor;
152 /** Construct object with three Lorentz indices. This constructor is for
153 * internal use only. Use the lortensor_symbolic() function instead.
154 * @see lortensor_symbolic */
155 lortensor::lortensor(lortensor_types const lt, const std::string & n, const ex & mu, const ex & nu, const ex & rho) : inherited(mu,nu,rho), type(lt), name(n)
157 debugmsg("lortensor constructor from lortensor_types,string,ex,ex,ex",LOGLEVEL_CONSTRUCT);
158 GINAC_ASSERT(all_of_type_lorentzidx());
159 if (lt == lortensor_symbolic)
160 serial = next_serial++;
163 tinfo_key=TINFO_lortensor;
166 /** Construct object with four Lorentz indices. This constructor is for
167 * internal use only. Use the lortensor_epsilon() or lortensor_symbolic()
169 * @see lortensor_epsilon
170 * @see lortensor_symbolic */
171 lortensor::lortensor(lortensor_types const lt, const std::string & n, const ex & mu, const ex & nu, const ex & rho, const ex & sigma) : inherited(mu,nu,rho,sigma), type(lt), name(n)
173 debugmsg("lortensor constructor from lortensor_types,string,ex,ex,ex,ex",LOGLEVEL_CONSTRUCT);
174 GINAC_ASSERT(all_of_type_lorentzidx());
175 if (lt == lortensor_symbolic)
176 serial = next_serial++;
179 tinfo_key=TINFO_lortensor;
182 /** Construct object with arbitrary number of Lorentz indices. This
183 * constructor is for internal use only. Use the lortensor_symbolic()
186 * @see lortensor_symbolic */
187 lortensor::lortensor(lortensor_types const lt, const std::string & n, const exvector & iv) : inherited(iv), type(lt), name(n)
189 debugmsg("lortensor constructor from lortensor_types,string,exvector",LOGLEVEL_CONSTRUCT);
190 GINAC_ASSERT(all_of_type_lorentzidx());
191 if (lt == lortensor_symbolic)
192 serial = next_serial++;
195 tinfo_key=TINFO_lortensor;
198 lortensor::lortensor(lortensor_types const lt, const std::string & n, unsigned s, const exvector & iv) : indexed(iv), type(lt), name(n), serial(s)
200 debugmsg("lortensor constructor from lortensor_types,string,unsigned,exvector",LOGLEVEL_CONSTRUCT);
201 GINAC_ASSERT(all_of_type_lorentzidx());
202 tinfo_key=TINFO_lortensor;
205 lortensor::lortensor(lortensor_types const lt, const std::string & n, unsigned s, exvector *ivp) : indexed(ivp), type(lt), name(n), serial(s)
207 debugmsg("lortensor constructor from lortensor_types,string,unsigned,exvector",LOGLEVEL_CONSTRUCT);
208 GINAC_ASSERT(all_of_type_lorentzidx());
209 tinfo_key=TINFO_lortensor;
217 /** Construct object from archive_node. */
218 lortensor::lortensor(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
220 debugmsg("lortensor constructor from archive_node", LOGLEVEL_CONSTRUCT);
222 if (!(n.find_unsigned("type", ty)))
223 throw (std::runtime_error("unknown lortensor type in archive"));
224 type = (lortensor_types)ty;
225 if (type == lortensor_symbolic) {
226 serial = next_serial++;
227 if (!(n.find_string("name", name)))
228 name = autoname_prefix() + ToString(serial);
233 /** Unarchive the object. */
234 ex lortensor::unarchive(const archive_node &n, const lst &sym_lst)
236 ex s = (new lortensor(n, sym_lst))->setflag(status_flags::dynallocated);
238 if (ex_to_lortensor(s).type == lortensor_symbolic) {
239 // If lortensor is in sym_lst, return the existing lortensor
240 for (unsigned i=0; i<sym_lst.nops(); i++) {
241 if (is_ex_of_type(sym_lst.op(i), lortensor) && (ex_to_lortensor(sym_lst.op(i)).name == ex_to_lortensor(s).name))
242 return sym_lst.op(i);
248 /** Archive the object. */
249 void lortensor::archive(archive_node &n) const
251 inherited::archive(n);
252 n.add_unsigned("type", type);
253 if (type == lortensor_symbolic)
254 n.add_string("name", name);
259 // functions overriding virtual functions from bases classes
264 basic * lortensor::duplicate() const
266 debugmsg("lortensor duplicate",LOGLEVEL_DUPLICATE);
267 return new lortensor(*this);
270 void lortensor::printraw(std::ostream & os) const
272 debugmsg("lortensor printraw",LOGLEVEL_PRINT);
273 os << "lortensor(type=" << (unsigned)type
276 os << ",serial=" << serial;
277 os << ",hash=" << hashvalue << ",flags=" << flags << ")";
280 void lortensor::printtree(std::ostream & os, unsigned indent) const
282 debugmsg("lortensor printtree",LOGLEVEL_PRINT);
283 os << std::string(indent,' ') <<"lortensor object: "
284 << "type=" << (unsigned)type << ","
285 << seq.size() << " indices" << std::endl;
286 printtreeindices(os,indent);
287 os << std::string(indent,' ') << "hash=" << hashvalue
288 << " (0x" << std::hex << hashvalue << std::dec << ")"
289 << ", flags=" << flags << std::endl;
292 void lortensor::print(std::ostream & os, unsigned upper_precedence) const
294 debugmsg("lortensor print",LOGLEVEL_PRINT);
299 case lortensor_delta:
302 case lortensor_epsilon:
305 case lortensor_symbolic:
310 os << "INVALID_LORTENSOR_OBJECT";
316 bool lortensor::info(unsigned inf) const
318 return inherited::info(inf);
321 ex lortensor::eval(int level) const
323 if (type==lortensor_g) {
324 // canonicalize indices
326 int sig=canonicalize_indices(iv,false); //symmetric
328 //something has changed while sorting indices, more evaluations later
329 return ex(sig) *lortensor(type,name,iv);
331 const lorentzidx & idx1=ex_to_lorentzidx(seq[0]);
332 const lorentzidx & idx2=ex_to_lorentzidx(seq[1]);
333 if ((!idx1.is_symbolic()) && (!idx2.is_symbolic())) {
334 //both indices are numeric
335 if ((idx1.get_value()==idx2.get_value())) {
337 if (idx1.get_value()==0){
341 if (idx1.is_covariant() != idx2.is_covariant()) {
342 // (_i,~i) or (~i,_i), i = 1...3
345 // (_i,_i) or (~i,~i), i= 1...3
350 // at least one off-diagonal
353 } else if (idx1.is_symbolic() && idx1.is_co_contra_pair(idx2)) {
357 return this -> hold();
362 int lortensor::compare_same_type(const basic & other) const
364 GINAC_ASSERT(is_of_type(other,lortensor));
365 const lortensor &o = static_cast<const lortensor &>(other);
369 return type < o.type ? -1 : 1;
372 if (type == lortensor_symbolic) {
373 // symbolic, compare serials
374 if (serial != o.serial) {
375 return serial < o.serial ? -1 : 1;
379 return inherited::compare_same_type(other);
382 bool lortensor::is_equal_same_type(const basic & other) const
384 GINAC_ASSERT(is_of_type(other,lortensor));
385 const lortensor &o = static_cast<const lortensor &>(other);
387 if (type != o.type) return false;
388 if (type == lortensor_symbolic && serial != o.serial) return false;
389 return inherited::is_equal_same_type(other);
392 unsigned lortensor::return_type(void) const
394 return return_types::commutative;
397 unsigned lortensor::return_type_tinfo(void) const
402 ex lortensor::thisexprseq(const exvector & v) const
404 return lortensor(type,name,serial,v);
407 ex lortensor::thisexprseq(exvector *vp) const
409 return lortensor(type,name,serial,vp);
413 // non-virtual functions in this class
418 /** Check whether all indices are of class lorentzidx or a subclass. This
419 * function is used internally to make sure that all constructed Lorentz
420 * tensors really carry Lorentz indices and not some other classes. */
421 bool lortensor::all_of_type_lorentzidx(void) const
423 for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++ cit) {
424 if (!is_ex_of_type(*cit,lorentzidx)) return false;
431 std::string & lortensor::autoname_prefix(void)
433 static std::string * s = new std::string("lortensor");
438 // static member variables
443 unsigned lortensor::next_serial=0;
449 /** Construct an object representing the metric tensor g. The indices must
450 * be of class lorentzidx.
452 * @param mu First index
453 * @param nu Second index
454 * @return newly constructed object */
455 lortensor lortensor_g(const ex & mu, const ex & nu)
457 return lortensor(lortensor::lortensor_g,"",mu,nu);
460 /** Construct an object representing the unity matrix delta. The indices
461 * must be of class lorentzidx.
463 * @param mu First index
464 * @param nu Second index
465 * @return newly constructed object */
466 lortensor lortensor_delta(const ex & mu, const ex & nu)
468 return lortensor(lortensor::lortensor_delta,"",mu,nu);
471 /** Construct an object representing the four-dimensional totally
472 * antisymmetric tensor epsilon. The indices must be of class lorentzidx.
474 * @param mu First index
475 * @param nu Second index
476 * @param rho Third index
477 * @param sigma Fourth index
478 * @return newly constructed object */
479 lortensor lortensor_epsilon(const ex & mu, const ex & nu, const ex & rho, const ex & sigma)
481 return lortensor(lortensor::lortensor_epsilon,"",mu,nu,rho,sigma);
484 /** Construct an object representing a symbolic Lorentz vector. The index
485 * must be of class lorentzidx.
487 * @param n Symbolic name
489 * @return newly constructed object */
490 lortensor lortensor_vector(const std::string & n, const ex & mu)
492 return lortensor(lortensor::lortensor_symbolic,n,mu);
495 /** Construct an object representing a symbolic Lorentz tensor of arbitrary
496 * rank. The indices must be of class lorentzidx.
498 * @param n Symbolic name
499 * @param iv Vector of indices
500 * @return newly constructed object */
501 lortensor lortensor_symbolic(const std::string & n, const exvector & iv)
503 return lortensor(lortensor::lortensor_symbolic,n,iv);
506 ex simplify_lortensor_mul(const ex & m)
508 GINAC_ASSERT(is_ex_exactly_of_type(m,mul));
509 exvector v_contracted;
511 // collect factors in an exvector, store squares twice
513 v_contracted.reserve(2*n);
514 for (int i=0; i<n; ++i) {
516 if (is_ex_exactly_of_type(f,power)&&f.op(1).is_equal(_ex2())) {
517 v_contracted.push_back(f.op(0));
518 v_contracted.push_back(f.op(0));
520 v_contracted.push_back(f);
524 unsigned replacements;
525 bool something_changed=false;
527 exvector::iterator it=v_contracted.begin();
528 while (it!=v_contracted.end()) {
529 // process only lor_g objects
530 if (is_ex_exactly_of_type(*it,lortensor) &&
531 (ex_to_lortensor(*it).type==lortensor::lortensor_g)) {
532 const lortensor & g=ex_to_lortensor(*it);
533 GINAC_ASSERT(g.seq.size()==2);
534 const idx & first_idx=ex_to_lorentzidx(g.seq[0]);
535 const idx & second_idx=ex_to_lorentzidx(g.seq[1]);
536 // g_{mu,mu} should have been contracted in lortensor::eval()
537 GINAC_ASSERT(!first_idx.is_equal(second_idx));
538 ex saved_g=*it; // save to restore it later
540 // try to contract first index
542 if (first_idx.is_symbolic()) {
543 replacements = subs_index_in_exvector(v_contracted,
544 first_idx.toggle_covariant(),second_idx);
545 if (replacements==0) {
546 // not contracted, restore g object
549 // a contracted index should occur exactly once
550 GINAC_ASSERT(replacements==1);
552 something_changed=true;
556 // try second index only if first was not contracted
557 if ((replacements==0)&&(second_idx.is_symbolic())) {
558 // first index not contracted, *it is again the original g object
559 replacements = subs_index_in_exvector(v_contracted,
560 second_idx.toggle_covariant(),first_idx);
561 if (replacements==0) {
562 // not contracted except in itself, restore g object
565 // a contracted index should occur exactly once
566 GINAC_ASSERT(replacements==1);
568 something_changed=true;
574 if (something_changed) {
575 return mul(v_contracted);
580 /** Perform some simplifications on an expression containing Lorentz tensors. */
581 ex simplify_lortensor(const ex & e)
583 // all simplification is done on expanded objects
584 ex e_expanded=e.expand();
586 // simplification of sum=sum of simplifications
587 if (is_ex_exactly_of_type(e_expanded,add)) {
589 for (unsigned i=0; i<e_expanded.nops(); ++i) {
590 sum += simplify_lortensor(e_expanded.op(i));
595 // simplification of (commutative) product
596 if (is_ex_exactly_of_type(e_expanded,mul)) {
597 return simplify_lortensor_mul(e);
600 // cannot do anything
608 const lortensor some_lortensor;
609 const std::type_info & typeid_lortensor = typeid(some_lortensor);
611 #ifndef NO_NAMESPACE_GINAC
613 #endif // ndef NO_NAMESPACE_GINAC