## 1D Particle in a Box 
<br>
All material within this notebook is based upon <i>Introduction to Computational Physical Chemistry</i>, by Joshua Schrier
<br><br>
Given a quantum mechanical particle in a box, such that the potential outside of the box is infinite, while the potential inside of the box is 0, the analytical solution to the Schrödinger equation is: <br>
<br>
$$ \psi_n(x) = \sqrt{\frac{2}{L}} \sin(\frac{nx\pi}{L})$$ <br>
<br>
The variables in the equation have the following meaning: <br>

$n$ specifies the quantum number of the system from 1 to infinity. <br>
$L$ represents the length of the box in Bohr Radius that the particle is in <br>
<br>
This $\psi_n$ represents the eigen values of the particle in the box. The energies of these eigenvalues are represented by: <br>
$$E_n = \frac{\hbar^2\pi^2n^2}{2mL^2}$$ <br>
<br>
$m$ refers to the mass of the particle in atomic units (a.u.) <br>
<br>
The probability of finding the particle at any particular location in the box is represented by $|\psi|^2$, meaning that the wave function is noramlized such that the probability of having to find the particle at <i>some</i> location within the box must be 1. This concept is matematically expressed as:
$$\int_0^L{|\psi_n|^2 dx} = 1$$ <br>
<br>
The wavefunctions $\psi_n$ are also orthogonal to one another, meaning that a set of $\psi_n$ will be orthonormal to each other.
$$\int_0^L{\psi_i^*(x)\psi_j(x)dx} = \delta_{ij}$$

## Dervivation of Particle in a 1D Box Solution

$$\hat{H}\psi = E\psi$$
The above is the Schrödinger equation with $\hat{H}$ being the Hamiltonian, $\psi$ representing the wavefunction of the system, and $E$ representing the energy of the system. <br>
$\hat{H} = U + K$, with $U$ being the potential energy of the system, and $K$ being the kinetic energy. <br>
<br>
To begin to solve the 1D particle in box, we will first determine a function to represent the potential energy of the sytem, $U$. To allow the particle to soley exist wihin the respect of a box that begins at $x=0$ and ends at $x=L$, it can be stated that the potential beyond the boundries $x=0$ and $x=L$ are infinite, preventing the particle from escaping the box, and nothing between the boundaries of the box, allowing the particle to freely exist anywhere within the box. <br>
$$U(x) = \begin{cases} \, \infty&  x \geq 0 \\
                        0 & 0 < x < L \\
                           \infty & x \leq L \end{cases}$$
<br>Now that the potential energy of the system is defined, the Kinetic Energy of the particle must also be defined, $K$. <br>
Kinetice energy is classically defined as $K = \frac{1}{2}mv^2$, with $v$ representing the velocity of the system. Noting the defintion of momentum $P = mv$ the following can be derived: 
$$\begin{align} P &= mv \\
                P^2 &= m^2v^2 \\
                \frac{P^2}{m} &= mv^2 = K \\
            \end{align}$$
$K$ is expresed in terms of $P$ as there is a quantum operator that can retrive the momentum of the particle from the wavefunction, $\hat{P}$. The operator is defined as follows: 
$$\hat{P}\psi = -i\hbar\frac{\partial}{\partial x}\psi$$
Writing $K$ using the definition of $\hat{P}$ yields the following: 
$$\begin{align} K &= \frac{1}{2} \frac{\hat{P}^2}{m} \\ 
                K &= \frac{1}{2} \frac{(-i\hbar\frac{\partial}{\partial x})^2}{m} \\
                K &= \frac{-\hbar^2\frac{\partial^2}{\partial x^2}}{2m}
    \end{align}
$$ 
Now we have the Hamiltonian for our system defined in terms of $U$ and $K$, and we can begin to solve the Schrödinger equation. 
$$\begin{align}\hat{H}\psi &= E\psi \\
               (P(x) - \frac{\hbar^2\frac{\partial^2}{\partial x^2}}{2m})\psi &= E \psi \\
               (-\frac{\hbar^2\frac{\partial^2}{\partial x^2}}{2m})\psi &= E\psi &&\mbox{Inside the box, } P(x) = 0
    \end{align}
