def df(f, args, output_type='l'):
    """Return an the 1-form df, differential of function f.

    Examples:
    =========

    >>> from tensor_analysis.tensor_fields import df
    >>> from sympy import symbols, sin
    >>> from tensor_analysis.arraypy import Arraypy
    >>> x1, x2, x3= symbols('x1 x2 x3')

    f it's a function the differential of that is calculated:

    >>> f=x1**2*x2 + sin(x2*x3 - x2)

    args it's a list of symbol arguments of the function f. It can be in list,
    array of arraypy or contravariant tensor:

    >>> args_t=Arraypy([1,3,1]).to_tensor(1)
    >>> args_t[1]=x1
    >>> args_t[2]=x2
    >>> args_t[3]=x3

    output_type  it is an optional parameter accepting  symbol value of
    'l', 'a' or  't' and indicative on the type of result of calculations:
    - 'l' it is  a result as a list(list);
    - 'a' it is a result as an unidimensional array of arraypy;
    - 't' it is a result as an unidimensional covariant tensor.

    Differential:

    >>> d = df(f, args_t, 't')
    >>> print(d)
    2*x1*x2 x1**2 + (x3 - 1)*cos(x2*x3 - x2) x2*cos(x2*x3 - x2)

    The valence of the returned tensor:

    >>> d.type_pq
    (0, 1)

    """
    # Handling of a vector of arguments
    check_vector_of_arguments(args)

    # The definition of the start index
    if isinstance(args, list):
        idx_start = 0
    else:
        idx_start = args.start_index[0]

    # Creating the output array in accordance with the start index
    n = len(args)
    array = Arraypy([1, n, idx_start])

    # Calculation
    for k in range(idx_start, idx_start + n):
        array[k] = diff(f, args[k])

    # Handling of an output array
    if output_type == 't' or output_type == Symbol('t'):
        differential = Arraypy.to_tensor(array, -1)
    elif output_type == 'a' or output_type == Symbol('a'):
        differential = array
    elif output_type == 'l' or output_type == Symbol('l'):
        differential = Arraypy.to_list(array)
    else:
        raise TypeError(
            "The third argument must be 't' - TensorArray,'a' - Arraypy, \
            'l' - list")
    # Output
    return differential
def curl(X, args, output_type=None):
    """Return the rotor vector field curl(X) of a vector field X in R^3
    (curl, rotation, rotor, vorticity).
    A rotor can be calculated for only in three-dimensional Euclidean space.

    Examples:
    =========

    >>> from tensor_analysis.tensor_fields import curl
    >>> from sympy import symbols, cos
    >>> from tensor_analysis.arraypy import Arraypy, TensorArray
    >>> x1, x2, x3 = symbols('x1 x2 x3')

    X is a vector field, args it's a list of symbol arguments of a vector field
    X. They can be a list, array arraypy or contravariant tensor:

    >>> X=Arraypy(3)
    >>> X_t=TensorArray(X,(1))
    >>> X_t[0]=x1*x2**3
    >>> X_t[1]=x2-cos(x3)
    >>> X_t[2]=x3**3-x1
    >>> arg=[x1,x2,x3]
    >>> r=curl(X_t,arg,'t')
    >>> print(r)
    -sin(x3) 1 -3*x1*x2**2
    >>> r.type_pq
    (1, 0)

    """
    # Handling of a vector of arguments
    check_vector_of_arguments(args)
    if len(args) != 3:
        raise ValueError("Three variables are required")
    # The definition of the start index
    if isinstance(args, list):
        idx_args = 0
    else:
        idx_args = args.start_index[0]

    # Handling of a vector field
    check_the_vector_field(X)
    if len(X) != 3:
        raise ValueError("A three-dimensional vector field is necessary")
    # The definition of the start index and type of output
    if isinstance(X, (TensorArray, Arraypy)):
        if isinstance(X, TensorArray):
            out_t = 't'
        idx_X = X.start_index[0]
    else:
        idx_X = 0
        out_t = 'l'

    # The definition type of output of an output array
    if output_type is None:
        if out_t is not None:
            output_type = out_t
        else:
            output_type = 'a'

    # The definition of the start index
    if isinstance(X, type(args)) and (idx_X != idx_args):
        raise ValueError(
            "The start index of vector field and vector of arguments must be \
            equal")
    idx_st = idx_X

    # Creating the output array in accordance with the start index
    array = Arraypy([1, 3, idx_st])

    # Calculation
    if isinstance(X, (TensorArray, Arraypy)):
        X = X.to_list()
    if isinstance(args, (TensorArray, Arraypy)):
        args = args.to_list()

    array[idx_st] = (diff(X[2], args[1]) - diff(X[1], args[2]))
    array[idx_st + 1] = diff(X[0], args[2]) - diff(X[2], args[0])
    array[idx_st + 2] = diff(X[1], args[0]) - diff(X[0], args[1])

    # Handling of an output array
    if output_type == 't' or output_type == Symbol('t'):
        rotor = Arraypy.to_tensor(array, 1)
    elif output_type == 'a' or output_type == Symbol('a'):
        rotor = array
    elif output_type == 'l' or output_type == Symbol('l'):
        rotor = Arraypy.to_list(array)
    else:
        raise TypeError(
            "The third argument must be 't'-tensor,'a'-Arraypy, \
            'l'-list")
    # Output
    return rotor
