Repository: einsteinpy/einsteinpy

Issue:
Implement index raising and lowering in Tensors
🐞 **Problem**
We have no way to know whether the Tensor has contravariant or covariant indices

🎯 **Goal**

The indices must be properly formatted in front of a symbol.

  - [x] Metric Tensor
  - [x] Christoffel Symbols
  - [x] Riemann Tensor
  - [x] Ricci Tensor
  - [x] Weyl Tensor

💡 **Possible solutions**

<!--- Not obligatory, but suggest an idea for implementing addition or change -->

📋  **Steps to solve the problem**

 * Comment below about what you've started working on.
 * Add, commit, push your changes
 * Submit a pull request and add this in comments - `Addresses #<put issue number here>`
 * Ask for a review in comments section of pull request
 * Celebrate your contribution to this project 🎉


Discussion:
pep8speaks: Hello @ritzvik! Thanks for opening this PR. We checked the lines you've touched for [PEP 8](https://www.python.org/dev/peps/pep-0008) issues, and found:

* In the file [`src/einsteinpy/symbolic/christoffel.py`](https://github.com/einsteinpy/einsteinpy/blob/ed7a61be1a9532e3e8bc41e458b7f0456dd9ddcf/src/einsteinpy/symbolic/christoffel.py):

> [Line 23:121](https://github.com/einsteinpy/einsteinpy/blob/ed7a61be1a9532e3e8bc41e458b7f0456dd9ddcf/src/einsteinpy/symbolic/christoffel.py#L23): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (135 > 120 characters)

* In the file [`src/einsteinpy/symbolic/metric.py`](https://github.com/einsteinpy/einsteinpy/blob/ed7a61be1a9532e3e8bc41e458b7f0456dd9ddcf/src/einsteinpy/symbolic/metric.py):

> [Line 20:121](https://github.com/einsteinpy/einsteinpy/blob/ed7a61be1a9532e3e8bc41e458b7f0456dd9ddcf/src/einsteinpy/symbolic/metric.py#L20): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (134 > 120 characters)

* In the file [`src/einsteinpy/symbolic/ricci.py`](https://github.com/einsteinpy/einsteinpy/blob/ed7a61be1a9532e3e8bc41e458b7f0456dd9ddcf/src/einsteinpy/symbolic/ricci.py):

> [Line 24:121](https://github.com/einsteinpy/einsteinpy/blob/ed7a61be1a9532e3e8bc41e458b7f0456dd9ddcf/src/einsteinpy/symbolic/ricci.py#L24): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (134 > 120 characters)
> [Line 34:1](https://github.com/einsteinpy/einsteinpy/blob/ed7a61be1a9532e3e8bc41e458b7f0456dd9ddcf/src/einsteinpy/symbolic/ricci.py#L34): [W293](https://duckduckgo.com/?q=pep8%20W293) blank line contains whitespace

* In the file [`src/einsteinpy/symbolic/riemann.py`](https://github.com/einsteinpy/einsteinpy/blob/ed7a61be1a9532e3e8bc41e458b7f0456dd9ddcf/src/einsteinpy/symbolic/riemann.py):

> [Line 24:121](https://github.com/einsteinpy/einsteinpy/blob/ed7a61be1a9532e3e8bc41e458b7f0456dd9ddcf/src/einsteinpy/symbolic/riemann.py#L24): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (136 > 120 characters)

* In the file [`src/einsteinpy/symbolic/tensor.py`](https://github.com/einsteinpy/einsteinpy/blob/ed7a61be1a9532e3e8bc41e458b7f0456dd9ddcf/src/einsteinpy/symbolic/tensor.py):

> [Line 28:121](https://github.com/einsteinpy/einsteinpy/blob/ed7a61be1a9532e3e8bc41e458b7f0456dd9ddcf/src/einsteinpy/symbolic/tensor.py#L28): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (134 > 120 characters)


codecov[bot]: # [Codecov](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278?src=pr&el=h1) Report
> Merging [#278](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278?src=pr&el=desc) into [master](https://codecov.io/gh/einsteinpy/einsteinpy/commit/b9c275ce11b8f5d6bcd2a8dc694039a769f30b09?src=pr&el=desc) will **decrease** coverage by `0.5%`.
> The diff coverage is `69.56%`.

[![Impacted file tree graph](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278/graphs/tree.svg?width=650&token=H3oDVYA11f&height=150&src=pr)](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #278      +/-   ##
==========================================
- Coverage   93.38%   92.88%   -0.51%     
==========================================
  Files          33       33              
  Lines        1134     1152      +18     
==========================================
+ Hits         1059     1070      +11     
- Misses         75       82       +7
```


| [Impacted Files](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/einsteinpy/symbolic/ricci.py](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278/diff?src=pr&el=tree#diff-c3JjL2VpbnN0ZWlucHkvc3ltYm9saWMvcmljY2kucHk=) | `91.3% <66.66%> (-3.94%)` | :arrow_down: |
| [src/einsteinpy/symbolic/metric.py](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278/diff?src=pr&el=tree#diff-c3JjL2VpbnN0ZWlucHkvc3ltYm9saWMvbWV0cmljLnB5) | `91.66% <66.66%> (-8.34%)` | :arrow_down: |
| [src/einsteinpy/symbolic/riemann.py](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278/diff?src=pr&el=tree#diff-c3JjL2VpbnN0ZWlucHkvc3ltYm9saWMvcmllbWFubi5weQ==) | `93.75% <66.66%> (-2.92%)` | :arrow_down: |
| [src/einsteinpy/symbolic/christoffel.py](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278/diff?src=pr&el=tree#diff-c3JjL2VpbnN0ZWlucHkvc3ltYm9saWMvY2hyaXN0b2ZmZWwucHk=) | `96.42% <66.66%> (-3.58%)` | :arrow_down: |
| [src/einsteinpy/symbolic/tensor.py](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278/diff?src=pr&el=tree#diff-c3JjL2VpbnN0ZWlucHkvc3ltYm9saWMvdGVuc29yLnB5) | `88.88% <72.72%> (-11.12%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278?src=pr&el=footer). Last update [b9c275c...ed7a61b](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

codecov[bot]: # [Codecov](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278?src=pr&el=h1) Report
> Merging [#278](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278?src=pr&el=desc) into [master](https://codecov.io/gh/einsteinpy/einsteinpy/commit/b9c275ce11b8f5d6bcd2a8dc694039a769f30b09?src=pr&el=desc) will **decrease** coverage by `0.5%`.
> The diff coverage is `69.56%`.

[![Impacted file tree graph](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278/graphs/tree.svg?width=650&token=H3oDVYA11f&height=150&src=pr)](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #278      +/-   ##
==========================================
- Coverage   93.38%   92.88%   -0.51%     
==========================================
  Files          33       33              
  Lines        1134     1152      +18     
==========================================
+ Hits         1059     1070      +11     
- Misses         75       82       +7
```


| [Impacted Files](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/einsteinpy/symbolic/ricci.py](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278/diff?src=pr&el=tree#diff-c3JjL2VpbnN0ZWlucHkvc3ltYm9saWMvcmljY2kucHk=) | `91.3% <66.66%> (-3.94%)` | :arrow_down: |
| [src/einsteinpy/symbolic/metric.py](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278/diff?src=pr&el=tree#diff-c3JjL2VpbnN0ZWlucHkvc3ltYm9saWMvbWV0cmljLnB5) | `91.66% <66.66%> (-8.34%)` | :arrow_down: |
| [src/einsteinpy/symbolic/riemann.py](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278/diff?src=pr&el=tree#diff-c3JjL2VpbnN0ZWlucHkvc3ltYm9saWMvcmllbWFubi5weQ==) | `93.75% <66.66%> (-2.92%)` | :arrow_down: |
| [src/einsteinpy/symbolic/christoffel.py](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278/diff?src=pr&el=tree#diff-c3JjL2VpbnN0ZWlucHkvc3ltYm9saWMvY2hyaXN0b2ZmZWwucHk=) | `96.42% <66.66%> (-3.58%)` | :arrow_down: |
| [src/einsteinpy/symbolic/tensor.py](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278/diff?src=pr&el=tree#diff-c3JjL2VpbnN0ZWlucHkvc3ltYm9saWMvdGVuc29yLnB5) | `88.88% <72.72%> (-11.12%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278?src=pr&el=footer). Last update [b9c275c...ed7a61b](https://codecov.io/gh/einsteinpy/einsteinpy/pull/278?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

ritzvik: @shreyasbapat Coverage increased! 
ritzvik: DON'T MERGE NOW
shreyasbapat: Okay!
shreyasbapat: It's not in the release! 

Patch:
diff --git a/docs/source/examples/Playing_with_Contravariant_and Covariant_Indices_in_Tensors(Symbolic).ipynb b/docs/source/examples/Playing_with_Contravariant_and Covariant_Indices_in_Tensors(Symbolic).ipynb
new file mode 100644
index 0000000..dc07a40
--- /dev/null
+++ b/docs/source/examples/Playing_with_Contravariant_and Covariant_Indices_in_Tensors(Symbolic).ipynb
@@ -0,0 +1,639 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Contravariant & Covariant indices in Tensors(Symbolic Module)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from einsteinpy.symbolic import SchwarzschildMetric, MetricTensor, ChristoffelSymbols, RiemannCurvatureTensor\n",
+    "import sympy\n",
+    "sympy.init_printing()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Analysing the schwarzschild metric along with performing various operations"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/latex": [
+       "$$\\left[\\begin{matrix}- \\frac{a}{r} + 1 & 0 & 0 & 0\\\\0 & - \\frac{1}{c^{2} \\left(- \\frac{a}{r} + 1\\right)} & 0 & 0\\\\0 & 0 & - \\frac{r^{2}}{c^{2}} & 0\\\\0 & 0 & 0 & - \\frac{r^{2} \\sin^{2}{\\left (\\theta \\right )}}{c^{2}}\\end{matrix}\\right]$$"
+      ],
+      "text/plain": [
+       "⎡  a                                      ⎤\n",
+       "⎢- ─ + 1       0         0         0      ⎥\n",
+       "⎢  r                                      ⎥\n",
+       "⎢                                         ⎥\n",
+       "⎢             -1                          ⎥\n",
+       "⎢   0     ────────────   0         0      ⎥\n",
+       "⎢          2 ⎛  a    ⎞                    ⎥\n",
+       "⎢         c ⋅⎜- ─ + 1⎟                    ⎥\n",
+       "⎢            ⎝  r    ⎠                    ⎥\n",
+       "⎢                                         ⎥\n",
+       "⎢                         2               ⎥\n",
+       "⎢                       -r                ⎥\n",
+       "⎢   0          0        ────       0      ⎥\n",
+       "⎢                         2               ⎥\n",
+       "⎢                        c                ⎥\n",
+       "⎢                                         ⎥\n",
+       "⎢                               2    2    ⎥\n",
+       "⎢                             -r ⋅sin (θ) ⎥\n",
+       "⎢   0          0         0    ────────────⎥\n",
+       "⎢                                   2     ⎥\n",
+       "⎣                                  c      ⎦"
+      ]
+     },
+     "execution_count": 2,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "sch = SchwarzschildMetric()\n",
+    "sch.tensor()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/latex": [
+       "$$\\left[\\begin{matrix}\\frac{r}{- a + r} & 0 & 0 & 0\\\\0 & \\frac{c^{2} \\left(a - r\\right)}{r} & 0 & 0\\\\0 & 0 & - \\frac{c^{2}}{r^{2}} & 0\\\\0 & 0 & 0 & - \\frac{c^{2}}{r^{2} \\sin^{2}{\\left (\\theta \\right )}}\\end{matrix}\\right]$$"
+      ],
+      "text/plain": [
+       "⎡  r                                 ⎤\n",
+       "⎢──────      0        0        0     ⎥\n",
+       "⎢-a + r                              ⎥\n",
+       "⎢                                    ⎥\n",
+       "⎢         2                          ⎥\n",
+       "⎢        c ⋅(a - r)                  ⎥\n",
+       "⎢  0     ──────────   0        0     ⎥\n",
+       "⎢            r                       ⎥\n",
+       "⎢                                    ⎥\n",
+       "⎢                      2             ⎥\n",
+       "⎢                    -c              ⎥\n",
+       "⎢  0         0       ────      0     ⎥\n",
+       "⎢                      2             ⎥\n",
+       "⎢                     r              ⎥\n",
+       "⎢                                    ⎥\n",
+       "⎢                               2    ⎥\n",
+       "⎢                             -c     ⎥\n",
+       "⎢  0         0        0    ──────────⎥\n",
+       "⎢                           2    2   ⎥\n",
+       "⎣                          r ⋅sin (θ)⎦"
+      ]
+     },
+     "execution_count": 3,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "sch_inv = sch.inv()\n",
+    "sch_inv.tensor()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAA0AAAASCAYAAACAa1QyAAAABHNCSVQICAgIfAhkiAAAAMJJREFUKJHF0j9LQlEYB+DH6BNYhJ/HxcmpD9CgQxCImxAIbi5u7eLSJji5NzQGDRItDtHQ3J0aSnS4LxJytBMN/eBw4XCe+77nD3/MCdqYYYkPFLhHC0cpdIk13nCLIcZ4j/kpKruojmbijzW8Bjz/TevXgW7s6zORz/h+5VY5xiIqNXLRKMA8F3QCPKOaA64CPClP8Md0AyxwlgN6AR5xmgP6AR4c2MP3Z3GBCVbKSywS619izTaDqHJo3OW0+8/ZALBUMPfsVQVVAAAAAElFTkSuQmCC\n",
+      "text/latex": [
+       "$$2$$"
+      ],
+      "text/plain": [
+       "2"
+      ]
+     },
+     "execution_count": 4,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "sch.order"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'ll'"
+      ]
+     },
+     "execution_count": 5,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "sch.config"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Obtaining Christoffel Symbols from Metric Tensor"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/latex": [
+       "$$\\left[\\begin{matrix}\\left[\\begin{matrix}0 & \\frac{a}{2 r^{2} \\left(- \\frac{a}{r} + 1\\right)} & 0 & 0\\\\\\frac{a}{2 r^{2} \\left(- \\frac{a}{r} + 1\\right)} & 0 & 0 & 0\\\\0 & 0 & 0 & 0\\\\0 & 0 & 0 & 0\\end{matrix}\\right] & \\left[\\begin{matrix}\\frac{a c^{2} \\left(- \\frac{a}{r} + 1\\right)}{2 r^{2}} & 0 & 0 & 0\\\\0 & - \\frac{a}{2 r^{2} \\left(- \\frac{a}{r} + 1\\right)} & 0 & 0\\\\0 & 0 & - r \\left(- \\frac{a}{r} + 1\\right) & 0\\\\0 & 0 & 0 & - r \\left(- \\frac{a}{r} + 1\\right) \\sin^{2}{\\left (\\theta \\right )}\\end{matrix}\\right] & \\left[\\begin{matrix}0 & 0 & 0 & 0\\\\0 & 0 & \\frac{1}{r} & 0\\\\0 & \\frac{1}{r} & 0 & 0\\\\0 & 0 & 0 & - \\sin{\\left (\\theta \\right )} \\cos{\\left (\\theta \\right )}\\end{matrix}\\right] & \\left[\\begin{matrix}0 & 0 & 0 & 0\\\\0 & 0 & 0 & \\frac{1}{r}\\\\0 & 0 & 0 & \\frac{\\cos{\\left (\\theta \\right )}}{\\sin{\\left (\\theta \\right )}}\\\\0 & \\frac{1}{r} & \\frac{\\cos{\\left (\\theta \\right )}}{\\sin{\\left (\\theta \\right )}} & 0\\end{matrix}\\right]\\end{matrix}\\right]$$"
+      ],
+      "text/plain": [
+       "⎡                                        ⎡   2 ⎛  a    ⎞                      \n",
+       "⎢                                        ⎢a⋅c ⋅⎜- ─ + 1⎟                      \n",
+       "⎢                                        ⎢     ⎝  r    ⎠                      \n",
+       "⎢⎡                      a             ⎤  ⎢──────────────        0             \n",
+       "⎢⎢      0         ──────────────  0  0⎥  ⎢        2                           \n",
+       "⎢⎢                   2 ⎛  a    ⎞      ⎥  ⎢     2⋅r                            \n",
+       "⎢⎢                2⋅r ⋅⎜- ─ + 1⎟      ⎥  ⎢                                    \n",
+       "⎢⎢                     ⎝  r    ⎠      ⎥  ⎢                     -a             \n",
+       "⎢⎢                                    ⎥  ⎢      0         ──────────────      \n",
+       "⎢⎢      a                             ⎥  ⎢                   2 ⎛  a    ⎞      \n",
+       "⎢⎢──────────────        0         0  0⎥  ⎢                2⋅r ⋅⎜- ─ + 1⎟      \n",
+       "⎢⎢   2 ⎛  a    ⎞                      ⎥  ⎢                     ⎝  r    ⎠      \n",
+       "⎢⎢2⋅r ⋅⎜- ─ + 1⎟                      ⎥  ⎢                                    \n",
+       "⎢⎢     ⎝  r    ⎠                      ⎥  ⎢                                   ⎛\n",
+       "⎢⎢                                    ⎥  ⎢      0               0         -r⋅⎜\n",
+       "⎢⎢      0               0         0  0⎥  ⎢                                   ⎝\n",
+       "⎢⎢                                    ⎥  ⎢                                    \n",
+       "⎢⎣      0               0         0  0⎦  ⎢                                    \n",
+       "⎢                                        ⎢      0               0             \n",
+       "⎣                                        ⎣                                    \n",
+       "\n",
+       "                              ⎤                                               \n",
+       "                              ⎥                                               \n",
+       "                              ⎥                                               \n",
+       " 0                 0          ⎥                                               \n",
+       "                              ⎥                             ⎡0  0    0       0\n",
+       "                              ⎥  ⎡0  0  0        0       ⎤  ⎢                 \n",
+       "                              ⎥  ⎢                       ⎥  ⎢                1\n",
+       "                              ⎥  ⎢      1                ⎥  ⎢0  0    0       ─\n",
+       " 0                 0          ⎥  ⎢0  0  ─        0       ⎥  ⎢                r\n",
+       "                              ⎥  ⎢      r                ⎥  ⎢                 \n",
+       "                              ⎥  ⎢                       ⎥  ⎢              cos\n",
+       "                              ⎥  ⎢   1                   ⎥  ⎢0  0    0     ───\n",
+       "                              ⎥  ⎢0  ─  0        0       ⎥  ⎢              sin\n",
+       "  a    ⎞                      ⎥  ⎢   r                   ⎥  ⎢                 \n",
+       "- ─ + 1⎟           0          ⎥  ⎢                       ⎥  ⎢   1  cos(θ)     \n",
+       "  r    ⎠                      ⎥  ⎣0  0  0  -sin(θ)⋅cos(θ)⎦  ⎢0  ─  ──────    0\n",
+       "                              ⎥                             ⎣   r  sin(θ)     \n",
+       "             ⎛  a    ⎞    2   ⎥                                               \n",
+       " 0        -r⋅⎜- ─ + 1⎟⋅sin (θ)⎥                                               \n",
+       "             ⎝  r    ⎠        ⎦                                               \n",
+       "\n",
+       "    ⎤\n",
+       "    ⎥\n",
+       "    ⎥\n",
+       "    ⎥\n",
+       "   ⎤⎥\n",
+       "   ⎥⎥\n",
+       "   ⎥⎥\n",
+       "   ⎥⎥\n",
+       "   ⎥⎥\n",
+       "   ⎥⎥\n",
+       "(θ)⎥⎥\n",
+       "───⎥⎥\n",
+       "(θ)⎥⎥\n",
+       "   ⎥⎥\n",
+       "   ⎥⎥\n",
+       "   ⎥⎥\n",
+       "   ⎦⎥\n",
+       "    ⎥\n",
+       "    ⎥\n",
+       "    ⎦"
+      ]
+     },
+     "execution_count": 6,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "chr = ChristoffelSymbols.from_metric(sch_inv) # can be initialized from sch also\n",
+    "chr.tensor()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'ull'"
+      ]
+     },
+     "execution_count": 7,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "chr.config"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Changing the first index to covariant"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/latex": [
+       "$$\\left[\\begin{matrix}\\left[\\begin{matrix}0 & \\frac{a}{2 r^{2}} & 0 & 0\\\\\\frac{a}{2 r^{2}} & 0 & 0 & 0\\\\0 & 0 & 0 & 0\\\\0 & 0 & 0 & 0\\end{matrix}\\right] & \\left[\\begin{matrix}- \\frac{a}{2 r^{2}} & 0 & 0 & 0\\\\0 & \\frac{a}{2 c^{2} \\left(a - r\\right)^{2}} & 0 & 0\\\\0 & 0 & \\frac{r}{c^{2}} & 0\\\\0 & 0 & 0 & \\frac{r \\sin^{2}{\\left (\\theta \\right )}}{c^{2}}\\end{matrix}\\right] & \\left[\\begin{matrix}0 & 0 & 0 & 0\\\\0 & 0 & - \\frac{r}{c^{2}} & 0\\\\0 & - \\frac{r}{c^{2}} & 0 & 0\\\\0 & 0 & 0 & \\frac{r^{2} \\sin{\\left (2 \\theta \\right )}}{2 c^{2}}\\end{matrix}\\right] & \\left[\\begin{matrix}0 & 0 & 0 & 0\\\\0 & 0 & 0 & - \\frac{r \\sin^{2}{\\left (\\theta \\right )}}{c^{2}}\\\\0 & 0 & 0 & - \\frac{r^{2} \\sin{\\left (2 \\theta \\right )}}{2 c^{2}}\\\\0 & - \\frac{r \\sin^{2}{\\left (\\theta \\right )}}{c^{2}} & - \\frac{r^{2} \\sin{\\left (2 \\theta \\right )}}{2 c^{2}} & 0\\end{matrix}\\right]\\end{matrix}\\right]$$"
+      ],
+      "text/plain": [
+       "⎡                    ⎡-a                                ⎤                     \n",
+       "⎢                    ⎢────        0        0       0    ⎥                     \n",
+       "⎢                    ⎢   2                              ⎥  ⎡0   0    0        \n",
+       "⎢                    ⎢2⋅r                               ⎥  ⎢                  \n",
+       "⎢⎡       a        ⎤  ⎢                                  ⎥  ⎢        -r        \n",
+       "⎢⎢ 0    ────  0  0⎥  ⎢            a                     ⎥  ⎢0   0   ───       \n",
+       "⎢⎢         2      ⎥  ⎢ 0    ─────────────  0       0    ⎥  ⎢          2       \n",
+       "⎢⎢      2⋅r       ⎥  ⎢         2        2               ⎥  ⎢         c        \n",
+       "⎢⎢                ⎥  ⎢      2⋅c ⋅(a - r)                ⎥  ⎢                  \n",
+       "⎢⎢ a              ⎥  ⎢                                  ⎥  ⎢   -r             \n",
+       "⎢⎢────   0    0  0⎥  ⎢                     r            ⎥  ⎢0  ───   0        \n",
+       "⎢⎢   2            ⎥  ⎢ 0          0        ──      0    ⎥  ⎢     2            \n",
+       "⎢⎢2⋅r             ⎥  ⎢                      2           ⎥  ⎢    c             \n",
+       "⎢⎢                ⎥  ⎢                     c            ⎥  ⎢                  \n",
+       "⎢⎢ 0     0    0  0⎥  ⎢                                  ⎥  ⎢              2   \n",
+       "⎢⎢                ⎥  ⎢                              2   ⎥  ⎢             r ⋅si\n",
+       "⎢⎣ 0     0    0  0⎦  ⎢                         r⋅sin (θ)⎥  ⎢0   0    0   ─────\n",
+       "⎢                    ⎢ 0          0        0   ─────────⎥  ⎢                  \n",
+       "⎢                    ⎢                              2   ⎥  ⎣                 2\n",
+       "⎣                    ⎣                             c    ⎦                     \n",
+       "\n",
+       "                                                       ⎤\n",
+       "         ⎡0       0             0              0      ⎤⎥\n",
+       "0     ⎤  ⎢                                            ⎥⎥\n",
+       "      ⎥  ⎢                                      2     ⎥⎥\n",
+       "      ⎥  ⎢                                -r⋅sin (θ)  ⎥⎥\n",
+       "0     ⎥  ⎢0       0             0         ─────────── ⎥⎥\n",
+       "      ⎥  ⎢                                      2     ⎥⎥\n",
+       "      ⎥  ⎢                                     c      ⎥⎥\n",
+       "      ⎥  ⎢                                            ⎥⎥\n",
+       "      ⎥  ⎢                                 2          ⎥⎥\n",
+       "0     ⎥  ⎢                               -r ⋅sin(2⋅θ) ⎥⎥\n",
+       "      ⎥  ⎢0       0             0        ─────────────⎥⎥\n",
+       "      ⎥  ⎢                                       2    ⎥⎥\n",
+       "      ⎥  ⎢                                    2⋅c     ⎥⎥\n",
+       "      ⎥  ⎢                                            ⎥⎥\n",
+       "n(2⋅θ)⎥  ⎢         2        2                         ⎥⎥\n",
+       "──────⎥  ⎢   -r⋅sin (θ)   -r ⋅sin(2⋅θ)                ⎥⎥\n",
+       "  2   ⎥  ⎢0  ───────────  ─────────────        0      ⎥⎥\n",
+       "⋅c    ⎦  ⎢         2              2                   ⎥⎥\n",
+       "         ⎣        c            2⋅c                    ⎦⎦"
+      ]
+     },
+     "execution_count": 8,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "new_chr = chr.change_config('lll') # changing the configuration to (covariant, covariant, covariant)\n",
+    "new_chr.tensor()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'lll'"
+      ]
+     },
+     "execution_count": 9,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "new_chr.config"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Any arbitary index configuration would also work!"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/latex": [
+       "$$\\left[\\begin{matrix}\\left[\\begin{matrix}0 & \\frac{a}{2 r \\left(- a + r\\right)} & 0 & 0\\\\\\frac{a c^{2} \\left(a - r\\right)}{2 r^{3}} & 0 & 0 & 0\\\\0 & 0 & 0 & 0\\\\0 & 0 & 0 & 0\\end{matrix}\\right] & \\left[\\begin{matrix}\\frac{a}{2 r \\left(a - r\\right)} & 0 & 0 & 0\\\\0 & \\frac{a}{2 r \\left(a - r\\right)} & 0 & 0\\\\0 & 0 & - \\frac{1}{r} & 0\\\\0 & 0 & 0 & - \\frac{1}{r}\\end{matrix}\\right] & \\left[\\begin{matrix}0 & 0 & 0 & 0\\\\0 & 0 & - a + r & 0\\\\0 & \\frac{1}{r} & 0 & 0\\\\0 & 0 & 0 & - \\frac{1}{\\tan{\\left (\\theta \\right )}}\\end{matrix}\\right] & \\left[\\begin{matrix}0 & 0 & 0 & 0\\\\0 & 0 & 0 & \\left(- a + r\\right) \\sin^{2}{\\left (\\theta \\right )}\\\\0 & 0 & 0 & \\frac{\\sin{\\left (2 \\theta \\right )}}{2}\\\\0 & \\frac{1}{r} & \\frac{1}{\\tan{\\left (\\theta \\right )}} & 0\\end{matrix}\\right]\\end{matrix}\\right]$$"
+      ],
+      "text/plain": [
+       "⎡                                    ⎡     a                            ⎤     \n",
+       "⎢⎡                   a            ⎤  ⎢───────────       0        0    0 ⎥     \n",
+       "⎢⎢     0        ────────────  0  0⎥  ⎢2⋅r⋅(a - r)                       ⎥  ⎡0 \n",
+       "⎢⎢              2⋅r⋅(-a + r)      ⎥  ⎢                                  ⎥  ⎢  \n",
+       "⎢⎢                                ⎥  ⎢                  a               ⎥  ⎢0 \n",
+       "⎢⎢   2                            ⎥  ⎢     0       ───────────   0    0 ⎥  ⎢  \n",
+       "⎢⎢a⋅c ⋅(a - r)                    ⎥  ⎢             2⋅r⋅(a - r)          ⎥  ⎢  \n",
+       "⎢⎢────────────       0        0  0⎥  ⎢                                  ⎥  ⎢0 \n",
+       "⎢⎢       3                        ⎥  ⎢                          -1      ⎥  ⎢  \n",
+       "⎢⎢    2⋅r                         ⎥  ⎢     0            0       ───   0 ⎥  ⎢  \n",
+       "⎢⎢                                ⎥  ⎢                           r      ⎥  ⎢  \n",
+       "⎢⎢     0             0        0  0⎥  ⎢                                  ⎥  ⎢0 \n",
+       "⎢⎢                                ⎥  ⎢                               -1 ⎥  ⎣  \n",
+       "⎢⎣     0             0        0  0⎦  ⎢     0            0        0   ───⎥     \n",
+       "⎣                                    ⎣                                r ⎦     \n",
+       "\n",
+       "                                                     ⎤\n",
+       "                     ⎡0  0    0            0        ⎤⎥\n",
+       " 0    0       0   ⎤  ⎢                              ⎥⎥\n",
+       "                  ⎥  ⎢                          2   ⎥⎥\n",
+       " 0  -a + r    0   ⎥  ⎢0  0    0     (-a + r)⋅sin (θ)⎥⎥\n",
+       "                  ⎥  ⎢                              ⎥⎥\n",
+       " 1                ⎥  ⎢                  sin(2⋅θ)    ⎥⎥\n",
+       " ─    0       0   ⎥  ⎢0  0    0         ────────    ⎥⎥\n",
+       " r                ⎥  ⎢                     2        ⎥⎥\n",
+       "                  ⎥  ⎢                              ⎥⎥\n",
+       "             -1   ⎥  ⎢   1    1                     ⎥⎥\n",
+       " 0    0     ──────⎥  ⎢0  ─  ──────         0        ⎥⎥\n",
+       "            tan(θ)⎦  ⎣   r  tan(θ)                  ⎦⎥\n",
+       "                                                     ⎥\n",
+       "                                                     ⎦"
+      ]
+     },
+     "execution_count": 10,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "new_chr2 = new_chr.change_config('lul')\n",
+    "new_chr2.tensor()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Obtaining Riemann Tensor from Christoffel Symbols and manipulating it's indices"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/latex": [
+       "$$\\left[\\begin{matrix}0 & 0 & 0 & 0\\\\0 & \\frac{a}{r^{2} \\left(a - r\\right)} & 0 & 0\\\\0 & 0 & \\frac{a}{2 r} & 0\\\\0 & 0 & 0 & \\frac{a \\sin^{2}{\\left (\\theta \\right )}}{2 r}\\end{matrix}\\right]$$"
+      ],
+      "text/plain": [
+       "⎡0      0        0       0    ⎤\n",
+       "⎢                             ⎥\n",
+       "⎢       a                     ⎥\n",
+       "⎢0  ──────────   0       0    ⎥\n",
+       "⎢    2                        ⎥\n",
+       "⎢   r ⋅(a - r)                ⎥\n",
+       "⎢                             ⎥\n",
+       "⎢                a            ⎥\n",
+       "⎢0      0       ───      0    ⎥\n",
+       "⎢               2⋅r           ⎥\n",
+       "⎢                             ⎥\n",
+       "⎢                         2   ⎥\n",
+       "⎢                    a⋅sin (θ)⎥\n",
+       "⎢0      0        0   ─────────⎥\n",
+       "⎣                       2⋅r   ⎦"
+      ]
+     },
+     "execution_count": 11,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "rm = RiemannCurvatureTensor.from_christoffels(new_chr2)\n",
+    "rm[0,0,:,:]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'ulll'"
+      ]
+     },
+     "execution_count": 12,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "rm.config"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/latex": [
+       "$$\\left[\\begin{matrix}0 & 0 & 0 & 0\\\\0 & - \\frac{a c^{4}}{r^{3}} & 0 & 0\\\\0 & 0 & \\frac{a c^{4}}{2 r^{4} \\left(- a + r\\right)} & 0\\\\0 & 0 & 0 & \\frac{a c^{4}}{2 r^{4} \\left(- a + r\\right) \\sin^{2}{\\left (\\theta \\right )}}\\end{matrix}\\right]$$"
+      ],
+      "text/plain": [
+       "⎡0    0           0                  0          ⎤\n",
+       "⎢                                               ⎥\n",
+       "⎢       4                                       ⎥\n",
+       "⎢   -a⋅c                                        ⎥\n",
+       "⎢0  ──────        0                  0          ⎥\n",
+       "⎢      3                                        ⎥\n",
+       "⎢     r                                         ⎥\n",
+       "⎢                                               ⎥\n",
+       "⎢                   4                           ⎥\n",
+       "⎢                a⋅c                            ⎥\n",
+       "⎢0    0     ─────────────            0          ⎥\n",
+       "⎢              4                                ⎥\n",
+       "⎢           2⋅r ⋅(-a + r)                       ⎥\n",
+       "⎢                                               ⎥\n",
+       "⎢                                      4        ⎥\n",
+       "⎢                                   a⋅c         ⎥\n",
+       "⎢0    0           0        ─────────────────────⎥\n",
+       "⎢                             4             2   ⎥\n",
+       "⎣                          2⋅r ⋅(-a + r)⋅sin (θ)⎦"
+      ]
+     },
+     "execution_count": 13,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "rm2 = rm.change_config(\"uuuu\")\n",
+    "rm2[0,0,:,:]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/latex": [
+       "$$\\left[\\begin{matrix}0 & 0 & 0 & 0\\\\0 & \\frac{a c^{2}}{r^{3}} & 0 & 0\\\\0 & 0 & - \\frac{a c^{2}}{2 r^{3}} & 0\\\\0 & 0 & 0 & - \\frac{a c^{2}}{2 r^{3}}\\end{matrix}\\right]$$"
+      ],
+      "text/plain": [
+       "⎡0   0      0       0   ⎤\n",
+       "⎢                       ⎥\n",
+       "⎢      2                ⎥\n",
+       "⎢   a⋅c                 ⎥\n",
+       "⎢0  ────    0       0   ⎥\n",
+       "⎢     3                 ⎥\n",
+       "⎢    r                  ⎥\n",
+       "⎢                       ⎥\n",
+       "⎢             2         ⎥\n",
+       "⎢         -a⋅c          ⎥\n",
+       "⎢0   0    ──────    0   ⎥\n",
+       "⎢             3         ⎥\n",
+       "⎢          2⋅r          ⎥\n",
+       "⎢                       ⎥\n",
+       "⎢                     2 ⎥\n",
+       "⎢                 -a⋅c  ⎥\n",
+       "⎢0   0      0     ──────⎥\n",
+       "⎢                     3 ⎥\n",
+       "⎣                  2⋅r  ⎦"
+      ]
+     },
+     "execution_count": 14,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "rm3 = rm2.change_config(\"lulu\")\n",
+    "rm3[0,0,:,:]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 15,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/latex": [
+       "$$\\left[\\begin{matrix}0 & 0 & 0 & 0\\\\0 & \\frac{a}{r^{2} \\left(a - r\\right)} & 0 & 0\\\\0 & 0 & \\frac{a}{2 r} & 0\\\\0 & 0 & 0 & \\frac{a \\sin^{2}{\\left (\\theta \\right )}}{2 r}\\end{matrix}\\right]$$"
+      ],
+      "text/plain": [
+       "⎡0      0        0       0    ⎤\n",
+       "⎢                             ⎥\n",
+       "⎢       a                     ⎥\n",
+       "⎢0  ──────────   0       0    ⎥\n",
+       "⎢    2                        ⎥\n",
+       "⎢   r ⋅(a - r)                ⎥\n",
+       "⎢                             ⎥\n",
+       "⎢                a            ⎥\n",
+       "⎢0      0       ───      0    ⎥\n",
+       "⎢               2⋅r           ⎥\n",
+       "⎢                             ⎥\n",
+       "⎢                         2   ⎥\n",
+       "⎢                    a⋅sin (θ)⎥\n",
+       "⎢0      0        0   ─────────⎥\n",
+       "⎣                       2⋅r   ⎦"
+      ]
+     },
+     "execution_count": 15,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "rm4 = rm3.change_config(\"ulll\")\n",
+    "rm4[0,0,:,:]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### It is seen that `rm` and `rm4` are same as they have the same configuration"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.6.8"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/source/jupyter.rst b/docs/source/jupyter.rst
index 73c2738..5b32166 100644
--- a/docs/source/jupyter.rst
+++ b/docs/source/jupyter.rst
@@ -7,6 +7,7 @@ Jupyter notebooks
    /examples/Visualizing_advance_of_perihelion_of_a_test_particle_in_Schwarzschild_space-time.ipynb
    /examples/Animations_in_EinsteinPy.ipynb
    /examples/Symbolically_Understanding_Christoffel_Symbol_and_Riemann_Curvature_Tensor_using_EinsteinPy.ipynb
