Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into weighted-trajecto…
Browse files Browse the repository at this point in the history
…ries
  • Loading branch information
pmenczel committed Apr 25, 2024
2 parents 9208fea + 63f1478 commit 3f774b2
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 64 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ jobs:
# Mac
# Mac has issues with MKL since september 2022.
- case-name: macos
os: macos-latest
# setup-miniconda not compatible with macos-latest presently.
# https://github.com/conda-incubator/setup-miniconda/issues/344
os: macos-12
python-version: "3.11"
condaforge: 1
nomkl: 1
Expand All @@ -119,7 +121,7 @@ jobs:

steps:
- uses: actions/checkout@v3
- uses: conda-incubator/setup-miniconda@v2
- uses: conda-incubator/setup-miniconda@v3
with:
auto-update-conda: true
python-version: ${{ matrix.python-version }}
Expand Down
1 change: 1 addition & 0 deletions doc/changes/2401.doc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Correct a mistake in the doc
56 changes: 10 additions & 46 deletions doc/development/release_distribution.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ In short, the steps you need to take are:

1. Prepare the release branch (see git_).
2. Run the "Build wheels, optionally deploy to PyPI" GitHub action to build binary and source packages and upload them to PyPI (see deploy_).
3. Retrieve the built documentation from GitHub (see docbuild_).
4. Create a GitHub release and uploaded the built files to it (see github_).
5. Update `qutip.org <https://qutip.org/>`_ with the new links and documentation (web_).
6. Update the conda feedstock, deploying the package to ``conda`` (cforge_).
3. Create a GitHub release and uploaded the built files to it (see github_).
4. Update `qutip.org <https://qutip.org/>`_ with the new links and documentation (web_).
5. Update the conda feedstock, deploying the package to ``conda`` (cforge_).



Expand Down Expand Up @@ -120,6 +119,8 @@ You should now have a branch that you can see on the GitHub website that is call
If you notice you have made a mistake, you can make additional pull requests to the release branch to fix it.
``master`` should look pretty similar, except the ``VERSION`` will be higher and have a ``.dev`` suffix, and the "Development Status" in ``setup.cfg`` will be different.

* Activate the readthedocs build for the newly created version branch and set it as the latest.

You are now ready to actually perform the release.
Go to deploy_.

