def __new__(cls, symbol, coords, matrix, **kwargs): """ Create a new Metric object. Parameters ---------- symbol : str Name of the tensor and the symbol to denote it by when printed. coords : iterable List of ~sympy.Symbol objects to denote the coordinates by which derivatives are taken with respect to. matrix : (list, tuple, ~sympy.Matrix, ~sympy.Array) Matrix representation of the tensor to be used in substitution. Can be of any type that is acceptable by ~sympy.Array. Examples -------- >>> from sympy import diag, symbols >>> from einsteinpy.symbolic.tensor import indices, expand_tensor >>> from einsteinpy.symbolic.metric import Metric >>> t, x, y, z = symbols('t x y z') >>> eta = Metric('eta', [t, x, y, z], diag(1, -1, -1, -1)) >>> mu, nu = indices('mu nu', eta) >>> expr = eta(mu, nu) * eta(-mu, -nu) >>> expand_tensor(expr) 4 """ array = Array(matrix) if array.rank() != 2 or array.shape[0] != array.shape[1]: raise ValueError( "matrix must be square, received matrix of shape {}".format( array.shape)) obj = TensorIndexType.__new__( cls, symbol, metric=cls._MetricId(symbol, False), dim=array.shape[0], dummy_fmt=symbol, **kwargs, ) obj = AbstractTensor.__new__(cls, obj, array) obj.metric = Tensor(obj.name, array, obj, covar=(-1, -1)) obj.coords = tuple(coords) ReplacementManager[obj] = array return obj
def __new__(cls, symbol, matrix, metric, **kwargs): """ Create a new Tensor object. Parameters ---------- symbol : str Name of the tensor and the symbol to denote it by when printed. matrix : (list, tuple, ~sympy.Matrix, ~sympy.Array) Matrix representation of the tensor to be used in substitution. Can be of any type that is acceptable by ~sympy.Array. metric : Metric Classify the tensor as being defined in terms of a metric. Notes ----- If the parameter ``symmetry`` is passed, the tensor object will defined using a specific symmetry. Example values are (see sympy documentation for the function ``tensorsymmetry``): ``[[1]]`` vector ``[[1]*n]`` symmetric tensor of rank ``n`` ``[[n]]`` antisymmetric tensor of rank ``n`` ``[[2, 2]]`` monoterm slot symmetry of the Riemann tensor ``[[1],[1]]`` vector*vector ``[[2],[1],[1]]`` (antisymmetric tensor)*vector*vector Additionally, the parameter ``covar`` indicates that the passed array corresponds to the covariance of the tensor it is intended to describe. Lastly, the parameter ``comm`` is used to indicate what commutation group the tensor belongs to. In other words, it describes what other types of tensors the one being created is allowed to commute with. There are three commutation groups: ``general`` for ordinary tensors, ``metric`` for metric tensors, and ``partial`` for partial derivatives. Examples -------- >>> from sympy import diag, symbols >>> from einsteinpy.symbolic.tensor import Tensor, indices, expand_tensor >>> from einsteinpy.symbolic.metric import Metric >>> E1, E2, E3, B1, B2, B3 = symbols('E1:4 B1:4') >>> em = [[0, -E1, -E2, -E3], [E1, 0, -B3, B2], [E2, B3, 0, -B1], [E3, -B2, B1, 0]] >>> t, x, y, z = symbols('t x y z') >>> eta = Metric('eta', [t, x, y, z], diag(1, -1, -1, -1)) >>> F = Tensor('F', em, eta, symmetry=[[2]]) >>> mu, nu = indices('mu nu', eta) >>> expr = F(mu, nu) + F(nu, mu) >>> expand_tensor(expr) 0 >>> expr = F(mu, nu) * F(-mu, -nu) >>> expand_tensor(expr) 2*B_1**2 + 2*B_2**2 + 2*B_3**2 - 2*E_1**2 - 2*E_2**2 - 2*E_3**2 """ array = Array(matrix) sym = kwargs.pop("symmetry", [[1] * array.rank()]) sym = tensorsymmetry(*sym) symtype = TensorType(array.rank() * [metric], sym) comm = kwargs.pop("comm", "general") covar = tuple(kwargs.pop("covar", array.rank() * [1])) if len(covar) != array.rank(): raise ValueError( "covariance signature {} does not match tensor rank {}".format( covar, array.rank())) count = defaultdict(int) # type: dict def dummy_fmt_gen(idxtype): # generate a generic index for the entry in ReplacementManager. fmt = idxtype.dummy_fmt n = count[idxtype] count[idxtype] += 1 return fmt % n obj = TensorHead.__new__(cls, symbol, symtype, comm=comm, **kwargs) obj = AbstractTensor.__new__(cls, obj, array) # resolves a bug with pretty printing. obj.__class__.__name__ = "TensorHead" obj.covar = covar idx_names = map(dummy_fmt_gen, obj.index_types) idx_generator = map(Index, idx_names, obj.index_types) idxs = [ idx if covar[pos] > 0 else -idx for pos, idx in enumerate(idx_generator) ] ReplacementManager[obj(*idxs)] = array return obj