$$
From the above, it can been seen that the 2nd partial derivative of our function with respect to $x$ must produce the same wavefunction once again with a difference in sign. In order to determine $\psi$, we can make and educated guess based upon its behaviour with derivaties. One example gueess would be:
$$A\cos(kx) + B\sin(kx)$$ 
Since the scend derivatives of the functions reproduce the original functions off by a sign change. The guess can now be tested with the boundry coefficents to determine the values of the constants $A$ and $k$. In the boundry conditions at $x=0$ and $x=L$, the particle wavefunction must decay to zero as the potential is infinitly high at these points. In other words:
$$\begin{align}
    \psi(0) &= 0 &\psi(L) &= 0 \\
    A\cos(0) + B\sin(0) &= 0 &A\cos(kL) + B\sin(kL) &= 0 \\
    A &= 0 &(0)\cos(kL) + B\sin(kL) &= 0 \\
    A&= 0  & B\sin(kL) &= 0 \\
    A &= 0 &\sin(kL) &= 0 \\
    A &= 0 &\sin(n\pi) &= 0 &&k=\frac{n\pi}{L}, \; n\in\mathbb{Z}
\end{align}$$
The values for $A$ and $k$ have been found, but in order to find the value of $B$, we must use the orthonormailty of the wavefunction as the particle must have a 100% chance of being somewhere within the box.
$$\begin{align}
    \int_0^L{|\psi^2| dx} &= 1 \\
    \int_0^L{A^2\sin^2(\frac{n\pi x}{L}) dx} &= 1 \\
    A^2\int_0^L{(\frac{1-\cos(\frac{2n\pi x}{L})}{2})dx} &= 1 &&\mbox{Use Trig. Identity}\\
    \frac{A^2}{2}\int_0^L{(1-\cos(\frac{2n\pi x}{L}))dx} &= 1 \\
    \frac{A^2}{2} \cdot ( x + \frac{\sin(\frac{2n\pi x}{L})}{\frac{2n\pi}{L}}) |^L_0 &= 1 \\
    \frac{A^2}{2} \cdot ( x + \frac{L\sin(\frac{2n\pi x}{L})}{2n\pi})|_0^L &= 1 \\
    \frac{A^2}{2} \cdot ( L + \frac{L\sin(2n\pi)}{2n\pi} - 0 - \frac{Lsin(0)}{2n\pi}) &= 1 \\
    \frac{A^2}{2} \cdot L &= 1 \\
    A^2 &= \frac{2}{L} \\
    A &= \sqrt{\frac{2}{L}}
\end{align}$$ <br>
Thus, our final wavefunction for the 1D particle in a box is:
$$\psi = \sqrt{\frac{2}{L}}\sin(\frac{n\pi x}{L})$$


```python
#import all needed packages here
import sys
sys.path.append("..\\Comp_Chem_Package")
import math
import color
import ipywidgets as widgets
from ipywidgets import interact, interactive_output
from scipy.integrate import quad as integrate
from pibUI import UI
from plotly.offline import iplot, init_notebook_mode
from plotly.subplots import make_subplots
init_notebook_mode(connected=True)
```







