Package cc.redberry.physics.feyncalc

Source Code of cc.redberry.physics.feyncalc.DiracTrace$Key5

/*
* Redberry: symbolic tensor computations.
*
* Copyright (c) 2010-2013:
*   Stanislav Poslavsky   <stvlpos@mail.ru>
*   Bolotin Dmitriy       <bolotin.dmitriy@gmail.com>
*
* This file is part of Redberry.
*
* Redberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Redberry is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Redberry. If not, see <http://www.gnu.org/licenses/>.
*/
package cc.redberry.physics.feyncalc;

import cc.redberry.core.context.CC;
import cc.redberry.core.graph.GraphType;
import cc.redberry.core.graph.PrimitiveSubgraph;
import cc.redberry.core.graph.PrimitiveSubgraphPartition;
import cc.redberry.core.indexgenerator.IndexGenerator;
import cc.redberry.core.indices.*;
import cc.redberry.core.number.Complex;
import cc.redberry.core.tensor.*;
import cc.redberry.core.tensor.iterator.FromChildToParentIterator;
import cc.redberry.core.transformations.EliminateMetricsTransformation;
import cc.redberry.core.transformations.Transformation;
import cc.redberry.core.transformations.expand.ExpandTransformation;
import cc.redberry.core.transformations.substitutions.SubstitutionTransformation;

import java.util.HashMap;

import static cc.redberry.core.indices.IndicesFactory.createSimple;
import static cc.redberry.core.indices.IndicesUtils.setType;
import static cc.redberry.core.tensor.Tensors.*;
import static cc.redberry.core.tensor.Tensors.simpleTensor;

/**
* @author Dmitry Bolotin
* @author Stanislav Poslavsky
*/
public class DiracTrace implements Transformation {
    private final int gammaName, gamma5Name, leviCivitaName;
    private final IndexType metricType, matrixType;
    private final LeviCivitaSimplify LeviCivitaSimplify;

    public DiracTrace() {
        this(parseSimple("G^a'_{a b'}"), parseSimple("G5^a'_b'"), parseSimple("e_{abcd}"));
    }

    public DiracTrace(SimpleTensor gammaMatrix) {
        //todo check correct input
        this.gammaName = gammaMatrix.getName();
        IndexType[] types = TraceUtils.extractTypesFromMatrix(gammaMatrix);
        this.metricType = types[0];
        this.matrixType = types[1];

        //creating default gamma5 tensor
        String gamma5String = CC.getNameManager().getNameDescriptor(gammaName).getName(null) + "5";
        StructureOfIndices gamma5Types = new StructureOfIndices(matrixType.getType(), 2, true, false);
        this.gamma5Name = CC.getNameManager().mapNameDescriptor(gamma5String, gamma5Types).getId();

        //creating default Levi-Civita tensor
        StructureOfIndices leviCivitaTypes = new StructureOfIndices(metricType.getType(), 4);
        this.leviCivitaName = CC.getNameManager().mapNameDescriptor("e", leviCivitaTypes).getId();
        SimpleTensor leviCivita = simpleTensor(leviCivitaName, IndicesFactory.createSimple(null,
                setType(metricType, 0),
                setType(metricType, 1),
                setType(metricType, 2),
                setType(metricType, 3)));
        this.LeviCivitaSimplify = new LeviCivitaSimplify(leviCivita);
    }

    public DiracTrace(SimpleTensor gammaMatrix, SimpleTensor gamma5, SimpleTensor leviCivita) {
        //todo check correct input
        this.gammaName = gammaMatrix.getName();
        this.gamma5Name = gamma5.getName();
        this.leviCivitaName = leviCivita.getName();
        IndexType[] types = TraceUtils.extractTypesFromMatrix(gammaMatrix);
        this.metricType = types[0];
        this.matrixType = types[1];
        this.LeviCivitaSimplify = new LeviCivitaSimplify(leviCivita);
    }

