Source code for einsteinpy.symbolic.helpers
import warnings
import numpy as np
import sympy
from sympy import ImmutableDenseNDimArray, derive_by_array
def raise_warning(WarningType, message):
warnings.warn(message, WarningType)
def _flatten_list(seq):
# flatten an arbitarily nested list
if not seq:
return []
if not isinstance(seq[0], list):
return [seq[0]] + _flatten_list(seq[1:])
return _flatten_list(seq[0]) + _flatten_list(seq[1:])
[docs]
def simplify_sympy_array(arr):
"""
Function to simplify sympy expression or array.
This function is explicitely defined as native ``simplify`` function within sympy
stopped working with sympy version change.
Parameters
----------
arr : ~sympy.tensor.array.ndim_array.NDimArray or ~sympy.core.expr.Expr
Any sympy array or expression.
Returns
-------
sympy.tensor.array.ndim_array.NDimArray or ~sympy.core.expr.Expr
Simplified sympy array or expression.
"""
try:
flattened_list = _flatten_list(arr.tolist())
simplified_flattened_list = [sympy.simplify(e) for e in flattened_list]
return sympy.Array(simplified_flattened_list, arr.shape)
except AttributeError:
return sympy.simplify(arr)
except IndexError:
return sympy.Array(sympy.simplify(sum(arr)))
[docs]
def sympy_to_np_array(arr):
"""
Function to convert sympy to numpy array
Parameters
----------
arr : ~sympy.tensor.array.ndim_array.NDimArray
Sympy Array
Returns
-------
~numpy.ndarray
Numpy Array
"""
return np.array(arr.tolist()).reshape(arr.shape)
[docs]
class TransformationMatrix(ImmutableDenseNDimArray):
"""
Class for defining transformation matrix for basis change of vectors and tensors.
"""
def __init__(
self,
iterable,
old_coords,
new_coords,
shape=None,
old2new=None,
new2old=None,
**kwargs
):
"""
Constructor.
Parameters
----------
iterable : iterable-object
2D list or array to pass a matrix.
old_coords : list or tuple
list of old coordinates.
For example, ``[x, y]``.
new_coords : list or tuple
list of new coordinates.
For example, ``[r, theta]``.
shape : tuple, optional
shape of the transformation matrix. Usually, not required.
Defaults to ``None``.
old2new : list or tuple, optional
List of expressions for new coordinates in terms of old coordinates.
For example, ``[x**2+y**2, atan2(y, x)]``.
new2old : list or tuple, optional
List of expressions for old coordinates in terms of new coordinates.
For example, ``[r*cos(theta), r*sin(theta)]``.
Raises
------
ValueError
Raised when tensor has a rank not equal to 2.
This is because, a matrix is expected.
"""
# __new__() is called after __init__() automatically
self._inv = None
self.old_coords, self.new_coords = old_coords, new_coords
self.old2new, self.new2old = old2new, new2old
def __new__(
cls,
iterable,
old_coords,
new_coords,
shape=None,
old2new=None,
new2old=None,
**kwargs
):
obj = super(TransformationMatrix, cls).__new__(cls, iterable, shape, **kwargs)
if not obj.rank() == 2:
raise ValueError("Expected a tensor with rank 2")
return obj
[docs]
@classmethod
def from_new2old(cls, old_coords, new_coords, new2old, **kwargs):
"""
Classmethod to obtain transformation matrix from old coordinates expressed
as a function of new coordinates.
Parameters
----------
old_coords : list or tuple
list of old coordinates.
For example, ``[x, y]``.
new_coords : list or tuple
list of new coordinates.
For example, ``[r, theta]``.
new2old : list or tuple, optional
List of expressions for old coordinates in terms of new coordinates.
For example, ``[r*cos(theta), r*sin(theta)]``.
"""
tmp_array = derive_by_array(new2old, new_coords)
tmp_array = sympy_to_np_array(tmp_array)
derivative_array = np.reciprocal(tmp_array)
return cls(
derivative_array,
old_coords,
new_coords,
old2new=None,
new2old=new2old,
**kwargs
)
@classmethod
def from_old2new(cls, old_coords, new_coords, old2new=None, new2old=None, **kwrags):
raise NotImplementedError
[docs]
def inv(self):
"""
Returns inverse of the transformation matrix
Returns
-------
~sympy.tensor.array.ndim_array.NDimArray
Inverse of the matrix.
"""
if self._inv is not None:
return self._inv
tmp_array = sympy_to_np_array(self)
tmp_array = np.reciprocal(tmp_array)
self._inv = ImmutableDenseNDimArray(tmp_array)
return self._inv
def _change_name(curr_name: str, context: str) -> str:
"""
Function to add descriptive tags to Tensor name, after the tensor is modified.
Currently handles Lorentz Transformation and Config Changes.
Parameters
----------
curr_name : str
Current name of the tensor
context : str
Context of name change - '__lt', for lorentz_transformation
- '__' + newconfig, for config_change (cc)
Returns
-------
str
Altered name of the tensor, with appropriate tags
"""
return curr_name + context if (curr_name is not None) else None