+   /examples/Playing_with_Contravariant_and Covariant_Indices_in_Tensors(Symbolic).ipynb
    /examples/Analysing_Earth_using_EinsteinPy!.ipynb
    /examples/Visualizing_frame_dragging_in_Kerr_spacetime.ipynb
    /examples/Visualizing_event_horizon_and_ergosphere_of_Kerr_black_hole.ipynb
diff --git a/src/einsteinpy/symbolic/__init__.py b/src/einsteinpy/symbolic/__init__.py
index 5ca00fc..774ffd0 100644
--- a/src/einsteinpy/symbolic/__init__.py
+++ b/src/einsteinpy/symbolic/__init__.py
@@ -4,4 +4,5 @@ from .metric import MetricTensor
 from .ricci import RicciTensor
 from .riemann import RiemannCurvatureTensor
 from .stress_energy_momentum import StressEnergyMomentumTensor
+from .tensor import Tensor
 from .vacuum_metrics import SchwarzschildMetric
diff --git a/src/einsteinpy/symbolic/christoffel.py b/src/einsteinpy/symbolic/christoffel.py
index 9dcc147..935cfd2 100644
--- a/src/einsteinpy/symbolic/christoffel.py
+++ b/src/einsteinpy/symbolic/christoffel.py
@@ -1,7 +1,7 @@
 import numpy as np
 import sympy
 
