From a2c8e2cd98f28b301478e62f922c38745c4b5cde Mon Sep 17 00:00:00 2001 From: Christian Bauer Date: Thu, 18 Jul 2002 20:08:52 +0000 Subject: [PATCH] synced to 1.0 (tens4delta and mink4metric replaced by the new index dimension scheme) --- ginac/clifford.cpp | 6 +- ginac/ex.h | 7 +- ginac/idx.cpp | 30 ++++++- ginac/idx.h | 7 ++ ginac/input_lexer.h | 3 + ginac/input_lexer.ll | 25 ++++-- ginac/input_parser.yy | 36 +++++++- ginac/tensor.cpp | 204 +++++------------------------------------- ginac/tensor.h | 55 +----------- ginac/tinfos.h | 2 - 10 files changed, 121 insertions(+), 254 deletions(-) diff --git a/ginac/clifford.cpp b/ginac/clifford.cpp index 2d8904f9..b912e423 100644 --- a/ginac/clifford.cpp +++ b/ginac/clifford.cpp @@ -502,17 +502,19 @@ ex dirac_trace(const ex & e, unsigned char rl, const ex & trONE) return _ex0; // Tr gamma5 gamma.mu gamma.nu gamma.rho gamma.sigma = 4I * epsilon(mu, nu, rho, sigma) + // (the epsilon is always 4-dimensional) if (num == 5) { ex b1, i1, b2, i2, b3, i3, b4, i4; base_and_index(e.op(1), b1, i1); base_and_index(e.op(2), b2, i2); base_and_index(e.op(3), b3, i3); base_and_index(e.op(4), b4, i4); - return trONE * I * (eps0123(i1, i2, i3, i4) * b1 * b2 * b3 * b4).simplify_indexed(); + return trONE * I * (lorentz_eps(ex_to(i1).replace_dim(_ex4), ex_to(i2).replace_dim(_ex4), ex_to(i3).replace_dim(_ex4), ex_to(i4).replace_dim(_ex4)) * b1 * b2 * b3 * b4).simplify_indexed(); } // Tr gamma5 S_2k = // I/4! * epsilon0123.mu1.mu2.mu3.mu4 * Tr gamma.mu1 gamma.mu2 gamma.mu3 gamma.mu4 S_2k + // (the epsilon is always 4-dimensional) exvector ix(num-1), bv(num-1); for (unsigned i=1; i(idx1).replace_dim(_ex4), ex_to(idx2).replace_dim(_ex4), ex_to(idx3).replace_dim(_ex4), ex_to(idx4).replace_dim(_ex4)) * trace_string(v.begin(), num - 4); } } diff --git a/ginac/ex.h b/ginac/ex.h index af5cac31..e84decd3 100644 --- a/ginac/ex.h +++ b/ginac/ex.h @@ -88,10 +88,11 @@ public: ex(long i); ex(unsigned long i); ex(double const d); + /** Construct ex from string and a list of symbols. The input grammar is - * similar to the GiNaC output format. All symbols to be used in the - * expression must be specified in a lst in the second argument. Undefined - * symbols and other parser errors will throw an exception. */ + * similar to the GiNaC output format. All symbols and indices to be used + * in the expression must be specified in a lst in the second argument. + * Undefined symbols and other parser errors will throw an exception. */ ex(const std::string &s, const ex &l); // non-virtual functions in this class diff --git a/ginac/idx.cpp b/ginac/idx.cpp index bf103f0f..59c3ebc3 100644 --- a/ginac/idx.cpp +++ b/ginac/idx.cpp @@ -26,6 +26,8 @@ #include "idx.h" #include "symbol.h" #include "lst.h" +#include "relational.h" +#include "operators.h" #include "print.h" #include "archive.h" #include "utils.h" @@ -301,6 +303,7 @@ int varidx::compare_same_type(const basic & other) const // Check variance last so dummy indices will end up next to each other if (covariant != o.covariant) return covariant ? -1 : 1; + return 0; } @@ -311,6 +314,7 @@ bool varidx::match_same_type(const basic & other) const if (covariant != o.covariant) return false; + return inherited::match_same_type(other); } @@ -402,8 +406,12 @@ bool idx::is_dummy_pair_same_type(const basic & other) const if (!value.is_equal(o.value)) return false; - // Also the dimension - return dim.is_equal(o.dim); + // Dimensions need not be equal but must be comparable (so we can + // determine the minimum dimension of contractions) + if (dim.is_equal(o.dim)) + return true; + + return (dim < o.dim || dim > o.dim || (is_a(dim) && is_a(o.dim)) || (is_a(dim) && is_a(o.dim))); } bool varidx::is_dummy_pair_same_type(const basic & other) const @@ -433,6 +441,24 @@ bool spinidx::is_dummy_pair_same_type(const basic & other) const // non-virtual functions ////////// +ex idx::replace_dim(const ex & new_dim) const +{ + idx *i_copy = static_cast(duplicate()); + i_copy->dim = new_dim; + i_copy->clearflag(status_flags::hash_calculated); + return i_copy->setflag(status_flags::dynallocated); +} + +ex idx::minimal_dim(const idx & other) const +{ + if (dim.is_equal(other.dim) || dim < other.dim || (is_a(dim) && is_a(other.dim))) + return dim; + else if (dim > other.dim || (is_a(dim) && is_a(other.dim))) + return other.dim; + else + throw (std::runtime_error("idx::minimal_dim: index dimensions cannot be ordered")); +} + ex varidx::toggle_variance(void) const { varidx *i_copy = static_cast(duplicate()); diff --git a/ginac/idx.h b/ginac/idx.h index b648c62a..0b31696c 100644 --- a/ginac/idx.h +++ b/ginac/idx.h @@ -85,6 +85,13 @@ public: /** Check whether the dimension is symbolic. */ bool is_dim_symbolic(void) const {return !is_exactly_a(dim);} + /** Make a new index with the same value but a different dimension. */ + ex replace_dim(const ex & new_dim) const; + + /** Return the minimum of the dimensions of this and another index. + * If this is undecidable, throw an exception. */ + ex minimal_dim(const idx & other) const; + protected: ex value; /**< Expression that constitutes the index (numeric or symbolic name) */ ex dim; /**< Dimension of space (can be symbolic or numeric) */ diff --git a/ginac/input_lexer.h b/ginac/input_lexer.h index b7cc3c01..ed3f94c6 100644 --- a/ginac/input_lexer.h +++ b/ginac/input_lexer.h @@ -50,6 +50,9 @@ class ex; /** Set the input string to be parsed by ginac_yyparse() (used internally). */ extern void set_lexer_string(const std::string &s); +/** Get name of symbol/index (used internally). */ +extern std::string get_symbol_name(const ex & s); + /** Set the list of predefined symbols for the lexer (used internally). */ extern void set_lexer_symbols(ex l); diff --git a/ginac/input_lexer.ll b/ginac/input_lexer.ll index 6396248d..4a5a6501 100644 --- a/ginac/input_lexer.ll +++ b/ginac/input_lexer.ll @@ -39,6 +39,7 @@ #include "numeric.h" #include "symbol.h" #include "lst.h" +#include "idx.h" using namespace GiNaC; namespace GiNaC { @@ -47,7 +48,7 @@ namespace GiNaC { } // namespace GiNaC -// Table of all used symbols +// Table of all used symbols/indices struct sym_def { sym_def() : predefined(false) {} sym_def(const ex &s, bool predef) : sym(s), predefined(predef) {} @@ -166,22 +167,34 @@ void set_lexer_string(const std::string &s) curr_pos = 0; } -// Set the list of predefined symbols +// Get name of symbol/index +std::string get_symbol_name(const ex & s) +{ + if (is_a(s)) + return ex_to(s).get_name(); + else if (is_a(s) && is_a(s.op(0))) + return ex_to(s.op(0)).get_name(); + else + throw (std::runtime_error("get_symbol_name(): unexpected expression type")); +} + +// Set the list of predefined symbols/indices void set_lexer_symbols(ex l) { syms.clear(); if (!is_exactly_a(l)) return; for (unsigned i=0; i(l.op(i))) - syms[ex_to(l.op(i)).get_name()] = sym_def(l.op(i), true); + const ex &o = l.op(i); + if (is_a(o) || (is_a(o) && is_a(o.op(0)))) + syms[get_symbol_name(o)] = sym_def(o, true); } } -// Check whether symbol was predefined +// Check whether symbol/index was predefined bool is_lexer_symbol_predefined(const ex &s) { - sym_tab::const_iterator i = syms.find(ex_to(s).get_name()); + sym_tab::const_iterator i = syms.find(get_symbol_name(s)); if (i == syms.end()) return false; else diff --git a/ginac/input_parser.yy b/ginac/input_parser.yy index 778b8347..ecdc317e 100644 --- a/ginac/input_parser.yy +++ b/ginac/input_parser.yy @@ -37,6 +37,8 @@ #include "lst.h" #include "power.h" #include "exprseq.h" +#include "idx.h" +#include "indexed.h" #include "matrix.h" #include "inifcns.h" @@ -49,6 +51,9 @@ ex parsed_ex; // Last error message returned by parser static std::string parser_error; + +// Prototypes +ex attach_index(const ex & base, ex i, bool covariant); %} /* Tokens (T_LITERAL means a literal value returned by the parser, but not @@ -63,6 +68,7 @@ static std::string parser_error; %left '*' '/' '%' %nonassoc NEG %right '^' +%left '.' '~' %nonassoc '!' %start input @@ -90,12 +96,12 @@ exp : T_NUMBER {$$ = $1;} if (is_lexer_symbol_predefined($1)) $$ = $1.eval(); else - throw (std::runtime_error("unknown symbol '" + ex_to($1).get_name() + "'")); + throw (std::runtime_error("unknown symbol '" + get_symbol_name($1) + "'")); } | T_LITERAL {$$ = $1;} | T_DIGITS {$$ = $1;} | T_SYMBOL '(' exprseq ')' { - std::string n = ex_to($1).get_name(); + std::string n = get_symbol_name($1); if (n == "sqrt") { if ($3.nops() != 1) throw (std::runtime_error("too many arguments to sqrt()")); @@ -118,6 +124,8 @@ exp : T_NUMBER {$$ = $1;} | '-' exp %prec NEG {$$ = -$2;} | '+' exp %prec NEG {$$ = $2;} | exp '^' exp {$$ = pow($1, $3);} + | exp '.' exp {$$ = attach_index($1, $3, true);} + | exp '~' exp {$$ = attach_index($1, $3, false);} | exp '!' {$$ = factorial($1);} | '(' exp ')' {$$ = $2;} | '{' list_or_empty '}' {$$ = $2;} @@ -150,6 +158,30 @@ row : exp {$$ = lst($1);} */ %% +// Attach index to expression +ex attach_index(const ex & base, ex i, bool covariant) +{ + // Toggle index variance if necessary + if (is_a(i)) { + const varidx &vi = ex_to(i); + if (vi.is_covariant() != covariant) + i = vi.toggle_variance(); + } else if (!covariant) + throw (std::runtime_error("index '" + get_symbol_name(i) + "' is not a varidx and cannot be contravariant")); + + // Add index to an existing indexed object, or create a new indexed + // object if there are no indices yet + if (is_a(base)) { + const ex &b = base.op(0); + exvector iv; + for (unsigned n=1; n(other)); - const mink4metric &o = static_cast(other); - - if (pos_sig != o.pos_sig) - return pos_sig ? -1 : 1; - else - return inherited::compare_same_type(other); -} - int tensepsilon::compare_same_type(const basic & other) const { GINAC_ASSERT(is_a(other)); @@ -208,17 +160,13 @@ int tensepsilon::compare_same_type(const basic & other) const return minkowski ? -1 : 1; else if (pos_sig != o.pos_sig) return pos_sig ? -1 : 1; - else if (four_dim != o.four_dim) - return four_dim ? -1 : 1; else return inherited::compare_same_type(other); } DEFAULT_PRINT_LATEX(tensdelta, "delta", "\\delta") -DEFAULT_PRINT_LATEX(tens4delta, "delta4", "{\\delta^{(4)}}") DEFAULT_PRINT(tensmetric, "g") DEFAULT_PRINT_LATEX(minkmetric, "eta", "\\eta") -DEFAULT_PRINT_LATEX(mink4metric, "eta4", "{\\eta^{(4)}}") DEFAULT_PRINT_LATEX(spinmetric, "eps", "\\varepsilon") DEFAULT_PRINT_LATEX(tensepsilon, "eps", "\\varepsilon") @@ -232,47 +180,19 @@ ex tensdelta::eval_indexed(const basic & i) const const idx & i1 = ex_to(i.op(1)); const idx & i2 = ex_to(i.op(2)); - // Trace of delta tensor is the dimension of the space - if (is_dummy_pair(i1, i2)) - return i1.get_dim(); - - // Numeric evaluation - if (static_cast(i).all_index_values_are(info_flags::integer)) { - int n1 = ex_to(i1.get_value()).to_int(), n2 = ex_to(i2.get_value()).to_int(); - if (n1 == n2) - return _ex1; - else - return _ex0; + // Trace of delta tensor is the (effective) dimension of the space + if (is_dummy_pair(i1, i2)) { + try { + return i1.minimal_dim(i2); + } catch (std::exception &e) { + return i.hold(); + } } - // No further simplifications - return i.hold(); -} - -/** Automatic symbolic evaluation of an indexed 4-dimensional delta tensor. */ -ex tens4delta::eval_indexed(const basic & i) const -{ - GINAC_ASSERT(is_a(i)); - GINAC_ASSERT(i.nops() == 3); - GINAC_ASSERT(is_a(i.op(0))); - - const idx & i1 = ex_to(i.op(1)); - const idx & i2 = ex_to(i.op(2)); - - // Trace of 4-dimensional delta tensor is four - if (is_dummy_pair(i1, i2)) - return _ex4; - - // 4-dimensional delta tensor with numeric index dimension of four or - // less gets replaced by ordinary delta tensor - if (i1.get_dim().is_equal(i2.get_dim()) && is_a(i1.get_dim()) - && ex_to(i1.get_dim()).to_int() <= 4) - return indexed(tensdelta(), sy_symm(), i.op(1), i.op(2)); - // Numeric evaluation if (static_cast(i).all_index_values_are(info_flags::integer)) { int n1 = ex_to(i1.get_value()).to_int(), n2 = ex_to(i2.get_value()).to_int(); - if (n1 == n2 && n1 < 4) + if (n1 == n2) return _ex1; else return _ex0; @@ -330,45 +250,6 @@ ex minkmetric::eval_indexed(const basic & i) const return inherited::eval_indexed(i); } -/** Automatic symbolic evaluation of an indexed 4-dimensional Lorentz metric - * tensor. */ -ex mink4metric::eval_indexed(const basic & i) const -{ - GINAC_ASSERT(is_a(i)); - GINAC_ASSERT(i.nops() == 3); - GINAC_ASSERT(is_a(i.op(0))); - GINAC_ASSERT(is_a(i.op(1))); - GINAC_ASSERT(is_a(i.op(2))); - - const varidx & i1 = ex_to(i.op(1)); - const varidx & i2 = ex_to(i.op(2)); - - // 4-dimensional Lorentz metric tensor with numeric index dimension of - // four or less gets replaced by ordinary Lorentz metric tensor - if (i1.get_dim().is_equal(i2.get_dim()) && is_a(i1.get_dim()) - && ex_to(i1.get_dim()).to_int() <= 4) - return indexed(minkmetric(pos_sig), sy_symm(), i.op(1), i.op(2)); - - // A metric tensor with one covariant and one contravariant index gets - // replaced by a delta tensor - if (i1.is_covariant() != i2.is_covariant()) - return indexed(tens4delta(), sy_symm(), i.op(1), i.op(2)); - - // Numeric evaluation - if (static_cast(i).all_index_values_are(info_flags::nonnegint)) { - int n1 = ex_to(i1.get_value()).to_int(), n2 = ex_to(i2.get_value()).to_int(); - if (n1 != n2 || n1 > 3) - return _ex0; - else if (n1 == 0) - return pos_sig ? _ex_1 : _ex1; - else - return pos_sig ? _ex1 : _ex_1; - } - - // No further simplifications - return i.hold(); -} - /** Automatic symbolic evaluation of an indexed metric tensor. */ ex spinmetric::eval_indexed(const basic & i) const { @@ -458,9 +339,15 @@ again: // Contraction found, remove this tensor and substitute the // index in the second object - *self = _ex1; - *other = other->subs(other_idx == *free_idx); - return true; + try { + // minimal_dim() throws an exception when index dimensions are not comparable + ex min_dim = self_idx->minimal_dim(other_idx); + *self = _ex1; + *other = other->subs(other_idx == free_idx->replace_dim(min_dim)); + return true; + } catch (std::exception &e) { + return false; + } } } } @@ -490,23 +377,6 @@ bool tensdelta::contract_with(exvector::iterator self, exvector::iterator other, return replace_contr_index(self, other); } -/** Contraction of an indexed 4-dimensional delta tensor with something else. */ -bool tens4delta::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const -{ - GINAC_ASSERT(is_a(*self)); - GINAC_ASSERT(is_a(*other)); - GINAC_ASSERT(self->nops() == 3); - GINAC_ASSERT(is_a(self->op(0))); - - // Only contract with 4-dimensional delta, metric and epsilon tensors - if (!(is_a(other->op(0)) || is_a(other->op(0)) || is_a(other->op(0)))) - return false; - - // Replace the dummy index with this tensor's other index and remove - // the tensor - return replace_contr_index(self, other); -} - /** Contraction of an indexed metric tensor with something else. */ bool tensmetric::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const { @@ -525,24 +395,6 @@ bool tensmetric::contract_with(exvector::iterator self, exvector::iterator other return replace_contr_index(self, other); } -/** Contraction of an indexed 4-dimensional Lorentz metric tensor with something else. */ -bool mink4metric::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const -{ - GINAC_ASSERT(is_a(*self)); - GINAC_ASSERT(is_a(*other)); - GINAC_ASSERT(self->nops() == 3); - GINAC_ASSERT(is_a(self->op(0))); - - // Only contract with 4-dimensional metric and epsilon tensors - if (!(is_a(other->op(0)) || is_a(other->op(0)))) - return false; - - // Replace the dummy index with this tensor's other index and remove - // the tensor - return replace_contr_index(self, other); -} - - /** Contraction of an indexed spinor metric with something else. */ bool spinmetric::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const { @@ -636,9 +488,7 @@ bool tensepsilon::contract_with(exvector::iterator self, exvector::iterator othe matrix M(num, num); for (int i=0; iop(i+1), other->op(j+1)); - else if (minkowski) + if (minkowski) M(i, j) = lorentz_g(self->op(i+1), other->op(j+1), pos_sig); else M(i, j) = metric_tensor(self->op(i+1), other->op(j+1)); @@ -736,19 +586,7 @@ ex lorentz_eps(const ex & i1, const ex & i2, const ex & i3, const ex & i4, bool if (!ex_to(i1).get_dim().is_equal(_ex4)) throw(std::runtime_error("index dimension of epsilon tensor must match number of indices")); - return indexed(tensepsilon(true, pos_sig, false), sy_anti(), i1, i2, i3, i4); -} - -ex eps0123(const ex & i1, const ex & i2, const ex & i3, const ex & i4, bool pos_sig) -{ - if (!is_a(i1) || !is_a(i2) || !is_a(i3) || !is_a(i4)) - throw(std::invalid_argument("indices of epsilon tensor must be of type varidx")); - - ex dim = ex_to(i1).get_dim(); - if (dim.is_equal(4)) - return lorentz_eps(i1, i2, i3, i4, pos_sig); - else - return indexed(tensepsilon(true, pos_sig, true), sy_anti(), i1, i2, i3, i4); + return indexed(tensepsilon(true, pos_sig), sy_anti(), i1, i2, i3, i4); } } // namespace GiNaC diff --git a/ginac/tensor.h b/ginac/tensor.h index 2fa8e661..7774f4ba 100644 --- a/ginac/tensor.h +++ b/ginac/tensor.h @@ -120,46 +120,6 @@ public: }; -/** This class represents a 4-dimensional delta tensor embedded in a - * higher-dimensional space. Its matrix representation is - * diag(1,1,1,1,0,0...). */ -class tens4delta : public tensor -{ - GINAC_DECLARE_REGISTERED_CLASS(tens4delta, tensor) - - // functions overriding virtual functions from base classes -public: - void print(const print_context & c, unsigned level = 0) const; - ex eval_indexed(const basic & i) const; - bool contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const; -}; - - -/** This class represents a 4-dimensional Minkowski tensor embedded in - * a higher-dimensional space (so it's not really a metric for that space; - * that's why this is not a subclass of tensmetric). Its matrix representation - * is diag(1,-1,-1,-1,0,0,...) or diag(-1,1,1,1,0,0,...). */ -class mink4metric : public tensor -{ - GINAC_DECLARE_REGISTERED_CLASS(mink4metric, tensor) - - // other constructors -public: - /** Construct Lorentz metric tensor with given signature. */ - mink4metric(bool pos_sig); - - // functions overriding virtual functions from base classes -public: - void print(const print_context & c, unsigned level = 0) const; - ex eval_indexed(const basic & i) const; - bool contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const; - - // member variables -private: - bool pos_sig; /**< If true, the metric is diag(-1,1,...). Otherwise it is diag(1,-1,...). */ -}; - - /** This class represents the totally antisymmetric epsilon tensor. If * indexed, all indices must be of the same type and their number must * be equal to the dimension of the index space. */ @@ -169,7 +129,7 @@ class tensepsilon : public tensor // other constructors public: - tensepsilon(bool minkowski, bool pos_sig, bool four_dim); + tensepsilon(bool minkowski, bool pos_sig); // functions overriding virtual functions from base classes public: @@ -181,7 +141,6 @@ public: private: bool minkowski; /**< If true, tensor is in Minkowski-type space. Otherwise it is in a Euclidean space. */ bool pos_sig; /**< If true, the metric is assumed to be diag(-1,1,1...). Otherwise it is diag(1,-1,-1,...). This is only relevant if minkowski = true. */ - bool four_dim; /**< If true, this is a four-dimensional object embedded in a higher-dimensional space */ }; @@ -254,18 +213,6 @@ ex epsilon_tensor(const ex & i1, const ex & i2, const ex & i3); * @return newly constructed epsilon tensor */ ex lorentz_eps(const ex & i1, const ex & i2, const ex & i3, const ex & i4, bool pos_sig = false); -/** Create an epsilon tensor in a 4-dimensional projection of a D-dimensional - * Minkowski space. It vanishes whenever one of the indices is not in the - * set {0, 1, 2, 3}. - * - * @param i1 First index - * @param i2 Second index - * @param i3 Third index - * @param i4 Fourth index - * @param pos_sig Whether the signature of the metric is positive - * @return newly constructed epsilon tensor */ -ex eps0123(const ex & i1, const ex & i2, const ex & i3, const ex & i4, bool pos_sig = false); - } // namespace GiNaC #endif // ndef __GINAC_TENSOR_H__ diff --git a/ginac/tinfos.h b/ginac/tinfos.h index d02caa83..03b7315e 100644 --- a/ginac/tinfos.h +++ b/ginac/tinfos.h @@ -75,8 +75,6 @@ const unsigned TINFO_tensmetric = 0x000e1002U; const unsigned TINFO_minkmetric = 0x000e2001U; const unsigned TINFO_spinmetric = 0x000e2002U; const unsigned TINFO_tensepsilon = 0x000e1003U; -const unsigned TINFO_tens4delta = 0x000e1004U; -const unsigned TINFO_mink4metric = 0x000e1005U; const unsigned TINFO_su3one = 0x000e1008U; const unsigned TINFO_su3t = 0x000e1009U; const unsigned TINFO_su3f = 0x000e100aU; -- 2.49.0