Skip to main content

Someone wanted to learn this too, so Grasp built them a personal learning path.

You can keep exploring this one or create your own

Simulating Wavepacket Evolution with Crank-Nicolson

Hello! Welcome back to our module on numerical methods.

In our last lesson, you successfully implemented a finite difference solver for the time-independent Schrödinger equation. By turning the TISE into a matrix eigenvalue problem, you were able to find the stationary states and energy levels for any 1D potential, including the double-well. This gave us a static picture of the allowed quantum states.

Today, we move from the static to the dynamic. Our goal is to answer the question: if we start a quantum system in some initial state (that is not a stationary state), how does it evolve in time? To do this, we will tackle the full time-dependent Schrödinger equation (TDSE).

Your learning outcome for this lesson is to:

  • Implement the Crank-Nicolson method to simulate wavepacket evolution for the 1D time-dependent Schrödinger equation.

This powerful technique is a workhorse in computational physics for simulating quantum dynamics, making it an essential addition to your numerical toolkit, especially given your interest in modeling new systems.

1. The Challenge of Time Evolution

The evolution of a quantum state is governed by the 1D time-dependent Schrödinger equation:

where is the same Hamiltonian operator you discretized in the last lesson.

Our task is to step the wavefunction forward in time. A simple approach might be to use a forward difference for the time derivative (the "Forward Time, Centered Space" or FTCS method):

Rearranging this gives an explicit update rule:

While simple, this method has a major flaw: it's not unitary. The operator does not preserve the norm of the wavefunction, meaning the total probability will not be conserved. Over many time steps, this numerical error accumulates, leading to an unstable solution that can either vanish or blow up.

We need a more stable method. The Crank-Nicolson method solves this by being smarter about how it approximates the derivatives.

2. The Crank-Nicolson Scheme

The core idea of the Crank-Nicolson method is to be more balanced. Instead of evaluating the right-hand side (the term) only at the current time , it uses an average of the values at the current time and the next time step .

The time derivative is still approximated with a central difference, but it's centered at :

The Hamiltonian part is also evaluated at this midpoint by averaging:

The following article provides a clear derivation of the method from these starting points.

Crank–Nicolson Method for the Time-Dependent Schrödinger ...

The article 'Crank–Nicolson Method for the Time-Dependent Schrödinger...' provides an excellent and concise derivation of the method. It's a great starting point to see how the equations are formed.

Please read the introduction and the section 'The Crank–Nicolson Method', stopping before 'Explicit form of the linear system'. Focus on how the TDSE is rearranged into the final linear equation, A * psi_n+1 = B * psi_n.

As you saw in the reading, putting these approximations into the TDSE and rearranging terms to separate the unknown future state () from the known current state () gives the central equation:

This is an implicit method because the unknown appears on both sides of the original discretized equation. The final form is a linear system , where we must solve for at each step.

The key advantage here is that the operator that evolves the state, , is unitary. This guarantees that the norm of the wavefunction is conserved at each step, making the algorithm unconditionally stable.

This idea of averaging an explicit and implicit step is very general. The following video explains it in the context of the diffusion equation, which is mathematically analogous to the Schrödinger equation in imaginary time.

Crank-Nicolson Method for the Diffusion Equation | Lecture 72 | Numerical Methods for Engineers

This video from Jeffrey Chasnov's excellent numerical methods series explains the motivation for Crank-Nicolson as an average of simpler methods, leading to superior stability.

Watch from the beginning to 04:11. Notice the parallels between the discretization of the diffusion equation and the TDSE. The core idea is the averaging of the spatial derivative operator at times l and l+1.

The structure of the update rule can be visualized with a "stencil" that shows which grid points are connected by the equation.

Crank-Nicolson Method Stencil Diagram
This diagram shows the grid points involved in a single Crank-Nicolson update. The state at the future point \((j, n+1)\) depends on its spatial neighbors at the future time as well as the point and its neighbors at the current time \((j-1, n), (j, n), (j+1, n)\). This 'H' shape is characteristic of the implicit nature of the scheme.

3. Implementation: From Matrix Equation to Algorithm

We now have a matrix equation to solve at each time step: .

From the last lesson, you know that the discretized Hamiltonian is a tridiagonal matrix. Because the matrices and are defined as , they are also tridiagonal.

Our task is to solve this tridiagonal system. A direct inversion of matrix would be computationally expensive (). Fortunately, for tridiagonal systems, there is a much faster method called the Thomas Algorithm (or the Tridiagonal Matrix Algorithm, TDMA), which is a specialized form of Gaussian elimination with a cost of only .

The article you read earlier continues with a perfect explanation of how to construct the matrices and and how the Thomas Algorithm is used to solve the system.

Crank–Nicolson Method for the Time-Dependent Schrödinger ...

Let's return to the article 'Crank–Nicolson Method for the Time-Dependent Schrödinger...' to see how this is implemented.