-from einsteinpy.symbolic.tensor import Tensor
+from einsteinpy.symbolic.tensor import Tensor, _change_config
 
 
 class ChristoffelSymbols(Tensor):
@@ -9,7 +9,7 @@ class ChristoffelSymbols(Tensor):
     Class for defining christoffel symbols
     """
 
-    def __init__(self, arr, syms):
+    def __init__(self, arr, syms, config="ull", parent_metric=None):
         """
         Constructor and Initializer
         
@@ -19,6 +19,10 @@ class ChristoffelSymbols(Tensor):
             Sympy Array or multi-dimensional list containing Sympy Expressions
         syms : tuple or list
             Tuple of crucial symbols dentoting time-axis, 1st, 2nd, and 3rd axis (t,x1,x2,x3)
+        config : str
+            Configuration of contravariant and covariant indices in tensor. 'u' for upper and 'l' for lower indices. Defaults to 'ull'.
+        parent_metric : ~einsteinpy.symbolic.metric.MetricTensor
+            Metric Tensor from which Christoffel symbol is calculated. Defaults to None.
 
         Raises
         ------
@@ -26,14 +30,27 @@ class ChristoffelSymbols(Tensor):
             Raised when arr is not a list or sympy Array
         TypeError
             syms is not a list or tuple
+        ValueError
+            config has more or less than 3 indices
         
         """
-        super(ChristoffelSymbols, self).__init__(arr)
+        super(ChristoffelSymbols, self).__init__(arr, config=config)
+        self._order = 3
+        self._parent_metric = parent_metric
         if isinstance(syms, (list, tuple)):
             self.syms = syms
             self.dims = len(self.syms)
         else:
             raise TypeError("syms should be a list or tuple")
+        if not len(config) == self._order:
+            raise ValueError("config should be of length {}".format(self._order))
+
+    @property
+    def parent_metric(self):
+        """
+        Returns the Metric from which Christoffel Symbol was derived, if available.
+        """
+        return self._parent_metric
 
     @classmethod
     def from_metric(cls, metric):
@@ -46,9 +63,13 @@ class ChristoffelSymbols(Tensor):
             Space-time Metric from which Christoffel Symbols are to be calculated
         
         """
+        if metric.config == "uu":
+            metric_cov = metric.inv()
+        else:
+            metric_cov = metric
         dims = metric.dims
         tmplist = np.zeros((dims, dims, dims), dtype=int).tolist()
-        mat, syms = metric.tensor(), metric.symbols()
+        mat, syms = metric_cov.tensor(), metric_cov.symbols()
         matinv = sympy.Matrix(mat.tolist()).inv()
         for t in range(dims ** 3):
             # i,j,k each goes from 0 to (dims-1)
