Advertisement
Guest User

Riemann tensor library

a guest
Oct 31st, 2015
454
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.66 KB | None | 0 0
  1. import sympy as sympy
  2. class Riemann:
  3.     """
  4.    Used for defining a Riemann curvature tensor or Ricci tensor
  5.    for a given metric between cartesian coordinates and another
  6.    orthognal coordinate system.
  7.    """
  8.     def __init__(self,g,sys_title="coordinate_system",dim=3,user_coord=None,flat_system=None, flat_g = None):
  9.         """
  10.        Contructor __init__ initializes the object for a given
  11.        metric g (symbolic matrix). The metric must be defined
  12.        with sympy variables u and v for the orthoganl basis in
  13.        the Cartesian coordinate system.
  14.  
  15.        g          : metric defined as nxn Sympy.Matrix object
  16.        sys_titles : descriptive information about the coordinate system
  17.                     besides Cartesian coordinates
  18.        dim        : R^2, R^3, or R^4
  19.        user_coord : User pre-defines coordinate system using Basescalar objects
  20.        metric_two_form : User provides a BaseScalar object
  21.        """
  22.         from sympy.diffgeom import Manifold, Patch
  23.         self.dim = dim
  24.         self.g = g
  25.         self.manifold = Manifold("M",dim)
  26.         self.patch = Patch("P",self.manifold)
  27.         if user_coord is None:
  28.             self._set_coordinates(sys_title)
  29.         else:
  30.             self._set_user_coordinates(sys_title,user_coord)        
  31.         self.metric = self._metric_to_twoform(g)
  32.         if flat_system == True:
  33.             print 'Setting dimension to one lower, and replacing the metric tensor with the flat metric.'
  34.             self.dim = dim - 1
  35.             self.g = flat_g
  36.     def _set_user_coordinates(self,sys_title,user_coord):
  37.         from sympy.diffgeom import CoordSystem
  38.         patch = self.patch
  39.         if self.dim==4:
  40.             #cartesian = CoordSystem("cartesian",patch, ["x", "y", "z", "t"])
  41.             #x, y, z, t = cartesian.coord_functions()
  42.             system = CoordSystem(sys_title, patch, [str(user_coord[0]),str(user_coord[1]),\
  43.                                                      str(user_coord[2]),str(user_coord[3])])
  44.             u, v, w, t = system.coord_functions()
  45.             self.w = w
  46.             self.t = t
  47.  
  48.         if self.dim==3:  
  49.             #cartesian = CoordSystem("cartesian",patch, ["x", "y", "z"])
  50.             #x, y, z = cartesian.coord_functions()
  51.             system = CoordSystem(sys_title, patch, [str(user_coord[0]),str(user_coord[1]),
  52.                                                      str(user_coord[2])])
  53.             u, v, w = system.coord_functions()
  54.             self.w = w
  55.            
  56.         if self.dim==2:
  57.             #cartesian = CoordSystem("cartesian",patch, ["x", "y"])
  58.             #x, y = cartesian.coord_functions()
  59.             system = CoordSystem(sys_title, patch, [str(user_coord[0]),str(user_coord[1])])
  60.             u, v = system.coord_functions()
  61.            
  62.         self.u, self.v = u, v
  63.         self.system = system    
  64.  
  65.     def _set_coordinates(self,sys_title):
  66.         from sympy.diffgeom import CoordSystem
  67.         patch = self.patch
  68.         if self.dim==4:
  69.             #cartesian = CoordSystem("cartesian",patch, ["x", "y", "z", "t"])
  70.             #x, y, z, t = cartesian.coord_functions()
  71.             system = CoordSystem(sys_title, patch, ["u", "v", "w","t"])
  72.             u, v, w, t = system.coord_functions()
  73.             self.w = w
  74.             self.t = t
  75.  
  76.         if self.dim==3:  
  77.             #cartesian = CoordSystem("cartesian",patch, ["x", "y", "z"])
  78.             #x, y, z = cartesian.coord_functions()
  79.             system = CoordSystem(sys_title, patch, ["u", "v", "w"])
  80.             u, v, w = system.coord_functions()
  81.             self.w = w
  82.            
  83.         if self.dim==2:
  84.             #cartesian = CoordSystem("cartesian",patch, ["x", "y"])
  85.             #x, y = cartesian.coord_functions()
  86.             system = CoordSystem(sys_title, patch, ["u", "v"])
  87.             u, v = system.coord_functions()
  88.            
  89.         self.u, self.v = u, v
  90.         self.system = system
  91.    
  92.     def _metric_to_twoform(self,g):
  93.         dim = self.dim
  94.         system = self.system
  95.         diff_forms = system.base_oneforms()
  96.         u_, v_ = self.u, self.v
  97.         u = u_
  98.         v = v_
  99.         if dim >= 3:
  100.             w_ = self.w
  101.             w = w_
  102.         if dim == 4:
  103.             t_ = self.t
  104.             t = t_
  105.  
  106.         from sympy import asin, acos, atan, cos, log, ln, exp, cosh, sin, sinh, sqrt, tan, tanh
  107.         import sympy.abc as abc
  108.         self._abc = abc
  109.         self._symbols = ['*','/','(',')',"'",'"']
  110.         self._letters = []
  111.         g_ = sympy.Matrix(dim*[dim*[0]])
  112.         # re-evaluate the metric for (u,v,w,t if 4D) which are Basescalar objects
  113.         for i in range(dim):
  114.             for j in range(dim):
  115.                 expr = str(g[i,j])
  116.                 self._try_expr(expr) # evaluate expr in a safe environment
  117.                 for letter in self._letters:
  118.                     exec('from sympy.abc import %s'%letter)
  119.                 g_[i,j] = eval(expr) # this will now work for any variables defined in sympy.abc
  120.                 g_[i,j] = g_[i,j].subs(u,u_)
  121.                 g_[i,j] = g_[i,j].subs(v,v_)
  122.                 if dim >= 3:
  123.                     g_[i,j] = g_[i,j].subs(w,w_)
  124.                 if dim == 4:
  125.                     g_[i,j] = g_[i,j].subs(t,t_)
  126.        
  127.         from sympy.diffgeom import TensorProduct
  128.         metric_diff_form = sum([TensorProduct(di, dj)*g_[i, j]
  129.                                for i, di in enumerate(diff_forms)
  130.                                for j, dj in enumerate(diff_forms)])    
  131.         return metric_diff_form
  132.  
  133.     def _try_expr(self,expr):
  134.         """
  135.        This is a help function used initially to evaluate the user-defined metric
  136.        elements as a sympy expression : expr. The purpose of this method is to
  137.        prevent the namespace of the user from being polluted by the command
  138.        'from sympy.abc import *'.
  139.  
  140.        expr : a string object to be evaluated as a sympy expression
  141.        """
  142.         from sympy import asin, acos, atan, cos, log, ln, exp, cosh, sin, sinh, sqrt, tan, tanh
  143.         letters = self._letters
  144.         abc = self._abc
  145.         try:
  146.             for letter in letters:
  147.                 exec('from sympy.abc import %s'%letter)  # re-execute after finding each unknown variable    
  148.             l_ = expr.count('(')
  149.             r_ = expr.count(')')
  150.             if l_ == r_:
  151.                 eval(expr)
  152.             elif l_ < r_:
  153.                 eval((r_-l_)*'('+expr)
  154.         except NameError as err:
  155.             msg = str(err)
  156.             pos = msg.find("'")
  157.             letter = msg[pos+1]
  158.             pos = pos +1
  159.             found = False
  160.             symbols = self._symbols
  161.             while (pos+1 < len(msg)) and (not found):
  162.                 more = msg[pos+1]
  163.                 for symb in symbols:
  164.                     if more==symb or more.isdigit():
  165.                         found = True
  166.                         break
  167.                 if found is False:
  168.                     letter = letter+more      
  169.                     pos = pos + 1
  170.             for alphabet in abc.__dict__:
  171.                 if letter == alphabet:
  172.                     letters.append(alphabet)
  173.                     self._try_expr(expr[expr.find(alphabet):]) # search for the next unknown variable
  174.  
  175.     def _tuple_to_list(self,t):
  176.         """
  177.        Recoursively turn a tuple to a list.
  178.        """
  179.         return list(map(self._tuple_to_list, t)) if isinstance(t, (list, tuple)) else t
  180.  
  181.     def _symplify_expr(self,expr): # this is a costly stage for complex expressions
  182.             """
  183.            Perform simplification of the provided expression.
  184.            Method returns a SymPy expression.
  185.            """
  186.             expr = sympy.trigsimp(expr)
  187.             expr = sympy.simplify(expr)
  188.             return expr
  189.  
  190.     def metric_to_Christoffel_1st(self):
  191.         from sympy.diffgeom import metric_to_Christoffel_1st
  192.         return metric_to_Christoffel_1st(self.metric)
  193.  
  194.     def metric_to_Christoffel_2nd(self):
  195.         from sympy.diffgeom import metric_to_Christoffel_2nd
  196.         return metric_to_Christoffel_2nd(self.metric)
  197.  
  198.     def find_Christoffel_tensor(self,form="simplified"):
  199.         """
  200.        Method determines the Riemann-Christoffel tensor
  201.        for a given metric(which must be in two-form).
  202.        
  203.        form : default value - "simplified"
  204.        If desired, a simplified form is returned.
  205.  
  206.        The returned value is a SymPy Matrix.
  207.        """
  208.         from sympy.diffgeom import metric_to_Riemann_components
  209.         metric = self.metric
  210.         R = metric_to_Riemann_components(metric)
  211.         simpR = self._tuple_to_list(R)
  212.         dim = self.dim
  213.         if form=="simplified":
  214.             print 'Performing simplifications on each component....'
  215.             for m in range(dim):
  216.                 for i in range(dim):
  217.                     for j in range(dim):
  218.                         for k in range(dim):
  219.                             expr = str(R[m][i][j][k])
  220.                             expr = self._symplify_expr(expr)
  221.                             simpR[m][i][j][k] = expr
  222.         self.Christoffel = sympy.Matrix(simpR)
  223.         return self.Christoffel
  224.  
  225.     def find_Ricci_tensor(self,form="simplified"):
  226.         """
  227.        Method determines the Ricci curvature tensor for
  228.        a given metric(which must be in two-form).
  229.        
  230.        form : default value - "simplified"
  231.        If desired, a simplified form is returned.
  232.  
  233.        The returned value is a SymPy Matrix.
  234.        """
  235.         from sympy.diffgeom import metric_to_Ricci_components
  236.         metric = self.metric
  237.         RR = metric_to_Ricci_components(metric)
  238.         simpRR = self._tuple_to_list(RR)
  239.         dim = self.dim
  240.         if form=="simplified":
  241.             print 'Performing simplifications on each component....'
  242.             for m in range(dim):
  243.                 for i in range(dim):
  244.                     expr = str(RR[m][i])
  245.                     expr = self._symplify_expr(expr)
  246.                     simpRR[m][i] = expr
  247.         self.Ricci = sympy.Matrix(simpRR)      
  248.         return self.Ricci
  249.  
  250.     def find_scalar_curvature(self):
  251.         """
  252.        Method performs scalar contraction on the Ricci tensor.
  253.        """
  254.         try:
  255.             Ricci = self.Ricci
  256.         except AttributeError:
  257.             print "Ricci tensor must be determined first."
  258.             return None
  259.         g = self.g
  260.         g_inv = self.g.inv()
  261.         scalar_curv = sympy.simplify(g_inv*Ricci)
  262.         scalar_curv = sympy.trace(scalar_curv)
  263.         self.scalar_curv = scalar_curv
  264.         return self.scalar_curv
  265.            
  266.  
  267. if __name__ == "__main__":
  268.     import find_metric
  269.     """
  270.    k = -1
  271.    g = find_metric.analytical(k) # k=0 gives flat space
  272.    R = Riemann(g=g,coords_sys="nontrivial",dim=3)
  273.    RC = R.find_Christoffel_tensor()
  274.    RR = R.find_Ricci_tensor()
  275.    scalarRR = R.find_scalar_curvature()
  276.  
  277.    print "\nThe analytical curve element has the following metric for k=%.1f"%k
  278.    print g
  279.    print "\nThe Ricci tensor is given as"
  280.    print RR
  281.    print "\nand the scalar curvature is"
  282.    print scalarRR
  283.    
  284.    """
  285.     from sympy.abc import r,theta, phi, u,v
  286.     g = find_metric.flat_sphere()
  287.     g = g.subs(u,r)
  288.     g = g.subs(v,theta)
  289.     R = Riemann(g, 'flat_sphere', dim = 3, user_coord=[r,theta,phi], flat_g = g[1:,1:])
  290.     C = R.metric_to_Christoffel_2nd(R.metric)
  291.     RC = R.find_Christoffel_tensor()
  292.     RR = R.find_Ricci_tensor()
  293.     scalarRR = R.find_scalar_curvature()
  294.  
  295.     print "\nThe 2D sphere has the following metric"
  296.     print g
  297.     print "\nThe Christoffel tensor is given as"
  298.     for m in range(dim):
  299.         for i in range(dim):
  300.             print RC[m,i]
  301.     print "\nThe Ricci tensor is given as"
  302.     print RR
  303.     print "\nand the scalar curvature is"
  304.     print scalarRR
  305.  
  306.     """
  307.    g = find_metric.toroidal_coordinates(form="simplified")
  308.    R = Riemann(g=g,coords_sys="toroidal",dim=2)
  309.    RC = R.find_Christoffel_tensor()
  310.    RR = R.find_Ricci_tensor()
  311.    print RC,"\n",RR
  312.    
  313.    g = find_metric.spherical_coordinates(form="simplified")
  314.    R = Riemann(g=g,coords_sys="spherical",dim=2)
  315.    RC = R.find_Christoffel_tensor()
  316.    RR = R.find_Ricci_tensor()
  317.    print RC,"\n",RR
  318.    
  319.    g = find_metric.cylindrical_coordinates(form="simplified")
  320.    R = Riemann(g=g,coords_sys="cylindrical",dim=3)
  321.    RC = R.find_Christoffel_tensor()
  322.    RR = R.find_Ricci_tensor()
  323.    print RC,"\n",RR      
  324.    
  325.    # Warning : This takes very long time (just to find g)!
  326.    g = find_metric.inverse_prolate_spheroidal_coordinates()
  327.    R = Riemann(g=g,coords_sys="inv_prolate_sphere",dim=3)
  328.    RC = R.find_Christoffel_tensor()
  329.    RR = R.find_Ricci_tensor()
  330.    print RC,"\n",RR
  331.    """
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement