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 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