def lie_xy(X, Y, args, output_type=None):
    """Return the vector field [X,Y], Lie bracket (commutator) of a vector
    fields X and Y.

    Examples:
    =========

    >>> from tensor_analysis.tensor_fields import lie_xy
    >>> from sympy import symbols, cos, sin
    >>> x1, x2, x3 = symbols('x1 x2 x3')

    X, Y is a vector field, args it's a list of symbol arguments.
    It's can be a list, array arraypy or contravariant tensor:

    >>> X=[x1*x2**3,x2-cos(x3),x3**3-x1]
    >>> Y = [x1**3*x2**3, x2*x3 - sin(x1*x3), x3**3 - x1**2]
    >>> arg = [x1, x2, x3]

    The Lie brackets of two vector fields:

    >>> lie = lie_xy(X, Y, arg,'a')
    >>> print(lie)
    2*x1**3*x2**6 + 3*x1**3*x2**2*(x2 - cos(x3)) - 3*x1*x2**2*(x2*x3 - \
    sin(x1*x3))
    -x1*x2**3*x3*cos(x1*x3) - x2*x3 + x3*(x2 - cos(x3)) + \
    (-x1 + x3**3)*(-x1*cos(x1*x3) + x2) - (-x1**2 + x3**3)*sin(x3) + sin(x1*x3)
    x1**3*x2**3 - 2*x1**2*x2**3 + 3*x3**2*(-x1 + x3**3) - \
    3*x3**2*(-x1**2 + x3**3)

    """

    # Handling of a vector of arguments
    check_vector_of_arguments(args)
    # The definition of the start index args
    if isinstance(args, list):
        idx_args = 0
    else:
        idx_args = args.start_index[0]

    # Handling of the first vector field
    check_the_vector_field(X)
    # The definition of the start index X and type of output
    if isinstance(X, (TensorArray, Arraypy)):
        if isinstance(X, TensorArray):
            out_t = 't'
        idx_X = X.start_index[0]
    else:
        idx_X = 0
        out_t = 'l'

    # Handling of the second vector field
    check_the_vector_field(Y)
    # The definition of the start index Y
    if isinstance(Y, (TensorArray, Arraypy)):
        idx_Y = Y.start_index[0]
    else:
        idx_Y = 0

    if len(Y) != len(X):
        raise ValueError(
            "The different number of arguments in the vector fields")
    elif len(args) != len(X) or len(args) != len(Y):
        raise ValueError(
            "The different number of components in the vector field and \
            vector of arguments")

    # Define the start index in the output tensor
    if type(Y) == type(X) == type(args):
        if idx_Y != idx_X or idx_Y != idx_args or idx_X != idx_args:
            raise ValueError(
                "The start index of vector fields and vector of argements \
                must be equal")
    if idx_Y != idx_X:
        raise ValueError(
            "The start index of vector fields must be equal")
    idx_st = idx_Y

    if output_type is None:
        if out_t is not None:
            output_type = out_t
        else:
            output_type = 'a'

    # Creating the output array in accordance with start indexes
    Li = Arraypy([1, len(X), idx_st])

    # Calculating
    if isinstance(Y, (TensorArray, Arraypy)):
        Y = Y.to_list()
    if isinstance(X, (TensorArray, Arraypy)):
        X = X.to_list()
    if isinstance(args, (TensorArray, Arraypy)):
        args = args.to_list()

    if X == Y:
        return 0
    else:
        indices = range(len(args))
        for i in indices:
            for k in indices:
                Li[i +
                   idx_st] += Add(diff(Y[i], args[k]) *
                                  X[k] -
                                  diff(X[i], args[k]) *
                                  Y[k])
    # Handling of an output array
    if output_type == 't' or output_type == Symbol('t'):
        Lie = Arraypy.to_tensor(Li, 1)
    elif output_type == 'a' or output_type == Symbol('a'):
        Lie = Li
    elif output_type == 'l' or output_type == Symbol('l'):
        Lie = Arraypy.to_list(Li)
    else:
        raise TypeError(
            "The third argument must be 't'-TensorArray,'a'-Arraypy, \
            'l'-list")

    # Output
    return Lie