@@ -64,7 +85,41 @@ class ChristoffelSymbols(Tensor):
                     - sympy.diff(mat[j, k], syms[n])
                 )
             tmplist[i][j][k] = tmpvar
-        return cls(tmplist, syms)
+        return cls(tmplist, syms, config="ull", parent_metric=metric)
+
+    def change_config(self, newconfig="lll", metric=None):
+        """
+        Changes the index configuration(contravariant/covariant)
+
+        Parameters
+        ----------
+        newconfig : str
+            Specify the new configuration. Defaults to 'lll'
+        metric : ~einsteinpy.symbolic.metric.MetricTensor or None
+            Parent metric tensor for changing indices.
+            Already assumes the value of the metric tensor from which it was initialized if passed with None. 
+            Compulsory if not initialized with 'from_metric'. Defaults to None.
+
+        Returns
+        -------
+        ~einsteinpy.symbolic.christoffel.ChristoffelSymbols
+            New tensor with new configuration. Defaults to 'lll'
+
+        Raises
+        ------
+        Exception
+            Raised when a parent metric could not be found.
+
+        """
+        if metric is None:
+            metric = self._parent_metric
+        if metric is None:
+            raise Exception("Parent Metric not found, can't do configuration change")
+        new_tensor = _change_config(self, metric, newconfig)
+        new_obj = ChristoffelSymbols(
+            new_tensor, self.syms, config=newconfig, parent_metric=metric
+        )
+        return new_obj
 
     def symbols(self):
         """
diff --git a/src/einsteinpy/symbolic/metric.py b/src/einsteinpy/symbolic/metric.py
index 37cec7d..82ea098 100644
--- a/src/einsteinpy/symbolic/metric.py
+++ b/src/einsteinpy/symbolic/metric.py
@@ -1,3 +1,5 @@
+import sympy
+
 from einsteinpy.symbolic.tensor import Tensor
 
 
@@ -6,7 +8,7 @@ class MetricTensor(Tensor):
     Class to define a metric tensor for a space-time
     """
 
