GPE#

Welcome to the documentation for GPE! To get started, please see Getting Started with the GPE.

GPE#

Documentation Status Tests Coverage

This project provides some explicit and pedagogical examples of how to implement the linear and non-linear Schrödinger equation.

CoCalc#

To build the documentation on CoCalc, open the following file:

This will build the documentation, and serve it on

https://cocalc.com/13fd6946-fdd9-474e-a824-5ba2b0d7efda/raw/.repositories/gpe/Docs/_build/html/index.html

You can also build the static documentation by running

make html

This will not update dynamically though.

Getting Started#

This package can be installed with Pip:

pip install .[full]

However, if you need to provision your environment properly with tools like the right version of Python, then you can use the machinery in the [Makefile][]:

make init        # Installs everything, building appropriate environments with micromamba
make shell       # Starts a new bash shell so you can run code.
make notebook    # Launches Jupyter Notbook
make doc-server  # Build and serve the documentation on http://127.0.0.1:8000

To see more details, please run make which will display the help.

  1. The main numerical issue is representing the continuous wavefunction on the computer and applying the kinetic energy operator which requires computing derivatives. Here we represent the functions using an equally spaced lattice in a periodic box and the Fast Fourier Transform (FFT). Technical details about this are described in the notebook:

  2. As a starting point, look at the following notebooks and code. These are fairly complete and well crafted. They should be used as an example of how you should write and test code and related documentation.

CoCalc#

To build the documentation on CoCalc, open the following file:

This will build the documentation, and serve it on https://cocalc.com//raw/.repositories/gpe/Docs/_build/html/index.html.

Developer Notes#

  1. Other notebooks demonstrate various applications of these techniques. These notebooks are often incomplete as they represent work in progress.

    • Docs/BEC2.md, gpe/bec2.py: Two component systems such as spin-orbit coupled (SOC) systems of BECs.

    • Docs/Minimization.md: This notebook describes work on the minimization algorithm for finding ground states. At the top level, we use the L_BFGS algorithm in SciPy, but while this does a good job of minimizing the energy, it completes too early to provide an adequate stationary state for evolution. To this algorithm we add a quasi-Newton Brodyen solver which completes the minimization, producing additionally a highly accurate stationary state.

    • Docs/SOC Solitons.md: Solitons in SOC BECs. This notebook demonstrates some analytic solutions with various combinations of bright and dark solitons.

    • Docs/Entrainment.md: Coupled systems with entrainment couplings between the superfluids. This work is related to experiments performed in Deep Gupta’s lab at UW.

See Docs/index.md for more details.

Conventions#

We use a couple of conventions in our code which are important for users to know about and for developers to maintain.

  • Interfaces: We strive to make explicit the interface of each major component through the file [gpe/interfaces.py]. Look here to see how to use the various components, and if you need to use something else, then consider adding that to the interface, but keep these clean. This is based on the zope.interface library and we used various functions in the code to check that our implementations provide the correct interfaces in our tests.

  • Factored Code: We strive to keep our code nicely factored in to functionally separate components. In particular, we have the following components:

    • State: These are the underlying objects that do the computation, providing the IState interface needed for pytimeode. In principle, one can put everything in here and be done – which might be a good development strategy at first – but does not lend itself to reuse.

    • Experiment: Instead, one should factor the computational machinery, such as the basis and functional, in the State class, then put the experimental details, such as the external potentials and procedure for getting the initial state, into an Experiment class to which the State class delegates. This allows one to perform the same experiment using a variety of different states - for example, modeling a 3D system in an axial tube. Experiment classes should provide the IExperiment interface to benefit from a bunch of utilities such as checkpoint/restart.

    • Simulation: For an actual project, one needs to run many different simulations with different parameters. This can be managed by a Simulation class.

  • Optimizations: Since this is research code, performance is important, but can come at a price of complicating the code. This is exemplified by making the code capable of working on both CPUs and GPUs through the cupy library. As a result, some functions need to be carefully written in order to be able to utilize both platforms. However, GPU functions are not very useful from the user perspective as they return GPU arrays that cannot be directly used in plots etc. We deal with this using the following strategy:

    • Write the CPU/GPU agnostic code in a special GPU function with a name ending with _GPU. These will then be automatically wrapped with a corresponding CPU function by a class decorator. Thus, developers would write get_density_GPU() and the decorator would write the public get_density() with a transfer of the data from the GPU to a numpy array if needed:

      • get_density_GPU(): Returns a CPU or GPU array of the density. Written by the developers. This is expected to be high performance.

      • get_density(): Returns a NumPy array on the CPU. Generated by the decorator if not explicitly provided. This is not expected to be high performance, so we use the wrapt library as recommended here.

Testing with Python#

Since python is an interpreted language, there is no compilation stage. While this can greatly speed development, it means that there are no check of your code until each line of code is actually executed. As a result, it is crucial that you ensure as much of your code as possible is executed by unit tests.

Here we use the py.test package to test our code. Writing tests simply amounts to adding files that look like tests which contain functions that start with test*(). Another option is to use doctests in your docstrings. Running the command py.test will then find and execute all of these tests. The configuration of the test system is done in two files:

  • setup.cfg: This file contains some instructions for the flake8 package which checks the code for compliance with the recommended practices of PEP8.

  • pytest.ini: This file configures the pytest. In particular, we enable the code coverage utility which will generate a coverage report in [htmlcov/index.html]. You should strive to ensure that 100% of your code is executed by your tests.

Testing Strategies#

Each test function should test a specific aspect of the code. This is so that when a test fails, it is clear which aspect of the code is broken. If a complex test breaks, you must then spend time debugging the failed test to find out exactly where things are failing.

Tests should run quickly so that running them does not slow your development cycle. You should be running tests frequently as you modify your code to make sure you do not break anything. If you need to make a slow test, you can mark it as a benchmark so that you can suppress running it during development.

Funding#

https://nsf.widen.net/content/txvhzmsofh/png/

Some of the material presented here is based upon work supported by the National Science Foundation under Grant Numbers 1707691, 2012190, and 2309322. Any opinions, findings, and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the National Science Foundation.

References#

Another option is to symlink the file into the Docs/ tree and then include it as part of the documentation. Note that this will probably not work on Windows.

cd Docs/
ln -s ../README.md .
hg add README.md