def grad(f, args, g=None, output_type=None):
    """Return the vector field gradient of a function f(x).

    Examples:
    =========

    >>> from tensor_analysis.tensor_fields import grad
    >>> from sympy import symbols, sin
    >>> from tensor_analysis.arraypy import Arraypy
    >>> x1, x2, x3 = symbols('x1 x2 x3')

    f it's a function the differential of that is calculated:

    >>> f=x1**2*x2 + sin(x2*x3 - x2)

    args it's a list of symbol arguments of function of f.
    It can be in list, array of arraypy or contravariant tensor:

    >>> args=[x1,x2,x3]

    g - optional parameter, metric tensor, which can be a matrix "Matrix",
    array of arraypy or covariant tensor:

    >>> g=Arraypy([2,3,1])
    >>> g_t=g.to_tensor((-1,-1))
    >>> g_t[1,1]=2
    >>> g_t[1,2]=1
    >>> g_t[1,3]=0
    >>> g_t[2,1]=1
    >>> g_t[2,2]=3
    >>> g_t[2,3]=0
    >>> g_t[3,1]=0
    >>> g_t[3,2]=0
    >>> g_t[3,3]=1

    output _ type  it is an optional parameter accepting  symbol value of
    'l', 'a' or  't' and indicative on the type of result of calculations:
    - 'l' it is  a result as a list(list);
    - 'a' it is a result as an unidimensional array of arraypy;
    - 't' it is a result as an unidimensional covariant tensor.

    Gradient:
    >>> gr=grad(f,args,g_t,'a')
    >>> print(gr)
    -x1**2/5 + 6*x1*x2/5 - (x3 - 1)*cos(x2*x3 - x2)/5 2*x1**2/5 - 2*x1*x2/5 + \
    2*(x3 - 1)*cos(x2*x3 - x2)/5 x2*cos(x2*x3 - x2)

    """
    # Handling of a vector of arguments
    check_vector_of_arguments(args)

    # The definition of the start index
    if isinstance(args, list):
        idx_args = 0
    else:
        idx_args = args.start_index[0]

    # Handling of the metric tensor
    # 1. if g is not NULL
    if g is not None:
        if output_type is None:
            output_type = 't'
        check_metric_tensor(g)

        # The definition of the start index
        if isinstance(g, Matrix):
            idx_st = 0
        else:
            idx_st = g.start_index[0]
        # The start index is the same
        if isinstance(g, type(args)) and idx_st != idx_args:
            raise ValueError(
                "The start index of the metric tensor and vector of arguments \
                must be equal")
        if isinstance(g, (TensorArray, Arraypy)):
            g = g.to_matrix()
    # 2.if g is NULL
    else:
        # g - the identity matrix
        g = eye(len(args))
        idx_st = 0

    # Creating the output array in accordance with start indexes
    n = len(args)
    array = Arraypy([1, n, idx_st])
    indices = range(idx_st, idx_st + n)

    # Calculating
    g_inv = g.inv()
    if isinstance(args, (TensorArray, Arraypy)):
        args = args.to_list()
    for i in indices:
        for j in indices:
            array[i] += (g_inv[i - idx_st, j - idx_st] * diff(f, args[j -
                                                                      idx_st]))

    # Handling of an output array
    if output_type == 't' or output_type == Symbol('t'):
        gradient = Arraypy.to_tensor(array, 1)
    elif output_type == 'a' or output_type == Symbol('a'):
        gradient = array
    elif output_type == 'l' or output_type == Symbol('l') or output_type is \
            None:
        gradient = Arraypy.to_list(array)
    else:
        raise TypeError(
            "The third argument must be 't' - tensor,'a' - Arraypy, \
            'l' - list")