-    def __init__(self, arr, syms):
+    def __init__(self, arr, syms, config="ll"):
         """
         Constructor and Initializer
         
@@ -16,6 +18,8 @@ class MetricTensor(Tensor):
             Sympy Array or multi-dimensional list containing Sympy Expressions
         syms : tuple or list
             Tuple of crucial symbols dentoting time-axis, 1st, 2nd, and 3rd axis (t,x1,x2,x3)
+        config : str
+            Configuration of contravariant and covariant indices in tensor. 'u' for upper and 'l' for lower indices. Defaults to 'll'.
 
         Raises
         ------
@@ -23,14 +27,74 @@ class MetricTensor(Tensor):
             Raised when arr is not a list or sympy Array
         TypeError
             syms is not a list or tuple
+        ValueError
+            config has more or less than 2 indices
         
         """
-        super(MetricTensor, self).__init__(arr)
+        super(MetricTensor, self).__init__(arr, config=config)
+        self._order = 2
+        self._invmetric = None
         if isinstance(syms, (list, tuple)):
             self.syms = syms
             self.dims = len(self.syms)
         else:
             raise TypeError("syms should be a list or tuple")
+        if not len(config) == self._order:
+            raise ValueError("config should be of length {}".format(self._order))
+
+    def change_config(self, newconfig="uu"):
+        """
+        Changes the index configuration(contravariant/covariant)
+
+        Parameters
+        ----------
+        newconfig : str
+            Specify the new configuration. Defaults to 'uu'
+
+        Returns
+        -------
+        ~einsteinpy.symbolic.metric.MetricTensor
+            New Metric with new configuration. Defaults to 'uu'
+
+        Raises
+        ------
+        ValueError
+            Raised when new configuration is not 'll' or 'uu'. 
+            This constraint is in place because we are dealing with Metric Tensor.
+
+        """
+        if newconfig == self.config:
+            return self
+        elif newconfig == "uu" or newconfig == "ll":
+            inv_met = MetricTensor(
+                sympy.simplify(sympy.Matrix(self.arr.tolist()).inv()).tolist(),
+                self.syms,
+                config=newconfig,
+            )
+            inv_met._invmetric = self
+            return inv_met
+        else:
+            raise ValueError(
+                "Configuration can't have one upper and one lower index in Metric Tensor."
+            )
+
+    def inv(self):
+        """
+        Returns the inverse of the Metric. 
+        Returns contravariant Metric if it is originally covariant or vice-versa.
+
+        Returns
+        -------
+        ~einsteinpy.symbolic.metric.MetricTensor
+            New Metric which is the inverse of original Metric.
+        
+        """
+        if self._invmetric is None:
+            if self.config == "ll":
+                self._invmetric = self.change_config("uu")
+            else:
+                self._invmetric = self.change_config("ll")
+        return self._invmetric
 
     def symbols(self):
         """
diff --git a/src/einsteinpy/symbolic/ricci.py b/src/einsteinpy/symbolic/ricci.py
index 95f4d1b..e1a0508 100644
--- a/src/einsteinpy/symbolic/ricci.py
+++ b/src/einsteinpy/symbolic/ricci.py
@@ -10,7 +10,7 @@ class RicciTensor(Tensor):
     Class for defining Ricci Tensor
     """
 
-    def __init__(self, arr, syms):
+    def __init__(self, arr, syms, config="ll", parent_metric=None):
         """
         Constructor and Initializer
 
@@ -20,6 +20,8 @@ class RicciTensor(Tensor):
             Sympy Array or multi-dimensional list containing Sympy Expressions
         syms : tuple or list
             Tuple of crucial symbols dentoting time-axis, 1st, 2nd, and 3rd axis (t,x1,x2,x3)
+        config : str
+            Configuration of contravariant and covariant indices in tensor. 'u' for upper and 'l' for lower indices. Defaults to 'll'.
 
         Raises
         ------
@@ -27,14 +29,20 @@ class RicciTensor(Tensor):
             Raised when arr is not a list or sympy Array
         TypeError
             syms is not a list or tuple
-
+        ValueError
+            config has more or less than 2 indices
+        
         """
-        super(RicciTensor, self).__init__(arr)
+        super(RicciTensor, self).__init__(arr, config=config)
+        self._order = 2
+        self._parent_metric = parent_metric
         if isinstance(syms, (list, tuple)):
             self.syms = syms
             self.dims = len(self.syms)
         else:
             raise TypeError("syms should be a list or tuple")
+        if not len(config) == self._order:
+            raise ValueError("config should be of length {}".format(self._order))
 
     @classmethod
     def from_riemann(cls, riemann):
diff --git a/src/einsteinpy/symbolic/riemann.py b/src/einsteinpy/symbolic/riemann.py
index ec04369..c671419 100644
--- a/src/einsteinpy/symbolic/riemann.py
+++ b/src/einsteinpy/symbolic/riemann.py
@@ -2,7 +2,7 @@ import numpy as np
 import sympy
 
 from einsteinpy.symbolic.christoffel import ChristoffelSymbols
-from einsteinpy.symbolic.tensor import Tensor
+from einsteinpy.symbolic.tensor import Tensor, _change_config
 
 
 class RiemannCurvatureTensor(Tensor):
@@ -10,7 +10,7 @@ class RiemannCurvatureTensor(Tensor):
     Class for defining Riemann Curvature Tensor
     """
 
-    def __init__(self, arr, syms):
+    def __init__(self, arr, syms, config="ulll", parent_metric=None):
         """
         Constructor and Initializer
         