Please read the sections 'Explicit form of the linear system' and 'Numerical Solution via the Thomas Algorithm'. Pay attention to: The explicit entries of the tridiagonal matrices A and B. The two-step process of the Thomas Algorithm: forward sweep (elimination) and backward substitution. The crucial efficiency gain: since A is constant for a time-independent potential, the forward sweep can be pre-computed before the time loop begins.

Now you have all the theoretical and algorithmic pieces. It's time to put them together in code.

4. A Python Implementation

Implementing the Crank-Nicolson method with the Thomas algorithm from scratch is a fantastic exercise. The following section of the matterwavex.com article provides a complete, well-commented Python script that does exactly this.

Crank–Nicolson Method for the Time-Dependent Schrödinger ...

This final reading from the same article provides the complete Python code to simulate a Gaussian wave packet tunneling through a potential barrier. This is the practical application of everything we've discussed.

Study the 'Python Code' section carefully. Trace the logic from the theory to the code: Parts 1-4: Setting up the physical system (constants, grids, initial wave packet, and potential). Part 5: This is the core of the algorithm. Identify where the diagonals of A and B are created. Note how the forward-sweep coefficients (c_prime) are pre-calculated. Then look at the thomas_solve function, which implements the rest of the algorithm. The main loop (in update function): See how at each step, the right-hand side d is constructed, thomas_solve is called to get the new psi, and the wavefunction is re-normalized.

The simulation in the article demonstrates a classic quantum phenomenon: a wavepacket impinging on a potential barrier that is higher than the particle's kinetic energy. You will see part of the wavepacket reflect and part of it tunnel through, a purely quantum effect.

The video below uses a slightly different numerical method (a simple explicit one) but provides an excellent visualization of what the wavepacket dynamics should look like. It also offers a great alternative way to check your results: by expanding the initial state in the energy eigenbasis (which you learned to find in the last lesson!).

Time-Dependent Schrodinger Equation in Python: Two Different Techniques

This video from Mr. P Solver, 'Time-Dependent Schrodinger Equation in Python', provides a fantastic visualization of wavepacket dynamics and compares a finite difference method to an eigenstate evolution method.

You can watch these sections to get a feel for the physics: Finite Difference (05:23 - 15:25): The method used here is simpler than Crank-Nicolson (it's an explicit FTCS scheme), but the general process of setting up the grid, potential, and time-stepping loop is very similar. Eigenstate Evolution (15:25 - 20:10): This is a completely different, semi-analytic method. It's a great reminder that if you know the eigenstates, you can compute the time evolution exactly. Animation (20:10 - 22:00): This is the key part. Observe how the initial state evolves and collapses into the potential well. Your Crank-Nicolson simulation should produce a very similar physical behavior.

Test your understanding! Apply your knowledge.

Now, let's connect this lesson with the previous one. Your task is to simulate quantum tunneling in the double-well potential.

Problem: Simulate the time evolution of a Gaussian wavepacket in the double-well potential you studied in the last lesson's exercise:

Instructions:

  1. Adapt the Python code from the matterwavex.com article.
  2. Replace the square barrier potential with the double-well potential. Use the same parameters as last time (e.g., , in atomic units).
  3. Modify the initial wavepacket so that it starts centered in one of the wells (e.g., at ), with zero initial momentum (). Make the packet narrow enough to fit mostly within that well.
  4. Run the simulation. You should observe the wavepacket tunneling back and forth between the two wells. This is a beautiful visualization of the superposition of the symmetric ground state and the anti-symmetric first excited state.
  5. Bonus: Try to measure the time it takes for the probability to move from one well to the other and back again (the tunneling period, ). In the previous lesson, you found the energies and for the two lowest states. How does your measured compare to the theoretical prediction ?
Show hints on what to expect

You should see the probability density "slosh" from the left well to the right well and then back again. The rate of this tunneling is determined by the energy splitting . A smaller energy splitting (which you found occurs for higher barriers) corresponds to a longer tunneling period, as the particle is more "trapped" in each well. This exercise beautifully connects the static eigenstate picture (energy splitting) with the dynamic picture (tunneling time).

Conclusion

In this lesson, you've added a crucial method for simulating quantum dynamics to your computational arsenal. By moving beyond simple explicit methods, you can now reliably model how quantum systems change over time.

Key Takeaways:

  • The Time-Dependent Schrödinger Equation can be solved numerically to simulate quantum dynamics.
  • Simple explicit methods like FTCS are often unstable because they don't conserve probability.
  • The Crank-Nicolson method is an implicit, unconditionally stable method that reformulates the TDSE into a sequence of linear systems, .
  • Because the discretized Hamiltonian is tridiagonal, the resulting system can be solved very efficiently in time using the Thomas Algorithm.

Preview of the Next Lesson:

So far, we have focused on single-particle quantum mechanics. However, your primary interest lies in many-body systems. In the next lesson, we will make the leap into this domain. You will apply exact diagonalization to calculate the ground state and low-lying excitations of a small quantum many-body system, such as a Heisenberg spin chain. This technique is a cornerstone of computational condensed matter physics.

Can't find a good explanation? Sign up and we'll make it for you

Sign up