# Output
    return gradient
def df(f, args, output_type='l'):
    """Return an the 1-form df, differential of function f.

    Examples:
    =========

    >>> from tensor_analysis.tensor_fields import df
    >>> from sympy import symbols, sin
    >>> from tensor_analysis.arraypy import Arraypy
    >>> x1, x2, x3= symbols('x1 x2 x3')

    f it's a function the differential of that is calculated:

    >>> f=x1**2*x2 + sin(x2*x3 - x2)

    args it's a list of symbol arguments of the function f. It can be in list,
    array of arraypy or contravariant tensor:

    >>> args_t=Arraypy([1,3,1]).to_tensor(1)
    >>> args_t[1]=x1
    >>> args_t[2]=x2
    >>> args_t[3]=x3

    output_type  it is an optional parameter accepting  symbol value of
    'l', 'a' or  't' and indicative on the type of result of calculations:
    - 'l' it is  a result as a list(list);
    - 'a' it is a result as an unidimensional array of arraypy;
    - 't' it is a result as an unidimensional covariant tensor.

    Differential:

    >>> d = df(f, args_t, 't')
    >>> print(d)
    2*x1*x2 x1**2 + (x3 - 1)*cos(x2*x3 - x2) x2*cos(x2*x3 - x2)

    The valence of the returned tensor:

    >>> d.type_pq
    (0, 1)

    """
    # Handling of a vector of arguments
    check_vector_of_arguments(args)

    # The definition of the start index
    if isinstance(args, list):
        idx_start = 0
    else:
        idx_start = args.start_index[0]

    # Creating the output array in accordance with the start index
    n = len(args)
    array = Arraypy([1, n, idx_start])

    # Calculation
    for k in range(idx_start, idx_start + n):
        array[k] = diff(f, args[k])

    # Handling of an output array
    if output_type == 't' or output_type == Symbol('t'):
        differential = Arraypy.to_tensor(array, -1)
    elif output_type == 'a' or output_type == Symbol('a'):
        differential = array
    elif output_type == 'l' or output_type == Symbol('l'):
        differential = Arraypy.to_list(array)
    else:
        raise TypeError(
            "The third argument must be 't' - TensorArray,'a' - Arraypy, \
            'l' - list")
    # Output
    return differential
def lie_xy(X, Y, args, output_type=None):
    """Return the vector field [X,Y], Lie bracket (commutator) of a vector
    fields X and Y.

    Examples:
    =========

    >>> from tensor_analysis.tensor_fields import lie_xy
    >>> from sympy import symbols, cos, sin
    >>> x1, x2, x3 = symbols('x1 x2 x3')

    X, Y is a vector field, args it's a list of symbol arguments.
    It's can be a list, array arraypy or contravariant tensor:

    >>> X=[x1*x2**3,x2-cos(x3),x3**3-x1]
    >>> Y = [x1**3*x2**3, x2*x3 - sin(x1*x3), x3**3 - x1**2]
    >>> arg = [x1, x2, x3]

    The Lie brackets of two vector fields:

    >>> lie = lie_xy(X, Y, arg,'a')
    >>> print(lie)
    2*x1**3*x2**6 + 3*x1**3*x2**2*(x2 - cos(x3)) - 3*x1*x2**2*(x2*x3 - \
    sin(x1*x3))
    -x1*x2**3*x3*cos(x1*x3) - x2*x3 + x3*(x2 - cos(x3)) + \
    (-x1 + x3**3)*(-x1*cos(x1*x3) + x2) - (-x1**2 + x3**3)*sin(x3) + sin(x1*x3)
    x1**3*x2**3 - 2*x1**2*x2**3 + 3*x3**2*(-x1 + x3**3) - \
    3*x3**2*(-x1**2 + x3**3)

    """

    # Handling of a vector of arguments
    check_vector_of_arguments(args)
    # The definition of the start index args
    if isinstance(args, list):
        idx_args = 0
    else:
        idx_args = args.start_index[0]

    # Handling of the first vector field
    check_the_vector_field(X)
    # The definition of the start index X and type of output
    if isinstance(X, (TensorArray, Arraypy)):
        if isinstance(X, TensorArray):
            out_t = 't'
        idx_X = X.start_index[0]
    else:
        idx_X = 0
        out_t = 'l'

    # Handling of the second vector field
    check_the_vector_field(Y)
    # The definition of the start index Y
    if isinstance(Y, (TensorArray, Arraypy)):
        idx_Y = Y.start_index[0]
    else:
        idx_Y = 0

    if len(Y) != len(X):
        raise ValueError(
            "The different number of arguments in the vector fields")
    elif len(args) != len(X) or len(args) != len(Y):
        raise ValueError(
            "The different number of components in the vector field and \
            vector of arguments")

    # Define the start index in the output tensor
    if type(Y) == type(X) == type(args):
        if idx_Y != idx_X or idx_Y != idx_args or idx_X != idx_args:
            raise ValueError(
                "The start index of vector fields and vector of argements \
                must be equal")
    if idx_Y != idx_X:
        raise ValueError("The start index of vector fields must be equal")
    idx_st = idx_Y

    if output_type is None:
        if out_t is not None:
            output_type = out_t
        else:
            output_type = 'a'

    # Creating the output array in accordance with start indexes
    Li = Arraypy([1, len(X), idx_st])

    # Calculating
    if isinstance(Y, (TensorArray, Arraypy)):
        Y = Y.to_list()
    if isinstance(X, (TensorArray, Arraypy)):
        X = X.to_list()
    if isinstance(args, (TensorArray, Arraypy)):
        args = args.to_list()

    if X == Y:
        return 0
    else:
        indices = range(len(args))
        for i in indices:
            for k in indices:
                Li[i + idx_st] += Add(
                    diff(Y[i], args[k]) * X[k] - diff(X[i], args[k]) * Y[k])
    # Handling of an output array
    if output_type == 't' or output_type == Symbol('t'):
        Lie = Arraypy.to_tensor(Li, 1)
    elif output_type == 'a' or output_type == Symbol('a'):
        Lie = Li
    elif output_type == 'l' or output_type == Symbol('l'):
        Lie = Arraypy.to_list(Li)
    else:
        raise TypeError(
            "The third argument must be 't'-TensorArray,'a'-Arraypy, \
            'l'-list")

    # Output
    return Lie