@@ -20,6 +20,8 @@ class RiemannCurvatureTensor(Tensor):
             Sympy Array or multi-dimensional list containing Sympy Expressions
         syms : tuple or list
             Tuple of crucial symbols dentoting time-axis, 1st, 2nd, and 3rd axis (t,x1,x2,x3)
+        config : str
+            Configuration of contravariant and covariant indices in tensor. 'u' for upper and 'l' for lower indices. Defaults to 'ulll'.
 
         Raises
         ------
@@ -27,17 +29,30 @@ class RiemannCurvatureTensor(Tensor):
             Raised when arr is not a list or sympy Array
         TypeError
             syms is not a list or tuple
+        ValueError
+            config has more or less than 4 indices
         
         """
-        super(RiemannCurvatureTensor, self).__init__(arr)
+        super(RiemannCurvatureTensor, self).__init__(arr, config=config)
+        self._order = 4
+        self._parent_metric = parent_metric
         if isinstance(syms, (list, tuple)):
             self.syms = syms
             self.dims = len(self.syms)
         else:
             raise TypeError("syms should be a list or tuple")
+        if not len(config) == self._order:
+            raise ValueError("config should be of length {}".format(self._order))
+
+    @property
+    def parent_metric(self):
+        """
+        Returns the Parent Metric, if available.
+        """
+        return self._parent_metric
 
     @classmethod
-    def from_christoffels(cls, chris):
+    def from_christoffels(cls, chris, parent_metric=None):
         """
         Get Riemann Tensor calculated from a Christoffel Symbols
 
@@ -45,8 +60,14 @@ class RiemannCurvatureTensor(Tensor):
         ----------
         chris : ~einsteinpy.symbolic.christoffel.ChristoffelSymbols
             Christoffel Symbols from which Riemann Curvature Tensor to be calculated
+        parent_metric : ~einsteinpy.symbolic.metric.MetricTensor or None
+            Corrosponding Metric for the Riemann Tensor. 
+            None if it should inherit the Parent Metric of Christoffel Symbols.
+            Defaults to None.
         
         """
+        if not chris.config == "ull":
+            chris = chris.change_config(newconfig="ull", metric=parent_metric)
         arr, syms = chris.tensor(), chris.symbols()
         dims = len(syms)
         riemann_list = (np.zeros(shape=(dims, dims, dims, dims), dtype=int)).tolist()
@@ -61,7 +82,9 @@ class RiemannCurvatureTensor(Tensor):
             for p in range(dims):
                 temp += arr[p, s, n] * arr[t, p, r] - arr[p, r, n] * arr[t, p, s]
             riemann_list[t][s][r][n] = sympy.simplify(temp)
-        return cls(riemann_list, syms)
+        if parent_metric is None:
+            parent_metric = chris.parent_metric
+        return cls(riemann_list, syms, config="ulll", parent_metric=parent_metric)
 
     @classmethod
     def from_metric(cls, metric):
@@ -75,7 +98,41 @@ class RiemannCurvatureTensor(Tensor):
         
         """
         ch = ChristoffelSymbols.from_metric(metric)
-        return cls.from_christoffels(ch)
+        return cls.from_christoffels(ch, parent_metric=None)
+
+    def change_config(self, newconfig="llll", metric=None):
+        """
+        Changes the index configuration(contravariant/covariant)
+
+        Parameters
+        ----------
+        newconfig : str
+            Specify the new configuration. Defaults to 'llll'
+        metric : ~einsteinpy.symbolic.metric.MetricTensor or None
+            Parent metric tensor for changing indices.
+            Already assumes the value of the metric tensor from which it was initialized if passed with None. 
+            Compulsory if not initialized with 'from_metric'. Defaults to None.
+
+        Returns
+        -------
+        ~einsteinpy.symbolic.christoffel.ChristoffelSymbols
+            New tensor with new configuration. Defaults to 'llll'
+
+        Raises
+        ------
+        Exception
+            Raised when a parent metric could not be found.
+
+        """
+        if metric is None:
+            metric = self._parent_metric
+        if metric is None:
+            raise Exception("Parent Metric not found, can't do configuration change")
+        new_tensor = _change_config(self, metric, newconfig)
+        new_obj = RiemannCurvatureTensor(
+            new_tensor, self.syms, config=newconfig, parent_metric=metric
+        )
+        return new_obj
 
     def symbols(self):
         """
diff --git a/src/einsteinpy/symbolic/tensor.py b/src/einsteinpy/symbolic/tensor.py
index 1b57f62..4d4f493 100644
--- a/src/einsteinpy/symbolic/tensor.py
+++ b/src/einsteinpy/symbolic/tensor.py
@@ -1,13 +1,74 @@
 import numpy as np
 import sympy
+from sympy import simplify, tensorcontraction, tensorproduct
+
+
+def _config_checker(config):
+    # check if the string for config contains 'u' and 'l' only
+    if not isinstance(config, str):
+        return False
+    for ch in config:
+        if (not ch == "l") and (not ch == "u"):
+            return False
+    return True
+
+
+def _difference_list(newconfig, oldconfig):
+    # defines a list of actions to be taken on a tensor
+    difflist = list()
+    for n_ch, o_ch in zip(newconfig, oldconfig):
+        if n_ch == o_ch:
+            difflist.append(0)
+        elif n_ch == "u":
+            difflist.append(1)
+        else:
+            difflist.append(-1)
+    return difflist
+
+
+def _change_config(tensor, metric, newconfig):
+    # check length and validity of new configuration
+    if not (len(newconfig) == len(tensor.config) and _config_checker(newconfig)):
+        raise ValueError
+
+    # seperate the contravariant & covariant metric tensors
+    if metric.config == "ll":
+        met_dict = {-1: metric.tensor(), 1: metric.inv().tensor()}
+    else:
+        met_dict = {-1: metric.inv().tensor(), 1: metric.tensor()}
+
+    # main code
+    def chain_config_change():
+        t = sympy.Array(tensor.tensor())
+        difflist = _difference_list(newconfig, tensor.config)
+        for i, action in enumerate(difflist):
+            if action == 0:
+                continue
+            else:
+                t = simplify(
+                    tensorcontraction(tensorproduct(met_dict[action], t), (1, 2 + i))
+                )
+                # reshuffle the indices
+                tmp = np.array(t).reshape(t.shape)
+                source, dest = (
+                    [p for p in range(len(t.shape))],
+                    [p for p in range(len(t.shape))],
+                )
+                dest.pop(i)
+                dest.insert(0, i)
+                tmp = np.moveaxis(tmp, source, dest)
+                t = sympy.Array(tmp)
+        return t
+
+    return chain_config_change()
 
 
 class Tensor:
     """
-    Base Class
+    Base Class for Tensor manipulation
     """
 
-    def __init__(self, arr):
+    def __init__(self, arr, config="ll"):
         """
         Constructor and Initializer
         
@@ -15,11 +76,15 @@ class Tensor:
         ----------
         arr : ~sympy.tensor.array.dense_ndim_array.ImmutableDenseNDimArray or list
             Sympy Array or multi-dimensional list containing Sympy Expressions
+        config : str
+            Configuration of contravariant and covariant indices in tensor. 'u' for upper and 'l' for lower indices. Defaults to 'll'.
 
         Raises
         ------
         TypeError
             Raised when arr is not a list or sympy array
