}
            if (res.isEmpty())
                return null;
            return res.equivalent();
        } else if (target instanceof Product) {
            Product product = (Product) target;
            Tensor derivative;
            List<Tensor> resultProducts = new ArrayList<>();
            for (int i = 0; i < product.size(); ++i) {
                derivative = getDerivative(product.getElements().get(i), var);
                if (derivative == null)
                    continue;
                Product clone = (Product) product.clone();
                clone.getElements().remove(i);
                if (!isOne(derivative))
                    clone.add(derivative);
                resultProducts.add(clone.equivalent());
            }
            if (resultProducts.isEmpty())
                return null;
            if (resultProducts.size() == 1)
                return resultProducts.get(0);
            return new Sum(resultProducts);
        } else if (target.getClass() == SimpleTensor.class) {
            SimpleTensor sp = (SimpleTensor) target;
            if (sp.getName() != var.getName())
                return null;
            if (sp.getIndices().size() == 0)
                return TensorNumber.createONE();
            Product kroneckers = new Product();
            Indices targetIndices = sp.getIndices();
            Indices varIndices = var.getIndices();
            for (int i = 0; i < sp.getIndices().size(); ++i)
                kroneckers.add(CC.createMetricOrKronecker(targetIndices.get(i), varIndices.get(i)));
            return kroneckers.equivalent();
        } else if (target.getClass() == TensorField.class) {
            TensorField field = (TensorField) target;
            Tensor[] args = field.getArgs();
            for (int i = 0; i < args.length; ++i)
                if (getDerivative(args[i], var) != null)
                    return Derivative.createFromInversed(target,var);
            return null;
        } else if (target instanceof AbstractScalarFunction) {
            AbstractScalarFunction func = (AbstractScalarFunction) target;
            Tensor der = getDerivative(func.getInnerTensor(), var);
            if (der == null)
                return null;
            if (isOne(der))
                return func.derivative();
            return new Product(func.derivative(), der);
        }
        //TODO get derivative ot derivative
        return null;
    }