def curl(X, args, output_type=None):
    """Return the rotor vector field curl(X) of a vector field X in R^3
    (curl, rotation, rotor, vorticity).
    A rotor can be calculated for only in three-dimensional Euclidean space.

    Examples:
    =========

    >>> from tensor_analysis.tensor_fields import curl
    >>> from sympy import symbols, cos
    >>> from tensor_analysis.arraypy import Arraypy, TensorArray
    >>> x1, x2, x3 = symbols('x1 x2 x3')

    X is a vector field, args it's a list of symbol arguments of a vector field
    X. They can be a list, array arraypy or contravariant tensor:

    >>> X=Arraypy(3)
    >>> X_t=TensorArray(X,(1))
    >>> X_t[0]=x1*x2**3
    >>> X_t[1]=x2-cos(x3)
    >>> X_t[2]=x3**3-x1
    >>> arg=[x1,x2,x3]
    >>> r=curl(X_t,arg,'t')
    >>> print(r)
    -sin(x3) 1 -3*x1*x2**2
    >>> r.type_pq
    (1, 0)

    """
    # Handling of a vector of arguments
    check_vector_of_arguments(args)
    if len(args) != 3:
        raise ValueError("Three variables are required")
    # The definition of the start index
    if isinstance(args, list):
        idx_args = 0
    else:
        idx_args = args.start_index[0]

    # Handling of a vector field
    check_the_vector_field(X)
    if len(X) != 3:
        raise ValueError("A three-dimensional vector field is necessary")
    # The definition of the start index and type of output
    if isinstance(X, (TensorArray, Arraypy)):
        if isinstance(X, TensorArray):
            out_t = 't'
        idx_X = X.start_index[0]
    else:
        idx_X = 0
        out_t = 'l'

    # The definition type of output of an output array
    if output_type is None:
        if out_t is not None:
            output_type = out_t
        else:
            output_type = 'a'

    # The definition of the start index
    if isinstance(X, type(args)) and (idx_X != idx_args):
        raise ValueError(
            "The start index of vector field and vector of arguments must be \
            equal")
    idx_st = idx_X

    # Creating the output array in accordance with the start index
    array = Arraypy([1, 3, idx_st])

    # Calculation
    if isinstance(X, (TensorArray, Arraypy)):
        X = X.to_list()
    if isinstance(args, (TensorArray, Arraypy)):
        args = args.to_list()

    array[idx_st] = (diff(X[2], args[1]) - diff(X[1], args[2]))
    array[idx_st + 1] = diff(X[0], args[2]) - diff(X[2], args[0])
    array[idx_st + 2] = diff(X[1], args[0]) - diff(X[0], args[1])

    # Handling of an output array
    if output_type == 't' or output_type == Symbol('t'):
        rotor = Arraypy.to_tensor(array, 1)
    elif output_type == 'a' or output_type == Symbol('a'):
        rotor = array
    elif output_type == 'l' or output_type == Symbol('l'):
        rotor = Arraypy.to_list(array)
    else:
        raise TypeError("The third argument must be 't'-tensor,'a'-Arraypy, \
            'l'-list")
    # Output
    return rotor