    @Override
    public Tensor transform(Tensor tensor) {
        //todo check for contains gammas
        tensor = ExpandTransformation.expand(tensor, EliminateMetricsTransformation.ELIMINATE_METRICS);
        tensor = EliminateMetricsTransformation.eliminate(tensor);
        FromChildToParentIterator iterator = new FromChildToParentIterator(tensor);
        Tensor current;
        out:
        while ((current = iterator.next()) != null) {
            if (isGammaOrGamma5(current)
                    && current.getIndices().getFree().size(matrixType) == 0) {
                iterator.set(Complex.ZERO);
            } else if (current instanceof Product) {
                if (current.getIndices().getFree().size(matrixType) != 0)
                    continue;
                Product product = (Product) current;
                ProductContent pc = product.getContent();
                int sizeOfIndexless = product.sizeOfIndexlessPart();
                PrimitiveSubgraph[] partition
                        = PrimitiveSubgraphPartition.calculatePartition(pc, matrixType);

                for (PrimitiveSubgraph subgraph : partition) {
                    if (subgraph.getGraphType() != GraphType.Cycle)
                        continue;

                    int[] positions = subgraph.getPartition();
                    //actual positions in current
                    for (int i = positions.length - 1; i >= 0; --i)
                        positions[i] = positions[i] + sizeOfIndexless;

                    int[] gg = calculateGammasInProduct(product.select(positions));
                    if (gg[0] + gg[1] != positions.length)
                        continue;

                    assert positions.length != 0;

                    if (positions.length == 1) {
                        iterator.set(Complex.ZERO);
                        continue out;
                    }

                    int gammasCount = gg[0];
                    int gamma5Count = gg[1];

                    if (gammasCount == 0) {
                        if (gamma5Count % 2 == 0) {
                            iterator.set(multiply(product.remove(positions), Complex.FOUR));
                            continue out;
                        } else {
                            iterator.set(Complex.ZERO);
                            continue out;
                        }
                    }

                    if (gamma5Count == 0 && gammasCount % 2 == 1) {
                        iterator.set(Complex.ZERO);
                        continue out;
                    }

                    if (gamma5Count % 2 == 1 && gammasCount % 2 == 1) {
                        iterator.set(Complex.ZERO);
                        continue out;
                    }

                    if (gamma5Count == 0)
                        current = traceWithout5(current, gammasCount);
                    else
                        current = trace5((Product) current, gammasCount, gamma5Count);

                }
                //todo d_i^i = 4
                iterator.set(current);
            }
        }
        return iterator.result();
    }

    //first is gamma, second is gamma5
    int[] calculateGammasInProduct(Tensor product) {
        int[] r = new int[2];
        for (Tensor t : product) {
            if (!(t instanceof SimpleTensor))
                continue;
            SimpleTensor st = (SimpleTensor) t;
            if (st.getName() == gammaName)
                ++r[0];
            if (st.getName() == gamma5Name)
                ++r[1];
        }
        return r;
    }

    /*
     * Trace without gamma5
     */

    private Tensor traceWithout5(Tensor tensor, int gammasCount) {
        tensor = createGammaSubstitution(gammasCount).transform(tensor);
        tensor = ExpandTransformation.expand(tensor, EliminateMetricsTransformation.ELIMINATE_METRICS);
        tensor = EliminateMetricsTransformation.eliminate(tensor);
        tensor = parseExpression("d^a_a = 4").transform(tensor);
        return tensor;
    }

    //cached trace identities
//todo make context independent
    private static final HashMap<Key, SubstitutionTransformation> cache = new HashMap<>();

    private static class Key {
        final int gammaName, gammasCount;
        final IndexType metricType, matrixType;

        private Key(int gammaName, int gammasCount, IndexType metricType, IndexType matrixType) {
            this.gammaName = gammaName;
            this.gammasCount = gammasCount;
            this.metricType = metricType;
            this.matrixType = matrixType;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o)
                return true;
            if (o == null || o.getClass() != Key.class)
                return false;
            Key k = (Key) o;
            return gammasCount == k.gammasCount &&
                    gammaName == k.gammaName
                    && metricType == k.metricType
                    && matrixType == k.matrixType;
        }