+        TypeError
+            Raised when config is not of type str or contains characters other than 'l' or 'u'
         
 
         """
@@ -29,6 +94,29 @@ class Tensor:
             self.arr = arr
         else:
             raise TypeError("Only multi-dimensional list or Sympy Array is expected")
+        if _config_checker(config):
+            self._config = config
+            self._order = len(config)
+        else:
+            raise TypeError(
+                "config is either not of type 'str' or does contain characters other than 'l' or 'u'"
+            )
+
+    @property
+    def order(self):
+        """
+        Returns the order of the Tensor
+
+        """
+        return self._order
+
+    @property
+    def config(self):
+        """
+        Returns the configuration of covariant and contravariant indices
+
+        """
+        return self._config
 
     def __getitem__(self, index):
         return self.arr[index]


Test patch:
diff --git a/src/einsteinpy/tests/test_symbolic/test_christoffel.py b/src/einsteinpy/tests/test_symbolic/test_christoffel.py
index a4910dd..fd9018d 100644
--- a/src/einsteinpy/tests/test_symbolic/test_christoffel.py
+++ b/src/einsteinpy/tests/test_symbolic/test_christoffel.py
@@ -50,3 +50,51 @@ def test_TypeError():
         assert False
     except TypeError:
         assert True
+
+
+def test_change_config():
+    x, y, z = sympy.symbols("x y z")
+
+    list3d = np.zeros((3, 3, 3), dtype=int).tolist()
+    for i in range(3):
+        list3d[i][i][i] = (x ** i) * (y * (2 - i)) + i * z
+    list3d[1][2][0] = list3d[1][0][2] = x * y * z
+    list3d[2][1][0] = list3d[2][0][1] = 4 * y
+
+    metriclist = np.identity(3).tolist()
+    metric = MetricTensor(metriclist, (x, y, z), "uu")
+    ch = ChristoffelSymbols(list3d, (x, y, z), "ull", parent_metric=metric)
+    chr_new = ch.change_config("llu")
+
+    for t in range(3):
+        i, j, k = t % 3, (int(t / 3)) % 3, (int(t / (3 ** 2))) % 3
+        assert sympy.simplify(ch[i, j, k] - chr_new[i, j, k]) == 0
+
+
+def test_wrong_number_of_indices_ValueError():
+    x, y, z = sympy.symbols("x y z")
+
+    list3d = np.zeros((3, 3, 3), dtype=int).tolist()
+    for i in range(3):
+        list3d[i][i][i] = (x ** i) * (y * (2 - i)) + i * z
+    list3d[1][2][0] = list3d[1][0][2] = x * y * z
+    list3d[2][1][0] = list3d[2][0][1] = 4 * y
+
+    try:
+        ch = ChristoffelSymbols(list3d, (x, y, z), "ulll")
+        assert False
+    except ValueError:
+        assert True
+
+
+def test_properties():
+    sch_inv = schwarzschild_metric()
+    ch = ChristoffelSymbols.from_metric(sch_inv)
+    assert ch.parent_metric == ch._parent_metric
+    # test change_config, should raise ValueError
+    ch._parent_metric = None
+    try:
+        ch_new = ch.change_config("lll")
+        assert False
+    except Exception:
+        return True
diff --git a/src/einsteinpy/tests/test_symbolic/test_metric.py b/src/einsteinpy/tests/test_symbolic/test_metric.py
index ca77dd4..ca8718d 100644
--- a/src/einsteinpy/tests/test_symbolic/test_metric.py
+++ b/src/einsteinpy/tests/test_symbolic/test_metric.py
@@ -35,3 +35,43 @@ def test_TypeError():
         assert False
     except TypeError:
         assert True
+
+
+def test_properties():
+    sch = schwarzschild_metric()
+    assert sch.config == "ll"
+    assert sch.order == 2
+
+
+def test_inv():
+    sch = schwarzschild_metric()
+    sch_inv = sch.inv()
+    assert sch == sch_inv.inv()
+    assert sch_inv == sch.inv()
+    for i in range(4):
+        # this is because schwarzschild metric is diagonal
+        assert sympy.simplify(sch[i, i] * sch_inv[i, i]) == 1
+
+
+def test_change_config_ValueError():
+    sch = schwarzschild_metric()
+    try:
+        sch_new = sch.change_config("ul")
+        assert False
+    except ValueError:
+        assert True
+
+
+def test_check_ValueError_on_incorrect_config_length():
+    sch = schwarzschild_metric()
+    try:
+        sch_new = MetricTensor(sch.tensor(), sch.syms, config="lll")
+        assert False
+    except ValueError:
+        assert True
+
+
+def test_use_original_config_in_change_config():
+    sch = schwarzschild_metric()
+    sch_new = sch.change_config("ll")
+    assert sch == sch_new
diff --git a/src/einsteinpy/tests/test_symbolic/test_riemann.py b/src/einsteinpy/tests/test_symbolic/test_riemann.py
index 0e36b40..3440e11 100644
--- a/src/einsteinpy/tests/test_symbolic/test_riemann.py
+++ b/src/einsteinpy/tests/test_symbolic/test_riemann.py
@@ -1,7 +1,23 @@
 import numpy as np
 import sympy
 
-from einsteinpy.symbolic import MetricTensor, RiemannCurvatureTensor
+from einsteinpy.symbolic import ChristoffelSymbols, MetricTensor, RiemannCurvatureTensor
+
+
+def schwarzschild_metric():
+    symbolstr = "t r theta phi"
+    syms = sympy.symbols(symbolstr)
+    G, M, c, a = sympy.symbols("G M c a")
+    # using metric values of schwarschild space-time
+    # a is schwarzschild radius
+    list2d = np.zeros((4, 4), dtype=int).tolist()
+    list2d[0][0] = 1 - (a / syms[1])
+    list2d[1][1] = -1 / ((1 - (a / syms[1])) * (c ** 2))
+    list2d[2][2] = -1 * (syms[1] ** 2) / (c ** 2)
+    list2d[3][3] = -1 * (syms[1] ** 2) * (sympy.sin(syms[2]) ** 2) / (c ** 2)
+    sch = MetricTensor(list2d, syms)
+    # print (sch.tensor())
+    return sch
 
 
 def spherical_metric():
@@ -36,3 +52,32 @@ def test_TypeError():
         assert False
     except TypeError:
         assert True
+
+
+def test_circular_index_config_same():
+    sch = schwarzschild_metric()
+    rm0 = RiemannCurvatureTensor.from_metric(sch)
+    rm1 = rm0.change_config("lulu")
+    rm2 = rm1.change_config("uuuu")
+    rm3 = rm2.change_config("ulll")
+    dims = sch.dims
+    for i in range(dims ** 4):
+        # t,s,r,n each goes from 0 to (dims-1)
+        # hack for codeclimate. Could be done with 4 nested for loops
+        n = i % dims
+        r = (int(i / dims)) % (dims)
+        s = (int(i / (dims ** 2))) % (dims)
+        t = (int(i / (dims ** 3))) % (dims)
+        assert sympy.simplify(rm3[n, r, s, t] - rm0[n, r, s, t]) == 0
+    assert rm0.parent_metric == rm0._parent_metric
+
+
+def test_no_exception_raised_passing_christoffel_with_unconventional_indices():
+    sch = schwarzschild_metric()
+    ch = ChristoffelSymbols.from_metric(sch)
+    ch2 = ch.change_config("uuu")
+    try:
+        rm = RiemannCurvatureTensor.from_christoffels(ch2)
+        assert True
+    except:
+        assert False
diff --git a/src/einsteinpy/tests/test_symbolic/test_tensor.py b/src/einsteinpy/tests/test_symbolic/test_tensor.py
index 8d19c0f..3aa406d 100644
--- a/src/einsteinpy/tests/test_symbolic/test_tensor.py
+++ b/src/einsteinpy/tests/test_symbolic/test_tensor.py
@@ -40,7 +40,7 @@ def test_Tensor_getitem():
         assert obj[p, q, r] - test_list[p][q][r] == 0
 
 
-def test_TypeError():
+def test_TypeError1():
     arr = 0
     try:
         obj = Tensor(arr)
@@ -49,6 +49,26 @@ def test_TypeError():
         assert True
 
 
+def test_TypeError2():
+    scht = schwarzschild_tensor().tensor()
+    # pass non str object
+    try:
+        obj = Tensor(scht, config=0)
+        assert False
+    except TypeError:
+        assert True
+
+
+def test_TypeError3():
+    scht = schwarzschild_tensor().tensor()
+    # pass string containing elements other than 'l' or 'u'
+    try:
+        obj = Tensor(scht, config="al")
+        assert False
+    except TypeError:
+        assert True
+
+
 def test_subs_single():
     # replacing only schwarzschild radius(a) with 0
     T = schwarzschild_tensor()
@@ -66,3 +86,9 @@ def test_subs_multiple():
     test_arr = T.subs([(a, 0), (c, 1)])
     assert simplify(test_arr.arr[0, 0] - 1) == 0
     assert simplify(test_arr.arr[1, 1] - (-1)) == 0
+
+
+def test_check_properties():
+    T = schwarzschild_tensor()
+    assert T.order == T._order
+    assert T.config == T._config