├── .gitignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── LICENSE ├── MANIFEST.ini ├── README.md ├── dist ├── spacetimeengine-0.1.11-py2-none-any.whl └── spacetimeengine-0.1.11.tar.gz ├── pyproject.toml ├── requirements.txt ├── resources └── spacetimeengine_logo.png ├── setup.py └── spacetimeengine ├── __init__.py ├── samples └── example.py ├── src ├── __init__.py ├── solutions.py └── spacetime.py ├── tests ├── __init__.py └── test_spacetime.py └── utilities.py /.gitignore: -------------------------------------------------------------------------------- 1 | .installed.cfg 2 | bin 3 | develop-eggs 4 | downloads 5 | eggs 6 | parts 7 | spacetimeengine.egg-info 8 | .egg-info 9 | src/*.egg-info 10 | lib 11 | lib64 12 | .DS_Store 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | include README.md 2 | include LICENSE 3 | include pyproject.toml 4 | recursive-include spacetimeengine *.py 5 | recursive-include spacetimeengine/resources * 6 | recursive-include spacetimeengine/samples * -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Citizen Code of Conduct 2 | 3 | ## 1. Purpose 4 | 5 | A primary goal of Spacetimeengine is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof). 6 | 7 | This code of conduct outlines our expectations for all those who participate in our community, as well as the consequences for unacceptable behavior. 8 | 9 | We invite all those who participate in Spacetimeengine to help us create safe and positive experiences for everyone. 10 | 11 | ## 2. Open [Source/Culture/Tech] Citizenship 12 | 13 | A supplemental goal of this Code of Conduct is to increase open [source/culture/tech] citizenship by encouraging participants to recognize and strengthen the relationships between our actions and their effects on our community. 14 | 15 | Communities mirror the societies in which they exist and positive action is essential to counteract the many forms of inequality and abuses of power that exist in society. 16 | 17 | If you see someone who is making an extra effort to ensure our community is welcoming, friendly, and encourages all participants to contribute to the fullest extent, we want to know. 18 | 19 | ## 3. Expected Behavior 20 | 21 | The following behaviors are expected and requested of all community members: 22 | 23 | * Participate in an authentic and active way. In doing so, you contribute to the health and longevity of this community. 24 | * Exercise consideration and respect in your speech and actions. 25 | * Attempt collaboration before conflict. 26 | * Refrain from demeaning, discriminatory, or harassing behavior and speech. 27 | * Be mindful of your surroundings and of your fellow participants. Alert community leaders if you notice a dangerous situation, someone in distress, or violations of this Code of Conduct, even if they seem inconsequential. 28 | * Remember that community event venues may be shared with members of the public; please be respectful to all patrons of these locations. 29 | 30 | ## 4. Unacceptable Behavior 31 | 32 | The following behaviors are considered harassment and are unacceptable within our community: 33 | 34 | * Violence, threats of violence or violent language directed against another person. 35 | * Sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory jokes and language. 36 | * Posting or displaying sexually explicit or violent material. 37 | * Posting or threatening to post other people's personally identifying information ("doxing"). 38 | * Personal insults, particularly those related to gender, sexual orientation, race, religion, or disability. 39 | * Inappropriate photography or recording. 40 | * Inappropriate physical contact. You should have someone's consent before touching them. 41 | * Unwelcome sexual attention. This includes, sexualized comments or jokes; inappropriate touching, groping, and unwelcomed sexual advances. 42 | * Deliberate intimidation, stalking or following (online or in person). 43 | * Advocating for, or encouraging, any of the above behavior. 44 | * Sustained disruption of community events, including talks and presentations. 45 | 46 | ## 5. Weapons Policy 47 | 48 | No weapons will be allowed at Spacetimeengine events, community spaces, or in other spaces covered by the scope of this Code of Conduct. Weapons include but are not limited to guns, explosives (including fireworks), and large knives such as those used for hunting or display, as well as any other item used for the purpose of causing injury or harm to others. Anyone seen in possession of one of these items will be asked to leave immediately, and will only be allowed to return without the weapon. Community members are further expected to comply with all state and local laws on this matter. 49 | 50 | ## 6. Consequences of Unacceptable Behavior 51 | 52 | Unacceptable behavior from any community member, including sponsors and those with decision-making authority, will not be tolerated. 53 | 54 | Anyone asked to stop unacceptable behavior is expected to comply immediately. 55 | 56 | If a community member engages in unacceptable behavior, the community organizers may take any action they deem appropriate, up to and including a temporary ban or permanent expulsion from the community without warning (and without refund in the case of a paid event). 57 | 58 | ## 7. Reporting Guidelines 59 | 60 | If you are subject to or witness unacceptable behavior, or have any other concerns, please notify a community organizer as soon as possible. spacetime.engineer@gmail.com. 61 | 62 | 63 | 64 | Additionally, community organizers are available to help community members engage with local law enforcement or to otherwise help those experiencing unacceptable behavior feel safe. In the context of in-person events, organizers will also provide escorts as desired by the person experiencing distress. 65 | 66 | ## 8. Addressing Grievances 67 | 68 | If you feel you have been falsely or unfairly accused of violating this Code of Conduct, you should notify with a concise description of your grievance. Your grievance will be handled in accordance with our existing governing policies. 69 | 70 | 71 | 72 | ## 9. Scope 73 | 74 | We expect all community participants (contributors, paid or otherwise; sponsors; and other guests) to abide by this Code of Conduct in all community venues--online and in-person--as well as in all one-on-one communications pertaining to community business. 75 | 76 | This code of conduct and its related procedures also applies to unacceptable behavior occurring outside the scope of community activities when such behavior has the potential to adversely affect the safety and well-being of community members. 77 | 78 | ## 10. Contact info 79 | 80 | spacetime.engineer@gmail.com 81 | 82 | ## 11. License and attribution 83 | 84 | The Citizen Code of Conduct is distributed by [Stumptown Syndicate](http://stumptownsyndicate.org) under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/). 85 | 86 | Portions of text derived from the [Django Code of Conduct](https://www.djangoproject.com/conduct/) and the [Geek Feminism Anti-Harassment Policy](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy). 87 | 88 | _Revision 2.3. Posted 6 March 2017._ 89 | 90 | _Revision 2.2. Posted 4 February 2016._ 91 | 92 | _Revision 2.1. Posted 23 June 2014._ 93 | 94 | _Revision 2.0, adopted by the [Stumptown Syndicate](http://stumptownsyndicate.org) board on 10 January 2013. Posted 17 March 2013._ 95 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019, Michael.C Ryan 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the contributors organization nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | ------------------------------------------------------------------------------------------------------------------------- 27 | 28 | Copyright © 2019 Michael.C Ryan 29 | 30 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 31 | 32 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 33 | 34 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 35 | -------------------------------------------------------------------------------- /MANIFEST.ini: -------------------------------------------------------------------------------- 1 | include README.md 2 | include LICENSE 3 | include pyproject.toml 4 | recursive-include spacetimeengine *.py 5 | recursive-include spacetimeengine/resources * 6 | recursive-include spacetimeengine/samples * -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![alt text](https://github.com/spacetimeengineer/spacetimeengine/blob/master/resources/spacetimeengine_logo.png) 2 | 3 | A Python utility built on Sympy (A symbolic mathematics library) which will analyze any given metric solution to the Einstein field equations. 4 | 5 | ![equation](https://latex.codecogs.com/png.latex?%5Cdpi%7B100%7D%20%5Chuge%20G_%7B%5Cmu%5Cnu%7D%20+%20%5CLambda%20g_%7B%5Cmu%5Cnu%7D%20%3D%20%5Cfrac%7B8%5Cpi%20G%7D%7Bc%5E4%7DT_%7B%5Cmu%5Cnu%7D) 6 | 7 | # Prerequisites (Linux) 8 | 9 | 1.) Install Python3 10 | 11 | $ sudo apt install python3 12 | 13 | 2.) Install pip3 14 | 15 | $ sudo apt install python3-pip 16 | 17 | 3.) Install git 18 | 19 | $ sudo apt-get install git 20 | 21 | # Prerequisites (MacOS) 22 | 23 | 1.) Install homebrew 24 | 25 | $ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" brew doctor 26 | 27 | 2.) Set python as an environmental variable. 28 | 29 | $ export PATH="/usr/local/opt/python/libexec/bin:$PATH" 30 | 31 | 3.) Install git 32 | 33 | $ brew install git 34 | 35 | 4.) Install python3 and pip3 (https://docs.python-guide.org/starting/install3/osx/) 36 | 37 | $ brew install python3 38 | $ brew postinstall python3 39 | 40 | # Prerequisites (Windows) 41 | 42 | 1.) Install Python3 & pip3 43 | 44 | Navigate to https://www.python.org/downloads/ 45 | 46 | 2.) Install git 47 | 48 | Navigate to https://gitforwindows.org/ 49 | 50 | # Installation with pip3 51 | 52 | 1.) Install with pip3 53 | 54 | $ pip3 install spacetimeengine 55 | 56 | 2.) Enter python shell 57 | 58 | $ python3 59 | 60 | 3.) Import spacetimeengine 61 | 62 | >> from spacetimeengine import * 63 | 64 | 4.) Create a SpaceTime object which describes the Schwarzschild spacetime 65 | 66 | >> schwarzschild_spacetime = SpaceTime(Solution().schwarzschild()) 67 | 68 | 5.) Enjoy watching the coefficients get computed. 69 | 70 | # Installation with git 71 | 72 | 1.) Clone repository 73 | 74 | $ git clone https://github.com/spacetimeengineer/spacetimeengine 75 | 76 | 2.) Enter directory 77 | 78 | $ cd spacetimeengine/spacetimeengine/samples 79 | 80 | 3.) Run example.py 81 | 82 | $ python3 example.py 83 | 84 | # Suggested Use 85 | 86 | If you are a student or researcher, and you find yourself reading a publication based in General Relativity which provides metric solutions, then this utility can be used for working out the curvature coefficients associated with the solution provided by the user. This can be a helpful utility as you read through the literature because you will be able to cross-reference the information provided by the literature with the values the spacetimeengine provides (this is why I developed it originally). More commonly, this utility can be used for error checking. 87 | 88 | ## [Metric Tensor](https://en.wikipedia.org/wiki/Metric_tensor) 89 | 90 | Generally speaking, any metric solution to the Einstein field equations will be packaged into a geometric object known as the metric tensor. The metric tensor is often represented in matrix form, and the spacetimeengine package adopts this representation. 91 | 92 | ![equation](https://latex.codecogs.com/png.latex?%5Cdpi%7B100%7D%20%5Chuge%20g_%7B%5Cmu%5Cnu%7D%3D%5Cbegin%7Bbmatrix%7D%20%5Cleft%20%28%201-%5Cfrac%7B2GM%7D%7Brc%5E%7B2%7D%7D%20%5Cright%20%29%20%26%200%20%26%200%20%26%200%20%5C%5C%200%20%26%20-%5Cleft%20%28%201-%5Cfrac%7B2GM%7D%7Brc%5E%7B2%7D%7D%20%5Cright%20%29%5E%7B-1%7D%20%26%200%20%26%200%20%5C%5C%200%20%26%200%20%26%20-r%5E%7B2%7D%20%26%200%20%5C%5C%200%20%26%200%20%26%200%20%26%20-r%5E%7B2%7D%5Csin%5E%7B2%7D%5Ctheta%20%5Cend%7Bbmatrix%7D) 93 | 94 | The spacetimeengine package employs the Sympy 'Matrix' object for packaging the metric tensor and it serves as the essential parameter for constructing a 'SpaceTime' object. The Solutions module currently stores some well-known metrics for study, but these can be used for understanding how to construct new solutions. 95 | 96 | # Constructing a solution (In development) 97 | 98 | Currently, all metric solutions are packaged by specifying four key parameters and storing them in an array. These parameters include an index configuration for the given metric solution, the coordinates to define the metric in terms of, the metric itself, and the cosmological constant. It is important to note that a zero-valued cosmological constant indicates the employment of a classical formulation to the Einstein field equations. Below represents a valid definition of the Schwarzschild stationary black hole solution. 99 | 100 | ```python 101 | def schwarzschild(self): 102 | 103 | # Assigns meaning to the coordinates. 104 | x0, x1, x2, x3 = symbols('t r theta phi') 105 | # Groups the coordinates in an array. 106 | coordinate_set = [x0, x1, x2, x3] 107 | 108 | # Constants required to describe the metric. 109 | G, M, c = symbols('G M c') 110 | 111 | # Metric. 112 | metric = Matrix([ 113 | [ (1-(2*G*M)/(x1*c**2)), 0, 0, 0 ], 114 | [ 0, - (1-(2*G*M)/(x1*c**2))**(-1), 0, 0 ], 115 | [ 0, 0, - x1**2, 0 ], 116 | [ 0, 0, 0, - x1**2*sin(x2)**2 ] 117 | ]) 118 | 119 | # Describes the index configuration which the metric represents. 120 | index_config = "dd" 121 | 122 | # Cosmological constant. 123 | cosmological_constant = 0 124 | 125 | # An array detailing the solution. 126 | solution_array = [ metric, coordinate_set, index_config, cosmological_constant ] 127 | 128 | # Returns solution 129 | return solution_array 130 | -------------------------------------------------------------------------------- /dist/spacetimeengine-0.1.11-py2-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spacetimeengineer/spacetimeengine/d5626c7cccc7964b63a2aa3b8c0738c4eff47cf3/dist/spacetimeengine-0.1.11-py2-none-any.whl -------------------------------------------------------------------------------- /dist/spacetimeengine-0.1.11.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spacetimeengineer/spacetimeengine/d5626c7cccc7964b63a2aa3b8c0738c4eff47cf3/dist/spacetimeengine-0.1.11.tar.gz -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=42", "wheel"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "spacetimeengine" 7 | version = "0.1.11" 8 | description = "A Python physics utility which can analyze any given metric solution to the Einstein field equations." 9 | readme = "README.md" 10 | authors = [ 11 | { name = "Michael.C Ryan", email = "spacetime.engineer@gmail.com" } 12 | ] 13 | license = { text = "BSD License" } 14 | requires-python = ">=3.6" 15 | classifiers = [ 16 | "Programming Language :: Python :: 3", 17 | "License :: OSI Approved :: BSD License", 18 | "Operating System :: OS Independent", 19 | "Topic :: Scientific/Engineering", 20 | "Topic :: Scientific/Engineering :: Mathematics", 21 | "Topic :: Scientific/Engineering :: Physics" 22 | ] 23 | dependencies = [ 24 | "sympy" 25 | ] 26 | 27 | [project.optional-dependencies] 28 | testing = [ 29 | "nose" 30 | ] 31 | 32 | [tool.setuptools.packages.find] 33 | where = ["."] 34 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | sympy -------------------------------------------------------------------------------- /resources/spacetimeengine_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spacetimeengineer/spacetimeengine/d5626c7cccc7964b63a2aa3b8c0738c4eff47cf3/resources/spacetimeengine_logo.png -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | with open("README.md", "r", encoding="utf-8") as fh: 4 | long_description = fh.read() 5 | 6 | setup( 7 | name="spacetimeengine", 8 | version="0.1.11", 9 | packages=find_packages(include=["spacetimeengine", "spacetimeengine.*"]), 10 | author="Michael.C Ryan", 11 | author_email="spacetime.engineer@gmail.com", 12 | description="A Python physics utility which can analyze any given metric solution to the Einstein field equations.", 13 | long_description=long_description, 14 | long_description_content_type="text/markdown", 15 | url="https://github.com/spacetimeengineer/spacetimeengine", 16 | project_urls={ 17 | "Documentation": "https://github.com/spacetimeengineer/spacetimeengine#readme", 18 | "Source": "https://github.com/spacetimeengineer/spacetimeengine", 19 | "Tracker": "https://github.com/spacetimeengineer/spacetimeengine/issues", 20 | }, 21 | license="BSD License", 22 | install_requires=[ 23 | "sympy>=1.0" 24 | ], 25 | extras_require={ 26 | "testing": ["nose"] 27 | }, 28 | tests_require=[ 29 | "nose" 30 | ], 31 | test_suite="nose.collector", 32 | classifiers=[ 33 | "Development Status :: 4 - Beta", 34 | "Intended Audience :: Science/Research", 35 | "Programming Language :: Python :: 3", 36 | "Programming Language :: Python :: 3.6", 37 | "Programming Language :: Python :: 3.7", 38 | "Programming Language :: Python :: 3.8", 39 | "Programming Language :: Python :: 3.9", 40 | "Programming Language :: Python :: 3.10", 41 | "License :: OSI Approved :: BSD License", 42 | "Operating System :: OS Independent", 43 | "Topic :: Scientific/Engineering", 44 | "Topic :: Scientific/Engineering :: Mathematics", 45 | "Topic :: Scientific/Engineering :: Physics", 46 | ], 47 | python_requires=">=3.6", 48 | include_package_data=True, # Ensures files specified in MANIFEST.in are included 49 | zip_safe=False, # Ensures the package can be safely installed as a directory 50 | ) -------------------------------------------------------------------------------- /spacetimeengine/__init__.py: -------------------------------------------------------------------------------- 1 | from spacetimeengine.src.solutions import * 2 | from spacetimeengine.src.spacetime import * 3 | -------------------------------------------------------------------------------- /spacetimeengine/samples/example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from spacetimeengine import * 3 | 4 | 5 | def main(): 6 | 7 | # Retrieves a known solution from the Solutions() class. 8 | blackhole = Solution().schwarzschild() 9 | 10 | # The current general model for describing the accellerated expansion of the universe. 11 | expanding_universe = Solution().friedmann_lemaitre_robertson_walker() 12 | 13 | # The most famous wormhole solution. 14 | wormhole = Solution().einstein_rosen_bridge() 15 | 16 | # Empty vacuum. 17 | flat_spacetime = Solution().minkowski() 18 | 19 | # A special case of a more general form of the Friedmann Lemaitre Robertson Walker solution. 20 | empty_expanding_universe = Solution().milne() 21 | 22 | # Gravity as we know it, without the high order effects. 23 | newtonian_gravity = Solution().weak_field_approximation() 24 | 25 | newtonian = SpaceTime(Solution().hypersphere()) 26 | 27 | if __name__ == "__main__": 28 | main() 29 | -------------------------------------------------------------------------------- /spacetimeengine/src/__init__.py: -------------------------------------------------------------------------------- 1 | from os.path import dirname, basename, isfile 2 | import glob 3 | modules = glob.glob(dirname(__file__)+"/*.py") 4 | __all__ = [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')] -------------------------------------------------------------------------------- /spacetimeengine/src/solutions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from sympy import * 3 | 4 | class Solution: 5 | 6 | def inverse_schwarzschild(self): 7 | """ 8 | Description 9 | =========== 10 | Returns the classic black hole solution. Uncharged and rotationally stationary. 11 | Examples 12 | ======== 13 | >>> print(Solution().schwarzschild()) 14 | >>> 15 | LaTeX representation 16 | ==================== 17 | """ 18 | 19 | # Index configuration for the metric 20 | index_config = "dd" 21 | # Physical constants. 22 | G, M, c = symbols('G M c') 23 | # Assigns meaning to the coordinates. 24 | tau = symbols('tau') 25 | x0 = Symbol('t') 26 | x1 = Symbol('r') 27 | x2 = Symbol('theta') 28 | x3 = Symbol('phi') 29 | # Reference to the coordiante system. 30 | coordinate_set = [x0, x1, x2, x3] 31 | # Cosmological constant. 32 | cosmological_constant = 0 33 | # Metric solution. 34 | metric = Matrix([ 35 | [ (1-(2*G*M)/(x1*c**2))**(-1), 0, 0, 0 ], 36 | [ 0, - (1-(2*G*M)/(x1*c**2)), 0, 0 ], 37 | [ 0, 0, - x1**2, 0 ], 38 | [ 0, 0, 0, - x1**2*sin(x2)**2 ] 39 | ]) 40 | 41 | # An array detailing the solution. 42 | solution_array = [ metric, coordinate_set, index_config, cosmological_constant ] 43 | return solution_array 44 | 45 | def minkowski(self, version = "euclidian"): 46 | """ 47 | Description 48 | =========== 49 | Returns Minkowski spacetime metric solution. 50 | 51 | Example 52 | ======= 53 | >> print(Solution().minkowski()) 54 | [Matrix([ 55 | [1, 0, 0, 0], 56 | [0, -1, 0, 0], 57 | [0, 0, -1, 0], 58 | [0, 0, 0, -1]]), [t, x, y, z], 'dd', 0] 59 | 60 | LaTeX representation 61 | ==================== 62 | 63 | URL Reference 64 | ============= 65 | https://en.wikipedia.org/wiki/Minkowski_space 66 | 67 | TODOs 68 | ===== 69 | - Link example with test. 70 | - Need higher quality tests. 71 | """ 72 | 73 | # Index configuration for the metric 74 | index_config = "dd" 75 | # Constants. 76 | c = symbols('c') 77 | # Assigns meaning to the coordinates. 78 | x0 = Symbol('t') 79 | x1 = Symbol('x') 80 | x2 = Symbol('y') 81 | x3 = Symbol('z') 82 | # Reference to the coordiante system. 83 | coordinate_set = [x0, x1, x2, x3] 84 | # Cosmological constant. 85 | cosmological_constant = 0 86 | 87 | if (version == "euclidian"): 88 | pass 89 | elif (version == "spherical"): 90 | pass 91 | else: 92 | pass 93 | 94 | #metric = Matrix([ 95 | # [ c**2, 0, 0, 0 ], 96 | # [ 0, -1, 0, 0 ], 97 | # [ 0, 0, -1, 0 ], 98 | # [ 0, 0, 0, -1 ] 99 | # ]) 100 | 101 | 102 | metric = Matrix([ 103 | [ 1, 0, 0, 0 ], 104 | [ 0, -1, 0, 0 ], 105 | [ 0, 0, -1, 0 ], 106 | [ 0, 0, 0, -1 ] 107 | ]) 108 | 109 | #metric = Matrix([ 110 | # [ 1, 0, 0, 0 ], 111 | # [ 0, -1, 0, 0 ], 112 | # [ 0, 0, -x1**2, 0 ], 113 | # [ 0, 0, 0, -x1**2*sin(x2)**2 ] 114 | # ]) 115 | 116 | # An array detailing the solution. 117 | solution_array = [ metric, coordinate_set, index_config, cosmological_constant ] 118 | return solution_array 119 | 120 | def weak_field_approximation(self): 121 | """ 122 | Description 123 | =========== 124 | Returns the Friedmann Lemaitre Robertson Walker metric which describes the spacetime for an expanding universe. 125 | Examples 126 | ======== 127 | >>> print(Solution().minkowski()) 128 | >>> 129 | LaTeX representation 130 | ==================== 131 | """ 132 | 133 | # Index configuration for the metric 134 | index_config = "dd" 135 | # Assigns meaning to the coordinates. 136 | 137 | x0 = Symbol('t') 138 | x1 = Symbol('r') 139 | x2 = Symbol('theta') 140 | x3 = Symbol('phi') 141 | # Physical constants. 142 | G, M, c = symbols('G M c') 143 | Ph = - G * M / x1 144 | # Reference to the coordiante system. 145 | coordinate_set = [x0, x1, x2, x3] 146 | # Cosmological constant. 147 | cosmological_constant = 0 148 | # Metric solution. 149 | metric = Matrix([ 150 | [ (1+2*Ph/c**2)*c**2, 0, 0, 0 ], 151 | [ 0, -1/(1+2*Ph/c**2), 0, 0 ], 152 | [ 0, 0, -x1**2, 0 ], 153 | [ 0, 0, 0, -x1**2*sin(x2)**2 ] 154 | ]) 155 | 156 | # An array detailing the solution. 157 | solution_array = [ metric, coordinate_set, index_config, cosmological_constant ] 158 | return solution_array 159 | 160 | 161 | def schwarzschild(self): 162 | """ 163 | Description 164 | =========== 165 | Returns the classic black hole solution. Uncharged and rotationally stationary. 166 | Examples 167 | ======== 168 | >>> print(Solution().schwarzschild()) 169 | >>> 170 | LaTeX representation 171 | ==================== 172 | """ 173 | 174 | # Index configuration for the metric 175 | index_config = "dd" 176 | # Physical constants. 177 | G, M, c = symbols('G M c') 178 | # Assigns meaning to the coordinates. 179 | tau = symbols('tau') 180 | x0 = Symbol('t') 181 | x1 = Symbol('r') 182 | x2 = Symbol('theta') 183 | x3 = Symbol('phi') 184 | # Reference to the coordiante system. 185 | coordinate_set = [x0, x1, x2, x3] 186 | # Cosmological constant. 187 | cosmological_constant = 0 188 | # Metric solution. 189 | metric = Matrix([ 190 | [ (1-(2*G*M)/(x1*c**2)), 0, 0, 0 ], 191 | [ 0, - (1-(2*G*M)/(x1*c**2))**(-1), 0, 0 ], 192 | [ 0, 0, - x1**2, 0 ], 193 | [ 0, 0, 0, - x1**2*sin(x2)**2 ] 194 | ]) 195 | 196 | # An array detailing the solution. 197 | solution_array = [ metric, coordinate_set, index_config, cosmological_constant ] 198 | return solution_array 199 | 200 | def friedmann_lemaitre_robertson_walker(self): 201 | """ 202 | Description 203 | =========== 204 | Returns the Friedmann Lemaitre Robertson Walker metric which describes the spacetime for an expanding universe. 205 | Examples 206 | ======== 207 | >>> print(Solution().friedmann_lemaitre_robertson_walker()) 208 | >>> 209 | LaTeX representation 210 | ==================== 211 | """ 212 | 213 | # Index configuration for the metric 214 | index_config = "dd" 215 | # Assigns meaning to the coordinates. 216 | x0 = Symbol('t') 217 | x1 = Symbol('r') 218 | x2 = Symbol('theta') 219 | x3 = Symbol('phi') 220 | # Reference to the coordiante system. 221 | coordinate_set = [x0, x1, x2, x3] 222 | # Required symbols and constants. 223 | k = symbols('k') 224 | a = Function('a')(x0) 225 | # Reference to the coordiante system. 226 | coordinate_set = [x0, x1, x2, x3] 227 | # Cosmological constant. 228 | cosmological_constant = 0 229 | # Metric solution. 230 | metric = Matrix([ 231 | [ 1, 0, 0, 0 ], 232 | [ 0, - a**2*(1-k*x1**2)**(-1), 0, 0 ], 233 | [ 0, 0, - a**2*x1**2, 0 ], 234 | [ 0, 0, 0, - a**2*x1**2*sin(x2)**2 ] 235 | ]) 236 | 237 | # An array detailing the solution. 238 | solution_array = [ metric, coordinate_set, index_config, cosmological_constant ] 239 | return solution_array 240 | 241 | # Most famous wormhole solution. 242 | def einstein_rosen_bridge(self): 243 | """ 244 | Description 245 | =========== 246 | Returns the metric for the most famous wormhole solution. 247 | Examples 248 | ======== 249 | >>> print(Solution().einstein_rosen_bridge()) 250 | >>> 251 | LaTeX representation 252 | ==================== 253 | """ 254 | 255 | # Index configuration for the metric 256 | index_config = "dd" 257 | # Required symbols and constants. 258 | m = symbols('m') 259 | # Assigns meaning to the coordinates. 260 | x0 = Symbol('t') 261 | x1 = Symbol('r') 262 | x2 = Symbol('theta') 263 | x3 = Symbol('phi') 264 | # Reference to the coordiante system. 265 | coordinate_set = [x0, x1, x2, x3] 266 | # Cosmological constant. 267 | cosmological_constant = 0 268 | # Metric solution. 269 | metric = Matrix([ 270 | [ (x1-2*m) / x1, 0, 0, 0 ], 271 | [ 0, - 4 * x1 / ( 2 * x1 - 4 * m ), 0, 0 ], 272 | [ 0, 0, - x1**2, 0 ], 273 | [ 0, 0, 0, - x1**2 * sin(x2)**2 ] 274 | ]) 275 | 276 | # An array detailing the solution. 277 | solution_array = [ metric, coordinate_set, index_config, cosmological_constant ] 278 | return solution_array 279 | 280 | def taub_nut(self): 281 | """ 282 | Description 283 | =========== 284 | Returns Taub-Nut metric. 285 | Examples 286 | ======== 287 | >>> print(taub_nut()) 288 | >>> 289 | LaTeX representation 290 | ==================== 291 | """ 292 | 293 | U, m, l = symbols('U m l') 294 | U = (2 * m * x0 + l**2 - x0**2) / ( x0**2 + l**2 ) 295 | taub_nut_metric = Matrix([ 296 | [ U**(-1), 0, 0, 0 ], 297 | [ 0, -4 * l**2 * U, -1 * cos(x2) * (4 * l**2 * U), 0 ], 298 | [ 0, -1 * cos(x2) * (4 * l**2 * U), -1 * (x0**2 + l**2), 0 ], 299 | [ 0, 0, 0, -1 * (x0**2 + l**2) * sin(x2) - (4 * l**2 * U) * cos(x2)**2 ] 300 | ]) 301 | 302 | return taub_nut_metric 303 | 304 | def milne(self): 305 | """ 306 | Description 307 | =========== 308 | Returns Milne metric. 309 | Examples 310 | ======== 311 | >>> print(Solution().milne()) 312 | >>> 313 | LaTeX representation 314 | ==================== 315 | """ 316 | 317 | # Index configuration for the metric 318 | index_config = "dd" 319 | # Required symbols and constants. 320 | c = symbols('c') 321 | # Assigns meaning to the coordinates. 322 | x0 = Symbol('t') 323 | x1 = Symbol('r') 324 | x2 = Symbol('theta') 325 | x3 = Symbol('phi') 326 | # Reference to the coordiante system. 327 | coordinate_set = [x0, x1, x2, x3] 328 | # Cosmological constant. 329 | cosmological_constant = 0 330 | # Metric solution. 331 | metric = Matrix([ 332 | [ 1, 0, 0, 0 ], 333 | [ 0, -x0**2, 0, 0 ], 334 | [ 0, 0, -x0**2*sinh(x1)**2, 0 ], 335 | [ 0, 0, 0, -x0**2*sinh(x1)**2*sin(x2)**2 ] 336 | ]) 337 | 338 | # An array detailing the solution. 339 | solution_array = [ metric, coordinate_set, index_config, cosmological_constant ] 340 | return solution_array 341 | 342 | def kerr(self): 343 | """ 344 | Description 345 | =========== 346 | Returns Kerr metric. 347 | Examples 348 | ======== 349 | >>> print(Solution().kerr()) 350 | >>> 351 | LaTeX representation 352 | ==================== 353 | """ 354 | x0, x1, x2, x3 = symbols('x0 x1 x2 x3') 355 | a, J, M, c, G, r, delt, sigm = symbols('a J M c G r Delta Sigma') 356 | a = (J/(M*c)) 357 | rs = (2*G*M/(c**2)) 358 | sigm = (x1**2 + (J/(M*c))**2 * cos(x2)**2) 359 | delt = (r**2 - x0 * (2*G*M/(c**2)) + (J/(M*c))**2) 360 | metric = Matrix([ 361 | [ (1 - rs * x1 / (x1**2 + (J/(M*c))**2 * cos(x2)**2) ), 0, 0, (2*G*M/(c**2))*x1*(J/(M*c))*sin(x2)**2 / (x1**2 + (J/(M*c))**2 * cos(x2)**2) ], 362 | [ 0, -1 * ( (r**2 - x0 * (2*G*M/(c**2)) + (J/(M*c))**2) / (x1**2 + (J/(M*c))**2 * cos(x2)**2) ), 0, 0 ], 363 | [ 0, 0, -1 * (x1**2 + (J/(M*c))**2 * cos(x2)**2), 0 ], 364 | [ (2*G*M/(c**2))*x1*(J/(M*c))*sin(x2)**2 / (x1**2 + (J/(M*c))**2 * cos(x2)**2), 0, 0, -1 * (x1**2 + (J/(M*c))**2 + (rs*x1*(J/(M*c))**2/(x1**2 + (J/(M*c))**2 * cos(x2)**2))*sin(x2))*sin(x2) ] 365 | ]) 366 | 367 | return kerr_metric 368 | 369 | def alcubierre(self): 370 | """ 371 | Description 372 | =========== 373 | Returns the famous Alcubierre 'warp-drive' metric solution. 374 | Examples 375 | ======== 376 | >>> from sympy import * 377 | >>> print(Solution().alcubierre()) 378 | >>> 379 | LaTeX representation 380 | ==================== 381 | """ 382 | # The classic warp drive solution. (This takes a long time to process!!!) (I suspect the compute time diverges. I think there is some recursive error) 383 | # Does not crash. 384 | xs = symbols('x_s')(x0) 385 | vs = xs.diff(x0) 386 | rs = sqrt((x1-xs)**2 + x2**2 + x3**2) 387 | fs = tanh(s * (rs + R)) - tanh(s * (rs - R)) / (2 * tanh( s * R )) 388 | alcubierre_spacetime = Matrix([ 389 | [ (vs**2 * fs**2 - 1), -2*vs*fs, -2*vs*fs, -2*vs*fs ], 390 | [ -2*vs*fs, -1, 0, 0 ], 391 | [ -2*vs*fs, 0, -1, 0 ], 392 | [ -2*vs*fs, 0, 0, -1 ] 393 | ]) 394 | 395 | def ellis(self): 396 | """ 397 | Description 398 | =========== 399 | Returns the original wormhole solution. 400 | Examples 401 | ======== 402 | >>> print(Solution().ellis()) 403 | >>> 404 | LaTeX representation 405 | ==================== 406 | """ 407 | 408 | ellis_drainhole_metric = Matrix([ 409 | [ 1, 0, 0, 0 ], 410 | [ 0, - 1, 0, 0 ], 411 | [ 0, 0, - ( k**2 + x1 ** 2 ), 0 ], 412 | [ 0, 0, 0, - (k**2 + x1 ** 2) * sin(x2)**2 ] 413 | ]) 414 | return ellis_drainhole_metric 415 | 416 | #Electrovacum solutions. 417 | 418 | def reissner_nordstrom(self): 419 | """ 420 | Description 421 | =========== 422 | Returns Reissner Nordstrom metric. 423 | Examples 424 | ======== 425 | >>> print(Solution().reissner_nordstrom()) 426 | >>> 427 | LaTeX representation 428 | ==================== 429 | """ 430 | # Index configuration for the metric 431 | index_config = "dd" 432 | # Required symbols and constants. 433 | m = symbols('m') 434 | # Assigns meaning to the coordinates. 435 | x0, x1, x2, x3 = symbols('t r theta phi') 436 | # Reference to the coordiante system. 437 | coordinate_set = [x0, x1, x2, x3] 438 | # Cosmological constant. 439 | cosmological_constant = 0 440 | # Metric solution. 441 | G, M, c, Q, k = symbols('G M c Q k') 442 | rs = 2 * G * M / ( c**2 ) 443 | rq = Q**2 * G * k / c**4 444 | metric = Matrix([ 445 | [ (1 + rs / x1 + rq**2 / x0**2), 0, 0, 0 ], 446 | [ 0, -1 * (1 + rs / x1 + rq**2 / x0**2)**(-1), 0, 0 ], 447 | [ 0, 0, -x1**2, 0 ], 448 | [ 0, 0, 0, -x1**2 * sin(x2)**2 ] 449 | ]) 450 | 451 | # An array detailing the solution. 452 | solution_array = [ metric, coordinate_set, index_config, cosmological_constant ] 453 | return solution_array 454 | 455 | def kerr_newman(self): 456 | """ 457 | Description 458 | =========== 459 | Returns Kerr-Newman metric. 460 | Examples 461 | ======== 462 | >>> print(Solution().kerr_newman()) 463 | >>> 464 | LaTeX representation 465 | ==================== 466 | """ 467 | 468 | x0, x1, x2, x3 = symbols('t r psi theta') 469 | G, M, c, Q, k = symbols('G M c Q k') 470 | rs = 2 * G * M / ( c**2 ) 471 | rq = Q**2 * G * k / c**4 472 | metric = Matrix([ 473 | [ (1 + rs / x1 + rq**2 / x0**2), 0, 0, 0 ], 474 | [ 0, -1 * (1 + rs / x1 + rq**2 / x0**2)**(-1), 0, 0 ], 475 | [ 0, 0, -x1**2, 0 ], 476 | [ 0, 0, 0, -x1**2 * sin(x2)**2 ] 477 | ]) 478 | 479 | return metric 480 | 481 | def ozsvath_schucking(self): 482 | """ 483 | Description 484 | =========== 485 | Returns the ozsvath schucking metric. 486 | Examples 487 | ======== 488 | >>> print(Solution().ozsvath_schucking()) 489 | >>> 490 | LaTeX representation 491 | ==================== 492 | """ 493 | ozsvath_schucking_metric = Matrix([ 494 | [ 1, 0, -2*x3, 0 ], 495 | [ 0, 0, 1*x3, 0 ], 496 | [ -2*x3, 1*x3, -1, 1 ], 497 | [ 0, 0, 1, 1 ] 498 | ]) 499 | return ozsvath_schucking_metric 500 | 501 | def godel(self): 502 | """ 503 | Description 504 | =========== 505 | Returns Godel metric. A famous classic spacetime which describes time travel. 506 | Examples 507 | ======== 508 | >>> print(Solution().godel()) 509 | >>> 510 | LaTeX representation 511 | ==================== 512 | ds^{2}={\frac {1}{2\omega ^{2}}}\left[-(dt+e^{x}dy)^{2}+dx^{2}+{\tfrac {1}{2}}e^{2x}dy^{2}+dz^{2}\right],\qquad -\infty >> print(Solution().schwarzschild()) 533 | >>> 534 | LaTeX representation 535 | ==================== 536 | """ 537 | x0, x1, x2, x3 = symbols('x0 x1 x2 x3') 538 | c = symbols('c') 539 | Ph = symbols('Phi')(x0) 540 | ax = symbols('ax')(x1) 541 | ay = symbols('ay')(x2) 542 | az = symbols('az')(x3) 543 | 544 | minkowski_metric = Matrix([ 545 | [ 1, 0, 0, 0 ], 546 | [ 0, -1, 0, 0 ], 547 | [ 0, 0, -1, 0 ], 548 | [ 0, 0, 0, -1 ] 549 | ]) 550 | 551 | h_tilde_tensor = Matrix([ 552 | [ 4*Ph / c**2, - ax/c**2, - ax/c**2, - az/c**2 ], 553 | [ - ax/c**2, 0, 0, 0 ], 554 | [ - ay/c**2, 0, 0, 0 ], 555 | [ - az/c**2, 0, 0, 0 ] 556 | ]) 557 | h_tilde_scalar = 0 558 | gravitomagnetic_metric = minkowski_metric + h_tilde_tensor + Rational('1/2') * minkowski_metric * h_tilde_scalar 559 | 560 | 561 | return gravitomagnetic_metric 562 | 563 | 564 | def alt_gem(self): 565 | """ 566 | Description 567 | =========== 568 | Returns the classic black hole solution. Uncharged and rotationally stationary. 569 | Examples 570 | ======== 571 | >>> print(Solution().schwarzschild()) 572 | >>> 573 | LaTeX representation 574 | ==================== 575 | """ 576 | x0, x1, x2, x3 = symbols('x0 x1 x2 x3') 577 | c = symbols('c') 578 | Ph = symbols('Phi')(x0) 579 | ax = symbols('ax')(x1) 580 | ay = symbols('ay')(x2) 581 | az = symbols('az')(x3) 582 | 583 | 584 | 585 | minkowski_metric = Matrix([ 586 | [ 1, 0, 0, 0 ], 587 | [ 0, -1, 0, 0 ], 588 | [ 0, 0, -1, 0 ], 589 | [ 0, 0, 0, -1 ] 590 | ]) 591 | 592 | h_tilde_tensor = Matrix([ 593 | [ 2*Ph / c**2, - ax/c**2, - ax/c**2, - az/c**2 ], 594 | [ - ax/c**2, Ph / c**2, 0, 0 ], 595 | [ - ay/c**2, 0, Ph / c**2, 0 ], 596 | [ - az/c**2, 0, 0, Ph / c**2 ] 597 | ]) 598 | h_tilde_scalar = 0 599 | gravitomagnetic_metric = minkowski_metric + h_tilde_tensor + Rational('1/2') * minkowski_metric * h_tilde_scalar 600 | 601 | 602 | return gravitomagnetic_metric 603 | 604 | def dark_energy(self): 605 | """ 606 | Description 607 | =========== 608 | Returns a metric which describes a spacetime where the dark energy is present. 609 | ======== 610 | >>> print(Solution().dark_energy()) 611 | >>> 612 | LaTeX representation 613 | ==================== 614 | """ 615 | 616 | # Index configuration for the metric 617 | index_config = "dd" 618 | # Required symbols and constants. 619 | c = symbols('c') 620 | # Assigns meaning to the coordinates. 621 | x0, x1, x2, x3 = symbols('t r psi theta') 622 | # Reference to the coordiante system. 623 | coordinate_set = [x0, x1, x2, x3] 624 | # Cosmological constant. 625 | cosmological_constant = 0 626 | # Metric solution. 627 | metric = Matrix([ 628 | [ c**2, 0, 0, 0 ], 629 | [ 0, -x0**2*c**2/(x0**2*c**2 - x1**2), 0, 0 ], 630 | [ 0, 0, -x1**2, 0 ], 631 | [ 0, 0, 0, -x1**2*sin(x2)**2 ] 632 | ]) 633 | 634 | # An array detailing the solution. 635 | solution_array = [ metric, coordinate_set, index_config, cosmological_constant ] 636 | return solution_array 637 | 638 | def hypersphere(self): 639 | """ 640 | Description 641 | =========== 642 | Returns a metric which describes a spacetime where the cosmic time is assigned to the meaning of a 4D hypersphere radius. The essential idea behind this spacetime is that the "3+1" dimensionality commonly referenced in physics can be meaningfully mapped to the "3+1" dimensionality associated with a hypersphere; by the "3" angular coordinates and the "1" radial coordinate. 643 | Examples 644 | ======== 645 | >>> print(Solution().friedmann_lemaitre_robertson_walker()) 646 | >>> 647 | LaTeX representation 648 | ==================== 649 | """ 650 | 651 | # Index configuration for the metric 652 | index_config = "dd" 653 | # Required symbols and constants. 654 | c = symbols('c') 655 | # Assigns meaning to the coordinates. 656 | x0, x1, x2, x3 = symbols('t psi theta phi') 657 | # Reference to the coordiante system. 658 | coordinate_set = [x0, x1, x2, x3] 659 | # Cosmological constant. 660 | cosmological_constant = 0 661 | # Metric solution. 662 | metric = Matrix([ 663 | [ 1, 0, 0, 0 ], 664 | [ 0, -x0**2, 0, 0 ], 665 | [ 0, 0, -x0**2*sin(x1)**2, 0 ], 666 | [ 0, 0, 0, -x0**2*sin(x1)**2*sin(x2)**2 ] 667 | ]) 668 | 669 | # An array detailing the solution. 670 | solution_array = [ metric, coordinate_set, index_config, cosmological_constant ] 671 | return solution_array 672 | 673 | def euclidian_4d(self): 674 | """ 675 | Description 676 | =========== 677 | Returns a metric which describes a spacetime where the cosmic time is assigned to the meaning of a 4D hypersphere radius. The essential idea behind this spacetime is that the "3+1" dimensionality commonly referenced in physics can be meaningfully mapped to the "3+1" dimensionality associated with a hypersphere; by the "3" angular coordinates and the "1" radial coordinate. 678 | Examples 679 | ======== 680 | >>> print(Solution().friedmann_lemaitre_robertson_walker()) 681 | >>> 682 | LaTeX representation 683 | ==================== 684 | """ 685 | 686 | # Index configuration for the metric 687 | index_config = "dd" 688 | # Assigns meaning to the coordinates. 689 | x0, x1, x2, x3 = symbols('x y z w') 690 | # Reference to the coordiante system. 691 | coordinate_set = [x0, x1, x2, x3] 692 | # Cosmological constant. 693 | cosmological_constant = 0 694 | # Metric solution. 695 | metric = Matrix([ 696 | [ 1, 0, 0, 0 ], 697 | [ 0, 1, 0, 0 ], 698 | [ 0, 0, 1, 0 ], 699 | [ 0, 0, 0, 1 ] 700 | ]) 701 | 702 | # An array detailing the solution. 703 | solution_array = [ metric, coordinate_set, index_config, cosmological_constant ] 704 | return solution_array 705 | 706 | def hypersphere_I(self): 707 | """ 708 | Description 709 | =========== 710 | Returns a metric which describes a spacetime where the cosmic time is assigned to the meaning of a 4D hypersphere radius. The essential idea behind this spacetime is that the "3+1" dimensionality commonly referenced in physics can be meaningfully mapped to the "3+1" dimensionality associated with a hypersphere; by the "3" angular coordinates and the "1" radial coordinate. 711 | Examples 712 | ======== 713 | >>> print(Solution().friedmann_lemaitre_robertson_walker()) 714 | >>> 715 | LaTeX representation 716 | ==================== 717 | """ 718 | 719 | # Index configuration for the metric 720 | index_config = "dd" 721 | # Required symbols and constants. 722 | c = symbols('c') 723 | # Assigns meaning to the coordinates. 724 | tau = symbols('tau') 725 | x0 = Function('t')(tau) 726 | x1 = Function('psi')(tau) 727 | x2 = Function('theta')(tau) 728 | x3 = Function('phi')(tau) 729 | # Reference to the coordiante system. 730 | coordinate_set = [x0, x1, x2, x3] 731 | # Cosmological constant. 732 | cosmological_constant = 0 733 | # Metric solution. 734 | metric = Matrix([ 735 | [ sin(x1)**2*sin(x2)**2*sin(x3)**2, x0*sin(x2)**2*sin(x3)**2*sin(x1)*cos(x1), x0*sin(x1)**2*sin(x3)**2*sin(x2)*cos(x2), x0*sin(x1)**2*sin(x2)**2*sin(x3)*cos(x3) ], 736 | [ x0*sin(x2)**2*sin(x3)**2*sin(x1)*cos(x1), x0 - x0**2 + x0**2*sin(x2)**2*sin(x3)**2 - x0**2*sin(x1)**2*sin(x2)**2*sin(x3)**2, x0**2*sin(x3)**2*sin(x1)*sin(x2)*cos(x1)*cos(x2), x0**2*sin(x2)**2*sin(x1)*sin(x3)*cos(x1)*cos(x3) ], 737 | [ x0*sin(x1)**2*sin(x3)**2*sin(x2)*cos(x2), x0**2*sin(x3)**2*sin(x1)*sin(x2)*cos(x1)*cos(x2), x0*sin(x2)**2 - x0**2*sin(x1)**2 + x0**2*sin(x1)**2*sin(x3)**2 - x0**2*sin(x1)**2*sin(x2)**2*sin(x3)**2, x0**2*sin(x1)**2*sin(x2)*sin(x3)*cos(x2)*cos(x3) ], 738 | [ x0*sin(x1)**2*sin(x2)**2*sin(x3)*cos(x3), x0**2*sin(x2)**2*sin(x1)*sin(x3)*cos(x1)*cos(x3), x0**2*sin(x1)**2*sin(x2)*sin(x3)*cos(x2)*cos(x3), -x0**2*sin(x1)**2*sin(x2)**2*sin(x3)**2 + x0*sin(x1)**2*sin(x2)**2] 739 | ]) 740 | 741 | # An array detailing the solution. 742 | solution_array = [ metric, coordinate_set, index_config, cosmological_constant ] 743 | return solution_array 744 | 745 | def hypersphere_II(self): 746 | """ 747 | Description 748 | =========== 749 | Returns a metric which describes a spacetime where the cosmic time is assigned to the meaning of a 4D hypersphere radius. The essential idea behind this spacetime is that the "3+1" dimensionality commonly referenced in physics can be meaningfully mapped to the "3+1" dimensionality associated with a hypersphere; by the "3" angular coordinates and the "1" radial coordinate. 750 | Examples 751 | ======== 752 | >>> print(Solution().friedmann_lemaitre_robertson_walker()) 753 | >>> 754 | LaTeX representation 755 | ==================== 756 | """ 757 | 758 | # Index configuration for the metric 759 | index_config = "dd" 760 | # Required symbols and constants. 761 | c = symbols('c') 762 | # Assigns meaning to the coordinates. 763 | s = Symbol('s') 764 | r = Symbol('r') 765 | x0 = Symbol('t') 766 | x1 = Symbol('psi') 767 | x2 = Symbol('theta') 768 | x3 = Symbol('phi') 769 | # Reference to the coordiante system. 770 | coordinate_set = [x0, x1, x2, x3] 771 | # Cosmological constant. 772 | cosmological_constant = 0 773 | # Metric solution. 774 | metric = Matrix([ 775 | [ 1-r**2/x0**2, x0*sin(x1)*cos(x1), 0, 0 ], 776 | [ x0*sin(x1)*cos(x1), r**2, 0, 0 ], 777 | [ 0, 0, 0, 0 ], 778 | [ 0, 0, 0, 0] 779 | ]) 780 | 781 | # An array detailing the solution. 782 | solution_array = [ metric, coordinate_set, index_config, cosmological_constant ] 783 | return solution_array 784 | -------------------------------------------------------------------------------- /spacetimeengine/src/spacetime.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from sympy import * 3 | 4 | class SpaceTime: 5 | 6 | # Run at object creation. 7 | def __init__(self, solution, suppress_printing = False): 8 | 9 | # Initializes coordinate set class object. 10 | self.coordinate_set = solution[1] 11 | # Integer amount of dimensions associated with metric solution. 12 | self.dimension_count = len(self.coordinate_set) 13 | # Simple array for counting through tensor indices. 14 | self.dimensions = range(len(self.coordinate_set)) 15 | # Upon a SpaceTime object creation, the user may choose to print the terms as they are computed. 16 | self.suppress_printing = suppress_printing 17 | 18 | # Sets the metric tensor and its inverse. 19 | self.metric_index_config = solution[2] 20 | if (self.metric_index_config == "uu"): 21 | self.metric_tensor_uu = solution[0] 22 | self.metric_tensor_dd = simplify(solution[0].inv()) 23 | elif(self.metric_index_config == "dd"): 24 | self.metric_tensor_dd = solution[0] 25 | self.metric_tensor_uu = simplify(solution[0].inv()) 26 | else: 27 | print("Invalid index_config string.") 28 | 29 | # Declares ( gravitational field ) connection class object. 30 | self.christoffel_symbols_udd = Matrix([ 31 | [ 32 | [ 0, 0, 0, 0 ], 33 | [ 0, 0, 0, 0 ], 34 | [ 0, 0, 0, 0 ], 35 | [ 0, 0, 0, 0 ] 36 | ], 37 | [ 38 | [ 0, 0, 0, 0 ], 39 | [ 0, 0, 0, 0 ], 40 | [ 0, 0, 0, 0 ], 41 | [ 0, 0, 0, 0 ] 42 | ], 43 | [ 44 | [ 0, 0, 0, 0 ], 45 | [ 0, 0, 0, 0 ], 46 | [ 0, 0, 0, 0 ], 47 | [ 0, 0, 0, 0 ] 48 | ], 49 | [ 50 | [ 0, 0, 0, 0 ], 51 | [ 0, 0, 0, 0 ], 52 | [ 0, 0, 0, 0 ], 53 | [ 0, 0, 0, 0 ] 54 | ] 55 | ]) 56 | # Declares the Christoffel symbols of the first kind class object. 57 | self.christoffel_symbols_ddd = Matrix([ 58 | [ 59 | [ 0, 0, 0, 0 ], 60 | [ 0, 0, 0, 0 ], 61 | [ 0, 0, 0, 0 ], 62 | [ 0, 0, 0, 0 ] 63 | ], 64 | [ 65 | [ 0, 0, 0, 0 ], 66 | [ 0, 0, 0, 0 ], 67 | [ 0, 0, 0, 0 ], 68 | [ 0, 0, 0, 0 ] 69 | ], 70 | [ 71 | [ 0, 0, 0, 0 ], 72 | [ 0, 0, 0, 0 ], 73 | [ 0, 0, 0, 0 ], 74 | [ 0, 0, 0, 0 ] 75 | ], 76 | [ 77 | [ 0, 0, 0, 0 ], 78 | [ 0, 0, 0, 0 ], 79 | [ 0, 0, 0, 0 ], 80 | [ 0, 0, 0, 0 ] 81 | ] 82 | ]) 83 | 84 | # Declares Riemann curvature tensor class object. 85 | self.riemann_tensor_uddd = Matrix([ 86 | [ 87 | [ 88 | [ 0, 0, 0, 0 ], 89 | [ 0, 0, 0, 0 ], 90 | [ 0, 0, 0, 0 ], 91 | [ 0, 0, 0, 0 ] 92 | ], 93 | [ 94 | [ 0, 0, 0, 0 ], 95 | [ 0, 0, 0, 0 ], 96 | [ 0, 0, 0, 0 ], 97 | [ 0, 0, 0, 0 ] 98 | ], 99 | [ 100 | [ 0, 0, 0, 0 ], 101 | [ 0, 0, 0, 0 ], 102 | [ 0, 0, 0, 0 ], 103 | [ 0, 0, 0, 0 ] 104 | ], 105 | [ 106 | [ 0, 0, 0, 0 ], 107 | [ 0, 0, 0, 0 ], 108 | [ 0, 0, 0, 0 ], 109 | [ 0, 0, 0, 0 ] 110 | ] 111 | ], 112 | [ 113 | [ 114 | [ 0, 0, 0, 0 ], 115 | [ 0, 0, 0, 0 ], 116 | [ 0, 0, 0, 0 ], 117 | [ 0, 0, 0, 0 ] 118 | ], 119 | [ 120 | [ 0, 0, 0, 0 ], 121 | [ 0, 0, 0, 0 ], 122 | [ 0, 0, 0, 0 ], 123 | [ 0, 0, 0, 0 ] 124 | ], 125 | [ 126 | [ 0, 0, 0, 0 ], 127 | [ 0, 0, 0, 0 ], 128 | [ 0, 0, 0, 0 ], 129 | [ 0, 0, 0, 0 ] 130 | ], 131 | [ 132 | [ 0, 0, 0, 0 ], 133 | [ 0, 0, 0, 0 ], 134 | [ 0, 0, 0, 0 ], 135 | [ 0, 0, 0, 0 ] 136 | ] 137 | ], 138 | [ 139 | [ 140 | [ 0, 0, 0, 0 ], 141 | [ 0, 0, 0, 0 ], 142 | [ 0, 0, 0, 0 ], 143 | [ 0, 0, 0, 0 ] 144 | ], 145 | [ 146 | [ 0, 0, 0, 0 ], 147 | [ 0, 0, 0, 0 ], 148 | [ 0, 0, 0, 0 ], 149 | [ 0, 0, 0, 0 ] 150 | ], 151 | [ 152 | [ 0, 0, 0, 0 ], 153 | [ 0, 0, 0, 0 ], 154 | [ 0, 0, 0, 0 ], 155 | [ 0, 0, 0, 0 ] 156 | ], 157 | [ 158 | [ 0, 0, 0, 0 ], 159 | [ 0, 0, 0, 0 ], 160 | [ 0, 0, 0, 0 ], 161 | [ 0, 0, 0, 0 ] 162 | ] 163 | ], 164 | [ 165 | [ 166 | [ 0, 0, 0, 0 ], 167 | [ 0, 0, 0, 0 ], 168 | [ 0, 0, 0, 0 ], 169 | [ 0, 0, 0, 0 ] 170 | ], 171 | [ 172 | [ 0, 0, 0, 0 ], 173 | [ 0, 0, 0, 0 ], 174 | [ 0, 0, 0, 0 ], 175 | [ 0, 0, 0, 0 ] 176 | ], 177 | [ 178 | [ 0, 0, 0, 0 ], 179 | [ 0, 0, 0, 0 ], 180 | [ 0, 0, 0, 0 ], 181 | [ 0, 0, 0, 0 ] 182 | ], 183 | [ 184 | [ 0, 0, 0, 0 ], 185 | [ 0, 0, 0, 0 ], 186 | [ 0, 0, 0, 0 ], 187 | [ 0, 0, 0, 0 ] 188 | ] 189 | ] 190 | ]) 191 | 192 | # Declares Riemann curvature tensor "dddd" type class object. 193 | self.riemann_tensor_dddd = Matrix([ 194 | [ 195 | [ 196 | [ 0, 0, 0, 0 ], 197 | [ 0, 0, 0, 0 ], 198 | [ 0, 0, 0, 0 ], 199 | [ 0, 0, 0, 0 ] 200 | ], 201 | [ 202 | [ 0, 0, 0, 0 ], 203 | [ 0, 0, 0, 0 ], 204 | [ 0, 0, 0, 0 ], 205 | [ 0, 0, 0, 0 ] 206 | ], 207 | [ 208 | [ 0, 0, 0, 0 ], 209 | [ 0, 0, 0, 0 ], 210 | [ 0, 0, 0, 0 ], 211 | [ 0, 0, 0, 0 ] 212 | ], 213 | [ 214 | [ 0, 0, 0, 0 ], 215 | [ 0, 0, 0, 0 ], 216 | [ 0, 0, 0, 0 ], 217 | [ 0, 0, 0, 0 ] 218 | ] 219 | ], 220 | [ 221 | [ 222 | [ 0, 0, 0, 0 ], 223 | [ 0, 0, 0, 0 ], 224 | [ 0, 0, 0, 0 ], 225 | [ 0, 0, 0, 0 ] 226 | ], 227 | [ 228 | [ 0, 0, 0, 0 ], 229 | [ 0, 0, 0, 0 ], 230 | [ 0, 0, 0, 0 ], 231 | [ 0, 0, 0, 0 ] 232 | ], 233 | [ 234 | [ 0, 0, 0, 0 ], 235 | [ 0, 0, 0, 0 ], 236 | [ 0, 0, 0, 0 ], 237 | [ 0, 0, 0, 0 ] 238 | ], 239 | [ 240 | [ 0, 0, 0, 0 ], 241 | [ 0, 0, 0, 0 ], 242 | [ 0, 0, 0, 0 ], 243 | [ 0, 0, 0, 0 ] 244 | ] 245 | ], 246 | [ 247 | [ 248 | [ 0, 0, 0, 0 ], 249 | [ 0, 0, 0, 0 ], 250 | [ 0, 0, 0, 0 ], 251 | [ 0, 0, 0, 0 ] 252 | ], 253 | [ 254 | [ 0, 0, 0, 0 ], 255 | [ 0, 0, 0, 0 ], 256 | [ 0, 0, 0, 0 ], 257 | [ 0, 0, 0, 0 ] 258 | ], 259 | [ 260 | [ 0, 0, 0, 0 ], 261 | [ 0, 0, 0, 0 ], 262 | [ 0, 0, 0, 0 ], 263 | [ 0, 0, 0, 0 ] 264 | ], 265 | [ 266 | [ 0, 0, 0, 0 ], 267 | [ 0, 0, 0, 0 ], 268 | [ 0, 0, 0, 0 ], 269 | [ 0, 0, 0, 0 ] 270 | ] 271 | ], 272 | [ 273 | [ 274 | [ 0, 0, 0, 0 ], 275 | [ 0, 0, 0, 0 ], 276 | [ 0, 0, 0, 0 ], 277 | [ 0, 0, 0, 0 ] 278 | ], 279 | [ 280 | [ 0, 0, 0, 0 ], 281 | [ 0, 0, 0, 0 ], 282 | [ 0, 0, 0, 0 ], 283 | [ 0, 0, 0, 0 ] 284 | ], 285 | [ 286 | [ 0, 0, 0, 0 ], 287 | [ 0, 0, 0, 0 ], 288 | [ 0, 0, 0, 0 ], 289 | [ 0, 0, 0, 0 ] 290 | ], 291 | [ 292 | [ 0, 0, 0, 0 ], 293 | [ 0, 0, 0, 0 ], 294 | [ 0, 0, 0, 0 ], 295 | [ 0, 0, 0, 0 ] 296 | ] 297 | ] 298 | ]) 299 | 300 | # Declares Weyl curvature tensor "dddd" type class object. 301 | self.weyl_tensor_dddd = Matrix([ 302 | [ 303 | [ 304 | [ 0, 0, 0, 0 ], 305 | [ 0, 0, 0, 0 ], 306 | [ 0, 0, 0, 0 ], 307 | [ 0, 0, 0, 0 ] 308 | ], 309 | [ 310 | [ 0, 0, 0, 0 ], 311 | [ 0, 0, 0, 0 ], 312 | [ 0, 0, 0, 0 ], 313 | [ 0, 0, 0, 0 ] 314 | ], 315 | [ 316 | [ 0, 0, 0, 0 ], 317 | [ 0, 0, 0, 0 ], 318 | [ 0, 0, 0, 0 ], 319 | [ 0, 0, 0, 0 ] 320 | ], 321 | [ 322 | [ 0, 0, 0, 0 ], 323 | [ 0, 0, 0, 0 ], 324 | [ 0, 0, 0, 0 ], 325 | [ 0, 0, 0, 0 ] 326 | ] 327 | ], 328 | [ 329 | [ 330 | [ 0, 0, 0, 0 ], 331 | [ 0, 0, 0, 0 ], 332 | [ 0, 0, 0, 0 ], 333 | [ 0, 0, 0, 0 ] 334 | ], 335 | [ 336 | [ 0, 0, 0, 0 ], 337 | [ 0, 0, 0, 0 ], 338 | [ 0, 0, 0, 0 ], 339 | [ 0, 0, 0, 0 ] 340 | ], 341 | [ 342 | [ 0, 0, 0, 0 ], 343 | [ 0, 0, 0, 0 ], 344 | [ 0, 0, 0, 0 ], 345 | [ 0, 0, 0, 0 ] 346 | ], 347 | [ 348 | [ 0, 0, 0, 0 ], 349 | [ 0, 0, 0, 0 ], 350 | [ 0, 0, 0, 0 ], 351 | [ 0, 0, 0, 0 ] 352 | ] 353 | ], 354 | [ 355 | [ 356 | [ 0, 0, 0, 0 ], 357 | [ 0, 0, 0, 0 ], 358 | [ 0, 0, 0, 0 ], 359 | [ 0, 0, 0, 0 ] 360 | ], 361 | [ 362 | [ 0, 0, 0, 0 ], 363 | [ 0, 0, 0, 0 ], 364 | [ 0, 0, 0, 0 ], 365 | [ 0, 0, 0, 0 ] 366 | ], 367 | [ 368 | [ 0, 0, 0, 0 ], 369 | [ 0, 0, 0, 0 ], 370 | [ 0, 0, 0, 0 ], 371 | [ 0, 0, 0, 0 ] 372 | ], 373 | [ 374 | [ 0, 0, 0, 0 ], 375 | [ 0, 0, 0, 0 ], 376 | [ 0, 0, 0, 0 ], 377 | [ 0, 0, 0, 0 ] 378 | ] 379 | ], 380 | [ 381 | [ 382 | [ 0, 0, 0, 0 ], 383 | [ 0, 0, 0, 0 ], 384 | [ 0, 0, 0, 0 ], 385 | [ 0, 0, 0, 0 ] 386 | ], 387 | [ 388 | [ 0, 0, 0, 0 ], 389 | [ 0, 0, 0, 0 ], 390 | [ 0, 0, 0, 0 ], 391 | [ 0, 0, 0, 0 ] 392 | ], 393 | [ 394 | [ 0, 0, 0, 0 ], 395 | [ 0, 0, 0, 0 ], 396 | [ 0, 0, 0, 0 ], 397 | [ 0, 0, 0, 0 ] 398 | ], 399 | [ 400 | [ 0, 0, 0, 0 ], 401 | [ 0, 0, 0, 0 ], 402 | [ 0, 0, 0, 0 ], 403 | [ 0, 0, 0, 0 ] 404 | ] 405 | ] 406 | ]) 407 | 408 | # Declares Riemann curvature tensor "uddd" type class object. 409 | self.weyl_tensor_uddd = Matrix([ 410 | [ 411 | [ 412 | [ 0, 0, 0, 0 ], 413 | [ 0, 0, 0, 0 ], 414 | [ 0, 0, 0, 0 ], 415 | [ 0, 0, 0, 0 ] 416 | ], 417 | [ 418 | [ 0, 0, 0, 0 ], 419 | [ 0, 0, 0, 0 ], 420 | [ 0, 0, 0, 0 ], 421 | [ 0, 0, 0, 0 ] 422 | ], 423 | [ 424 | [ 0, 0, 0, 0 ], 425 | [ 0, 0, 0, 0 ], 426 | [ 0, 0, 0, 0 ], 427 | [ 0, 0, 0, 0 ] 428 | ], 429 | [ 430 | [ 0, 0, 0, 0 ], 431 | [ 0, 0, 0, 0 ], 432 | [ 0, 0, 0, 0 ], 433 | [ 0, 0, 0, 0 ] 434 | ] 435 | ], 436 | [ 437 | [ 438 | [ 0, 0, 0, 0 ], 439 | [ 0, 0, 0, 0 ], 440 | [ 0, 0, 0, 0 ], 441 | [ 0, 0, 0, 0 ] 442 | ], 443 | [ 444 | [ 0, 0, 0, 0 ], 445 | [ 0, 0, 0, 0 ], 446 | [ 0, 0, 0, 0 ], 447 | [ 0, 0, 0, 0 ] 448 | ], 449 | [ 450 | [ 0, 0, 0, 0 ], 451 | [ 0, 0, 0, 0 ], 452 | [ 0, 0, 0, 0 ], 453 | [ 0, 0, 0, 0 ] 454 | ], 455 | [ 456 | [ 0, 0, 0, 0 ], 457 | [ 0, 0, 0, 0 ], 458 | [ 0, 0, 0, 0 ], 459 | [ 0, 0, 0, 0 ] 460 | ] 461 | ], 462 | [ 463 | [ 464 | [ 0, 0, 0, 0 ], 465 | [ 0, 0, 0, 0 ], 466 | [ 0, 0, 0, 0 ], 467 | [ 0, 0, 0, 0 ] 468 | ], 469 | [ 470 | [ 0, 0, 0, 0 ], 471 | [ 0, 0, 0, 0 ], 472 | [ 0, 0, 0, 0 ], 473 | [ 0, 0, 0, 0 ] 474 | ], 475 | [ 476 | [ 0, 0, 0, 0 ], 477 | [ 0, 0, 0, 0 ], 478 | [ 0, 0, 0, 0 ], 479 | [ 0, 0, 0, 0 ] 480 | ], 481 | [ 482 | [ 0, 0, 0, 0 ], 483 | [ 0, 0, 0, 0 ], 484 | [ 0, 0, 0, 0 ], 485 | [ 0, 0, 0, 0 ] 486 | ] 487 | ], 488 | [ 489 | [ 490 | [ 0, 0, 0, 0 ], 491 | [ 0, 0, 0, 0 ], 492 | [ 0, 0, 0, 0 ], 493 | [ 0, 0, 0, 0 ] 494 | ], 495 | [ 496 | [ 0, 0, 0, 0 ], 497 | [ 0, 0, 0, 0 ], 498 | [ 0, 0, 0, 0 ], 499 | [ 0, 0, 0, 0 ] 500 | ], 501 | [ 502 | [ 0, 0, 0, 0 ], 503 | [ 0, 0, 0, 0 ], 504 | [ 0, 0, 0, 0 ], 505 | [ 0, 0, 0, 0 ] 506 | ], 507 | [ 508 | [ 0, 0, 0, 0 ], 509 | [ 0, 0, 0, 0 ], 510 | [ 0, 0, 0, 0 ], 511 | [ 0, 0, 0, 0 ] 512 | ] 513 | ] 514 | ]) 515 | 516 | # Declares Riemann curvature tensor "dduu" type class object. 517 | self.weyl_tensor_dduu = Matrix([ 518 | [ 519 | [ 520 | [ 0, 0, 0, 0 ], 521 | [ 0, 0, 0, 0 ], 522 | [ 0, 0, 0, 0 ], 523 | [ 0, 0, 0, 0 ] 524 | ], 525 | [ 526 | [ 0, 0, 0, 0 ], 527 | [ 0, 0, 0, 0 ], 528 | [ 0, 0, 0, 0 ], 529 | [ 0, 0, 0, 0 ] 530 | ], 531 | [ 532 | [ 0, 0, 0, 0 ], 533 | [ 0, 0, 0, 0 ], 534 | [ 0, 0, 0, 0 ], 535 | [ 0, 0, 0, 0 ] 536 | ], 537 | [ 538 | [ 0, 0, 0, 0 ], 539 | [ 0, 0, 0, 0 ], 540 | [ 0, 0, 0, 0 ], 541 | [ 0, 0, 0, 0 ] 542 | ] 543 | ], 544 | [ 545 | [ 546 | [ 0, 0, 0, 0 ], 547 | [ 0, 0, 0, 0 ], 548 | [ 0, 0, 0, 0 ], 549 | [ 0, 0, 0, 0 ] 550 | ], 551 | [ 552 | [ 0, 0, 0, 0 ], 553 | [ 0, 0, 0, 0 ], 554 | [ 0, 0, 0, 0 ], 555 | [ 0, 0, 0, 0 ] 556 | ], 557 | [ 558 | [ 0, 0, 0, 0 ], 559 | [ 0, 0, 0, 0 ], 560 | [ 0, 0, 0, 0 ], 561 | [ 0, 0, 0, 0 ] 562 | ], 563 | [ 564 | [ 0, 0, 0, 0 ], 565 | [ 0, 0, 0, 0 ], 566 | [ 0, 0, 0, 0 ], 567 | [ 0, 0, 0, 0 ] 568 | ] 569 | ], 570 | [ 571 | [ 572 | [ 0, 0, 0, 0 ], 573 | [ 0, 0, 0, 0 ], 574 | [ 0, 0, 0, 0 ], 575 | [ 0, 0, 0, 0 ] 576 | ], 577 | [ 578 | [ 0, 0, 0, 0 ], 579 | [ 0, 0, 0, 0 ], 580 | [ 0, 0, 0, 0 ], 581 | [ 0, 0, 0, 0 ] 582 | ], 583 | [ 584 | [ 0, 0, 0, 0 ], 585 | [ 0, 0, 0, 0 ], 586 | [ 0, 0, 0, 0 ], 587 | [ 0, 0, 0, 0 ] 588 | ], 589 | [ 590 | [ 0, 0, 0, 0 ], 591 | [ 0, 0, 0, 0 ], 592 | [ 0, 0, 0, 0 ], 593 | [ 0, 0, 0, 0 ] 594 | ] 595 | ], 596 | [ 597 | [ 598 | [ 0, 0, 0, 0 ], 599 | [ 0, 0, 0, 0 ], 600 | [ 0, 0, 0, 0 ], 601 | [ 0, 0, 0, 0 ] 602 | ], 603 | [ 604 | [ 0, 0, 0, 0 ], 605 | [ 0, 0, 0, 0 ], 606 | [ 0, 0, 0, 0 ], 607 | [ 0, 0, 0, 0 ] 608 | ], 609 | [ 610 | [ 0, 0, 0, 0 ], 611 | [ 0, 0, 0, 0 ], 612 | [ 0, 0, 0, 0 ], 613 | [ 0, 0, 0, 0 ] 614 | ], 615 | [ 616 | [ 0, 0, 0, 0 ], 617 | [ 0, 0, 0, 0 ], 618 | [ 0, 0, 0, 0 ], 619 | [ 0, 0, 0, 0 ] 620 | ] 621 | ] 622 | ]) 623 | 624 | # Declares the covariant Ricci curvature tensor class object. 625 | self.ricci_tensor_dd = Matrix([ 626 | [ 0, 0, 0, 0 ], 627 | [ 0, 0, 0, 0 ], 628 | [ 0, 0, 0, 0 ], 629 | [ 0, 0, 0, 0 ] 630 | ]) 631 | 632 | # Declares the contravariant Ricci curvature tensor class object. 633 | self.ricci_tensor_uu = Matrix([ 634 | [ 0, 0, 0, 0 ], 635 | [ 0, 0, 0, 0 ], 636 | [ 0, 0, 0, 0 ], 637 | [ 0, 0, 0, 0 ] 638 | ]) 639 | 640 | # Declares the mixed Ricci curvature tensor class object. 641 | self.ricci_tensor_ud = Matrix([ 642 | [ 0, 0, 0, 0 ], 643 | [ 0, 0, 0, 0 ], 644 | [ 0, 0, 0, 0 ], 645 | [ 0, 0, 0, 0 ] 646 | ]) 647 | 648 | # Declares Ricci curvature tensor class object. 649 | self.ricci_scalar = 0 650 | 651 | # Declares the covariant Einstein curvature tensor class object. 652 | self.einstein_tensor_dd = Matrix([ 653 | [ 0, 0, 0, 0 ], 654 | [ 0, 0, 0, 0 ], 655 | [ 0, 0, 0, 0 ], 656 | [ 0, 0, 0, 0 ] 657 | ]) 658 | 659 | # Declares the contravariant Einstein curvature tensor class object. 660 | self.einstein_tensor_uu = Matrix([ 661 | [ 0, 0, 0, 0 ], 662 | [ 0, 0, 0, 0 ], 663 | [ 0, 0, 0, 0 ], 664 | [ 0, 0, 0, 0 ] 665 | ]) 666 | 667 | # Declares the mixed Einstein curvature tensor class object. 668 | self.einstein_tensor_ud = Matrix([ 669 | [ 0, 0, 0, 0 ], 670 | [ 0, 0, 0, 0 ], 671 | [ 0, 0, 0, 0 ], 672 | [ 0, 0, 0, 0 ] 673 | ]) 674 | 675 | # Declares the covariant stress-energy tensor class object. 676 | self.stress_energy_tensor_dd = Matrix([ 677 | [ 0, 0, 0, 0 ], 678 | [ 0, 0, 0, 0 ], 679 | [ 0, 0, 0, 0 ], 680 | [ 0, 0, 0, 0 ] 681 | ]) 682 | 683 | # Declares the contravariant stress-energy tensor class object. 684 | self.stress_energy_tensor_uu = Matrix([ 685 | [ 0, 0, 0, 0 ], 686 | [ 0, 0, 0, 0 ], 687 | [ 0, 0, 0, 0 ], 688 | [ 0, 0, 0, 0 ] 689 | ]) 690 | 691 | # Declares the mixed stress-energy tensor class object. 692 | self.stress_energy_tensor_ud = Matrix([ 693 | [ 0, 0, 0, 0 ], 694 | [ 0, 0, 0, 0 ], 695 | [ 0, 0, 0, 0 ], 696 | [ 0, 0, 0, 0 ] 697 | ]) 698 | 699 | # Declares the contravariant Schouten tensor class object. 700 | self.schouten_tensor_uu = Matrix([ 701 | [ 0, 0, 0, 0 ], 702 | [ 0, 0, 0, 0 ], 703 | [ 0, 0, 0, 0 ], 704 | [ 0, 0, 0, 0 ] 705 | ]) 706 | 707 | # Declares the covariant Schouten tensor class object. 708 | self.schouten_tensor_dd = Matrix([ 709 | [ 0, 0, 0, 0 ], 710 | [ 0, 0, 0, 0 ], 711 | [ 0, 0, 0, 0 ], 712 | [ 0, 0, 0, 0 ] 713 | ]) 714 | 715 | # Declares cosmological constant class object. 716 | self.cosmological_constant = 0 717 | 718 | # Acceleration vectors. 719 | self.proper_acceleration = [ 0, 0, 0, 0 ] 720 | self.coordinate_acceleration = [ 0, 0, 0, 0 ] 721 | self.geodesic_deviation_acceleration = [ 0, 0, 0, 0 ] 722 | 723 | # Velocity vectors. 724 | self.proper_velocity = [ 0, 0, 0, 0 ] 725 | self.coordinate_velocity = [ 0, 0, 0, 0 ] 726 | self.geodesic_velocity= [ 0, 0, 0, 0 ] 727 | 728 | # Position vectors. 729 | self.proper_position = [ 0, 0, 0, 0 ] 730 | self.coordinate_position = [ 0, 0, 0, 0 ] 731 | self.geodesic_deviation_position = [ 0, 0, 0, 0 ] 732 | 733 | """ 734 | Initializing object functions 735 | ============================= 736 | """ 737 | 738 | # TODO 739 | # finish all of these functions. 740 | 741 | self.set_all_metric_coefficients("dd") 742 | #self.set_all_metric_coefficients("uu") 743 | self.set_all_connection_coefficients("udd") 744 | #self.set_all_connection_coefficients("ddd") 745 | self.set_all_riemann_coefficients("uddd") 746 | #self.set_all_riemann_coefficients("dddd") 747 | self.set_all_ricci_coefficients("dd") 748 | #self.set_all_weyl_coefficients("dddd") 749 | #self.set_all_weyl_coefficients("uddd") 750 | self.set_all_schouten_coefficients("dd") 751 | #self.set_all_cotton_coefficients("ddd") 752 | #self.set_all_ricci_coefficients("uu") 753 | #self.set_all_ricci_coefficients("ud") 754 | self.set_ricci_scalar() 755 | self.set_all_einstein_coefficients("dd") 756 | #self.set_all_einstein_coefficients("uu") 757 | #self.set_all_einstein_coefficients("ud") 758 | self.set_all_stress_energy_coefficients("dd") 759 | #self.set_all_stress_energy_coefficients("uu") 760 | #self.set_all_stress_energy_coefficients("ud") 761 | #self.set_cosmological_constant(solution[3]) 762 | self.set_all_proper_time_geodesic_accelerations() 763 | self.set_all_coordinate_time_geodesic_accelerations() 764 | self.set_all_geodesic_deviation_accelerations() 765 | 766 | """ 767 | Metric coefficient functions 768 | ============================ 769 | """ 770 | 771 | def get_metric_coefficient(self, index_config, mu, nu): 772 | """ 773 | Description 774 | =========== 775 | Gets a single metric coefficient from class object for a given index configuration and index value pair. 776 | 777 | Example 778 | ======= 779 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 780 | >> print(newtonian.get_metric_coefficient("uu",1,1)) 781 | >> 782 | 783 | LaTeX representation 784 | ==================== 785 | g_{ij} 786 | g^{ij} 787 | 788 | URL Reference 789 | ============= 790 | https://en.wikipedia.org/wiki/Metric_tensor 791 | 792 | TODOs 793 | ===== 794 | - Link example with test. 795 | - Need higher quality tests. 796 | """ 797 | 798 | if (index_config == "uu"): 799 | return self.metric_tensor_uu[mu, nu] 800 | elif(index_config == "dd"): 801 | return self.metric_tensor_dd[mu, nu] 802 | else: 803 | print("Invalid index_config string.") 804 | 805 | def set_metric_coefficient(self, index_config, mu, nu, expression): 806 | """ 807 | Description 808 | =========== 809 | Sets a single metric coefficient equal to a given expression. 810 | WARNING: This function is used for memory managment purposes and is not reccomended. for regular use since it can easily create contradictions within a solution easily. This may have more uses in the future. 811 | 812 | Example 813 | ======= 814 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 815 | >> print(newtonian.set_metric_coefficient("uu",1,1),0) 816 | 817 | LaTeX representation 818 | ==================== 819 | g_{23} = # set_metric_coefficient("dd",2,3,0) 820 | g^{03} = # set_metric_coefficient("uu",0,3,0) 821 | 822 | URL Reference 823 | ============= 824 | https://en.wikipedia.org/wiki/Metric_tensor 825 | 826 | TODOs 827 | ===== 828 | - Link example with test. 829 | - Need higher quality tests. 830 | """ 831 | 832 | if (index_config == "uu"): 833 | self.metric_tensor_uu[mu,nu] = expression 834 | elif(index_config == "dd"): 835 | self.metric_tensor_dd[mu,nu] = expression 836 | else: 837 | print("Invalid index_config string.") 838 | 839 | 840 | def set_all_metric_coefficients(self, index_config): 841 | """ 842 | Description 843 | =========== 844 | Sets all metric coefficients for a given index configuration. It retrieves these values from the solution input. 845 | * Effectively this function only is needed when the user specifies a print on object creation. 846 | 847 | Example 848 | ======= 849 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 850 | >> newtonian.set_all_metric_coefficients("uu") # Redundant becasue function is called at creation of SpaceTime object. 851 | 852 | LaTeX representation 853 | ==================== 854 | g_{ij} 855 | g^{ij} 856 | 857 | URL Reference 858 | ============= 859 | https://en.wikipedia.org/wiki/Metric_tensor 860 | 861 | TODOs 862 | ===== 863 | - Link example with test. 864 | - Need higher quality tests. 865 | """ 866 | 867 | if (index_config == "uu"): 868 | if(self.suppress_printing == False): 869 | print("") 870 | print("") 871 | print("Metric tensor coefficients (uu)") 872 | print("===============================") 873 | for mu in self.dimensions: 874 | for nu in self.dimensions: 875 | self.print_metric_coefficient(index_config, mu, nu) 876 | elif(index_config == "dd"): 877 | if(self.suppress_printing == False): 878 | print("") 879 | print("") 880 | print("Metric tensor coefficients (dd)") 881 | print("===============================") 882 | for mu in self.dimensions: 883 | for nu in self.dimensions: 884 | self.print_metric_coefficient(index_config, mu, nu) 885 | else: 886 | print("Invalid index_config string.") 887 | 888 | def print_metric_coefficient(self, index_config, mu, nu): 889 | """ 890 | Description 891 | =========== 892 | Prints a single metric tensor coefficient. 893 | 894 | Example 895 | ======= 896 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 897 | >> newtonian.print_metric_coefficient("uu",3,1) 898 | 0 899 | LaTeX representation 900 | ==================== 901 | g_{ij} 902 | g^{ij} 903 | 904 | URL Reference 905 | ============= 906 | https://en.wikipedia.org/wiki/Metric_tensor 907 | 908 | TODOs 909 | ===== 910 | - Link example with test. 911 | - Need higher quality tests. 912 | """ 913 | 914 | if (index_config == "uu"): 915 | print("") 916 | pprint(Eq(Symbol('g^%s%s' % (mu, nu)), self.get_metric_coefficient(index_config, mu, nu))) 917 | elif(index_config == "dd"): 918 | print("") 919 | pprint(Eq(Symbol('g_%s%s' % (mu, nu)), self.get_metric_coefficient(index_config, mu, nu))) 920 | else: 921 | print("Invalid index_config string.") 922 | 923 | def print_all_metric_coefficients(self, index_config): 924 | """ 925 | Description 926 | =========== 927 | Prints all metric tensor coefficients. 928 | 929 | Example 930 | ======= 931 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 932 | >> newtonian.print_all_metric_coefficients("uu") 933 | ... 934 | LaTeX representation 935 | ==================== 936 | g_{ij} 937 | g^{ij} 938 | 939 | URL Reference 940 | ============= 941 | https://en.wikipedia.org/wiki/Metric_tensor 942 | 943 | TODOs 944 | ===== 945 | - Link example with test. 946 | - Need higher quality tests. 947 | """ 948 | 949 | if (index_config == "uu"): 950 | for mu in self.dimensions: 951 | for nu in self.dimensions: 952 | self.print_metric_coefficient(index_config, mu, nu) 953 | elif(index_config == "dd"): 954 | for mu in self.dimensions: 955 | for nu in self.dimensions: 956 | self.print_metric_coefficient(index_config, mu, nu) 957 | else: 958 | print("Invalid index_config string.") 959 | 960 | """ 961 | Connection coefficient functions 962 | ================================ 963 | """ 964 | 965 | def get_connection_coefficient(self, index_config, i, k, l): 966 | """ 967 | Description 968 | =========== 969 | Gets a single connection coefficients from class object. 970 | 971 | Example 972 | ======= 973 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 974 | >> print(newtonian.get_connection_coefficient("udd",1,1,1)) 975 | 2*G*M*(G*M/(c**2*r) - 1/2)/(c**2*r**2*(-2*G*M/(c**2*r) + 1)**2) 976 | 977 | LaTeX representation 978 | ==================== 979 | \Gamma^{i}_{kl} 980 | \Gamma_{ikl} 981 | 982 | URL Reference 983 | ============= 984 | https://en.wikipedia.org/wiki/Christoffel_symbols 985 | 986 | TODOs 987 | ===== 988 | - Link example with test. 989 | - Need higher quality tests. 990 | """ 991 | 992 | if(index_config == "udd"): 993 | return self.christoffel_symbols_udd[i,k][l] 994 | elif(index_config == "ddd"): 995 | return self.christoffel_symbols_ddd[i,k][l] 996 | else: 997 | print("Invalid index_config string.") 998 | 999 | def set_connection_coefficient(self, index_config, i, k, l, expression): 1000 | """ 1001 | Description 1002 | =========== 1003 | Sets a single connection coefficient equal to a given expression. 1004 | WARNING: This function is used for memory managment purposes and is not reccomended for regular use since it can easily create contradictions within a solution easily. This may have more uses in the future. 1005 | 1006 | Example 1007 | ======= 1008 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1009 | >> newtonian.set_connection_coefficient("ud",1,1,1,0) 1010 | 1011 | LaTeX representation 1012 | ==================== 1013 | \Gamma^{i}_{kl}, 1014 | \Gamma_{ikl} 1015 | 1016 | URL Reference 1017 | ============= 1018 | https://en.wikipedia.org/wiki/Christoffel_symbols 1019 | 1020 | TODOs 1021 | ===== 1022 | - Link example with test. 1023 | - Need higher quality tests. 1024 | """ 1025 | 1026 | if(index_config == "udd"): 1027 | self.christoffel_symbols_udd[i,k][l] = expression 1028 | elif(index_config == "ddd"): 1029 | self.christoffel_symbols_ddd[i,k][l] = expression 1030 | else: 1031 | print("Invalid index_config string.") 1032 | 1033 | def set_all_connection_coefficients(self, index_config): 1034 | """ 1035 | Description 1036 | =========== 1037 | Sets all connection coefficient values for reuse. Allows for the removal of redundant calculations. 1038 | WARNING: Redundant since this is called at creation of SpaceTime object. 1039 | 1040 | Example 1041 | ======= 1042 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1043 | >> newtonian.set_all_connection_coefficients("udd") 1044 | 1045 | LaTeX representation 1046 | ==================== 1047 | \Gamma^{i}_{kl} 1048 | \Gamma_{ikl} 1049 | 1050 | URL Reference 1051 | ============= 1052 | https://en.wikipedia.org/wiki/Christoffel_symbols 1053 | 1054 | TODOs 1055 | ===== 1056 | - Link example with test. 1057 | - Need higher quality tests. 1058 | """ 1059 | 1060 | if(index_config == "udd"): 1061 | if(self.suppress_printing == False): 1062 | print("") 1063 | print("") 1064 | print("Connection coefficients (udd)") 1065 | print("=============================") 1066 | for i in self.dimensions: 1067 | for k in self.dimensions: 1068 | for l in self.dimensions: 1069 | self.set_connection_coefficient(index_config, i, k, l, self.compute_connection_coefficient(index_config, i, k, l)) 1070 | if(self.suppress_printing == False): 1071 | self.print_connection_coefficient(index_config, i, k, l ) 1072 | elif(index_config == "ddd"): 1073 | if(self.suppress_printing == False): 1074 | print("") 1075 | print("") 1076 | print("Connection coefficients (ddd)") 1077 | print("=============================") 1078 | for i in self.dimensions: 1079 | for k in self.dimensions: 1080 | for l in self.dimensions: 1081 | self.set_connection_coefficient(index_config, i, k, l, self.compute_connection_coefficient(index_config, i, k, l)) 1082 | if(self.suppress_printing == False): 1083 | self.print_connection_coefficient(index_config, i, k, l ) 1084 | else: 1085 | print("Invalid index_config string.") 1086 | 1087 | def compute_connection_coefficient(self, index_config, i, k, l): 1088 | """ 1089 | Description 1090 | =========== 1091 | Computes a single connection coefficient. 1092 | 1093 | Example 1094 | ======= 1095 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1096 | >> newtonian.compute_connection_coefficients("udd",0,0,0) 1097 | 1098 | LaTeX representation 1099 | ==================== 1100 | \Gamma^{i}_{kl} 1101 | \Gamma_{ikl} 1102 | 1103 | URL Reference 1104 | ============= 1105 | https://en.wikipedia.org/wiki/Christoffel_symbols 1106 | 1107 | TODOs 1108 | ===== 1109 | - Link example with test. 1110 | - Need higher quality tests. 1111 | """ 1112 | 1113 | connection = 0 1114 | if index_config == "udd": 1115 | for m in self.dimensions: 1116 | connection = connection+Rational('1/2')*self.metric_tensor_uu[m,i]*(diff(self.metric_tensor_dd[k,m], self.coordinate_set[l])+diff(self.metric_tensor_dd[l,m], self.coordinate_set[k])-diff(self.metric_tensor_dd[k,l], self.coordinate_set[m])) 1117 | return connection 1118 | elif index_config == "ddd": 1119 | connection = Rational('1/2')*(diff(self.metric_tensor_dd[i,k], self.coordinate_set[l])+diff(self.metric_tensor_dd[i,l], self.coordinate_set[k])-diff(self.metric_tensor_dd[k,l], self.coordinate_set[i])) 1120 | return simplify(connection) 1121 | else: 1122 | print("Invalid index_config string.") 1123 | 1124 | def print_connection_coefficient(self, index_config, i, j, k ): 1125 | """ 1126 | Description 1127 | =========== 1128 | Prints a single connection coefficient. 1129 | 1130 | Example 1131 | ======= 1132 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1133 | >> newtonian.print_connection_coefficient("udd",0,0,0) 1134 | 1135 | Γ⁰₀₀ = 0 1136 | 1137 | LaTeX representation 1138 | ==================== 1139 | \Gamma^{i}_{kl} 1140 | \Gamma_{ikl} 1141 | 1142 | URL Reference 1143 | ============= 1144 | https://en.wikipedia.org/wiki/Christoffel_symbols 1145 | 1146 | TODOs 1147 | ===== 1148 | - Link example with test. 1149 | - Need higher quality tests. 1150 | """ 1151 | 1152 | if(index_config == "udd"): 1153 | print("") 1154 | pprint(Eq(Symbol('Gamma^%s_%s%s' % (i, j, k)),self.get_connection_coefficient(index_config, i, j, k ))) 1155 | elif(index_config == "ddd"): 1156 | print("") 1157 | # TODO 1158 | # MUST TEST 1159 | pprint(Eq(Symbol('Gamma_%s%s%s' % (i, j, k)),self.get_connection_coefficient(index_config, i, j, k ))) 1160 | else: 1161 | print("Invalid index_config string.") 1162 | 1163 | # Prints all connection coefficients. 1164 | def print_all_connection_coefficients(self, index_config): 1165 | """ 1166 | Description 1167 | =========== 1168 | Prints all connection coefficients for a given index configuration. 1169 | 1170 | Example 1171 | ======= 1172 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1173 | >> newtonian.print_all_connection_coefficients("udd") 1174 | 1175 | Γ⁰₀₀ = 0 1176 | 1177 | ... 1178 | ... 1179 | ... 1180 | 1181 | Γ³₃₃ = 0 1182 | 1183 | LaTeX representation 1184 | ==================== 1185 | \Gamma^{i}_{kl} 1186 | \Gamma_{ikl} 1187 | 1188 | URL Reference 1189 | ============= 1190 | https://en.wikipedia.org/wiki/Christoffel_symbols 1191 | 1192 | TODOs 1193 | ===== 1194 | - Link example with test. 1195 | - Need higher quality tests. 1196 | """ 1197 | 1198 | if(index_config == "udd"): 1199 | for lam in self.dimensions: 1200 | for mu in self.dimensions: 1201 | for nu in self.dimensions: 1202 | print("") 1203 | self.print_connection_coefficient(index_config, lam, mu, nu ) 1204 | elif(index_config == "ddd"): 1205 | for lam in self.dimensions: 1206 | for mu in self.dimensions: 1207 | for nu in self.dimensions: 1208 | print("") 1209 | self.print_connection_coefficient(index_config, lam, mu, nu ) 1210 | else: 1211 | print("Invalid index_config string.") 1212 | 1213 | """ 1214 | Riemann coefficient functions 1215 | ============================= 1216 | """ 1217 | 1218 | def get_riemann_coefficient(self, index_config, rho, sig, mu, nu): 1219 | """ 1220 | Description 1221 | =========== 1222 | Gets a single Riemann coefficients from class object. 1223 | 1224 | Example 1225 | ======= 1226 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1227 | >> pprint(newtonian.get_riemann_coefficient("uddd",0,1,2,3)) 1228 | 0 1229 | 1230 | LaTeX representation 1231 | ==================== 1232 | R^{i}_{jkl} -> (i,j,k,l) = (rho,sig,mu,nu) 1233 | R_{ijkl} -> (i,j,k,l) = (rho,sig,mu,nu) 1234 | 1235 | URL Reference 1236 | ============= 1237 | https://en.wikipedia.org/wiki/List_of_formulas_in_Riemannian_geometry#Riemann_curvature_tensor 1238 | https://en.wikipedia.org/wiki/Riemann_curvature_tensor 1239 | 1240 | TODOs 1241 | ===== 1242 | - Link example with test. 1243 | - Need higher quality tests. 1244 | - Needs functionality for other index configurations. 1245 | """ 1246 | 1247 | if(index_config == "uddd"): 1248 | return self.riemann_tensor_uddd[int(rho*16/self.dimension_count+sig)][mu][nu] 1249 | elif(index_config == "dddd"): 1250 | return self.riemann_tensor_dddd[int(rho*16/self.dimension_count+sig)][mu][nu] 1251 | else: 1252 | print("Invalid index_config string.") 1253 | 1254 | def set_riemann_coefficient(self, index_config, rho, sig, mu, nu, expression): 1255 | """ 1256 | Description 1257 | =========== 1258 | Sets a single Riemann coefficient equal to a given expression. 1259 | WARNING: This function is used for memory managment purposes and is not reccomended for interactive use. 1260 | 1261 | Example 1262 | ======= 1263 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1264 | >> pprint(newtonian.set_riemann_coefficient("uddd",0,1,2,3),0) 1265 | 1266 | LaTeX representation 1267 | ==================== 1268 | R^{i}_{jkl} -> (i,j,k,l) = (rho,sig,mu,nu) 1269 | R_{ijkl} -> (i,j,k,l) = (rho,sig,mu,nu) 1270 | 1271 | URL Reference 1272 | ============= 1273 | https://en.wikipedia.org/wiki/List_of_formulas_in_Riemannian_geometry#Riemann_curvature_tensor 1274 | https://en.wikipedia.org/wiki/Riemann_curvature_tensor 1275 | 1276 | TODOs 1277 | ===== 1278 | - Link example with test. 1279 | - Need higher quality tests. 1280 | - Needs functionality for other index configurations. 1281 | """ 1282 | 1283 | if(index_config == "uddd"): 1284 | self.riemann_tensor_uddd[int(rho*16/self.dimension_count+sig)][mu][nu] = expression 1285 | elif(index_config == "dddd"): 1286 | # TODO 1287 | # MUST TEST 1288 | self.riemann_tensor_dddd[int(rho*16/self.dimension_count+sig)][mu][nu] = expression 1289 | else: 1290 | print("Invalid index_config string.") 1291 | 1292 | def set_all_riemann_coefficients(self, index_config): 1293 | """ 1294 | Description 1295 | =========== 1296 | Sets all Riemann coefficients values for reuse. Allows for the removal of redundant calculations. 1297 | WARNING: Redundant becasue function is already called at creation of SpaceTime object. 1298 | 1299 | Example 1300 | ======= 1301 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1302 | >> pprint(newtonian.set_all_riemann_coefficients("uddd") 1303 | 1304 | LaTeX representation 1305 | ==================== 1306 | R^{i}_{jkl} -> (i,j,k,l) = (rho,sig,mu,nu) 1307 | R_{ijkl} -> (i,j,k,l) = (rho,sig,mu,nu) 1308 | 1309 | URL Reference 1310 | ============= 1311 | https://en.wikipedia.org/wiki/List_of_formulas_in_Riemannian_geometry#Riemann_curvature_tensor 1312 | https://en.wikipedia.org/wiki/Riemann_curvature_tensor 1313 | 1314 | TODOs 1315 | ===== 1316 | - Link example with test. 1317 | - Need higher quality tests. 1318 | - Needs functionality for other index configurations. 1319 | """ 1320 | 1321 | if index_config == "uddd": 1322 | if(self.suppress_printing == False): 1323 | print("") 1324 | print("") 1325 | print("Riemann curvature tensor coefficients (uddd)") 1326 | print("============================================") 1327 | for rho in self.dimensions: 1328 | for sig in self.dimensions: 1329 | for mu in self.dimensions: 1330 | for nu in self.dimensions: 1331 | self.set_riemann_coefficient(index_config, rho, sig, mu, nu, self.compute_riemann_coefficient(index_config, rho, sig, mu, nu)) 1332 | if(self.suppress_printing == False): 1333 | self.print_riemann_coefficient(index_config, rho, sig, mu, nu) 1334 | elif index_config == "dddd": 1335 | if(self.suppress_printing == False): 1336 | print("") 1337 | print("") 1338 | print("Riemann curvature tensor coefficients (dddd)") 1339 | print("============================================") 1340 | for rho in self.dimensions: 1341 | for sig in self.dimensions: 1342 | for mu in self.dimensions: 1343 | for nu in self.dimensions: 1344 | # TODO 1345 | # MUST TEST 1346 | self.set_riemann_coefficient(index_config, rho, sig, mu, nu, self.compute_riemann_coefficient(index_config, rho, sig, mu, nu)) 1347 | if(self.suppress_printing == False): 1348 | self.print_riemann_coefficient(index_config, rho, sig, mu, nu) 1349 | else: 1350 | print("Invalid index_config string.") 1351 | 1352 | def compute_riemann_coefficient(self, index_config, rho, sig, mu, nu): 1353 | """ 1354 | Description 1355 | =========== 1356 | Computes a single Riemann tensor coefficient. 1357 | 1358 | Example 1359 | ======= 1360 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1361 | >> print(newtonian.compute_riemann_coefficient("uddd",0,2,2,0)) 1362 | G*M/(c**2*r) 1363 | 1364 | LaTeX representation 1365 | ==================== 1366 | R^{i}_{jkl} -> (i,j,k,l) = (rho,sig,mu,nu) 1367 | R_{ijkl} -> (i,j,k,l) = (rho,sig,mu,nu) 1368 | 1369 | URL Reference 1370 | ============= 1371 | https://en.wikipedia.org/wiki/List_of_formulas_in_Riemannian_geometry#Riemann_curvature_tensor 1372 | https://en.wikipedia.org/wiki/Riemann_curvature_tensor 1373 | 1374 | TODOs 1375 | ===== 1376 | - Link example with test. 1377 | - Need higher quality tests. 1378 | - Needs functionality for other index configurations. 1379 | """ 1380 | 1381 | riemann_coefficient = 0 1382 | if index_config == "uddd": 1383 | riemann_coefficient = diff(self.get_connection_coefficient("udd", rho, nu, sig), self.coordinate_set[mu]) - diff(self.get_connection_coefficient("udd", rho, mu, sig), self.coordinate_set[nu]) 1384 | for lam in self.dimensions: 1385 | riemann_coefficient = riemann_coefficient + self.get_connection_coefficient("udd", rho, mu, lam)*self.get_connection_coefficient("udd", lam, nu, sig) - self.get_connection_coefficient("udd", rho, nu, lam)*self.get_connection_coefficient("udd", lam, mu, sig) 1386 | riemann_coefficient = simplify(riemann_coefficient) 1387 | return riemann_coefficient 1388 | elif index_config == "dddd": 1389 | riemann_coefficient = Rational('1/2')*(self.get_metric_coefficient("dd", rho, nu).diff(self.coordinate_set[sig]).diff(self.coordinate_set[mu]) + self.get_metric_coefficient("dd", sig, mu).diff(self.coordinate_set[rho]).diff(self.coordinate_set[nu])-self.get_metric_coefficient("dd", rho, mu).diff(self.coordinate_set[sig]).diff(self.coordinate_set[nu])-self.get_metric_coefficient("dd", sig, nu).diff(self.coordinate_set[rho]).diff(self.coordinate_set[mu])) 1390 | for n in self.dimensions: 1391 | for p in self.dimensions: 1392 | riemann_coefficient = riemann_coefficient + self.get_metric_coefficient("dd", n, p)*(self.get_connection_coefficient("udd", n, sig, mu)*self.get_connection_coefficient("udd", p, rho, nu)-self.get_connection_coefficient("udd", n, sig, nu)*self.get_connection_coefficient("udd", p, rho, mu)) 1393 | riemann_coefficient = simplify(riemann_coefficient) 1394 | return riemann_coefficient 1395 | else: 1396 | print("Invalid index_config string.") 1397 | 1398 | def print_riemann_coefficient(self, index_config, rho, sig, mu, nu): 1399 | """ 1400 | Description 1401 | =========== 1402 | Prints a single Riemann coefficient. 1403 | 1404 | Example 1405 | ======= 1406 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1407 | >> newtonian.print_riemann_coefficient("uddd",0,2,2,0) 1408 | 1409 | G⋅M 1410 | R⁰₂₂₀ = ──── 1411 | 2 1412 | c ⋅r 1413 | 1414 | LaTeX representation 1415 | ==================== 1416 | R^{i}_{jkl} -> (i,j,k,l) = (rho,sig,mu,nu) 1417 | R_{ijkl} -> (i,j,k,l) = (rho,sig,mu,nu) 1418 | 1419 | URL Reference 1420 | ============= 1421 | https://en.wikipedia.org/wiki/List_of_formulas_in_Riemannian_geometry#Riemann_curvature_tensor 1422 | https://en.wikipedia.org/wiki/Riemann_curvature_tensor 1423 | 1424 | TODOs 1425 | ===== 1426 | - Link example with test. 1427 | - Need higher quality tests. 1428 | - Needs functionality for other index configurations. 1429 | """ 1430 | 1431 | if index_config == "uddd": 1432 | print("") 1433 | pprint(Eq(Symbol('R^%s_%s%s%s' % (rho, sig, mu, nu)), self.get_riemann_coefficient(index_config, rho, sig, mu, nu))) 1434 | elif index_config == "dddd": 1435 | print("") 1436 | pprint(Eq(Symbol('R_%s%s%s%s' % (rho, sig, mu, nu)), self.get_riemann_coefficient(index_config, rho, sig, mu, nu))) 1437 | else: 1438 | print("Invalid index_config string.") 1439 | 1440 | def print_all_riemann_coefficients(self, index_config): 1441 | """ 1442 | Description 1443 | =========== 1444 | Prints all connection coefficients. 1445 | 1446 | Example 1447 | ======= 1448 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1449 | >> newtonian.print_all_riemann_coefficients("uddd") 1450 | 1451 | R⁰₀₀₀ = 0 1452 | 1453 | R⁰₀₀₁ = 0 1454 | 1455 | R⁰₀₀₂ = 0 1456 | 1457 | ... 1458 | 1459 | LaTeX representation 1460 | ==================== 1461 | R^{i}_{jkl} -> (i,j,k,l) = (rho,sig,mu,nu) 1462 | R_{ijkl} -> (i,j,k,l) = (rho,sig,mu,nu) 1463 | 1464 | URL Reference 1465 | ============= 1466 | https://en.wikipedia.org/wiki/List_of_formulas_in_Riemannian_geometry#Riemann_curvature_tensor 1467 | https://en.wikipedia.org/wiki/Riemann_curvature_tensor 1468 | 1469 | TODOs 1470 | ===== 1471 | - Link example with test. 1472 | - Need higher quality tests. 1473 | - Needs functionality for other index configurations. 1474 | """ 1475 | 1476 | if index_config == "uddd": 1477 | for rho in self.dimensions: 1478 | for sig in self.dimensions: 1479 | for mu in self.dimensions: 1480 | for nu in self.dimensions: 1481 | self.print_riemann_coefficient(index_config, rho, sig, mu, nu) 1482 | elif index_config == "dddd": 1483 | for rho in self.dimensions: 1484 | for sig in self.dimensions: 1485 | for mu in self.dimensions: 1486 | for nu in self.dimensions: 1487 | self.print_riemann_coefficient(index_config, rho, sig, mu, nu) 1488 | else: 1489 | print("Invalid index_config string.") 1490 | 1491 | 1492 | """ 1493 | Weyl coefficient functions 1494 | ========================== 1495 | """ 1496 | 1497 | def get_weyl_coefficient(self, index_config, i, k, l, m): 1498 | """ 1499 | Description 1500 | =========== 1501 | Gets a single Weyl coefficients from class object. 1502 | 1503 | Example 1504 | ======= 1505 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1506 | >> pprint(newtonian.get_weyl_coefficient("dddd",0,1,2,3)) 1507 | 0 1508 | 1509 | LaTeX Representation 1510 | ==================== 1511 | C_{iklm} 1512 | 1513 | URL Reference 1514 | ============= 1515 | https://en.wikipedia.org/wiki/Weyl_tensor 1516 | 1517 | TODOs 1518 | ===== 1519 | - Link example with test. 1520 | - Need higher quality tests. 1521 | - Needs functionality for other index configurations. 1522 | """ 1523 | 1524 | if(index_config == "uddd"): 1525 | # TODO 1526 | # MUST TEST 1527 | return self.weyl_tensor_uddd[int(i*16/self.dimension_count+k)][l][m] 1528 | elif(index_config == "dduu"): 1529 | # TODO 1530 | # MUST TEST 1531 | return self.weyl_tensor_dduu[int(i*16/self.dimension_count+k)][l][m] 1532 | elif(index_config == "dddd"): 1533 | # TODO 1534 | # MUST TEST 1535 | return self.weyl_tensor_dddd[int(i*16/self.dimension_count+k)][l][m] 1536 | else: 1537 | print("Invalid index_config string.") 1538 | 1539 | def set_weyl_coefficient(self, index_config, i, k, l, m, expression): 1540 | """ 1541 | Description 1542 | =========== 1543 | Sets a single Weyl coefficient from class object equal to the value of a given expression. 1544 | 1545 | Example 1546 | ======= 1547 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1548 | >> pprint(newtonian.set_weyl_coefficient("dddd",0,1,2,3,0)) 1549 | 1550 | LaTeX Representation 1551 | ==================== 1552 | C_{iklm} 1553 | 1554 | URL Reference 1555 | ============= 1556 | https://en.wikipedia.org/wiki/Weyl_tensor 1557 | 1558 | TODOs 1559 | ===== 1560 | - Link example with test. 1561 | - Need higher quality tests. 1562 | - Needs functionality for other index configurations. 1563 | """ 1564 | 1565 | if(index_config == "uddd"): 1566 | # TODO 1567 | # MUST TEST 1568 | self.weyl_tensor_uddd[int(i*16/self.dimension_count+k)][l][m] = expression 1569 | elif(index_config == "dduu"): 1570 | # TODO 1571 | # MUST TEST 1572 | self.weyl_tensor_dduu[int(i*16/self.dimension_count+k)][l][m] = expression 1573 | elif(index_config == "dddd"): 1574 | # TODO 1575 | # MUST TEST 1576 | self.weyl_tensor_dddd[int(i*16/self.dimension_count+k)][l][m] = expression 1577 | else: 1578 | print("Invalid index_config string.") 1579 | 1580 | def set_all_weyl_coefficients(self, index_config): 1581 | """ 1582 | Description 1583 | =========== 1584 | Sets and computes all Weyl coefficients. 1585 | 1586 | Example 1587 | ======= 1588 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1589 | >> pprint(newtonian.set_all_weyl_coefficients("dddd")) 1590 | 1591 | LaTeX Representation 1592 | ==================== 1593 | C_{iklm} 1594 | 1595 | URL Reference 1596 | ============= 1597 | https://en.wikipedia.org/wiki/Weyl_tensor 1598 | 1599 | TODOs 1600 | ===== 1601 | - Link example with test. 1602 | - Need higher quality tests. 1603 | - Needs functionality for other index configurations. 1604 | """ 1605 | 1606 | if index_config == "uddd": 1607 | if(self.suppress_printing == False): 1608 | print("") 1609 | print("") 1610 | print("Weyl curvature tensor coefficients (uddd)") 1611 | print("=========================================") 1612 | for i in self.dimensions: 1613 | for k in self.dimensions: 1614 | for l in self.dimensions: 1615 | for m in self.dimensions: 1616 | self.set_weyl_coefficient(index_config, i, k, l, m, self.compute_weyl_coefficient(index_config, i, k, l, m)) 1617 | if(self.suppress_printing == False): 1618 | self.print_weyl_coefficient(index_config, i, k, l, m) 1619 | elif index_config == "dduu": 1620 | if(self.suppress_printing == False): 1621 | print("") 1622 | print("") 1623 | print("Weyl curvature tensor coefficients (dduu)") 1624 | print("=========================================") 1625 | for i in self.dimensions: 1626 | for k in self.dimensions: 1627 | for l in self.dimensions: 1628 | for m in self.dimensions: 1629 | # TODO 1630 | # MUST TEST 1631 | self.set_weyl_coefficient(index_config, i, k, l, m, self.compute_weyl_coefficient(index_config, i, k, l, m)) 1632 | if(self.suppress_printing == False): 1633 | self.print_weyl_coefficient(index_config, i, k, l, m) 1634 | elif index_config == "dddd": 1635 | if(self.suppress_printing == False): 1636 | print("") 1637 | print("") 1638 | print("Weyl curvature tensor coefficients (dddd)") 1639 | print("=========================================") 1640 | for i in self.dimensions: 1641 | for k in self.dimensions: 1642 | for l in self.dimensions: 1643 | for m in self.dimensions: 1644 | # TODO 1645 | # MUST TEST 1646 | self.set_weyl_coefficient(index_config, i, k, l, m, self.compute_weyl_coefficient(index_config, i, k, l, m)) 1647 | if(self.suppress_printing == False): 1648 | self.print_weyl_coefficient(index_config, i, k, l, m) 1649 | else: 1650 | print("Invalid index_config string.") 1651 | 1652 | def compute_weyl_coefficient(self, index_config, i, k, l, m): 1653 | """ 1654 | Description 1655 | =========== 1656 | Sets and computes all Weyl coefficients. 1657 | 1658 | Example 1659 | ======= 1660 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1661 | >> pprint(newtonian.compute_weyl_coefficient("dddd",0,1,2,3)) 1662 | 0 1663 | 1664 | LaTeX Representation 1665 | ==================== 1666 | C_{iklm} 1667 | 1668 | URL Reference 1669 | ============= 1670 | https://en.wikipedia.org/wiki/Weyl_tensor 1671 | 1672 | TODOs 1673 | ===== 1674 | - Link example with test. 1675 | - Need higher quality tests. 1676 | - Needs functionality for other index configurations. 1677 | """ 1678 | 1679 | n = len(self.coordinate_set) 1680 | weyl_coefficient = 0 1681 | if(index_config == "uddd"): 1682 | # TODO 1683 | # MUST TEST 1684 | pass 1685 | elif(index_config == "dduu"): 1686 | # TODO 1687 | # MUST TEST 1688 | pass 1689 | elif(index_config == "dddd"): 1690 | weyl_coefficient = self.get_riemann_coefficient("dddd", i, k, l, m) + Rational('1/'+str(n-2))*(self.get_ricci_coefficient("dd",i,m)*self.get_metric_coefficient("dd",k,l)-self.get_ricci_coefficient("dd",i,l)*self.get_metric_coefficient("dd",k,m)+self.get_ricci_coefficient("dd",k,l)*self.get_metric_coefficient("dd",i,m)-self.get_ricci_coefficient("dd",k,m)*self.get_metric_coefficient("dd",i,l))+Rational('1/'+str(int((n-1)*(n-2))))*self.get_ricci_scalar()*(self.get_metric_coefficient("dd", i, l)*self.get_metric_coefficient("dd", k, m)-self.get_metric_coefficient("dd", i, m)*self.get_metric_coefficient("dd", k, l)) 1691 | return simplify(weyl_coefficient) 1692 | else: 1693 | print("Invalid index_config string.") 1694 | 1695 | def print_weyl_coefficient(self, index_config, i, k, l, m): 1696 | """ 1697 | Description 1698 | =========== 1699 | Prints a single Weyl coefficient. 1700 | 1701 | Example 1702 | ======= 1703 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1704 | >> pprint(newtonian.compute_weyl_coefficient("dddd",0,0,0,0)) 1705 | 0 1706 | 1707 | LaTeX Representation 1708 | ==================== 1709 | C_{iklm} 1710 | 1711 | URL Reference 1712 | ============= 1713 | https://en.wikipedia.org/wiki/Weyl_tensor 1714 | 1715 | TODOs 1716 | ===== 1717 | - Link example with test. 1718 | - Need higher quality tests. 1719 | - Needs functionality for other index configurations. 1720 | """ 1721 | 1722 | if(index_config == "uddd"): 1723 | # TODO 1724 | # MUST TEST 1725 | print("") 1726 | pprint(Eq(Symbol('C^%s_%s%s%s' % (i, k, l, m)), self.get_weyl_coefficient(index_config, i, k, l, m))) 1727 | elif(index_config == "dduu"): 1728 | # TODO 1729 | # MUST TEST 1730 | print("") 1731 | pprint(Eq(Symbol('C_%s%s^%s%s' % (i, k, l, m)), self.get_weyl_coefficient(index_config, i, k, l, m))) 1732 | elif(index_config == "dddd"): 1733 | # TODO 1734 | # MUST TEST 1735 | print("") 1736 | pprint(Eq(Symbol('C_%s%s%s%s' % (i, k, l, m)), self.get_weyl_coefficient(index_config, i, k, l, m))) 1737 | else: 1738 | print("Invalid index_config string.") 1739 | 1740 | def print_all_weyl_coefficients(self, index_config): 1741 | """ 1742 | Description 1743 | =========== 1744 | Prints all Weyl coefficients. 1745 | 1746 | Example 1747 | ======= 1748 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1749 | >> pprint(newtonian.print_all_weyl_coefficients("dddd")) 1750 | 1751 | C₀₀₀₀ = 0 1752 | 1753 | C₀₀₀₁ = 0 1754 | 1755 | C₀₀₀₂ = 0 1756 | 1757 | ... 1758 | 1759 | C₃₃₃₂ = 0 1760 | 1761 | C₃₃₃₃ = 0 1762 | 1763 | LaTeX Representation 1764 | ==================== 1765 | C_{iklm} 1766 | 1767 | URL Reference 1768 | ============= 1769 | https://en.wikipedia.org/wiki/Weyl_tensor 1770 | 1771 | TODOs 1772 | ===== 1773 | - Link example with test. 1774 | - Need higher quality tests. 1775 | - Needs functionality for other index configurations. 1776 | """ 1777 | 1778 | if index_config == "uddd": 1779 | for i in self.dimensions: 1780 | for k in self.dimensions: 1781 | for l in self.dimensions: 1782 | for m in self.dimensions: 1783 | self.print_weyl_coefficient(index_config, i, k, l, m) 1784 | elif index_config == "dduu": 1785 | for i in self.dimensions: 1786 | for k in self.dimensions: 1787 | for l in self.dimensions: 1788 | for m in self.dimensions: 1789 | # TODO 1790 | # MUST TEST 1791 | self.print_weyl_coefficient(index_config, i, k, l, m) 1792 | elif index_config == "dddd": 1793 | for i in self.dimensions: 1794 | for k in self.dimensions: 1795 | for l in self.dimensions: 1796 | for m in self.dimensions: 1797 | # TODO 1798 | # MUST TEST 1799 | self.print_weyl_coefficient(index_config, i, k, l, m) 1800 | 1801 | """ 1802 | Ricci coefficient functions 1803 | ============================= 1804 | """ 1805 | 1806 | def get_ricci_coefficient(self, index_config, mu, nu): 1807 | """ 1808 | Description 1809 | =========== 1810 | Gets a single Ricci coefficient from class object. 1811 | 1812 | Example 1813 | ======= 1814 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1815 | >> pprint(newtonian.get_ricci_coefficient("dd",0,0)) 1816 | 0 1817 | 1818 | LaTeX Representation 1819 | ==================== 1820 | R_{m,n} 1821 | R^{m,n} 1822 | 1823 | URL Reference 1824 | ============= 1825 | https://en.wikipedia.org/wiki/Ricci_curvature 1826 | 1827 | TODOs 1828 | ===== 1829 | - Link example with test. 1830 | - Need higher quality tests. 1831 | - Needs functionality for other index configurations. 1832 | """ 1833 | 1834 | if (index_config == "uu"): 1835 | return self.ricci_tensor_uu[mu,nu] 1836 | elif(index_config == "dd"): 1837 | return self.ricci_tensor_dd[mu,nu] 1838 | else: 1839 | print("Invalid index_config string.") 1840 | 1841 | def set_ricci_coefficient(self, index_config, mu, nu, expression): 1842 | """ 1843 | Description 1844 | =========== 1845 | Sets a single Ricci coefficient from class object. 1846 | 1847 | Example 1848 | ======= 1849 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1850 | >> newtonian.set_ricci_coefficient("dd",0,0,0) 1851 | 1852 | LaTeX Representation 1853 | ==================== 1854 | R_{m,n} 1855 | R^{m,n} 1856 | 1857 | URL Reference 1858 | ============= 1859 | https://en.wikipedia.org/wiki/Ricci_curvature 1860 | 1861 | TODOs 1862 | ===== 1863 | - Link example with test. 1864 | - Need higher quality tests. 1865 | - Needs functionality for other index configurations. 1866 | """ 1867 | 1868 | if (index_config == "uu"): 1869 | self.ricci_tensor_uu[mu,nu] = expression 1870 | elif(index_config == "dd"): 1871 | self.ricci_tensor_dd[mu,nu] = expression 1872 | else: 1873 | print("Invalid index_config string.") 1874 | 1875 | # Sets all Ricci coefficient values for reuse. Allows for the removal of redundant calculations. 1876 | def set_all_ricci_coefficients(self, index_config): 1877 | """ 1878 | Description 1879 | =========== 1880 | Computes and sets all Ricci tensor class object coefficients. Runs at object creation. 1881 | 1882 | Example 1883 | ======= 1884 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1885 | >> newtonian.set_all_ricci_coefficients("dd") 1886 | 1887 | LaTeX Representation 1888 | ==================== 1889 | R_{m,n} 1890 | R^{m,n} 1891 | 1892 | URL Reference 1893 | ============= 1894 | https://en.wikipedia.org/wiki/Ricci_curvature 1895 | 1896 | TODOs 1897 | ===== 1898 | - Link example with test. 1899 | - Need higher quality tests. 1900 | - Needs functionality for other index configurations. 1901 | """ 1902 | 1903 | if(index_config == "uu"): 1904 | if(self.suppress_printing == False): 1905 | print("") 1906 | print("") 1907 | print("Ricci curvature tensor coefficients (uu)") 1908 | print("========================================") 1909 | for mu in self.dimensions: 1910 | for nu in self.dimensions: 1911 | self.set_ricci_coefficient(index_config, mu, nu, self.compute_ricci_coefficient(index_config, mu, nu)) 1912 | if(self.suppress_printing == False): 1913 | self.print_ricci_coefficient(index_config, mu, nu) 1914 | elif(index_config == "dd"): 1915 | if(self.suppress_printing == False): 1916 | print("") 1917 | print("") 1918 | print("Ricci curvature tensor coefficients (dd)") 1919 | print("========================================") 1920 | for mu in self.dimensions: 1921 | for nu in self.dimensions: 1922 | self.set_ricci_coefficient(index_config, mu, nu, self.compute_ricci_coefficient(index_config, mu, nu)) 1923 | if(self.suppress_printing == False): 1924 | self.print_ricci_coefficient(index_config, mu, nu) 1925 | 1926 | def compute_ricci_coefficient(self, index_config, mu, nu): 1927 | """ 1928 | Description 1929 | =========== 1930 | Computes a single Ricci tensor coefficient. 1931 | 1932 | Example 1933 | ======= 1934 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1935 | >> print(newtonian.compute_ricci_coefficient("dd",0,0)) 1936 | 0 1937 | 1938 | LaTeX Representation 1939 | ==================== 1940 | R_{m,n} 1941 | R^{m,n} 1942 | 1943 | URL Reference 1944 | ============= 1945 | https://en.wikipedia.org/wiki/Ricci_curvature 1946 | 1947 | TODOs 1948 | ===== 1949 | - Link example with test. 1950 | - Need higher quality tests. 1951 | - Needs functionality for other index configurations. 1952 | """ 1953 | 1954 | ricci_coefficient = 0 1955 | if index_config == "dd": 1956 | for lam in self.dimensions: 1957 | ricci_coefficient = ricci_coefficient + self.get_riemann_coefficient("uddd", lam, mu, lam, nu) 1958 | ricci_coefficient = simplify(ricci_coefficient) 1959 | elif index_config == "uu": 1960 | print("") 1961 | elif index_config == "ud" or index_config == "du": 1962 | print("") 1963 | else: 1964 | print("Invalid index_config string.") 1965 | 1966 | return ricci_coefficient 1967 | 1968 | def print_ricci_coefficient(self, index_config, mu, nu): 1969 | """ 1970 | Description 1971 | =========== 1972 | Prints a single Ricci coefficient. 1973 | 1974 | Example 1975 | ======= 1976 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 1977 | >> newtonian.print_ricci_coefficient("dd",0,0) 1978 | 1979 | R₀₀ = 0 1980 | 1981 | LaTeX Representation 1982 | ==================== 1983 | R_{m,n} 1984 | R^{m,n} 1985 | 1986 | URL Reference 1987 | ============= 1988 | https://en.wikipedia.org/wiki/Ricci_curvature 1989 | 1990 | TODOs 1991 | ===== 1992 | - Link example with test. 1993 | - Need higher quality tests. 1994 | - Needs functionality for other index configurations. 1995 | """ 1996 | 1997 | if (index_config == "uu"): 1998 | print("") 1999 | pprint(Eq(Symbol('R^%s%s' % (mu, nu)), self.get_ricci_coefficient(index_config, mu, nu))) 2000 | elif(index_config == "dd"): 2001 | print("") 2002 | pprint(Eq(Symbol('R_%s%s' % (mu, nu)), self.get_ricci_coefficient(index_config, mu, nu))) 2003 | else: 2004 | print("Invalid index_config string.") 2005 | 2006 | # Prints all Ricci coefficients. 2007 | def print_all_ricci_coefficients(self, index_config): 2008 | """ 2009 | Description 2010 | =========== 2011 | Prints a single Weyl coefficient. 2012 | 2013 | Example 2014 | ======= 2015 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2016 | >> pprint(newtonian.print_all_ricci_coefficients("dd")) 2017 | 2018 | R₀₀ = 0 2019 | 2020 | R₀₁ = 0 2021 | 2022 | R₀₂ = 0 2023 | 2024 | LaTeX Representation 2025 | ==================== 2026 | R_{m,n} 2027 | R^{m,n} 2028 | 2029 | URL Reference 2030 | ============= 2031 | https://en.wikipedia.org/wiki/Ricci_curvature 2032 | 2033 | TODOs 2034 | ===== 2035 | - Link example with test. 2036 | - Need higher quality tests. 2037 | - Needs functionality for other index configurations. 2038 | """ 2039 | for mu in self.dimensions: 2040 | for nu in self.dimensions: 2041 | self.print_ricci_coefficient(index_config, mu, nu) 2042 | 2043 | """ 2044 | Ricci scalar functions 2045 | ====================== 2046 | """ 2047 | 2048 | def get_ricci_scalar(self): 2049 | """ 2050 | Description 2051 | =========== 2052 | Gets the Ricci scalar class object. 2053 | 2054 | Example 2055 | ======= 2056 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2057 | >> pprint(newtonian.get_ricci_scalar()) 2058 | 0 2059 | 2060 | LaTeX Representation 2061 | ==================== 2062 | R = g^{mn} R_{mn} 2063 | 2064 | URL Reference 2065 | ============= 2066 | https://en.wikipedia.org/wiki/Ricci_curvature 2067 | 2068 | TODOs 2069 | ===== 2070 | - Link example with test. 2071 | - Need higher quality tests. 2072 | - Needs functionality for other index configurations. 2073 | """ 2074 | 2075 | return self.ricci_scalar 2076 | 2077 | def set_ricci_scalar(self): 2078 | """ 2079 | Description 2080 | =========== 2081 | # Sets Ricci scalar from class object. 2082 | 2083 | Example 2084 | ======= 2085 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2086 | >> pprint(newtonian.set_ricci_scalar()) 2087 | 2088 | LaTeX Representation 2089 | ==================== 2090 | R = g^{mn} R_{mn} 2091 | 2092 | URL Reference 2093 | ============= 2094 | https://en.wikipedia.org/wiki/Ricci_curvature 2095 | 2096 | TODOs 2097 | ===== 2098 | - Link example with test. 2099 | - Need higher quality tests. 2100 | - Needs functionality for other index configurations. 2101 | """ 2102 | 2103 | self.ricci_scalar = self.compute_ricci_scalar() 2104 | if(self.suppress_printing == False): 2105 | print("") 2106 | print("") 2107 | print("Ricci curvature scalar") 2108 | print("======================") 2109 | self.print_ricci_scalar() 2110 | 2111 | def compute_ricci_scalar(self): 2112 | """ 2113 | Description 2114 | =========== 2115 | # Computes the Ricci scalar. 2116 | 2117 | Example 2118 | ======= 2119 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2120 | >> pprint(newtonian.compute_ricci_scalar()) 2121 | 2122 | LaTeX Representation 2123 | ==================== 2124 | R = g^{mn} R_{mn} 2125 | 2126 | URL Reference 2127 | ============= 2128 | https://en.wikipedia.org/wiki/Ricci_curvature 2129 | 2130 | TODOs 2131 | ===== 2132 | - Link example with test. 2133 | - Need higher quality tests. 2134 | - Needs functionality for other index configurations. 2135 | """ 2136 | 2137 | ricci_scalar = 0 2138 | for mu in self.dimensions: 2139 | for nu in self.dimensions: 2140 | ricci_scalar = ricci_scalar + self.metric_tensor_uu[mu, nu] * self.get_ricci_coefficient("dd", mu, nu) 2141 | ricci_scalar = simplify(ricci_scalar) 2142 | return ricci_scalar 2143 | 2144 | def print_ricci_scalar(self): 2145 | """ 2146 | Description 2147 | =========== 2148 | # Prints Ricci scalar. 2149 | 2150 | Example 2151 | ======= 2152 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2153 | >> pprint(newtonian.print_ricci_scalar()) 2154 | 2155 | R = 0 2156 | 2157 | LaTeX Representation 2158 | ==================== 2159 | R = g^{mn} R_{mn} 2160 | 2161 | URL Reference 2162 | ============= 2163 | https://en.wikipedia.org/wiki/Ricci_curvature 2164 | 2165 | TODOs 2166 | ===== 2167 | - Link example with test. 2168 | - Need higher quality tests. 2169 | - Needs functionality for other index configurations. 2170 | """ 2171 | 2172 | print("") 2173 | pprint(Eq(Symbol('R'), self.get_ricci_scalar())) 2174 | 2175 | """ 2176 | Einstein tensor functions 2177 | ========================= 2178 | """ 2179 | 2180 | def get_einstein_coefficient(self, index_config, mu, nu): 2181 | """ 2182 | Description 2183 | =========== 2184 | Gets a single Einstein coefficient from class object. 2185 | 2186 | Example 2187 | ======= 2188 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2189 | >> pprint(newtonian.get_einstein_coefficient("dd",0,0)) 2190 | 0 2191 | 2192 | LaTeX Representation 2193 | ==================== 2194 | G = R_{mn} - R/2 g_{mn} 2195 | 2196 | URL Reference 2197 | ============= 2198 | https://en.wikipedia.org/wiki/Einstein_tensor 2199 | 2200 | TODOs 2201 | ===== 2202 | - Link example with test. 2203 | - Need higher quality tests. 2204 | - Needs functionality for other index configurations. 2205 | """ 2206 | 2207 | if (index_config == "uu"): 2208 | # TODO 2209 | # MUST TEST 2210 | return self.einstein_tensor_uu[mu, nu] 2211 | elif(index_config == "dd"): 2212 | return self.einstein_tensor_dd[mu, nu] 2213 | else: 2214 | print("Invalid index_config string.") 2215 | 2216 | def set_einstein_coefficient(self, index_config, mu, nu, expression): 2217 | """ 2218 | Description 2219 | =========== 2220 | Sets a single Ricci coefficient from class object. 2221 | 2222 | Example 2223 | ======= 2224 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2225 | >> newtonian.set_einstein_coefficient("dd",0,0,0) 2226 | 2227 | LaTeX Representation 2228 | ==================== 2229 | G = R_{mn} - R/2 g_{mn} 2230 | 2231 | URL Reference 2232 | ============= 2233 | https://en.wikipedia.org/wiki/Einstein_tensor 2234 | 2235 | TODOs 2236 | ===== 2237 | - Link example with test. 2238 | - Need higher quality tests. 2239 | - Needs functionality for other index configurations. 2240 | """ 2241 | 2242 | if (index_config == "uu"): 2243 | # TODO 2244 | # MUST TEST 2245 | self.einstein_tensor_uu[mu, nu] = expression 2246 | elif(index_config == "dd"): 2247 | self.einstein_tensor_dd[mu, nu] = expression 2248 | else: 2249 | print("Invalid index_config string.") 2250 | 2251 | def set_all_einstein_coefficients(self, index_config): 2252 | """ 2253 | Description 2254 | =========== 2255 | Sets all Einstein coefficient values for reuse. Allows for the removal of redundant calculations. 2256 | 2257 | Example 2258 | ======= 2259 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2260 | >> newtonian.set_all_einstein_coefficients("dd") 2261 | 2262 | LaTeX Representation 2263 | ==================== 2264 | G = R_{mn} - R/2 g_{mn} 2265 | 2266 | URL Reference 2267 | ============= 2268 | https://en.wikipedia.org/wiki/Einstein_tensor 2269 | 2270 | TODOs 2271 | ===== 2272 | - Link example with test. 2273 | - Need higher quality tests. 2274 | - Needs functionality for other index configurations. 2275 | """ 2276 | 2277 | if (index_config=="uu"): 2278 | if(self.suppress_printing == False): 2279 | print("") 2280 | print("") 2281 | print("Einstein curvature tensor coefficients (uu)") 2282 | print("===========================================") 2283 | for mu in self.dimensions: 2284 | for nu in self.dimensions: 2285 | self.set_einstein_coefficient(index_config, mu, nu, self.compute_einstein_coefficient(index_config, mu, nu)) 2286 | if(self.suppress_printing == False): 2287 | self.print_einstein_coefficient(index_config, mu, nu) 2288 | elif (index_config == "dd"): 2289 | if(self.suppress_printing == False): 2290 | print("") 2291 | print("") 2292 | print("Einstein curvature tensor coefficients (dd)") 2293 | print("===========================================") 2294 | for mu in self.dimensions: 2295 | for nu in self.dimensions: 2296 | self.set_einstein_coefficient(index_config, mu, nu, self.compute_einstein_coefficient(index_config, mu, nu)) 2297 | if(self.suppress_printing == False): 2298 | self.print_einstein_coefficient(index_config, mu, nu) 2299 | else: 2300 | print("Invalid index_config string.") 2301 | 2302 | def compute_einstein_coefficient(self, index_config, mu, nu): 2303 | """ 2304 | Description 2305 | =========== 2306 | Computes a single Einstein tensor coefficient. 2307 | 2308 | Example 2309 | ======= 2310 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2311 | >> print(Newtonian.compute_einstein_coefficient("dd",0,0)) 2312 | 0 2313 | 2314 | LaTeX Representation 2315 | ==================== 2316 | G = R_{mn} - R/2 g_{mn} 2317 | 2318 | URL Reference 2319 | ============= 2320 | https://en.wikipedia.org/wiki/Einstein_tensor 2321 | 2322 | TODOs 2323 | ===== 2324 | - Link example with test. 2325 | - Need higher quality tests. 2326 | - Needs functionality for other index configurations. 2327 | """ 2328 | 2329 | einstein_coefficient = 0 2330 | if index_config == "dd": 2331 | einstein_coefficient = self.get_ricci_coefficient("dd", mu, nu) - Rational('1/2') * self.get_ricci_scalar() * self.metric_tensor_dd[mu,nu] 2332 | einstein_coefficient = simplify(einstein_coefficient) 2333 | elif index_config == "uu": 2334 | # TODO 2335 | # MUST TEST 2336 | print("") 2337 | elif index_config == "ud" or index_config == "du": 2338 | # TODO 2339 | # MUST TEST 2340 | print("") 2341 | else: 2342 | print("Invalid index_config string.") 2343 | return einstein_coefficient 2344 | 2345 | def print_einstein_coefficient(self, index_config, mu, nu): 2346 | """ 2347 | Description 2348 | =========== 2349 | Prints a single Einstein coefficient. 2350 | 2351 | Example 2352 | ======= 2353 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2354 | >> print(newtonian.print_einstein_coefficient("dd",0,0)) 2355 | 2356 | G₀₀ = 0 2357 | 2358 | LaTeX Representation 2359 | ==================== 2360 | G = R_{mn} - R/2 g_{mn} 2361 | 2362 | URL Reference 2363 | ============= 2364 | https://en.wikipedia.org/wiki/Einstein_tensor 2365 | 2366 | TODOs 2367 | ===== 2368 | - Link example with test. 2369 | - Need higher quality tests. 2370 | - Needs functionality for other index configurations. 2371 | """ 2372 | 2373 | if (index_config == "uu"): 2374 | # TODO 2375 | # MUST TEST 2376 | print("") 2377 | pprint(Eq(Symbol('G^%s%s' % (mu, nu)), self.get_einstein_coefficient(index_config, mu, nu))) 2378 | elif(index_config == "dd"): 2379 | print("") 2380 | pprint(Eq(Symbol('G_%s%s' % (mu, nu)), self.get_einstein_coefficient(index_config, mu, nu))) 2381 | else: 2382 | print("Invalid index_config string.") 2383 | 2384 | def print_all_einstein_coefficients(self, index_config): 2385 | """ 2386 | Description 2387 | =========== 2388 | Prints all Einstein coefficients. 2389 | 2390 | Example 2391 | ======= 2392 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2393 | >> pprint(newtonian.print_all_einstein_coefficients("dd")) 2394 | 2395 | 2396 | G₀₀ = 0 2397 | 2398 | G₀₁ = 0 2399 | 2400 | G₀₂ = 0 2401 | 2402 | G₀₃ = 0 2403 | 2404 | ... 2405 | 2406 | G₃₂ = 0 2407 | 2408 | G₃₃ = 0 2409 | 2410 | LaTeX Representation 2411 | ==================== 2412 | G = R_{mn} - R/2 g_{mn} 2413 | 2414 | URL Reference 2415 | ============= 2416 | https://en.wikipedia.org/wiki/Einstein_tensor 2417 | 2418 | TODOs 2419 | ===== 2420 | - Link example with test. 2421 | - Need higher quality tests. 2422 | - Needs functionality for other index configurations. 2423 | """ 2424 | 2425 | for mu in self.dimensions: 2426 | for nu in self.dimensions: 2427 | self.print_einstein_coefficient(index_config, mu, nu) 2428 | 2429 | 2430 | """ 2431 | Stress-energy-momentum tensor functions 2432 | ======================================= 2433 | """ 2434 | 2435 | def get_stress_energy_coefficient(self, index_config, mu, nu): 2436 | """ 2437 | Description 2438 | =========== 2439 | Returns a stress-energy coefficient for a given associated index pair and index configuration. 2440 | 2441 | Example 2442 | ======= 2443 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2444 | >> pprint(newtonian.get_stress_energy_coefficient("dd",0,0)) 2445 | 0 2446 | 2447 | LaTeX Representation 2448 | ==================== 2449 | T_{mn} = frac{c^{4}}{8 \pi G} G_{mn} 2450 | 2451 | URL Reference 2452 | ============= 2453 | https://en.wikipedia.org/wiki/Stress%E2%80%93energy_tensor 2454 | 2455 | TODOs 2456 | ===== 2457 | - Link example with test. 2458 | - Need higher quality tests. 2459 | - Needs functionality for other index configurations. 2460 | """ 2461 | 2462 | if (index_config == "uu"): 2463 | # TODO 2464 | # MUST TEST 2465 | return self.stress_energy_tensor_uu[mu, nu] 2466 | elif(index_config == "dd"): 2467 | return self.stress_energy_tensor_dd[mu, nu] 2468 | else: 2469 | print("Invalid index_config string.") 2470 | 2471 | def set_stress_energy_coefficient(self, index_config, mu, nu, expression): 2472 | """ 2473 | Description 2474 | =========== 2475 | Sets a single stress-energy coefficient from class object. 2476 | 2477 | Example 2478 | ======= 2479 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2480 | >> newtonian.set_stress_energy_coefficient("dd",0,0,0) 2481 | 2482 | LaTeX Representation 2483 | ==================== 2484 | T_{mn} = frac{c^{4}}{8 \pi G} G_{mn} 2485 | 2486 | URL Reference 2487 | ============= 2488 | https://en.wikipedia.org/wiki/Stress%E2%80%93energy_tensor 2489 | 2490 | TODOs 2491 | ===== 2492 | - Link example with test. 2493 | - Need higher quality tests. 2494 | - Needs functionality for other index configurations. 2495 | """ 2496 | 2497 | if (index_config == "uu"): 2498 | # TODO 2499 | # MUST TEST 2500 | self.stress_energy_tensor_uu[mu, nu] = expression 2501 | elif(index_config == "dd"): 2502 | self.stress_energy_tensor_dd[mu, nu] = expression 2503 | else: 2504 | print("Invalid index_config string.") 2505 | 2506 | def set_all_stress_energy_coefficients(self, index_config): 2507 | """ 2508 | Description 2509 | =========== 2510 | Sets all stress-energy coefficient values for reuse. Allows for the removal of redundant calculations. 2511 | 2512 | Example 2513 | ======= 2514 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2515 | >> newtonian.set_all_stress_energy_coefficients("dd") 2516 | 2517 | LaTeX Representation 2518 | ==================== 2519 | T_{mn} = frac{c^{4}}{8 \pi G} G_{mn} 2520 | 2521 | URL Reference 2522 | ============= 2523 | https://en.wikipedia.org/wiki/Stress%E2%80%93energy_tensor 2524 | 2525 | TODOs 2526 | ===== 2527 | - Link example with test. 2528 | - Need higher quality tests. 2529 | - Needs functionality for other index configurations. 2530 | """ 2531 | 2532 | if (index_config=="uu"): 2533 | if(self.suppress_printing == False): 2534 | print("") 2535 | print("") 2536 | print("Stress-energy-momentum tensor coefficients (uu)") 2537 | print("===============================================") 2538 | for mu in self.dimensions: 2539 | for nu in self.dimensions: 2540 | self.set_stress_energy_coefficient(index_config, mu, nu, self.compute_stress_energy_coefficient(index_config, mu, nu)) 2541 | if(self.suppress_printing == False): 2542 | self.print_stress_energy_coefficient(index_config, mu, nu) 2543 | elif (index_config == "dd"): 2544 | if(self.suppress_printing == False): 2545 | print("") 2546 | print("") 2547 | print("Stress-energy-momentum tensor coefficients (dd)") 2548 | print("===============================================") 2549 | for mu in self.dimensions: 2550 | for nu in self.dimensions: 2551 | self.set_stress_energy_coefficient(index_config, mu, nu, self.compute_stress_energy_coefficient(index_config, mu, nu)) 2552 | if(self.suppress_printing == False): 2553 | self.print_stress_energy_coefficient(index_config, mu, nu) 2554 | else: 2555 | print("Invalid index_config string.") 2556 | 2557 | def compute_stress_energy_coefficient(self, index_config, mu, nu): 2558 | """ 2559 | Description 2560 | =========== 2561 | Sets all stress-energy coefficient values for reuse. Allows for the removal of redundant calculations. 2562 | 2563 | Example 2564 | ======= 2565 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2566 | >> print(newtonian.compute_stress_energy_coefficient("dd",0,0)) 2567 | 0 2568 | 2569 | LaTeX Representation 2570 | ==================== 2571 | T_{mn} = frac{c^{4}}{8 \pi G} G_{mn} 2572 | 2573 | URL Reference 2574 | ============= 2575 | https://en.wikipedia.org/wiki/Stress%E2%80%93energy_tensor 2576 | 2577 | TODOs 2578 | ===== 2579 | - Link example with test. 2580 | - Need higher quality tests. 2581 | - Needs functionality for other index configurations. 2582 | """ 2583 | 2584 | stress_energy_coefficient = 0 2585 | c, G = symbols('c G') 2586 | if index_config == "dd": 2587 | stress_energy_coefficient = c**4/(8*pi*G)*self.get_einstein_coefficient(index_config, mu, nu) + c**4/(8*pi*G) * self.cosmological_constant * self.metric_tensor_dd[mu,nu] 2588 | elif index_config == "uu": 2589 | stress_energy_coefficient = c**4/(8*pi*G)*self.get_einstein_coefficient(index_config, mu, nu) 2590 | elif index_config == "ud" or index_config == "du": 2591 | pass 2592 | else: 2593 | print("Invalid index_config string.") 2594 | return simplify(stress_energy_coefficient) 2595 | 2596 | def print_stress_energy_coefficient(self, index_config, mu, nu): 2597 | """ 2598 | Description 2599 | =========== 2600 | Prints a single stress-energy coefficient. 2601 | 2602 | Example 2603 | ======= 2604 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2605 | >> newtonian.print_stress_energy_coefficient("dd",0,0) 2606 | 2607 | T₀₀ = 0 2608 | 2609 | LaTeX Representation 2610 | ==================== 2611 | T_{mn} = frac{c^{4}}{8 \pi G} G_{mn} 2612 | 2613 | URL Reference 2614 | ============= 2615 | https://en.wikipedia.org/wiki/Stress%E2%80%93energy_tensor 2616 | 2617 | TODOs 2618 | ===== 2619 | - Link example with test. 2620 | - Need higher quality tests. 2621 | - Needs functionality for other index configurations. 2622 | """ 2623 | 2624 | if (index_config == "uu"): 2625 | print("") 2626 | pprint(Eq(Symbol('T^%s%s' % (mu, nu)), self.get_stress_energy_coefficient(index_config, mu, nu))) 2627 | elif(index_config == "dd"): 2628 | print("") 2629 | pprint(Eq(Symbol('T_%s%s' % (mu, nu)), self.get_stress_energy_coefficient(index_config, mu, nu))) 2630 | else: 2631 | print("Invalid index_config string.") 2632 | 2633 | def print_all_stress_energy_coefficients(self, index_config): 2634 | """ 2635 | Description 2636 | =========== 2637 | Prints all stress-energy coefficients. 2638 | 2639 | Example 2640 | ======= 2641 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2642 | >> newtonian.print_all_stress_energy_coefficients("dd") 2643 | 2644 | T₀₀ = 0 2645 | 2646 | T₀₁ = 0 2647 | 2648 | T₀₂ = 0 2649 | 2650 | ... 2651 | 2652 | T₃₂ = 0 2653 | 2654 | T₃₃ = 0 2655 | 2656 | LaTeX Representation 2657 | ==================== 2658 | T_{mn} = frac{c^{4}}{8 \pi G} G_{mn} 2659 | 2660 | URL Reference 2661 | ============= 2662 | https://en.wikipedia.org/wiki/Stress%E2%80%93energy_tensor 2663 | 2664 | TODOs 2665 | ===== 2666 | - Link example with test. 2667 | - Need higher quality tests. 2668 | - Needs functionality for other index configurations. 2669 | """ 2670 | for mu in self.dimensions: 2671 | for nu in self.dimensions: 2672 | self.print_stress_energy_coefficient(index_config, mu, nu) 2673 | 2674 | """ 2675 | Cosmological constant functions 2676 | =============================== 2677 | """ 2678 | def get_cosmological_constant(self): 2679 | """ 2680 | Description 2681 | =========== 2682 | Prints all stress-energy coefficients. 2683 | 2684 | Example 2685 | ======= 2686 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2687 | >> print(newtonian.get_cosmological_constant()) 2688 | 0 2689 | 2690 | LaTeX Representation 2691 | ==================== 2692 | \Lambda 2693 | 2694 | URL Reference 2695 | ============= 2696 | https://en.wikipedia.org/wiki/Cosmological_constant 2697 | https://en.wikipedia.org/wiki/Friedmann_equations 2698 | https://en.wikipedia.org/wiki/Friedmann%E2%80%93Lema%C3%AEtre%E2%80%93Robertson%E2%80%93Walker_metric 2699 | https://en.wikipedia.org/wiki/Dark_energy 2700 | https://en.wikipedia.org/wiki/Accelerating_expansion_of_the_universe 2701 | 2702 | TODOs 2703 | ===== 2704 | - Link example with test. 2705 | - Need higher quality tests. 2706 | - Needs functionality for other index configurations. 2707 | """ 2708 | 2709 | return self.cosmological_constant 2710 | 2711 | def set_cosmological_constant(self, expression): 2712 | """ 2713 | Description 2714 | =========== 2715 | Sets cosmological constant from class object. 2716 | 2717 | Example 2718 | ======= 2719 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2720 | >> print(newtonian.set_cosmological_constant(0)) 2721 | 2722 | LaTeX Representation 2723 | ==================== 2724 | \Lambda 2725 | 2726 | URL Reference 2727 | ============= 2728 | https://en.wikipedia.org/wiki/Cosmological_constant 2729 | https://en.wikipedia.org/wiki/Friedmann_equations 2730 | https://en.wikipedia.org/wiki/Friedmann%E2%80%93Lema%C3%AEtre%E2%80%93Robertson%E2%80%93Walker_metric 2731 | https://en.wikipedia.org/wiki/Dark_energy 2732 | https://en.wikipedia.org/wiki/Accelerating_expansion_of_the_universe 2733 | 2734 | TODOs 2735 | ===== 2736 | - Link example with test. 2737 | - Need higher quality tests. 2738 | - Needs functionality for other index configurations. 2739 | """ 2740 | self.cosmological_constant = expression 2741 | if(self.suppress_printing == False): 2742 | print("") 2743 | print("") 2744 | print("Cosmological constant") 2745 | print("=====================") 2746 | self.print_cosmological_constant() 2747 | 2748 | def print_cosmological_constant(self): 2749 | """ 2750 | Description 2751 | =========== 2752 | Sets cosmological constant from class object. 2753 | 2754 | Example 2755 | ======= 2756 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2757 | >> newtonian.print_cosmological_constant() 2758 | 2759 | LaTeX Representation 2760 | ==================== 2761 | \Lambda 2762 | 2763 | URL Reference 2764 | ============= 2765 | https://en.wikipedia.org/wiki/Cosmological_constant 2766 | https://en.wikipedia.org/wiki/Friedmann_equations 2767 | https://en.wikipedia.org/wiki/Friedmann%E2%80%93Lema%C3%AEtre%E2%80%93Robertson%E2%80%93Walker_metric 2768 | https://en.wikipedia.org/wiki/Dark_energy 2769 | https://en.wikipedia.org/wiki/Accelerating_expansion_of_the_universe 2770 | 2771 | TODOs 2772 | ===== 2773 | - Link example with test. 2774 | - Need higher quality tests. 2775 | - Needs functionality for other index configurations. 2776 | """ 2777 | print("") 2778 | pprint(Eq(Symbol('Lambda'), self.get_cosmological_constant())) 2779 | 2780 | 2781 | """ 2782 | Proper geodesic functions 2783 | ========================= 2784 | """ 2785 | 2786 | def get_proper_time_geodesic_acceleration(self, lam): 2787 | return self.proper_acceleration[lam] 2788 | 2789 | def set_proper_time_geodesic_acceleration(self, lam, expression): 2790 | self.proper_acceleration[lam] = expression 2791 | 2792 | def set_all_proper_time_geodesic_accelerations(self): 2793 | if(self.suppress_printing == False): 2794 | print("") 2795 | print("") 2796 | print("Proper acceleration vectors") 2797 | print("============================") 2798 | for lam in self.dimensions: 2799 | self.set_proper_time_geodesic_acceleration(lam, self.compute_proper_time_geodesic_acceleration(lam)) 2800 | if(self.suppress_printing == False): 2801 | self.print_proper_time_geodesic_acceleration(lam) 2802 | 2803 | def compute_proper_time_geodesic_acceleration(self, lam): 2804 | acceleration = 0 2805 | for mu in self.dimensions: 2806 | for nu in self.dimensions: 2807 | acceleration = acceleration + -1*self.get_connection_coefficient("udd",lam,mu,nu)*Derivative(self.coordinate_set[mu],Symbol('tau'))*Derivative(self.coordinate_set[nu],Symbol('tau')) 2808 | return simplify(acceleration) 2809 | 2810 | def print_proper_time_geodesic_acceleration(self, lam): 2811 | print("") 2812 | pprint(Eq(Derivative(Derivative(self.coordinate_set[lam],Symbol('tau')),Symbol('tau')), self.get_proper_time_geodesic_acceleration(lam))) 2813 | 2814 | def print_all_proper_time_geodesic_accelerations(self): 2815 | for lam in self.dimensions: 2816 | self.print_proper_time_geodesic_acceleration(lam) 2817 | 2818 | """ 2819 | Coordinate geodesic functions 2820 | ============================= 2821 | """ 2822 | 2823 | def get_coordinate_time_geodesic_acceleration(self, lam): 2824 | return self.coordinate_acceleration[lam] 2825 | 2826 | def set_coordinate_time_geodesic_acceleration(self, lam, expression): 2827 | self.coordinate_acceleration[lam] = expression 2828 | 2829 | def set_all_coordinate_time_geodesic_accelerations(self): 2830 | if(self.suppress_printing == False): 2831 | print("") 2832 | print("") 2833 | print("Coordinate acceleration vectors") 2834 | print("===============================") 2835 | for lam in self.dimensions: 2836 | self.set_coordinate_time_geodesic_acceleration(lam, self.compute_coordinate_time_geodesic_acceleration(lam)) 2837 | if(self.suppress_printing == False): 2838 | self.print_coordinate_time_geodesic_acceleration(lam) 2839 | 2840 | def compute_coordinate_time_geodesic_acceleration(self, lam): 2841 | acceleration = 0 2842 | for mu in self.dimensions: 2843 | for nu in self.dimensions: 2844 | acceleration = acceleration + -1*self.get_connection_coefficient("udd",lam,mu,nu)*diff(self.coordinate_set[mu],self.coordinate_set[0])*diff(self.coordinate_set[nu],self.coordinate_set[0])+self.get_connection_coefficient("udd",0,mu,nu)*Derivative(self.coordinate_set[mu],self.coordinate_set[0])*Derivative(self.coordinate_set[nu],self.coordinate_set[0])*Derivative(self.coordinate_set[lam],self.coordinate_set[0]) 2845 | return simplify(acceleration) 2846 | 2847 | # Velocity 2848 | #pprint(Eq(Derivative(self.coordinate_set[lam],self.coordinate_set[0]), integrate(acc,Symbol('t')))) 2849 | 2850 | def print_coordinate_time_geodesic_acceleration(self, lam): 2851 | print("") 2852 | pprint(Eq(Derivative(Derivative(self.coordinate_set[lam],self.coordinate_set[0]),self.coordinate_set[0]), self.get_coordinate_time_geodesic_acceleration(lam))) 2853 | 2854 | def print_all_coordinate_time_geodesic_accelerations(self): 2855 | for lam in self.dimensions: 2856 | self.print_coordinate_time_geodesic_acceleration(lam) 2857 | 2858 | """ 2859 | Geodesic deviation functions 2860 | ============================ 2861 | """ 2862 | 2863 | def get_geodesic_deviation_acceleration(self, lam): 2864 | return self.geodesic_deviation_acceleration[lam] 2865 | 2866 | def set_geodesic_deviation_acceleration(self, lam, expression): 2867 | self.geodesic_deviation_acceleration[lam] = expression 2868 | 2869 | def set_all_geodesic_deviation_accelerations(self): 2870 | if(self.suppress_printing == False): 2871 | print("") 2872 | print("") 2873 | print("Geodesic deviation vectors") 2874 | print("==========================") 2875 | for lam in self.dimensions: 2876 | self.set_geodesic_deviation_acceleration(lam, self.compute_geodesic_deviation_acceleration(lam)) 2877 | if(self.suppress_printing == False): 2878 | self.print_separation_geodesic_acceleration(lam) 2879 | 2880 | def compute_geodesic_deviation_acceleration(self, lam): 2881 | acceleration = 0 2882 | for mu in self.dimensions: 2883 | acceleration = 0 2884 | for nu in self.dimensions: 2885 | for rho in self.dimensions: 2886 | for sig in self.dimensions: 2887 | acceleration = acceleration + self.get_riemann_coefficient("uddd", mu, nu, rho, sig)*Derivative(self.coordinate_set[nu],Symbol('tau'))*Derivative(self.coordinate_set[rho],Symbol('tau'))*Symbol('xi_'+str(sig)) 2888 | return simplify(acceleration) 2889 | 2890 | def print_separation_geodesic_acceleration(self, lam): 2891 | print("") 2892 | pprint(Eq(Derivative(Derivative(Symbol('xi_'+str(lam)),Symbol('tau')),Symbol('tau')), self.get_geodesic_deviation_acceleration(lam))) 2893 | 2894 | def print_all_separation_geodesic_accelerations(self): 2895 | for lam in self.dimensions: 2896 | self.print_separation_geodesic_acceleration(lam) 2897 | 2898 | """ 2899 | schouten tensor functions 2900 | ======================= 2901 | """ 2902 | 2903 | def get_schouten_coefficient(self, index_config, mu, nu): 2904 | """ 2905 | Description 2906 | =========== 2907 | Returns a schouten coefficient for a given associated index pair and index configuration. 2908 | 2909 | Example 2910 | ======= 2911 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2912 | >> print(newtonian.get_schouten_coefficient("dd",0,0)) 2913 | G*M*(2*G*M - c**2*r)*Derivative(t, t)**2/(c**2*r**3) 2914 | 2915 | LaTeX Representation 2916 | ==================== 2917 | P_{ij} = frac{1}{n-2}\left ( R_{ij} - frac{R}{2d-2}\: g_{ij} ) 2918 | 2919 | URL Reference 2920 | ============= 2921 | https://en.wikipedia.org/wiki/Stress%E2%80%93energy_tensor 2922 | 2923 | TODOs 2924 | ===== 2925 | - Link example with test. 2926 | - Need higher quality tests. 2927 | - Needs functionality for other index configurations. 2928 | """ 2929 | 2930 | if (index_config == "uu"): 2931 | # TODO 2932 | # MUST TEST 2933 | return self.schouten_tensor_uu[mu, nu] 2934 | elif(index_config == "dd"): 2935 | return self.schouten_tensor_dd[mu, nu] 2936 | else: 2937 | print("Invalid index_config string.") 2938 | 2939 | def set_schouten_coefficient(self, index_config, mu, nu, expression): 2940 | """ 2941 | Description 2942 | =========== 2943 | Sets (computes) a schouten coefficient for a given associated index pair and index configuration. 2944 | 2945 | Example 2946 | ======= 2947 | >> newtonian = SpaceTime(Solution().weak_field_approximation(), True) 2948 | >> newtonian.set_schouten_coefficient("dd",0,0,G*M*(2*G*M - c**2*r)*Derivative(t, t)**2/(c**2*r**3))) 2949 | 2950 | LaTeX Representation 2951 | ==================== 2952 | P_{ij} = frac{1}{n-2}\left ( R_{ij} - frac{R}{2d-2}\: g_{ij} ) 2953 | 2954 | URL Reference 2955 | ============= 2956 | https://en.wikipedia.org/wiki/Stress%E2%80%93energy_tensor 2957 | 2958 | TODOs 2959 | ===== 2960 | - Link example with test. 2961 | - Need higher quality tests. 2962 | - Needs functionality for other index configurations. 2963 | """ 2964 | if (index_config == "uu"): 2965 | self.schouten_tensor_uu[mu, nu] = expression 2966 | elif(index_config == "dd"): 2967 | self.schouten_tensor_dd[mu, nu] = expression 2968 | else: 2969 | print("Invalid index_config string.") 2970 | 2971 | def set_all_schouten_coefficients(self, index_config): 2972 | if (index_config=="uu"): 2973 | if(self.suppress_printing == False): 2974 | print("") 2975 | print("") 2976 | print("Schouten tensor coefficients (uu)") 2977 | print("=================================") 2978 | for mu in self.dimensions: 2979 | for nu in self.dimensions: 2980 | self.set_schouten_coefficient(index_config, mu, nu, self.compute_schouten_coefficient(index_config, mu, nu)) 2981 | if(self.suppress_printing == False): 2982 | self.print_schouten_coefficient(index_config, mu, nu) 2983 | elif (index_config == "dd"): 2984 | if(self.suppress_printing == False): 2985 | print("") 2986 | print("") 2987 | print("Schouten tensor coefficients (dd)") 2988 | print("=================================") 2989 | for mu in self.dimensions: 2990 | for nu in self.dimensions: 2991 | self.set_schouten_coefficient(index_config, mu, nu, self.compute_schouten_coefficient(index_config, mu, nu)) 2992 | if(self.suppress_printing == False): 2993 | self.print_schouten_coefficient(index_config, mu, nu) 2994 | else: 2995 | print("Invalid index_config string.") 2996 | 2997 | def compute_schouten_coefficient(self, index_config, mu, nu): 2998 | acceleration = 0 2999 | for lam in self.dimensions: 3000 | acceleration = acceleration + -1*self.get_connection_coefficient("udd",lam,mu,nu)*Derivative(self.coordinate_set[mu],self.coordinate_set[0])*Derivative(self.coordinate_set[nu],self.coordinate_set[0])+self.get_connection_coefficient("udd",0,mu,nu)*Derivative(self.coordinate_set[mu],self.coordinate_set[0])*Derivative(self.coordinate_set[nu],self.coordinate_set[0])*Derivative(self.coordinate_set[lam],self.coordinate_set[0]) 3001 | return simplify(acceleration) 3002 | 3003 | def print_schouten_coefficient(self, index_config, mu, nu): 3004 | if (index_config == "uu"): 3005 | print("") 3006 | pprint(Eq(Symbol('P^%s%s' % (mu, nu)), self.get_schouten_coefficient(index_config, mu, nu))) 3007 | elif(index_config == "dd"): 3008 | print("") 3009 | pprint(Eq(Symbol('P_%s%s' % (mu, nu)), self.get_schouten_coefficient(index_config, mu, nu))) 3010 | else: 3011 | print("Invalid index_config string.") 3012 | 3013 | def print_all_schouten_coefficients(self, index_config): 3014 | for mu in self.dimensions: 3015 | for nu in self.dimensions: 3016 | self.print_schouten_coefficient(index_config, mu, nu) -------------------------------------------------------------------------------- /spacetimeengine/tests/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from sympy import * 3 | from src.spacetime import * 4 | from src.solutions import * 5 | import unittest 6 | 7 | class Test(unittest.TestCase): 8 | 9 | def test_compute_stress_energy_coefficient(self): 10 | black_hole = SpaceTime(Solution().schwarzschild(), True) 11 | vacuum_stress_energy_tensor_dd = Matrix([ 12 | [ 0, 0, 0, 0 ], 13 | [ 0, 0, 0, 0 ], 14 | [ 0, 0, 0, 0 ], 15 | [ 0, 0, 0, 0 ] 16 | ]) 17 | self.assertEqual(black_hole.stress_energy_tensor_dd, vacuum_stress_energy_tensor_dd) 18 | 19 | def test_compute_einstein_coefficient(self): 20 | black_hole = SpaceTime(Solution().schwarzschild(), True) 21 | vacuum_einstein_tensor_dd = Matrix([ 22 | [ 0, 0, 0, 0 ], 23 | [ 0, 0, 0, 0 ], 24 | [ 0, 0, 0, 0 ], 25 | [ 0, 0, 0, 0 ] 26 | ]) 27 | self.assertEqual(black_hole.einstein_tensor_dd, vacuum_einstein_tensor_dd) 28 | 29 | def test_compute_ricci_coefficient(self): 30 | black_hole = SpaceTime(Solution().schwarzschild(), True) 31 | vacuum_ricci_tensor_dd = Matrix([ 32 | [ 0, 0, 0, 0 ], 33 | [ 0, 0, 0, 0 ], 34 | [ 0, 0, 0, 0 ], 35 | [ 0, 0, 0, 0 ] 36 | ]) 37 | self.assertEqual(black_hole.ricci_tensor_dd, vacuum_ricci_tensor_dd) 38 | 39 | def test_compute_riemann_coefficient(self): 40 | black_hole = SpaceTime(Solution().schwarzschild(), True) 41 | # The ommision of the Matrix object is due to the form in which the riemann tensor was constructed in the SpaceTime class. 42 | # Sympy does not handle multidimensional matricies in a straitforward way. 43 | vacuum_riemann_tensor_uddd = [[ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ]] 44 | self.assertEqual(black_hole.riemann_tensor_uddd[15], vacuum_riemann_tensor_uddd) 45 | 46 | def test_compute_connection_coefficient(self): 47 | flat_spacetime = SpaceTime(Solution().minkowski(), True) 48 | # The ommision of the Matrix object is due to the form in which the riemann tensor was constructed in the SpaceTime class. 49 | # Sympy does not handle multidimensional matricies in a straitforward way. 50 | vacuum_christoffel_symbols_udd = Matrix([ 51 | [ 52 | [ 0, 0, 0, 0 ], 53 | [ 0, 0, 0, 0 ], 54 | [ 0, 0, 0, 0 ], 55 | [ 0, 0, 0, 0 ] 56 | ], 57 | [ 58 | [ 0, 0, 0, 0 ], 59 | [ 0, 0, 0, 0 ], 60 | [ 0, 0, 0, 0 ], 61 | [ 0, 0, 0, 0 ] 62 | ], 63 | [ 64 | [ 0, 0, 0, 0 ], 65 | [ 0, 0, 0, 0 ], 66 | [ 0, 0, 0, 0 ], 67 | [ 0, 0, 0, 0 ] 68 | ], 69 | [ 70 | [ 0, 0, 0, 0 ], 71 | [ 0, 0, 0, 0 ], 72 | [ 0, 0, 0, 0 ], 73 | [ 0, 0, 0, 0 ] 74 | ] 75 | ]) 76 | self.assertEqual(flat_spacetime.christoffel_symbols_udd, vacuum_christoffel_symbols_udd) 77 | 78 | def test_first_bianchi_identity(self): 79 | black_hole = SpaceTime(Solution().schwarzschild(), True) 80 | a = black_hole.get_riemann_coefficient("dddd", 0, 1, 2, 3) 81 | b = black_hole.get_riemann_coefficient("dddd", 0, 2, 3, 1) 82 | c = black_hole.get_riemann_coefficient("dddd", 0, 3, 1, 2) 83 | 84 | self.assertEqual(a + b + c, 0) 85 | 86 | def test_riemann_skew_symmetry(self): 87 | black_hole = SpaceTime(Solution().schwarzschild(), True) 88 | a = black_hole.get_riemann_coefficient("dddd", 0, 1, 2, 3) 89 | b = black_hole.get_riemann_coefficient("dddd", 1, 0, 2, 3) 90 | c = black_hole.get_riemann_coefficient("dddd", 0, 1, 3, 2) 91 | 92 | self.assertEqual(a, -1*b) 93 | self.assertEqual(a, -1*c) 94 | 95 | unittest.main() 96 | -------------------------------------------------------------------------------- /spacetimeengine/tests/test_spacetime.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from sympy import * 3 | from spacetimeengine.spacetime import * 4 | from spacetimeengine.solutions import * 5 | import unittest 6 | 7 | class Test(unittest.TestCase): 8 | 9 | def test_compute_stress_energy_coefficient(self): 10 | black_hole = SpaceTime(Solution().schwarzschild(), True) 11 | vacuum_stress_energy_tensor_dd = Matrix([ 12 | [ 0, 0, 0, 0 ], 13 | [ 0, 0, 0, 0 ], 14 | [ 0, 0, 0, 0 ], 15 | [ 0, 0, 0, 0 ] 16 | ]) 17 | self.assertEqual(black_hole.stress_energy_tensor_dd, vacuum_stress_energy_tensor_dd) 18 | 19 | def test_compute_einstein_coefficient(self): 20 | black_hole = SpaceTime(Solution().schwarzschild(), True) 21 | vacuum_einstein_tensor_dd = Matrix([ 22 | [ 0, 0, 0, 0 ], 23 | [ 0, 0, 0, 0 ], 24 | [ 0, 0, 0, 0 ], 25 | [ 0, 0, 0, 0 ] 26 | ]) 27 | self.assertEqual(black_hole.einstein_tensor_dd, vacuum_einstein_tensor_dd) 28 | 29 | def test_compute_ricci_coefficient(self): 30 | black_hole = SpaceTime(Solution().schwarzschild(), True) 31 | vacuum_ricci_tensor_dd = Matrix([ 32 | [ 0, 0, 0, 0 ], 33 | [ 0, 0, 0, 0 ], 34 | [ 0, 0, 0, 0 ], 35 | [ 0, 0, 0, 0 ] 36 | ]) 37 | self.assertEqual(black_hole.ricci_tensor_dd, vacuum_ricci_tensor_dd) 38 | 39 | def test_compute_riemann_coefficient(self): 40 | black_hole = SpaceTime(Solution().schwarzschild(), True) 41 | # The ommision of the Matrix object is due to the form in which the riemann tensor was constructed in the SpaceTime class. 42 | # Sympy does not handle multidimensional matricies in a straitforward way. 43 | vacuum_riemann_tensor_uddd = [[ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ]] 44 | self.assertEqual(black_hole.riemann_tensor_uddd[15], vacuum_riemann_tensor_uddd) 45 | 46 | def test_compute_connection_coefficient(self): 47 | flat_spacetime = SpaceTime(Solution().minkowski(), True) 48 | # The ommision of the Matrix object is due to the form in which the riemann tensor was constructed in the SpaceTime class. 49 | # Sympy does not handle multidimensional matricies in a straitforward way. 50 | vacuum_christoffel_symbols_udd = Matrix([ 51 | [ 52 | [ 0, 0, 0, 0 ], 53 | [ 0, 0, 0, 0 ], 54 | [ 0, 0, 0, 0 ], 55 | [ 0, 0, 0, 0 ] 56 | ], 57 | [ 58 | [ 0, 0, 0, 0 ], 59 | [ 0, 0, 0, 0 ], 60 | [ 0, 0, 0, 0 ], 61 | [ 0, 0, 0, 0 ] 62 | ], 63 | [ 64 | [ 0, 0, 0, 0 ], 65 | [ 0, 0, 0, 0 ], 66 | [ 0, 0, 0, 0 ], 67 | [ 0, 0, 0, 0 ] 68 | ], 69 | [ 70 | [ 0, 0, 0, 0 ], 71 | [ 0, 0, 0, 0 ], 72 | [ 0, 0, 0, 0 ], 73 | [ 0, 0, 0, 0 ] 74 | ] 75 | ]) 76 | self.assertEqual(flat_spacetime.christoffel_symbols_udd, vacuum_christoffel_symbols_udd) 77 | 78 | def test_first_bianchi_identity(self): 79 | black_hole = SpaceTime(Solution().schwarzschild(), True) 80 | a = black_hole.get_riemann_coefficient("dddd", 0, 1, 2, 3) 81 | b = black_hole.get_riemann_coefficient("dddd", 0, 2, 3, 1) 82 | c = black_hole.get_riemann_coefficient("dddd", 0, 3, 1, 2) 83 | 84 | self.assertEqual(a + b + c, 0) 85 | 86 | def test_riemann_skew_symmetry(self): 87 | black_hole = SpaceTime(Solution().schwarzschild(), True) 88 | a = black_hole.get_riemann_coefficient("dddd", 0, 1, 2, 3) 89 | b = black_hole.get_riemann_coefficient("dddd", 1, 0, 2, 3) 90 | c = black_hole.get_riemann_coefficient("dddd", 0, 1, 3, 2) 91 | 92 | self.assertEqual(a, -1*b) 93 | self.assertEqual(a, -1*c) 94 | 95 | unittest.main() -------------------------------------------------------------------------------- /spacetimeengine/utilities.py: -------------------------------------------------------------------------------- 1 | def covariant_derividive(): 2 | return True 3 | 4 | def tensor_constraction(): 5 | return True 6 | 7 | """ 8 | Cotton tensor functions 9 | ======================= 10 | """ 11 | 12 | def get_cotton_coefficient(self): 13 | return True 14 | 15 | def set_cotton_coefficient(self): 16 | return True 17 | 18 | def set_all_cotton_coefficients(self): 19 | return True 20 | 21 | def compute_cotton_coefficient(self): 22 | if(self.suppress_printing == False): 23 | print("") 24 | print("") 25 | print("Cotton Coefficients") 26 | print("===================") 27 | for lam in self.dimensions: 28 | print("") 29 | acc = 0 30 | 31 | def print_separation_geodesic(self, lam): 32 | return True 33 | 34 | def print_all_separation_geodesics(self): 35 | return True --------------------------------------------------------------------------------