def grad(f, args, g=None, output_type=None):
    """Return the vector field gradient of a function f(x).

    Examples:
    =========

    >>> from tensor_analysis.tensor_fields import grad
    >>> from sympy import symbols, sin
    >>> from tensor_analysis.arraypy import Arraypy
    >>> x1, x2, x3 = symbols('x1 x2 x3')

    f it's a function the differential of that is calculated:

    >>> f=x1**2*x2 + sin(x2*x3 - x2)

    args it's a list of symbol arguments of function of f.
    It can be in list, array of arraypy or contravariant tensor:

    >>> args=[x1,x2,x3]

    g - optional parameter, metric tensor, which can be a matrix "Matrix",
    array of arraypy or covariant tensor:

    >>> g=Arraypy([2,3,1])
    >>> g_t=g.to_tensor((-1,-1))
    >>> g_t[1,1]=2
    >>> g_t[1,2]=1
    >>> g_t[1,3]=0
    >>> g_t[2,1]=1
    >>> g_t[2,2]=3
    >>> g_t[2,3]=0
    >>> g_t[3,1]=0
    >>> g_t[3,2]=0
    >>> g_t[3,3]=1

    output _ type  it is an optional parameter accepting  symbol value of
    'l', 'a' or  't' and indicative on the type of result of calculations:
    - 'l' it is  a result as a list(list);
    - 'a' it is a result as an unidimensional array of arraypy;
    - 't' it is a result as an unidimensional covariant tensor.

    Gradient:
    >>> gr=grad(f,args,g_t,'a')
    >>> print(gr)
    -x1**2/5 + 6*x1*x2/5 - (x3 - 1)*cos(x2*x3 - x2)/5 2*x1**2/5 - 2*x1*x2/5 + \
    2*(x3 - 1)*cos(x2*x3 - x2)/5 x2*cos(x2*x3 - x2)

    """
    # Handling of a vector of arguments
    check_vector_of_arguments(args)

    # The definition of the start index
    if isinstance(args, list):
        idx_args = 0
    else:
        idx_args = args.start_index[0]

    # Handling of the metric tensor
    # 1. if g is not NULL
    if g is not None:
        if output_type is None:
            output_type = 't'
        check_metric_tensor(g)

        # The definition of the start index
        if isinstance(g, Matrix):
            idx_st = 0
        else:
            idx_st = g.start_index[0]
        # The start index is the same
        if isinstance(g, type(args)) and idx_st != idx_args:
            raise ValueError(
                "The start index of the metric tensor and vector of arguments \
                must be equal")
        if isinstance(g, (TensorArray, Arraypy)):
            g = g.to_matrix()
    # 2.if g is NULL
    else:
        # g - the identity matrix
        g = eye(len(args))
        idx_st = 0

    # Creating the output array in accordance with start indexes
    n = len(args)
    array = Arraypy([1, n, idx_st])
    indices = range(idx_st, idx_st + n)

    # Calculating
    g_inv = g.inv()
    if isinstance(args, (TensorArray, Arraypy)):
        args = args.to_list()
    for i in indices:
        for j in indices:
            array[i] += (g_inv[i - idx_st, j - idx_st] *
                         diff(f, args[j - idx_st]))

    # Handling of an output array
    if output_type == 't' or output_type == Symbol('t'):
        gradient = Arraypy.to_tensor(array, 1)
    elif output_type == 'a' or output_type == Symbol('a'):
        gradient = array
    elif output_type == 'l' or output_type == Symbol('l') or output_type is \
            None:
        gradient = Arraypy.to_list(array)
    else:
        raise TypeError(
            "The third argument must be 't' - tensor,'a' - Arraypy, \
            'l' - list")


# Output
    return gradient