```python
#All Functions Defined Here

#Analytical Solution for 1D Particle in a Box
#x is the position of the particle in 1D space in Bohr Radius
#n is the quantum number from 1 to infinity
#L is the box length in Bohr Radius
def psi(x, n, L):
    return math.sqrt( 2 / L ) * math.sin(n * x * math.pi / L)

#------------------------------------------------------------------------

#Function to Compute the Energy of the specified eigenstate
#Note, due to use of atomic units, hbar disappears from the energy 
#equation since it is equal to 1
#n is the specified quantum number
#L is the box length in Bohr Radius
#m is the mass of the particle in box in A.U.
def E(n, L, m):
    return pow(math.pi * n / L, 2) / (2 * m)  

#------------------------------------------------------------------------

#Computes the Energy and Wavefunction data used for graphing
#qn is the list of quantum numbers use in the calculation
#L is the length of the box in Bohr Radius
#m is the mass of the particle in the box in A.U.
#points is the number of points that should be used to perform the computation 
#     The larger the number of points, the higher the resolution of the graph produced
def dataComputation(qn, L, points, m):
    
    #Calculate all computed variables here
    dx = L / points

    yData = [ [] for n in qn]
    prob = [ [] for n in qn ]
    xData = [x * dx for x in range(points)]
    expec = [ [] for n in qn]

    EData = [ [E(n, L, m)] * len(xData) for n in qn]

    #Perform Main Computation Here
    for nIndex, n in enumerate(qn):
        for x in xData: 
            yData[nIndex].append( psi(x, n, L) )
            prob[nIndex].append( psi(x, n, L) ** 2 )
            
            integrand = lambda r : (psi(r, n, L) ** 2) * r
            expec[nIndex].append( integrate( integrand, 0, x)[0])
            
    return xData, yData, EData, prob, expec

#------------------------------------------------------------------------

#Function used to graph the data
#xData is a list of x points that are to be graphed
#yData is a list of y points that are to be graphed
#EData is a list of energy values to graph
#prob is the y values for the probabiliity of finding the particle in any part of the box,
#expec is the expectation value for the position of the particle in the box
#qn is a list of quantum numbers to graph
def graph(xData, yData, EData, prob, expec, qn):
    
    figure = {
        "data": [], 
        "layout":{
            "xaxis":{"title":"Distance in Bohr Radius"},
            "yaxis":{"title": "Hartrees"},
            "title":{"text":"$\mbox{Wavefunctions: } \psi$"}
        }
    }

    figure2 = {
        "data":[],
        "layout":{
            "xaxis":{"title":"Distance in Bohr Radius"},
            "yaxis":{"title":"Psi Squared"},
            "title":{"text":"$\mbox{Wavefunction Probability: } \psi^2$"}
        }
    }
    
    figure3 = {
        "data":[],
        "layout":{
            "xaxis":{"title":"Distance in Bohr Radius"},
            "yaxis":{"title":"Distance in Bohr Radius"},
            "title":{"text":"$\mbox{Position Expectation Values: } \int_0^{L}{\psi^2 dx}$"}
        }
    }
    
    for nIndex, n in enumerate(qn):
        
        lineColor = color.getColor()        
        
        figure["data"].append(
            {
                "type":"scatter",
                "x":xData,
                "y":[y + EData[nIndex][index] for index, y in enumerate(yData[nIndex])],
                "name": "n=" + str(n) + " Psi",
                "connectgaps": True,
                "mode":"lines",
                "line":{"color":lineColor}
            }
        )
        
        figure["data"].append(
           { 
               "type":"scatter",
               "x":xData,
               "y":EData[nIndex],
               "name":"n=" + str(n) + " Energy",
               "connectgaps": True,   
               "mode":"lines",
               "line":{"dash":"dash", "color":lineColor}
           }
        )
        
        figure2["data"].append(
            {
                "type":"scatter",
                "x":xData,
                "y":prob[nIndex],
                "mode":"lines",
                "connectgaps":True,
                "name":"n=" + str(n),
                "line":{"color":lineColor}
            }
        )
        
        figure3["data"].append(
            {
                "type":"scatter",
                "x":xData,
                "y":expec[nIndex],
                "mode":"lines",
                "connectgaps":True,
                "name":"n="+str(n),
                "line":{"color":lineColor}
            }
        )
    
    iplot(figure)
    iplot(figure2)
    iplot(figure3)
    
#------------------------------------------------------------------------

#main function used to allow the program to run with a graphic interface
#qnInput is the list of quantum numbers directly inputted by the user
#L is the length of the box in Bohr Radius
#points is the number of points to use to compute the data for the graph 
#       The more points used in the computation , the greater the resolution of the graph
#m is the mass of the particle in A.U.
#graphBool is a boolean representing whether the data should be graphed or not
def main(graphBool=True, dimension=1):
    
    if(graphBool):
          
        qnInput = qnUI.value
        L = LUI.value
        points = pointsUI.value
        m = mUI.value
        
        #Reset the execute button's value and color
        executeButton.value = False
        
        qn = []

        #perform input checking on qn
        for n in qnInput.split(","):

            if(n.isspace() or n == ""):
                continue
            else:
                n.strip()
            try:
                qn.append(int(n))
            except:
                print("Warning! Only numbers sparated by commas are considered valid input for quantum" + "numbers!\n" + str(n) + " is not considered a valid quantum number.")
                return

        qn = list(set(qn))
        
        data = [qn, L, points, m, points]
        xData, yData, EData, prob, expec = dataComputation(qn, L, points, m)
        graph(xData, yData, EData, prob, expec, qn)
        
        #Print Oout Overlap Matrix Values in a nicely formatted manner
        mathString = "<font size='5'>Overlap Values:$\;\int_0^L{\psi_i\psi_j dr}$<br>" 
        
        for n in qn:
            mathString += "$\qquad\psi_{" + str(n) + "}$" 
        mathString += "<br>"
        for row in qn:
            mathString += "$\psi_{" + str(row) + "}\quad$"
            for col in qn:
                psiI = lambda x : psi(x, row, L) * psi(x, col, L)
                mathString += "$" + str(abs(round(integrate(psiI, 0, L)[0], 4))) + "\quad\;\;\;$" 
            mathString += "<br>"
            
        mathString += "</font>"

        #display the latex string to the user
        math = widgets.HTMLMath(
            value = mathString,
        )
        
        display(math)
```