Expand Down Expand Up @@ -189,7 +190,7 @@ Go to the `"Actions" tab at the top of the QuTiP code repository <https://github
Click on the "Build wheels, optionally deploy to PyPI" action in the left-hand sidebar.
Click the "Run workflow" dropdown in the header notification; it should look like the image below.

.. image:: /figures/release_guide_run_build_workflow.png
.. image:: ../figures/release_guide_run_build_workflow.png

- Use the drop-down menu to choose the branch or tag you want to release from.
This should be called ``qutip-4.5.X`` or similar, depending on what you made earlier.
Expand All @@ -212,7 +213,7 @@ Download Built Files
When the build is complete, click into its summary screen.
This is the main screen used to both monitor the build and see its output, and should look like the below image on a success.

.. image:: /figures/release_guide_after_workflow.png
.. image:: ../figures/release_guide_after_workflow.png

The built binary wheels and the source distribution are the "build artifacts" at the bottom.
You need to download both the wheels and the source distribution.
Expand All @@ -233,20 +234,6 @@ You will see a message saying "Built wheels will be deployed" if you typed in th
If you see "Only building wheels" but you meant to deploy the release to PyPI, you can cancel the workflow and re-run it after typing the confirmation.


.. _docbuild:

Getting the Built Documentation
+++++++++++++++++++++++++++++++

The documentation will have been built automatically for you by a GitHub Action when you merged the final pull request into the release branch before building the wheels.
You do not need to re-release the documentation on either GitHub or the website if this is a patch release, unless there were changes within it.

Go to the "Actions" tab at the top of the ``qutip/qutip`` repository, and click the "Build HTML documentation" heading in the left column.
You should see a list of times this action has run; click the most recent one whose name is exactly "Build HTML documentation", with the release branch name next to it (e.g. ``qutip-4.6.X``).
Download the ``qutip_html_docs`` artifact to your local machine and unzip it somewhere safe.
These are all the HTML files for the built documentation; you should be able to open ``index.html`` in your own web browser and check that everything is working.


.. _github:

Making a Release on GitHub
Expand Down Expand Up @@ -276,29 +263,6 @@ Website
This assumes that qutip.github.io has already been forked and familiarity with the website updating workflow.
The documentation need not be updated for every patch release.

Copying New Files
-----------------

You only need to copy in new documentation to the website repository.
Do not copy the ``.whl``, ``.tar.gz`` or ``.zip`` files into the git repository, because we can access the public links from the GitHub release stage, and this keeps the website ``.git`` folder a reasonable size.

For all releases move (no new docs) or copy (for new docs) the ``qutip-doc-<MAJOR>.<MINOR>.pdf`` into the folder ``downloads/<MAJOR>.<MINOR>.<MICRO>``.

The legacy html documentation should be in a subfolder like ::

docs/<MAJOR>.<MINOR>

For a major or minor release the previous version documentation should be moved into this folder.

The latest version HTML documentation should be the folder ::

docs/latest

For any release which new documentation is included
- copy the contents ``qutip/doc/_build/html`` into this folder. **Note that the underscores at start of the subfolder names will need to be removed, otherwise Jekyll will ignore the folders**. There is a script in the ``docs`` folder for this.
https://github.com/qutip/qutip.github.io/blob/master/docs/remove_leading_underscores.py


HTML File Updates
-----------------

Expand All @@ -312,12 +276,12 @@ HTML File Updates

- Edit ``_includes/sidebar.html``

* The 'Latest release' version should be updated. The gztar and zip file links will need the micro release number updating in the traceEvent and file name.
* The link to the documentation folder and PDF file (if created) should be updated.
* Add the new version and release date. Only actively developed version should be listed. Micro replace the previous entry but the last major can be kept.
* Link to the installation instruction, documentation, source code and changelog should be updated.

- Edit ``documentation.html``

* The previous release tags should be moved (copied) to the 'Previous releases' section.
* For major and minor release, the previous release tags should be moved (copied) to the 'Previous releases' section and the links to the readthedocs of the new version added the to 'Latest releases' section.

.. _cforge:

Expand Down
2 changes: 1 addition & 1 deletion doc/guide/guide-basics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ Conversion between storage type is done using the :meth:`.Qobj.to` method.
>>> q.to("CSR").data
CSR(shape=(4, 4), nnz=3)

>>> q.to("CSR").data_as("CSR_matrix")
>>> q.to("CSR").data_as("csr_matrix")
<4x4 sparse matrix of type '<class 'numpy.complex128'>'
with 3 stored elements in Compressed Sparse Row format>

Expand Down
4 changes: 2 additions & 2 deletions qutip/core/cy/coefficient.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ cdef class InterCoefficient(Coefficient):

@classmethod
def from_PPoly(cls, ppoly, **_):
return cls.restore(ppoly.x, ppoly.c)
return cls.restore(ppoly.x, np.array(ppoly.c, complex, copy=False))

@classmethod
def from_Bspline(cls, spline, **_):
Expand All @@ -528,7 +528,7 @@ cdef class InterCoefficient(Coefficient):
poly = np.concatenate([
spline(tlist, i) / fact[i]
for i in range(spline.k, -1, -1)
]).reshape((spline.k+1, -1))
]).reshape((spline.k+1, -1)).astype(complex, copy=False)
return cls.restore(tlist, poly)

cpdef Coefficient copy(self):
Expand Down
14 changes: 8 additions & 6 deletions qutip/solver/integrator/krylov.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def _prepare(self):
krylov_tridiag, krylov_basis = \
self._lanczos_algorithm(rand_ket(N).data)
if (
krylov_tridiag.shape[0] < self.options["krylov_dim"]
krylov_tridiag.shape[0] < krylov_dim
or krylov_tridiag.shape[0] == N
):
self._max_step = np.inf
Expand Down Expand Up @@ -138,20 +138,22 @@ def krylov_error(t):
self._compute_psi(t, *reduced_state)
) / self.options["atol"])

dt = self.options["min_step"]
# Under 0 will cause an infinite loop in the while loop bellow.
dt = max(self.options["min_step"], 1e-14)
max_step = max(self.options["max_step"], dt)
err = krylov_error(dt)
if err > 0:
ValueError(
raise ValueError(
f"With the krylov dim of {self.options['krylov_dim']}, the "
f"error with the minimum step {dt} is {err}, higher than the "
f"desired tolerance of {self.options['atol']}."
)

while krylov_error(dt * 10) < 0 and dt < self.options["max_step"]:
while krylov_error(dt * 10) < 0 and dt < max_step:
dt *= 10

if dt > self.options["max_step"]:
return self.options["max_step"]
if dt > max_step:
return max_step

sol = root_scalar(f=krylov_error, bracket=[dt, dt * 10],
method="brentq", xtol=self.options['atol'])
Expand Down
6 changes: 5 additions & 1 deletion qutip/solver/propagator.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ def propagator(H, t, c_ops=(), args=None, options=None, **kwargs):
that can be made into :obj:`.QobjEvo` are also accepted.
t : float or array-like
Time or list of times for which to evaluate the propagator.
Time or list of times for which to evaluate the propagator. If a single
time ``t`` is passed, the propagator from ``0`` to ``t`` is computed.
When ``t`` is a list, the propagators from the first time in the list
to each elements in ``t`` is returned. In that case, the first output
will always be the identity matrix.
c_ops : list, optional
List of Qobj or QobjEvo collapse operators.
Expand Down
26 changes: 24 additions & 2 deletions qutip/tests/core/test_coefficient.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,9 +381,13 @@ def test_CoeffArray(order):
assert derrs[i] == pytest.approx(0.0, abs=0.0001)


def test_CoeffFromScipy():
@pytest.mark.parametrize('imag', [True, False])
def test_CoeffFromScipyPPoly(imag):
tlist = np.linspace(0, 1.01, 101)
y = np.exp((-1 + 1j) * tlist)
if imag:
y = np.exp(-1j * tlist)
else:
y = np.exp(-1 * tlist)

coeff = coefficient(y, tlist=tlist, order=3)
from_scipy = coefficient(interp.CubicSpline(tlist, y))
Expand All @@ -398,6 +402,24 @@ def test_CoeffFromScipy():
_assert_eq_over_interval(coeff, from_scipy, rtol=1e-8, inside=True)


@pytest.mark.parametrize('imag', [True, False])
def test_CoeffFromScipyBSpline(imag):
tlist = np.linspace(-0.1, 1.1, 121)
if imag:
y = np.exp(-1j * tlist)
else:
y = np.exp(-1 * tlist)

spline = interp.BSpline(tlist, y, 2)

def func(t):
return complex(spline(t))

coverted = coefficient(spline)
raw_scipy = coefficient(func)
_assert_eq_over_interval(coverted, raw_scipy, rtol=1e-8, inside=True)


@pytest.mark.parametrize('map_func', [
pytest.param(qutip.solver.parallel.parallel_map, id='parallel_map'),
pytest.param(qutip.solver.parallel.loky_pmap, id='loky_pmap'),
Expand Down
2 changes: 1 addition & 1 deletion qutip/tests/solver/test_nm_mcsolve.py
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ def test_super_H(improved_sampling):
qutip.liouvillian(H), state, times, ops_and_rates, e_ops, ntraj=ntraj,
target_tol=0.1, options={'map': 'serial',
"improved_sampling": improved_sampling})
np.testing.assert_allclose(mc_expected.expect[0], mc.expect[0], atol=0.5)
np.testing.assert_allclose(mc_expected.expect[0], mc.expect[0], atol=0.65)


def test_NonMarkovianMCSolver_run():
Expand Down
16 changes: 13 additions & 3 deletions qutip/tests/solver/test_sesolve.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,9 +301,19 @@ def test_krylovsolve(always_compute_step):
e_op.dims = H.dims
tlist = np.linspace(0, 1, 11)
ref = sesolve(H, psi0, tlist, e_ops=[e_op]).expect[0]
options = {"always_compute_step", always_compute_step}
krylov_sol = krylovsolve(H, psi0, tlist, 20, e_ops=[e_op]).expect[0]
np.testing.assert_allclose(ref, krylov_sol)
options = {"always_compute_step": always_compute_step}
krylov_sol = krylovsolve(H, psi0, tlist, 20, e_ops=[e_op], options=options)
np.testing.assert_allclose(ref, krylov_sol.expect[0])


def test_krylovsolve_error():
H = qutip.rand_herm(256, density=0.2)
psi0 = qutip.basis([256], [255])
tlist = np.linspace(0, 1, 11)
options = {"min_step": 1e10}
with pytest.raises(ValueError) as err:
krylovsolve(H, psi0, tlist, 20, options=options)
assert "error with the minimum step" in str(err.value)


def test_feedback():
Expand Down

0 comments on commit 3f774b2

Please sign in to comment.