        @Override
        public int hashCode() {
            int result = gammaName;
            result = 31 * result + metricType.hashCode();
            result = 31 * result + matrixType.hashCode();
            return result;
        }
    }

    private SubstitutionTransformation createGammaSubstitution(int gammasCount) {
        Key key = new Key(gammaName, gammasCount, metricType, matrixType);
        SubstitutionTransformation sub = cache.get(key);
        if (sub != null)
            return sub;
        Tensor[] gammas = new Tensor[gammasCount];
        IndexGenerator generator = new IndexGenerator();
        int firstUpper, u = firstUpper = generator.generate(matrixType), i;
        for (i = 0; i < gammasCount; ++i) {
            gammas[i] = Tensors.simpleTensor(gammaName,
                    createSimple(null,
                            u | 0x80000000,
                            i == gammasCount - 1 ? firstUpper : (u = generator.generate(matrixType)),
                            generator.generate(metricType)));

        }
        sub = new SubstitutionTransformation(Tensors.multiply(gammas), traceOfArray(gammas, metricType));
        cache.put(key, sub);
        return sub;
    }

    static Tensor traceOfArray(Tensor[] product, IndexType metricType) {
        if (product.length == 1)
            return Complex.ZERO;
        if (product.length == 2)
            return multiply(Complex.FOUR,
                    createMetricOrKronecker(product[0].getIndices().get(metricType, 0),
                            product[1].getIndices().get(metricType, 0)));
        if (product.length % 2 != 0)
            return Complex.ZERO;
        SumBuilder sb = new SumBuilder();
        Tensor temp;
        for (int i = 0; i < product.length - 1; ++i) {
            temp = multiply(Complex.TWO,
                    createMetricOrKronecker(product[i].getIndices().get(metricType, 0),
                            product[i + 1].getIndices().get(metricType, 0)),
                    traceOfArray(subArray(product, i, i + 1), metricType));
            if (i % 2 != 0)
                temp = negate(temp);
            sb.put(temp);
            swap(product, i, i + 1);
        }
        return multiply(Complex.ONE_HALF, sb.build());
    }

    /*
     * Trace with gamma5
     */

    private Tensor trace5(Product product, int gammasCount, int gamma5Count) {
        if (gamma5Count == 0)
            return traceWithout5(product, gammasCount);
        if (gamma5Count % 2 == 1 && (gammasCount < 4 || gammasCount % 2 == 1))
            return Complex.ZERO;

        //extracting gamma matrices
        ProductBuilder gammasBuilder = new ProductBuilder(0, gammasCount + gamma5Count);
        int i;
        Tensor t, nonGammaPart = product;
        for (i = product.size() - 1; i >= 0; --i) {
            t = product.get(i);
            if (!isGammaOrGamma5(t))
                continue;

            //removing gamma from product
            if (nonGammaPart instanceof Product)
                nonGammaPart = ((Product) nonGammaPart).remove(i);
            else {
//                assert nonGammaPart instanceof SimpleTensor;
//                assert ((SimpleTensor) nonGammaPart).getName() == gammaName;
                nonGammaPart = Complex.ONE;
            }

            gammasBuilder.put(t);
        }

        Tensor gammasPart = gammasBuilder.build();
        SubstitutionTransformation[] gamma5 = gamma5Substitution();
        //eliminating multiple gamma5s
        gammasPart = eliminateGamma5((Product) gammasPart, gamma5[0]);

        //even number of gamma5s
        //then all of them were eliminated
        if (gamma5Count % 2 == 0) {
            t = traceWithout5(gammasPart, gammasCount);
            return multiply(nonGammaPart, t);
        }

        //main routine
        t = gamma5[1].transform(gammasPart);
        t = ExpandTransformation.expand(t);
        t = EliminateMetricsTransformation.eliminate(t);
        if (t instanceof Sum) {
            SumBuilder sb = new SumBuilder();
            for (Tensor tt : t) {
                assert tt instanceof Product;
                int[] gg = calculateGammasInProduct(tt);
                sb.put(trace5((Product) tt, gg[0], gg[1]));
            }
            t = sb.build();
        } else if (t instanceof Product) {
            int[] gg = calculateGammasInProduct(t);
            if (gg[0] != 0 || gg[1] != 0)
                t = trace5((Product) t, gg[0], gg[1]);
        }
        t = multiply(nonGammaPart, t);
        t = ExpandTransformation.expand(t, EliminateMetricsTransformation.ELIMINATE_METRICS);
        t = EliminateMetricsTransformation.eliminate(t);
        t = LeviCivitaSimplify.transform(t);
        t = parseExpression("d_a^a=4").transform(t);
        return t;
    }

    private Tensor eliminateGamma5(Product tensor, SubstitutionTransformation sub) {
        //find and remove temporary any non gamma5 matrix:
        Tensor pivot = null;
        Tensor t;
        for (int i = tensor.size() - 1; i >= 0; --i) {
            t = tensor.get(i);
            if (t instanceof SimpleTensor && ((SimpleTensor) t).getName() == gammaName) {
                pivot = t;
                tensor = (Product) tensor.remove(i);
                break;
            }
        }
        Tensor temp;
        t = tensor;
        do {
            temp = t;
            t = sub.transform(temp);
            t = EliminateMetricsTransformation.eliminate(t);
        } while (temp != t);

        return multiply(t, pivot);
    }

    //todo make context independent
    private static HashMap<Key5, SubstitutionTransformation[]> cache5 = new HashMap<>();

    private static final class Key5 extends Key {
        final int gamma5Name, leviCivita;

        private Key5(int gammaName, int gammasCount, IndexType metricType, IndexType matrixType, int gamma5Name, int leviCivita) {
            super(gammaName, gammasCount, metricType, matrixType);
            this.gamma5Name = gamma5Name;
            this.leviCivita = leviCivita;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o)
                return true;
            if (o == null || o.getClass() != Key5.class)
                return false;
            Key5 k = (Key5) o;
            return super.equals(o)
                    && gamma5Name == k.gamma5Name
                    && leviCivita == k.leviCivita;
        }

        @Override
        public int hashCode() {
            int result = super.hashCode();
            result = 31 * result + gamma5Name;
            return result;
        }

    }

    //first is swapping, second is trace of 4x1 and Chiholm-Kahane identitie
    private SubstitutionTransformation[] gamma5Substitution() {
        Key5 key = new Key5(gammaName, 3, metricType, matrixType, gamma5Name, leviCivitaName);
        SubstitutionTransformation[] subs = cache5.get(key);
        if (subs != null)
            return subs;
        subs = new SubstitutionTransformation[2];
        Expression[] expressions = new Expression[3];

        //G5*G_m = -G_m*G5
        expressions[0] = expression(
                multiply(
                        simpleTensor(gamma5Name, createSimple(null,
                                setType(matrixType, 0x80000000),
                                setType(matrixType, 1))),
                        simpleTensor(gammaName, createSimple(null,
                                setType(metricType, 0),
                                setType(matrixType, 1 | 0x80000000),
                                setType(matrixType, 2))))
                ,
                multiply(
                        Complex.MINUS_ONE,
                        simpleTensor(gammaName, createSimple(null,
                                setType(metricType, 0),
                                setType(matrixType, 0x80000000),
                                setType(matrixType, 1))),
                        simpleTensor(gamma5Name, createSimple(null,
                                setType(matrixType, 1 | 0x80000000),
                                setType(matrixType, 2))))
        );

        //G5*G5 = 1
        expressions[1] = expression(
                multiply(
                        simpleTensor(gamma5Name, createSimple(null,
                                setType(matrixType, 0x80000000),
                                setType(matrixType, 1))),
                        simpleTensor(gamma5Name, createSimple(null,
                                setType(matrixType, 1 | 0x80000000),
                                setType(matrixType, 2))))
                , createKronecker(setType(matrixType, 0x80000000), setType(matrixType, 2)));

        //Tr[G5] = 0
        expressions[2] = expression(simpleTensor(gamma5Name, createSimple(null,
                setType(matrixType, 0x80000000 | 0),
                setType(matrixType, 0))),
                Complex.ZERO);

        subs[0] = new SubstitutionTransformation(expressions);

        expressions = new Expression[2];

        //Tr[G_a*G_b*G_c*G_d*G5] = -4*I*e_abcd
        ProductBuilder pb = new ProductBuilder(0, 5);
        for (int i = 0; i < 4; ++i) {
            pb.put(simpleTensor(gammaName,
                    createSimple(null,
                            setType(metricType, i),
                            setType(matrixType, 0x80000000 | i),
                            setType(matrixType, i + 1))));
        }
        pb.put(simpleTensor(gamma5Name,
                createSimple(null,
                        setType(matrixType, 0x80000000 | 4),
                        setType(matrixType, 0))));
        expressions[0] = expression(pb.build(),
                multiply(Complex.MINUS_ONE, Complex.FOUR, Complex.IMAGE_ONE,
                        simpleTensor(leviCivitaName, createSimple(null, 0, 1, 2, 3))));

        //Chiholm-Kahane identitie:
        //G_a*G_b*G_c = g_ab*G_c-g_ac*G_b+g_bc*G_a-I*e_abcd*G5*G^d
        Tensor lhs = multiply(
                simpleTensor(gammaName, createSimple(null,
                        setType(metricType, 0),
                        setType(matrixType, 0x80000000),
                        setType(matrixType, 1))),
                simpleTensor(gammaName, createSimple(null,
                        setType(metricType, 1),
                        setType(matrixType, 1 | 0x80000000),
                        setType(matrixType, 2))),
                simpleTensor(gammaName, createSimple(null,
                        setType(metricType, 2),
                        setType(matrixType, 2 | 0x80000000),
                        setType(matrixType, 3)))
        );


        SumBuilder rhs = new SumBuilder();
        Tensor temp;
        for (int i = 0; i < 3; ++i) {
            temp = multiply(simpleTensor(gammaName,
                    createSimple(null,
                            setType(metricType, i),
                            setType(matrixType, 0x80000000),
                            setType(matrixType, 3))),
                    i == 0 ? createMetric(setType(metricType, 1), setType(metricType, 2))
                            : i == 1 ? createMetric(setType(metricType, 0), setType(metricType, 2))
                            : createMetric(setType(metricType, 0), setType(metricType, 1)));
            rhs.put(i == 1 ? negate(temp) : temp);
        }

        temp = multiply(Complex.MINUS_ONE, Complex.IMAGE_ONE,
                simpleTensor(leviCivitaName, createSimple(null,
                        setType(metricType, 0),
                        setType(metricType, 1),
                        setType(metricType, 2),
                        setType(metricType, 3))),
                simpleTensor(gamma5Name, createSimple(null,
                        setType(matrixType, 0x80000000),
                        setType(matrixType, 1))),
                simpleTensor(gammaName, createSimple(null,
                        setType(metricType, 0x80000000 | 3),
                        setType(matrixType, 1 | 0x80000000),
                        setType(matrixType, 3))));
        rhs.put(temp);
        expressions[1] = expression(lhs, rhs.build());
        subs[1] = new SubstitutionTransformation(expressions);
        cache5.put(key, subs);
        return subs;
    }

    private boolean isGammaOrGamma5(Tensor tensor) {
        return tensor instanceof SimpleTensor
                && (((SimpleTensor) tensor).getName() == gammaName || ((SimpleTensor) tensor).getName() == gamma5Name);
    }

    private static Tensor[] subArray(Tensor[] array, int a, int b) {
        Tensor[] result = new Tensor[array.length - 2];
        int k = 0;
        for (int i = 0; i < array.length; ++i) {
            if (i == a || i == b)
                continue;
            result[k++] = array[i];
        }
        return result;
    }

    private static void swap(Tensor[] array, int a, int b) {
        Tensor temp = array[a];
        array[a] = array[b];
        array[b] = temp;
    }

    public static Tensor trace(Tensor tensor) {
        return new DiracTrace().transform(tensor);
    }
}
TOP

Related Classes of cc.redberry.physics.feyncalc.DiracTrace$Key5

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.