```python
#Quantum Numer Input System
qnUI = widgets.Text(
    value = "1, 2, 3",
    description = "",  
)
qnLabel = widgets.Label("Quantum Number(s)")
qnLabel.layout.width = "35%"
#Box Length Input System in Bohr Radius
LUI = widgets.BoundedFloatText(
    value = 10,
    min = pow(10, -100),
    max = pow(10, 100)
)
LUILabel = widgets.Label("Box Length in Bohr Radius")
LUILabel.layout.width = "35%"

#Number of Points Input System, 
#The larger this number the greater the resolution of the graph will be
pointsUI = widgets.BoundedIntText(
    min = 0, 
    max = pow(10,100),
    value = 200
)
pointsLabel = widgets.Label("Number of Points")
pointsLabel.layout.width = "35%"

#Mass of the Particle in A.U.
mUI = widgets.BoundedIntText(
    min = 1,
    max = pow(10, 100),
    value = 1,
)
mLabel = widgets.Label("Mass of Particle in A.U.")
mLabel.layout.width = "35%"

#button to allow the user to graph the specified settings for the particle in a box
executeButton = widgets.ToggleButton(
    description = "Graph",
    disabled = False,
)
executeButton.layout.margin = "3% 0 0 30%"

#prepare layout for the input widgets
#then start the widgets to run
layout = widgets.VBox([widgets.HBox([qnLabel, qnUI]),
                       widgets.HBox([LUILabel, LUI]),
                       widgets.HBox([mLabel, mUI]),
                       widgets.HBox([pointsLabel, pointsUI]),
                       widgets.HBox([executeButton])
                      ])

ui = interactive_output(main, { "graphBool":executeButton} )
display( 
     layout, ui
 )
```


    VBox(children=(HBox(children=(Label(value='Quantum Number(s)', layout=Layout(width='35%')), Text(value='1, 2, …



    Output()


## 2D Particle in a Box
<br>
The 2D Particle in a box can be handled as the case of two 1D particles in a box, meaning that one 1D solution represents the x-axis while the other represents the y-axis. In more detail, the 2D eigenstates are the multiple of the respective 1D eigenstates, and the eigen values are the sum of the respective 1D eigen values. This can be represented as follows:
<br><br>
$$\begin{align}
    \psi_{2D}(x,y) &= \psi_{1D}(x, n_x)\psi_{1D}(y, n_y) \\
    \psi_{2D}(x,y) &= \left(\sqrt{\frac{2}{L_x}}\sin\left(\frac{n_x\pi x}{L_x}\right)\right)\left(\sqrt{\frac{2}{L_y}}\sin\left(\frac{n_y\pi y}{L_y}\right)\right)  \\
    \psi_{2D} &= \frac{2}{\sqrt{L_xL_y}}\sin\left(\frac{n_x\pi x}{L_x}\right)\sin\left(\frac{n_y\pi y}{L_y}\right)
\end{align}$$
<br><br>
$$\begin{align}
    E_{2D}(n_x, n_y) &= E_{1D}(n_x) + E_{1D}(n_y) \\
    E_{2D}(n) &= \frac{\hbar^2\pi^2n_x^2}{2mL_x^2} + \frac{\hbar^2\pi^2n_y^2}{2mL_y^2} \\
    E_{2D}(n) &= \frac{\hbar^2\pi^2}{2m}\left(\frac{n_x^2}{L_x}+\frac{n_y^2}{L_y}\right)
\end{align}$$
<br><br>
For the 2D particle in a box case, there are circumstances under where the energy of the system is equal for diffrent values of $n_x$ and $n_y$. States with the same energy value are said to be "degenerate." As the example, the state with $n_x=1,\; n_y=2$ and the state with $n_x=2,\; n_y=1$ are degenerate.


```python
#All functions defined here

#Computes the plotable data for the 2D Particle in a Box Simulation
def compute2DData():
    pass

#------------------------------------------------------------------------

```

790a74b675ff71bf6134435a4a069c2204e7779d
ipynb
Jupyter Notebook
Learning/Particle in a Box/Particle in a Box.ipynb
GaryZ700/CatLab_CompChem
4a3dee5a3778eb8b69b53b9d0e9ed6321cadedea
MIT
2021-11-13T12:21:52.000Z
2021-11-13T12:21:52.000Z
Learning/Particle in a Box/Particle in a Box.ipynb
GaryZ700/CatLab_CompChem
4a3dee5a3778eb8b69b53b9d0e9ed6321cadedea
MIT
Learning/Particle in a Box/Particle in a Box.ipynb
GaryZ700/CatLab_CompChem
4a3dee5a3778eb8b69b53b9d0e9ed6321cadedea
MIT
Qwen/Qwen-72B
1. YES
2. YES