We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
math term missed in dimenet_utils.associated_legendre_polynomials
### 🛠 Proposed Refactor

In order to get the function of 'spherical harmonics' basis used in DimeNet, we need to calc 'Associated Legendre Polynomial' in math. But I just found a term missed in torch_geometric.nn.models.dimenet_utils.associated_legendre_polynomials(). 

The author of DimeNet use `zero_m_only=True` by default, so there will be no error when running the code by default. 

But just a warning for those who also read or use this code, the author of the code (version of pyg: 2.3.1) missed a term when calculating $P_l^l$ which make all results except $P_l^0$ wrong.  [original code here](https://github.com/pyg-team/pytorch_geometric/blob/f71ead8ade8a67be23982114cfff649b7d074cfb/torch_geometric/nn/models/dimenet_utils.py#L86)

Take the result of $P_1^1$ as an example:

original code will output -1, but according to eq.14 at https://mathworld.wolfram.com/AssociatedLegendrePolynomial.html, the ground truth result is $-(1-x^2)^{0.5}$. 

### Suggest a potential alternative/fix

Beyond adding the missed term, I also add some comment to help understanding.
```python
def associated_legendre_polynomials(k, zero_m_only=True):
    '''
    helper function to calc Y_l^m
    '''
    z = sym.symbols('z')
    P_l_m = [[0] * (j + 1) for j in range(k)]

    P_l_m[0][0] = 1
    if k > 0:
        P_l_m[1][0] = z

        for j in range(2, k):
            P_l_m[j][0] = sym.simplify(((2 * j - 1) * z * P_l_m[j - 1][0] -
                                        (j - 1) * P_l_m[j - 2][0]) / j) # use the property of eq.7: https://mathworld.wolfram.com/AssociatedLegendrePolynomial.html
        if not zero_m_only:
            for i in range(1, k):
                P_l_m[i][i] = sym.simplify((1 - 2 * i) * P_l_m[i - 1][i - 1]*(1-z**2)**0.5) # add missed term (*(1-z**2)**0.5) here
                if i + 1 < k:
                    P_l_m[i + 1][i] = sym.simplify(
                        (2 * i + 1) * z * P_l_m[i][i]) # use the property of eq.11: https://mathworld.wolfram.com/AssociatedLegendrePolynomial.html
                for j in range(i + 2, k):
                    P_l_m[j][i] = sym.simplify(
                        ((2 * j - 1) * z * P_l_m[j - 1][i] -
                         (i + j - 1) * P_l_m[j - 2][i]) / (j - i)) # use the property of eq.7: https://mathworld.wolfram.com/AssociatedLegendrePolynomial.html

    return P_l_m
```
After fixing this tiny bug, all the results are the right

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `torch_geometric/nn/models/dimenet_utils.py`
Content:
```
1 # Shameless steal from: https://github.com/klicperajo/dimenet
2 
3 import numpy as np
4 from scipy import special as sp
5 from scipy.optimize import brentq
6 
7 try:
8     import sympy as sym
9 except ImportError:
10     sym = None
11 
12 
13 def Jn(r, n):
14     return np.sqrt(np.pi / (2 * r)) * sp.jv(n + 0.5, r)
15 
16 
17 def Jn_zeros(n, k):
18     zerosj = np.zeros((n, k), dtype='float32')
19     zerosj[0] = np.arange(1, k + 1) * np.pi
20     points = np.arange(1, k + n) * np.pi
21     racines = np.zeros(k + n - 1, dtype='float32')
22     for i in range(1, n):
23         for j in range(k + n - 1 - i):
24             foo = brentq(Jn, points[j], points[j + 1], (i, ))
25             racines[j] = foo
26         points = racines
27         zerosj[i][:k] = racines[:k]
28 
29     return zerosj
30 
31 
32 def spherical_bessel_formulas(n):
33     x = sym.symbols('x')
34 
35     f = [sym.sin(x) / x]
36     a = sym.sin(x) / x
37     for i in range(1, n):
38         b = sym.diff(a, x) / x
39         f += [sym.simplify(b * (-x)**i)]
40         a = sym.simplify(b)
41     return f
42 
43 
44 def bessel_basis(n, k):
45     zeros = Jn_zeros(n, k)
46     normalizer = []
47     for order in range(n):
48         normalizer_tmp = []
49         for i in range(k):
50             normalizer_tmp += [0.5 * Jn(zeros[order, i], order + 1)**2]
51         normalizer_tmp = 1 / np.array(normalizer_tmp)**0.5
52         normalizer += [normalizer_tmp]
53 
54     f = spherical_bessel_formulas(n)
55     x = sym.symbols('x')
56     bess_basis = []
57     for order in range(n):
58         bess_basis_tmp = []
59         for i in range(k):
60             bess_basis_tmp += [
61                 sym.simplify(normalizer[order][i] *
62                              f[order].subs(x, zeros[order, i] * x))
63             ]
64         bess_basis += [bess_basis_tmp]
65     return bess_basis
66 
67 
68 def sph_harm_prefactor(k, m):
69     return ((2 * k + 1) * np.math.factorial(k - abs(m)) /
70             (4 * np.pi * np.math.factorial(k + abs(m))))**0.5
71 
72 
73 def associated_legendre_polynomials(k, zero_m_only=True):
74     z = sym.symbols('z')
75     P_l_m = [[0] * (j + 1) for j in range(k)]
76 
77     P_l_m[0][0] = 1
78     if k > 0:
79         P_l_m[1][0] = z
80 
81         for j in range(2, k):
82             P_l_m[j][0] = sym.simplify(((2 * j - 1) * z * P_l_m[j - 1][0] -
83                                         (j - 1) * P_l_m[j - 2][0]) / j)
84         if not zero_m_only:
85             for i in range(1, k):
86                 P_l_m[i][i] = sym.simplify((1 - 2 * i) * P_l_m[i - 1][i - 1])
87                 if i + 1 < k:
88                     P_l_m[i + 1][i] = sym.simplify(
89                         (2 * i + 1) * z * P_l_m[i][i])
90                 for j in range(i + 2, k):
91                     P_l_m[j][i] = sym.simplify(
92                         ((2 * j - 1) * z * P_l_m[j - 1][i] -
93                          (i + j - 1) * P_l_m[j - 2][i]) / (j - i))
94 
95     return P_l_m
96 
97 
98 def real_sph_harm(k, zero_m_only=True, spherical_coordinates=True):
99     if not zero_m_only:
100         S_m = [0]
101         C_m = [1]
102         for i in range(1, k):
103             x = sym.symbols('x')
104             y = sym.symbols('y')
105             S_m += [x * S_m[i - 1] + y * C_m[i - 1]]
106             C_m += [x * C_m[i - 1] - y * S_m[i - 1]]
107 
108     P_l_m = associated_legendre_polynomials(k, zero_m_only)
109     if spherical_coordinates:
110         theta = sym.symbols('theta')
111         z = sym.symbols('z')
112         for i in range(len(P_l_m)):
113             for j in range(len(P_l_m[i])):
114                 if not isinstance(P_l_m[i][j], int):
115                     P_l_m[i][j] = P_l_m[i][j].subs(z, sym.cos(theta))
116         if not zero_m_only:
117             phi = sym.symbols('phi')
118             for i in range(len(S_m)):
119                 S_m[i] = S_m[i].subs(x,
120                                      sym.sin(theta) * sym.cos(phi)).subs(
121                                          y,
122                                          sym.sin(theta) * sym.sin(phi))
123             for i in range(len(C_m)):
124                 C_m[i] = C_m[i].subs(x,
125                                      sym.sin(theta) * sym.cos(phi)).subs(
126                                          y,
127                                          sym.sin(theta) * sym.sin(phi))
128 
129     Y_func_l_m = [['0'] * (2 * j + 1) for j in range(k)]
130     for i in range(k):
131         Y_func_l_m[i][0] = sym.simplify(sph_harm_prefactor(i, 0) * P_l_m[i][0])
132 
133     if not zero_m_only:
134         for i in range(1, k):
135             for j in range(1, i + 1):
136                 Y_func_l_m[i][j] = sym.simplify(
137                     2**0.5 * sph_harm_prefactor(i, j) * C_m[j] * P_l_m[i][j])
138         for i in range(1, k):
139             for j in range(1, i + 1):
140                 Y_func_l_m[i][-j] = sym.simplify(
141                     2**0.5 * sph_harm_prefactor(i, -j) * S_m[j] * P_l_m[i][j])
142 
143     return Y_func_l_m
144
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/torch_geometric/nn/models/dimenet_utils.py b/torch_geometric/nn/models/dimenet_utils.py
--- a/torch_geometric/nn/models/dimenet_utils.py
+++ b/torch_geometric/nn/models/dimenet_utils.py
@@ -71,6 +71,7 @@
 
 
 def associated_legendre_polynomials(k, zero_m_only=True):
+    r"""Helper function to calculate Y_l^m."""
     z = sym.symbols('z')
     P_l_m = [[0] * (j + 1) for j in range(k)]
 
@@ -79,15 +80,22 @@
         P_l_m[1][0] = z
 
         for j in range(2, k):
+            # Use the property of Eq (7) in
+            # https://mathworld.wolfram.com/AssociatedLegendrePolynomial.html:
             P_l_m[j][0] = sym.simplify(((2 * j - 1) * z * P_l_m[j - 1][0] -
                                         (j - 1) * P_l_m[j - 2][0]) / j)
         if not zero_m_only:
             for i in range(1, k):
-                P_l_m[i][i] = sym.simplify((1 - 2 * i) * P_l_m[i - 1][i - 1])
+                P_l_m[i][i] = sym.simplify(
+                    (1 - 2 * i) * P_l_m[i - 1][i - 1] * (1 - z**2)**0.5)
                 if i + 1 < k:
+                    # Use the property of Eq (11) in
+                    # https://mathworld.wolfram.com/AssociatedLegendrePolynomial.html:
                     P_l_m[i + 1][i] = sym.simplify(
                         (2 * i + 1) * z * P_l_m[i][i])
                 for j in range(i + 2, k):
+                    # Use the property of Eq (7) in
+                    # https://mathworld.wolfram.com/AssociatedLegendrePolynomial.html:
                     P_l_m[j][i] = sym.simplify(
                         ((2 * j - 1) * z * P_l_m[j - 1][i] -
                          (i + j - 1) * P_l_m[j - 2][i]) / (j - i))

{"golden_diff": "diff --git a/torch_geometric/nn/models/dimenet_utils.py b/torch_geometric/nn/models/dimenet_utils.py\n--- a/torch_geometric/nn/models/dimenet_utils.py\n+++ b/torch_geometric/nn/models/dimenet_utils.py\n@@ -71,6 +71,7 @@\n \n \n def associated_legendre_polynomials(k, zero_m_only=True):\n+    r\"\"\"Helper function to calculate Y_l^m.\"\"\"\n     z = sym.symbols('z')\n     P_l_m = [[0] * (j + 1) for j in range(k)]\n \n@@ -79,15 +80,22 @@\n         P_l_m[1][0] = z\n \n         for j in range(2, k):\n+            # Use the property of Eq (7) in\n+            # https://mathworld.wolfram.com/AssociatedLegendrePolynomial.html:\n             P_l_m[j][0] = sym.simplify(((2 * j - 1) * z * P_l_m[j - 1][0] -\n                                         (j - 1) * P_l_m[j - 2][0]) / j)\n         if not zero_m_only:\n             for i in range(1, k):\n-                P_l_m[i][i] = sym.simplify((1 - 2 * i) * P_l_m[i - 1][i - 1])\n+                P_l_m[i][i] = sym.simplify(\n+                    (1 - 2 * i) * P_l_m[i - 1][i - 1] * (1 - z**2)**0.5)\n                 if i + 1 < k:\n+                    # Use the property of Eq (11) in\n+                    # https://mathworld.wolfram.com/AssociatedLegendrePolynomial.html:\n                     P_l_m[i + 1][i] = sym.simplify(\n                         (2 * i + 1) * z * P_l_m[i][i])\n                 for j in range(i + 2, k):\n+                    # Use the property of Eq (7) in\n+                    # https://mathworld.wolfram.com/AssociatedLegendrePolynomial.html:\n                     P_l_m[j][i] = sym.simplify(\n                         ((2 * j - 1) * z * P_l_m[j - 1][i] -\n                          (i + j - 1) * P_l_m[j - 2][i]) / (j - i))\n", "issue": "math term missed in dimenet_utils.associated_legendre_polynomials\n### \ud83d\udee0 Proposed Refactor\n\nIn order to get the function of 'spherical harmonics' basis used in DimeNet, we need to calc 'Associated Legendre Polynomial' in math. But I just found a term missed in torch_geometric.nn.models.dimenet_utils.associated_legendre_polynomials(). \r\n\r\nThe author of DimeNet use `zero_m_only=True` by default, so there will be no error when running the code by default. \r\n\r\nBut just a warning for those who also read or use this code, the author of the code (version of pyg: 2.3.1) missed a term when calculating $P_l^l$ which make all results except $P_l^0$ wrong.  [original code here](https://github.com/pyg-team/pytorch_geometric/blob/f71ead8ade8a67be23982114cfff649b7d074cfb/torch_geometric/nn/models/dimenet_utils.py#L86)\r\n\r\nTake the result of $P_1^1$ as an example:\r\n\r\noriginal code will output -1, but according to eq.14 at https://mathworld.wolfram.com/AssociatedLegendrePolynomial.html, the ground truth result is $-(1-x^2)^{0.5}$. \n\n### Suggest a potential alternative/fix\n\nBeyond adding the missed term, I also add some comment to help understanding.\r\n```python\r\ndef associated_legendre_polynomials(k, zero_m_only=True):\r\n    '''\r\n    helper function to calc Y_l^m\r\n    '''\r\n    z = sym.symbols('z')\r\n    P_l_m = [[0] * (j + 1) for j in range(k)]\r\n\r\n    P_l_m[0][0] = 1\r\n    if k > 0:\r\n        P_l_m[1][0] = z\r\n\r\n        for j in range(2, k):\r\n            P_l_m[j][0] = sym.simplify(((2 * j - 1) * z * P_l_m[j - 1][0] -\r\n                                        (j - 1) * P_l_m[j - 2][0]) / j) # use the property of eq.7: https://mathworld.wolfram.com/AssociatedLegendrePolynomial.html\r\n        if not zero_m_only:\r\n            for i in range(1, k):\r\n                P_l_m[i][i] = sym.simplify((1 - 2 * i) * P_l_m[i - 1][i - 1]*(1-z**2)**0.5) # add missed term (*(1-z**2)**0.5) here\r\n                if i + 1 < k:\r\n                    P_l_m[i + 1][i] = sym.simplify(\r\n                        (2 * i + 1) * z * P_l_m[i][i]) # use the property of eq.11: https://mathworld.wolfram.com/AssociatedLegendrePolynomial.html\r\n                for j in range(i + 2, k):\r\n                    P_l_m[j][i] = sym.simplify(\r\n                        ((2 * j - 1) * z * P_l_m[j - 1][i] -\r\n                         (i + j - 1) * P_l_m[j - 2][i]) / (j - i)) # use the property of eq.7: https://mathworld.wolfram.com/AssociatedLegendrePolynomial.html\r\n\r\n    return P_l_m\r\n```\r\nAfter fixing this tiny bug, all the results are the right\n", "before_files": [{"content": "# Shameless steal from: https://github.com/klicperajo/dimenet\n\nimport numpy as np\nfrom scipy import special as sp\nfrom scipy.optimize import brentq\n\ntry:\n    import sympy as sym\nexcept ImportError:\n    sym = None\n\n\ndef Jn(r, n):\n    return np.sqrt(np.pi / (2 * r)) * sp.jv(n + 0.5, r)\n\n\ndef Jn_zeros(n, k):\n    zerosj = np.zeros((n, k), dtype='float32')\n    zerosj[0] = np.arange(1, k + 1) * np.pi\n    points = np.arange(1, k + n) * np.pi\n    racines = np.zeros(k + n - 1, dtype='float32')\n    for i in range(1, n):\n        for j in range(k + n - 1 - i):\n            foo = brentq(Jn, points[j], points[j + 1], (i, ))\n            racines[j] = foo\n        points = racines\n        zerosj[i][:k] = racines[:k]\n\n    return zerosj\n\n\ndef spherical_bessel_formulas(n):\n    x = sym.symbols('x')\n\n    f = [sym.sin(x) / x]\n    a = sym.sin(x) / x\n    for i in range(1, n):\n        b = sym.diff(a, x) / x\n        f += [sym.simplify(b * (-x)**i)]\n        a = sym.simplify(b)\n    return f\n\n\ndef bessel_basis(n, k):\n    zeros = Jn_zeros(n, k)\n    normalizer = []\n    for order in range(n):\n        normalizer_tmp = []\n        for i in range(k):\n            normalizer_tmp += [0.5 * Jn(zeros[order, i], order + 1)**2]\n        normalizer_tmp = 1 / np.array(normalizer_tmp)**0.5\n        normalizer += [normalizer_tmp]\n\n    f = spherical_bessel_formulas(n)\n    x = sym.symbols('x')\n    bess_basis = []\n    for order in range(n):\n        bess_basis_tmp = []\n        for i in range(k):\n            bess_basis_tmp += [\n                sym.simplify(normalizer[order][i] *\n                             f[order].subs(x, zeros[order, i] * x))\n            ]\n        bess_basis += [bess_basis_tmp]\n    return bess_basis\n\n\ndef sph_harm_prefactor(k, m):\n    return ((2 * k + 1) * np.math.factorial(k - abs(m)) /\n            (4 * np.pi * np.math.factorial(k + abs(m))))**0.5\n\n\ndef associated_legendre_polynomials(k, zero_m_only=True):\n    z = sym.symbols('z')\n    P_l_m = [[0] * (j + 1) for j in range(k)]\n\n    P_l_m[0][0] = 1\n    if k > 0:\n        P_l_m[1][0] = z\n\n        for j in range(2, k):\n            P_l_m[j][0] = sym.simplify(((2 * j - 1) * z * P_l_m[j - 1][0] -\n                                        (j - 1) * P_l_m[j - 2][0]) / j)\n        if not zero_m_only:\n            for i in range(1, k):\n                P_l_m[i][i] = sym.simplify((1 - 2 * i) * P_l_m[i - 1][i - 1])\n                if i + 1 < k:\n                    P_l_m[i + 1][i] = sym.simplify(\n                        (2 * i + 1) * z * P_l_m[i][i])\n                for j in range(i + 2, k):\n                    P_l_m[j][i] = sym.simplify(\n                        ((2 * j - 1) * z * P_l_m[j - 1][i] -\n                         (i + j - 1) * P_l_m[j - 2][i]) / (j - i))\n\n    return P_l_m\n\n\ndef real_sph_harm(k, zero_m_only=True, spherical_coordinates=True):\n    if not zero_m_only:\n        S_m = [0]\n        C_m = [1]\n        for i in range(1, k):\n            x = sym.symbols('x')\n            y = sym.symbols('y')\n            S_m += [x * S_m[i - 1] + y * C_m[i - 1]]\n            C_m += [x * C_m[i - 1] - y * S_m[i - 1]]\n\n    P_l_m = associated_legendre_polynomials(k, zero_m_only)\n    if spherical_coordinates:\n        theta = sym.symbols('theta')\n        z = sym.symbols('z')\n        for i in range(len(P_l_m)):\n            for j in range(len(P_l_m[i])):\n                if not isinstance(P_l_m[i][j], int):\n                    P_l_m[i][j] = P_l_m[i][j].subs(z, sym.cos(theta))\n        if not zero_m_only:\n            phi = sym.symbols('phi')\n            for i in range(len(S_m)):\n                S_m[i] = S_m[i].subs(x,\n                                     sym.sin(theta) * sym.cos(phi)).subs(\n                                         y,\n                                         sym.sin(theta) * sym.sin(phi))\n            for i in range(len(C_m)):\n                C_m[i] = C_m[i].subs(x,\n                                     sym.sin(theta) * sym.cos(phi)).subs(\n                                         y,\n                                         sym.sin(theta) * sym.sin(phi))\n\n    Y_func_l_m = [['0'] * (2 * j + 1) for j in range(k)]\n    for i in range(k):\n        Y_func_l_m[i][0] = sym.simplify(sph_harm_prefactor(i, 0) * P_l_m[i][0])\n\n    if not zero_m_only:\n        for i in range(1, k):\n            for j in range(1, i + 1):\n                Y_func_l_m[i][j] = sym.simplify(\n                    2**0.5 * sph_harm_prefactor(i, j) * C_m[j] * P_l_m[i][j])\n        for i in range(1, k):\n            for j in range(1, i + 1):\n                Y_func_l_m[i][-j] = sym.simplify(\n                    2**0.5 * sph_harm_prefactor(i, -j) * S_m[j] * P_l_m[i][j])\n\n    return Y_func_l_m\n", "path": "torch_geometric/nn/models/dimenet_utils.py"}], "after_files": [{"content": "# Shameless steal from: https://github.com/klicperajo/dimenet\n\nimport numpy as np\nfrom scipy import special as sp\nfrom scipy.optimize import brentq\n\ntry:\n    import sympy as sym\nexcept ImportError:\n    sym = None\n\n\ndef Jn(r, n):\n    return np.sqrt(np.pi / (2 * r)) * sp.jv(n + 0.5, r)\n\n\ndef Jn_zeros(n, k):\n    zerosj = np.zeros((n, k), dtype='float32')\n    zerosj[0] = np.arange(1, k + 1) * np.pi\n    points = np.arange(1, k + n) * np.pi\n    racines = np.zeros(k + n - 1, dtype='float32')\n    for i in range(1, n):\n        for j in range(k + n - 1 - i):\n            foo = brentq(Jn, points[j], points[j + 1], (i, ))\n            racines[j] = foo\n        points = racines\n        zerosj[i][:k] = racines[:k]\n\n    return zerosj\n\n\ndef spherical_bessel_formulas(n):\n    x = sym.symbols('x')\n\n    f = [sym.sin(x) / x]\n    a = sym.sin(x) / x\n    for i in range(1, n):\n        b = sym.diff(a, x) / x\n        f += [sym.simplify(b * (-x)**i)]\n        a = sym.simplify(b)\n    return f\n\n\ndef bessel_basis(n, k):\n    zeros = Jn_zeros(n, k)\n    normalizer = []\n    for order in range(n):\n        normalizer_tmp = []\n        for i in range(k):\n            normalizer_tmp += [0.5 * Jn(zeros[order, i], order + 1)**2]\n        normalizer_tmp = 1 / np.array(normalizer_tmp)**0.5\n        normalizer += [normalizer_tmp]\n\n    f = spherical_bessel_formulas(n)\n    x = sym.symbols('x')\n    bess_basis = []\n    for order in range(n):\n        bess_basis_tmp = []\n        for i in range(k):\n            bess_basis_tmp += [\n                sym.simplify(normalizer[order][i] *\n                             f[order].subs(x, zeros[order, i] * x))\n            ]\n        bess_basis += [bess_basis_tmp]\n    return bess_basis\n\n\ndef sph_harm_prefactor(k, m):\n    return ((2 * k + 1) * np.math.factorial(k - abs(m)) /\n            (4 * np.pi * np.math.factorial(k + abs(m))))**0.5\n\n\ndef associated_legendre_polynomials(k, zero_m_only=True):\n    r\"\"\"Helper function to calculate Y_l^m.\"\"\"\n    z = sym.symbols('z')\n    P_l_m = [[0] * (j + 1) for j in range(k)]\n\n    P_l_m[0][0] = 1\n    if k > 0:\n        P_l_m[1][0] = z\n\n        for j in range(2, k):\n            # Use the property of Eq (7) in\n            # https://mathworld.wolfram.com/AssociatedLegendrePolynomial.html:\n            P_l_m[j][0] = sym.simplify(((2 * j - 1) * z * P_l_m[j - 1][0] -\n                                        (j - 1) * P_l_m[j - 2][0]) / j)\n        if not zero_m_only:\n            for i in range(1, k):\n                P_l_m[i][i] = sym.simplify(\n                    (1 - 2 * i) * P_l_m[i - 1][i - 1] * (1 - z**2)**0.5)\n                if i + 1 < k:\n                    # Use the property of Eq (11) in\n                    # https://mathworld.wolfram.com/AssociatedLegendrePolynomial.html:\n                    P_l_m[i + 1][i] = sym.simplify(\n                        (2 * i + 1) * z * P_l_m[i][i])\n                for j in range(i + 2, k):\n                    # Use the property of Eq (7) in\n                    # https://mathworld.wolfram.com/AssociatedLegendrePolynomial.html:\n                    P_l_m[j][i] = sym.simplify(\n                        ((2 * j - 1) * z * P_l_m[j - 1][i] -\n                         (i + j - 1) * P_l_m[j - 2][i]) / (j - i))\n\n    return P_l_m\n\n\ndef real_sph_harm(k, zero_m_only=True, spherical_coordinates=True):\n    if not zero_m_only:\n        S_m = [0]\n        C_m = [1]\n        for i in range(1, k):\n            x = sym.symbols('x')\n            y = sym.symbols('y')\n            S_m += [x * S_m[i - 1] + y * C_m[i - 1]]\n            C_m += [x * C_m[i - 1] - y * S_m[i - 1]]\n\n    P_l_m = associated_legendre_polynomials(k, zero_m_only)\n    if spherical_coordinates:\n        theta = sym.symbols('theta')\n        z = sym.symbols('z')\n        for i in range(len(P_l_m)):\n            for j in range(len(P_l_m[i])):\n                if not isinstance(P_l_m[i][j], int):\n                    P_l_m[i][j] = P_l_m[i][j].subs(z, sym.cos(theta))\n        if not zero_m_only:\n            phi = sym.symbols('phi')\n            for i in range(len(S_m)):\n                S_m[i] = S_m[i].subs(x,\n                                     sym.sin(theta) * sym.cos(phi)).subs(\n                                         y,\n                                         sym.sin(theta) * sym.sin(phi))\n            for i in range(len(C_m)):\n                C_m[i] = C_m[i].subs(x,\n                                     sym.sin(theta) * sym.cos(phi)).subs(\n                                         y,\n                                         sym.sin(theta) * sym.sin(phi))\n\n    Y_func_l_m = [['0'] * (2 * j + 1) for j in range(k)]\n    for i in range(k):\n        Y_func_l_m[i][0] = sym.simplify(sph_harm_prefactor(i, 0) * P_l_m[i][0])\n\n    if not zero_m_only:\n        for i in range(1, k):\n            for j in range(1, i + 1):\n                Y_func_l_m[i][j] = sym.simplify(\n                    2**0.5 * sph_harm_prefactor(i, j) * C_m[j] * P_l_m[i][j])\n        for i in range(1, k):\n            for j in range(1, i + 1):\n                Y_func_l_m[i][-j] = sym.simplify(\n                    2**0.5 * sph_harm_prefactor(i, -j) * S_m[j] * P_l_m[i][j])\n\n    return Y_func_l_m\n", "path": "torch_geometric/nn/models/dimenet_utils.py"}]}