3 * Implementation of GiNaC's special tensors. */
6 * GiNaC Copyright (C) 1999-2001 Johannes Gutenberg University Mainz, Germany
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.
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.
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
28 #include "relational.h"
36 GINAC_IMPLEMENT_REGISTERED_CLASS(tensor, basic)
37 GINAC_IMPLEMENT_REGISTERED_CLASS(tensdelta, tensor)
38 GINAC_IMPLEMENT_REGISTERED_CLASS(tensmetric, tensor)
39 GINAC_IMPLEMENT_REGISTERED_CLASS(minkmetric, tensmetric)
40 GINAC_IMPLEMENT_REGISTERED_CLASS(tensepsilon, tensor)
43 // default constructor, destructor, copy constructor assignment operator and helpers
46 #define DEFAULT_CTORS(classname) \
47 classname::classname() : inherited(TINFO_##classname) \
49 debugmsg(#classname " default constructor", LOGLEVEL_CONSTRUCT); \
51 void classname::copy(const classname & other) \
53 inherited::copy(other); \
55 void classname::destroy(bool call_parent) \
58 inherited::destroy(call_parent); \
61 tensor::tensor(unsigned ti) : inherited(ti)
63 debugmsg("tensor constructor from unsigned", LOGLEVEL_CONSTRUCT); \
67 DEFAULT_CTORS(tensdelta)
68 DEFAULT_CTORS(tensmetric)
69 DEFAULT_CTORS(tensepsilon)
71 minkmetric::minkmetric() : pos_sig(false)
73 debugmsg("minkmetric default constructor", LOGLEVEL_CONSTRUCT);
74 tinfo_key = TINFO_minkmetric;
77 minkmetric::minkmetric(bool ps) : pos_sig(ps)
79 debugmsg("minkmetric constructor from bool", LOGLEVEL_CONSTRUCT);
80 tinfo_key = TINFO_minkmetric;
83 void minkmetric::copy(const minkmetric & other)
85 inherited::copy(other);
86 pos_sig = other.pos_sig;
89 void minkmetric::destroy(bool call_parent)
92 inherited::destroy(call_parent);
99 #define DEFAULT_ARCHIVING(classname) \
100 classname::classname(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) \
102 debugmsg(#classname " constructor from archive_node", LOGLEVEL_CONSTRUCT); \
104 ex classname::unarchive(const archive_node &n, const lst &sym_lst) \
106 return (new classname(n, sym_lst))->setflag(status_flags::dynallocated); \
108 void classname::archive(archive_node &n) const \
110 inherited::archive(n); \
113 DEFAULT_ARCHIVING(tensor)
114 DEFAULT_ARCHIVING(tensdelta)
115 DEFAULT_ARCHIVING(tensmetric)
116 DEFAULT_ARCHIVING(tensepsilon)
118 minkmetric::minkmetric(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
120 debugmsg("minkmetric constructor from archive_node", LOGLEVEL_CONSTRUCT);
121 n.find_bool("pos_sig", pos_sig);
124 ex minkmetric::unarchive(const archive_node &n, const lst &sym_lst)
126 return (new minkmetric(n, sym_lst))->setflag(status_flags::dynallocated);
129 void minkmetric::archive(archive_node &n) const
131 inherited::archive(n);
132 n.add_bool("pos_sig", pos_sig);
136 // functions overriding virtual functions from bases classes
139 #define DEFAULT_COMPARE(classname) \
140 int classname::compare_same_type(const basic & other) const \
142 /* by default, two tensors of the same class are always identical */ \
146 DEFAULT_COMPARE(tensor)
147 DEFAULT_COMPARE(tensdelta)
148 DEFAULT_COMPARE(tensmetric)
149 DEFAULT_COMPARE(tensepsilon)
151 int minkmetric::compare_same_type(const basic & other) const
153 GINAC_ASSERT(is_of_type(other, minkmetric));
154 const minkmetric &o = static_cast<const minkmetric &>(other);
156 if (pos_sig != o.pos_sig)
157 return pos_sig ? -1 : 1;
159 return inherited::compare_same_type(other);
162 void tensdelta::print(std::ostream & os, unsigned upper_precedence) const
164 debugmsg("tensdelta print",LOGLEVEL_PRINT);
168 void tensmetric::print(std::ostream & os, unsigned upper_precedence) const
170 debugmsg("tensmetric print",LOGLEVEL_PRINT);
174 void minkmetric::print(std::ostream & os, unsigned upper_precedence) const
176 debugmsg("minkmetric print",LOGLEVEL_PRINT);
180 void tensepsilon::print(std::ostream & os, unsigned upper_precedence) const
182 debugmsg("tensepsilon print",LOGLEVEL_PRINT);
186 /** Automatic symbolic evaluation of an indexed delta tensor. */
187 ex tensdelta::eval_indexed(const basic & i) const
189 GINAC_ASSERT(is_of_type(i, indexed));
190 GINAC_ASSERT(i.nops() == 3);
191 GINAC_ASSERT(is_ex_of_type(i.op(0), tensdelta));
193 const idx & i1 = ex_to_idx(i.op(1));
194 const idx & i2 = ex_to_idx(i.op(2));
196 // Trace of delta tensor is the dimension of the space
197 if (is_dummy_pair(i1, i2))
200 // No further simplifications
204 /** Automatic symbolic evaluation of an indexed metric tensor. */
205 ex tensmetric::eval_indexed(const basic & i) const
207 GINAC_ASSERT(is_of_type(i, indexed));
208 GINAC_ASSERT(i.nops() == 3);
209 GINAC_ASSERT(is_ex_of_type(i.op(0), tensmetric));
210 GINAC_ASSERT(is_ex_of_type(i.op(1), varidx));
211 GINAC_ASSERT(is_ex_of_type(i.op(2), varidx));
213 const varidx & i1 = ex_to_varidx(i.op(1));
214 const varidx & i2 = ex_to_varidx(i.op(2));
216 // A metric tensor with one covariant and one contravariant index gets
217 // replaced by a delta tensor
218 if (i1.is_covariant() != i2.is_covariant())
219 return delta_tensor(i1, i2);
221 // No further simplifications
225 /** Automatic symbolic evaluation of an indexed Lorentz metric tensor. */
226 ex minkmetric::eval_indexed(const basic & i) const
228 GINAC_ASSERT(is_of_type(i, indexed));
229 GINAC_ASSERT(i.nops() == 3);
230 GINAC_ASSERT(is_ex_of_type(i.op(0), minkmetric));
231 GINAC_ASSERT(is_ex_of_type(i.op(1), varidx));
232 GINAC_ASSERT(is_ex_of_type(i.op(2), varidx));
234 const varidx & i1 = ex_to_varidx(i.op(1));
235 const varidx & i2 = ex_to_varidx(i.op(2));
237 // Numeric evaluation
238 if (static_cast<const indexed &>(i).all_index_values_are(info_flags::nonnegint)) {
239 int n1 = ex_to_numeric(i1.get_value()).to_int(), n2 = ex_to_numeric(i2.get_value()).to_int();
243 return pos_sig ? _ex_1() : _ex1();
245 return pos_sig ? _ex1() : _ex_1();
248 // Perform the usual evaluations of a metric tensor
249 return inherited::eval_indexed(i);
252 /** Contraction of an indexed delta tensor with something else. */
253 bool tensdelta::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
255 GINAC_ASSERT(is_ex_of_type(*self, indexed));
256 GINAC_ASSERT(is_ex_of_type(*other, indexed));
257 GINAC_ASSERT(self->nops() == 3);
258 GINAC_ASSERT(is_ex_of_type(self->op(0), tensdelta));
260 // Try to contract first index
261 const idx *self_idx = &ex_to_idx(self->op(1));
262 const idx *free_idx = &ex_to_idx(self->op(2));
263 bool first_index_tried = false;
266 if (self_idx->is_symbolic()) {
267 for (int i=1; i<other->nops(); i++) {
268 const idx &other_idx = ex_to_idx(other->op(i));
269 if (is_dummy_pair(*self_idx, other_idx)) {
271 // Contraction found, remove delta tensor and substitute
272 // index in second object
274 *other = other->subs(other_idx == *free_idx);
280 if (!first_index_tried) {
282 // No contraction with first index found, try second index
283 self_idx = &ex_to_idx(self->op(2));
284 free_idx = &ex_to_idx(self->op(1));
285 first_index_tried = true;
292 /** Contraction of an indexed metric tensor with something else. */
293 bool tensmetric::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
295 GINAC_ASSERT(is_ex_of_type(*self, indexed));
296 GINAC_ASSERT(is_ex_of_type(*other, indexed));
297 GINAC_ASSERT(self->nops() == 3);
298 GINAC_ASSERT(is_ex_of_type(self->op(0), tensmetric));
300 // If contracting with the delta tensor, let the delta do it
301 // (don't raise/lower delta indices)
302 if (is_ex_exactly_of_type(other->op(0), tensdelta))
305 // Try to contract first index
306 const idx *self_idx = &ex_to_idx(self->op(1));
307 const idx *free_idx = &ex_to_idx(self->op(2));
308 bool first_index_tried = false;
311 if (self_idx->is_symbolic()) {
312 for (int i=1; i<other->nops(); i++) {
313 const idx &other_idx = ex_to_idx(other->op(i));
314 if (is_dummy_pair(*self_idx, other_idx)) {
316 // Contraction found, remove metric tensor and substitute
317 // index in second object
319 *other = other->subs(other_idx == *free_idx);
325 if (!first_index_tried) {
327 // No contraction with first index found, try second index
328 self_idx = &ex_to_idx(self->op(2));
329 free_idx = &ex_to_idx(self->op(1));
330 first_index_tried = true;
341 ex delta_tensor(const ex & i1, const ex & i2)
343 if (!is_ex_of_type(i1, idx) || !is_ex_of_type(i2, idx))
344 throw(std::invalid_argument("indices of delta tensor must be of type idx"));
346 return indexed(tensdelta(), indexed::symmetric, i1, i2);
349 ex metric_tensor(const ex & i1, const ex & i2)
351 if (!is_ex_of_type(i1, varidx) || !is_ex_of_type(i2, varidx))
352 throw(std::invalid_argument("indices of metric tensor must be of type varidx"));
354 return indexed(tensmetric(), i1, i2);
357 ex lorentz_g(const ex & i1, const ex & i2, bool pos_sig)
359 if (!is_ex_of_type(i1, varidx) || !is_ex_of_type(i2, varidx))
360 throw(std::invalid_argument("indices of metric tensor must be of type varidx"));
362 return indexed(minkmetric(pos_sig), indexed::symmetric, i1, i2);
365 ex epsilon_tensor(const ex & i1, const ex & i2)
367 if (!is_ex_of_type(i1, idx) || !is_ex_of_type(i2, idx))
368 throw(std::invalid_argument("indices of epsilon tensor must be of type idx"));
369 if (!ex_to_idx(i1).get_dim().is_equal(_ex2()) || !ex_to_idx(i2).get_dim().is_equal(_ex2()))
370 throw(std::invalid_argument("index dimension of epsilon tensor must match number of indices"));
372 return indexed(tensepsilon(), indexed::antisymmetric, i1, i2);