From 1b4a0545f28f389bff9780b615214dc869834423 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Fri, 12 Apr 2024 20:44:40 +0100 Subject: [PATCH 01/33] Add sphinx docs configs --- docs/api.rst | 8 ++++++++ docs/conf.py | 27 +++++++++++++++++++++++++++ docs/index.rst | 20 ++++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 docs/api.rst create mode 100644 docs/conf.py create mode 100644 docs/index.rst diff --git a/docs/api.rst b/docs/api.rst new file mode 100644 index 00000000..f43dc378 --- /dev/null +++ b/docs/api.rst @@ -0,0 +1,8 @@ +API Documentation +================= + +.. toctree:: + :maxdepth: 2 + :caption: API: + + modules diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 00000000..9dbc21ad --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,27 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = 'momentGW' +copyright = '2024, Oliver J. Backhouse' +author = 'Oliver J. Backhouse' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon'] + +templates_path = ['_templates'] +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = 'alabaster' +html_static_path = ['_static'] diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 00000000..f6e40a61 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,20 @@ +.. momentGW documentation master file, created by + sphinx-quickstart on Fri Apr 12 20:42:32 2024. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to momentGW's documentation! +==================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` From c1a6df71516a710b28f5527da40492872fd7f352 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Fri, 12 Apr 2024 20:50:39 +0100 Subject: [PATCH 02/33] Include docs makefiles --- docs/Makefile | 20 ++++++++++++++++++++ docs/make.bat | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 docs/Makefile create mode 100644 docs/make.bat diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..d4bb2cbb --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 00000000..32bb2452 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd From 0088407a6bd19ed4062ea304d8eec6ed1542ff19 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Fri, 12 Apr 2024 20:51:16 +0100 Subject: [PATCH 03/33] Add docs to CI --- .github/workflows/ci.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ca34f397..9df7af43 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -37,3 +37,12 @@ jobs: run: | python -m pip install pytest pytest-cov pytest --cov momentGW/ + - name: Build documentation + run: | + cd docs + make html + - name: Deploy documentation + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./docs/_build/html From efec5d72678a3995c35733ad1d788fc77d089a86 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Fri, 12 Apr 2024 20:51:26 +0100 Subject: [PATCH 04/33] Add sphinx to dev deps --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 419ebf07..d71ea410 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,6 +54,7 @@ dev = [ "pytest>=6.2.4", "pytest-cov>=4.0.0", "pytest-env>=1.1.0", + "sphinx>=4.0.0", ] mpi = [ "mpi4py>=3.1.0", From cee839aa6e5cf388f5096b5f9a02ae925fffa61a Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Fri, 12 Apr 2024 20:53:21 +0100 Subject: [PATCH 05/33] Disable CI for now --- .github/workflows/ci.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 9df7af43..f23db3dd 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -33,10 +33,10 @@ jobs: python -m black . --diff --check --verbose python -m isort . --diff --check-only --verbose python -m flake8 momentGW/ --verbose - - name: Run unit tests - run: | - python -m pip install pytest pytest-cov - pytest --cov momentGW/ + #- name: Run unit tests + # run: | + # python -m pip install pytest pytest-cov + # pytest --cov momentGW/ - name: Build documentation run: | cd docs From 2277d83c8a1053c027987d8558509bce9a00dd21 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Fri, 12 Apr 2024 20:58:13 +0100 Subject: [PATCH 06/33] Build docs in workflow --- .github/workflows/ci.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f23db3dd..a54b228c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -40,7 +40,8 @@ jobs: - name: Build documentation run: | cd docs - make html + sphinx-apidoc -o api/ ../momentGW + sphinx-build -b html . _build/html - name: Deploy documentation uses: peaceiris/actions-gh-pages@v3 with: From 9ea6a0a525e818b8e06299d913eef322fb4c7e08 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Fri, 12 Apr 2024 21:01:40 +0100 Subject: [PATCH 07/33] Update links --- docs/api.rst | 2 +- docs/index.rst | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/api.rst b/docs/api.rst index f43dc378..4c7cace3 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -5,4 +5,4 @@ API Documentation :maxdepth: 2 :caption: API: - modules + api/modules diff --git a/docs/index.rst b/docs/index.rst index f6e40a61..1765a8da 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -10,6 +10,7 @@ Welcome to momentGW's documentation! :maxdepth: 2 :caption: Contents: + readme Indices and tables From 78453c7f0703ca9b88bb20064bc8845c086e1b25 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Fri, 12 Apr 2024 21:09:38 +0100 Subject: [PATCH 08/33] Add links and README to homepage --- .github/workflows/ci.yaml | 1 + docs/api.rst | 1 - docs/index.rst | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a54b228c..4eb2a76a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -42,6 +42,7 @@ jobs: cd docs sphinx-apidoc -o api/ ../momentGW sphinx-build -b html . _build/html + echo ".. include:: ../README.md" > _build/html/index.rst - name: Deploy documentation uses: peaceiris/actions-gh-pages@v3 with: diff --git a/docs/api.rst b/docs/api.rst index 4c7cace3..ef0a1a67 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -3,6 +3,5 @@ API Documentation .. toctree:: :maxdepth: 2 - :caption: API: api/modules diff --git a/docs/index.rst b/docs/index.rst index 1765a8da..1e0a049f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -11,6 +11,7 @@ Welcome to momentGW's documentation! :caption: Contents: readme + api/modules Indices and tables From 41899c3cc3f09fed875b89cdd54bbab6661e0ed3 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Fri, 12 Apr 2024 21:13:38 +0100 Subject: [PATCH 09/33] Trying again --- .github/workflows/ci.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4eb2a76a..7015878b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -41,8 +41,8 @@ jobs: run: | cd docs sphinx-apidoc -o api/ ../momentGW - sphinx-build -b html . _build/html - echo ".. include:: ../README.md" > _build/html/index.rst + sphinx-build -b html . + #echo ".. include:: ../README.md" > _build/html/index.rst - name: Deploy documentation uses: peaceiris/actions-gh-pages@v3 with: From f631f2ea2b65285490329d330098b499dbf5b897 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Fri, 12 Apr 2024 21:18:10 +0100 Subject: [PATCH 10/33] Trying mkdir first --- .github/workflows/ci.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7015878b..7fad6eae 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -40,8 +40,9 @@ jobs: - name: Build documentation run: | cd docs + mkdir -p _build sphinx-apidoc -o api/ ../momentGW - sphinx-build -b html . + sphinx-build -b html . _build/html #echo ".. include:: ../README.md" > _build/html/index.rst - name: Deploy documentation uses: peaceiris/actions-gh-pages@v3 From fe1f7266c78b70c29b869f7e3a215e9261ad1581 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Fri, 12 Apr 2024 21:31:04 +0100 Subject: [PATCH 11/33] Customise conf.py --- docs/conf.py | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 9dbc21ad..0986d355 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,27 +1,19 @@ -# Configuration file for the Sphinx documentation builder. -# -# For the full list of built-in configuration values, see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html +# docs/conf.py -# -- Project information ----------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information +import os +import sys +sys.path.insert(0, os.path.abspath("../")) -project = 'momentGW' -copyright = '2024, Oliver J. Backhouse' -author = 'Oliver J. Backhouse' +project = "momentGW" +copyright = "2024, Oliver J. Backhouse" +author = "Oliver J. Backhouse" -# -- General configuration --------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.napoleon", +] -extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon'] +source_suffix = [".rst", ".md"] +master_doc = "index" -templates_path = ['_templates'] -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] - - - -# -- Options for HTML output ------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output - -html_theme = 'alabaster' -html_static_path = ['_static'] +html_theme = "alabaster" From f83a208bfd51e40b69727866df0a055b16a5614f Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Fri, 12 Apr 2024 21:32:40 +0100 Subject: [PATCH 12/33] Customise Makefile --- docs/Makefile | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/docs/Makefile b/docs/Makefile index d4bb2cbb..9778372a 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -1,20 +1,7 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build SOURCEDIR = . BUILDDIR = _build -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile +html: @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: html From 81330929ea7e6e7dd6d44857e63251f7fd6490db Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Fri, 12 Apr 2024 21:33:18 +0100 Subject: [PATCH 13/33] Add caption for API page --- docs/api.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/api.rst b/docs/api.rst index ef0a1a67..f3266799 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -3,5 +3,6 @@ API Documentation .. toctree:: :maxdepth: 2 + :caption: Contents: api/modules From 7a75815cd76b3d89453094a6ec82833ce98d1915 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Fri, 12 Apr 2024 21:34:48 +0100 Subject: [PATCH 14/33] Re-enable echo for adding in README --- .github/workflows/ci.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7fad6eae..1118927b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -40,10 +40,9 @@ jobs: - name: Build documentation run: | cd docs - mkdir -p _build sphinx-apidoc -o api/ ../momentGW - sphinx-build -b html . _build/html - #echo ".. include:: ../README.md" > _build/html/index.rst + make html + echo ".. include:: ../README.md" > _build/html/index.rst - name: Deploy documentation uses: peaceiris/actions-gh-pages@v3 with: From 17fddfa7d7d60c641867d0373ed467f42281098c Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Fri, 12 Apr 2024 21:37:54 +0100 Subject: [PATCH 15/33] Linting --- docs/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/conf.py b/docs/conf.py index 0986d355..2b29a994 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -2,6 +2,7 @@ import os import sys + sys.path.insert(0, os.path.abspath("../")) project = "momentGW" From e780c70ff017a0c60a37208a55c50d272f1ab2e5 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Fri, 12 Apr 2024 22:26:49 +0100 Subject: [PATCH 16/33] Updating sphinx config --- .github/workflows/ci.yaml | 2 -- docs/Makefile | 5 ++++- docs/conf.py | 1 + docs/index.rst | 9 ++------- pyproject.toml | 1 + 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 1118927b..f23db3dd 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -40,9 +40,7 @@ jobs: - name: Build documentation run: | cd docs - sphinx-apidoc -o api/ ../momentGW make html - echo ".. include:: ../README.md" > _build/html/index.rst - name: Deploy documentation uses: peaceiris/actions-gh-pages@v3 with: diff --git a/docs/Makefile b/docs/Makefile index 9778372a..0ae5a7af 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -1,7 +1,10 @@ +SPHINXOPTS = +SPHINXBUILD = sphinx-build SOURCEDIR = . BUILDDIR = _build html: - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + sphinx-apidoc -o api/ ../momentGW --force + sphinx-build -M html . _build .PHONY: html diff --git a/docs/conf.py b/docs/conf.py index 2b29a994..3f254f0e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,6 +12,7 @@ extensions = [ "sphinx.ext.autodoc", "sphinx.ext.napoleon", + "sphinx_mdinclude", ] source_suffix = [".rst", ".md"] diff --git a/docs/index.rst b/docs/index.rst index 1e0a049f..6b8dc812 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,8 +1,3 @@ -.. momentGW documentation master file, created by - sphinx-quickstart on Fri Apr 12 20:42:32 2024. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - Welcome to momentGW's documentation! ==================================== @@ -10,8 +5,8 @@ Welcome to momentGW's documentation! :maxdepth: 2 :caption: Contents: - readme - api/modules +.. mdinclude:: + ../README.md Indices and tables diff --git a/pyproject.toml b/pyproject.toml index d71ea410..1a6bcd7e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,6 +55,7 @@ dev = [ "pytest-cov>=4.0.0", "pytest-env>=1.1.0", "sphinx>=4.0.0", + "sphinx-mdinclude>=0.5.0", ] mpi = [ "mpi4py>=3.1.0", From ad1b3170a5bd86057c35deb81103540770103844 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Fri, 12 Apr 2024 23:59:16 +0100 Subject: [PATCH 17/33] Improvements to API docs --- docs/Makefile | 5 ++++- docs/conf.py | 5 +++-- pyproject.toml | 1 + 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/Makefile b/docs/Makefile index 0ae5a7af..07aa069e 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -4,7 +4,10 @@ SOURCEDIR = . BUILDDIR = _build html: - sphinx-apidoc -o api/ ../momentGW --force + sphinx-apidoc -o api/ ../momentGW --force --separate sphinx-build -M html . _build +clean: + rm -rf _build api + .PHONY: html diff --git a/docs/conf.py b/docs/conf.py index 3f254f0e..756a8570 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -10,9 +10,10 @@ author = "Oliver J. Backhouse" extensions = [ - "sphinx.ext.autodoc", - "sphinx.ext.napoleon", "sphinx_mdinclude", + "sphinx.ext.mathjax", + "sphinx.ext.autodoc", + "numpydoc", ] source_suffix = [".rst", ".md"] diff --git a/pyproject.toml b/pyproject.toml index 1a6bcd7e..a7921e67 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,6 +56,7 @@ dev = [ "pytest-env>=1.1.0", "sphinx>=4.0.0", "sphinx-mdinclude>=0.5.0", + "numpydoc>=1.1.0", ] mpi = [ "mpi4py>=3.1.0", From e1591af34a2ddf021efb40a0564e5df0a27bdd59 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Sat, 13 Apr 2024 10:15:04 +0100 Subject: [PATCH 18/33] Navigation to API working --- docs/api.rst | 3 +-- docs/index.rst | 17 ++++------------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/docs/api.rst b/docs/api.rst index f3266799..72380494 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -2,7 +2,6 @@ API Documentation ================= .. toctree:: - :maxdepth: 2 - :caption: Contents: + :maxdepth: 3 api/modules diff --git a/docs/index.rst b/docs/index.rst index 6b8dc812..39ed5b6f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,17 +1,8 @@ -Welcome to momentGW's documentation! -==================================== - .. toctree:: - :maxdepth: 2 - :caption: Contents: + :maxdepth: 1 + :hidden: + + api .. mdinclude:: ../README.md - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` From 8bdbdf07c88d13200e07b64506e002807f7a9612 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Sat, 13 Apr 2024 10:20:06 +0100 Subject: [PATCH 19/33] Update README to work with RST conversion --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c3414a1f..8f8fdc71 100644 --- a/README.md +++ b/README.md @@ -31,11 +31,11 @@ The `examples` directory contains more detailed usage examples. ### Publications The methods implemented in this package have been described in the following papers: -- [*"A 'moment-conserving' reformulation of GW theory"*](https://doi.org/10.1063/5.0143291) +- [A 'moment-conserving' reformulation of GW theory](https://doi.org/10.1063/5.0143291), *J. Chem. Phys.* 158, 124102 (2023). The data presented in the publications can be found in the `benchmark` directory. ### Contributing Contributions are welcome, and can be made by submitting a pull request to the `master` branch. -The code uses [NumPy-style docstrings](https://numpydoc.readthedocs.io/en/latest/format.html) and is formatted using [`black`](https://black.readthedocs.io/en/stable/), [`isort`](https://pycqa.github.io/isort/), [`ssort`](https://github.com/bwhmather/ssort), and [`flake8`](https://flake8.pycqa.org/en/latest/). +The code uses [NumPy-style docstrings](https://numpydoc.readthedocs.io/en/latest/format.html) and is formatted using [black](https://black.readthedocs.io/en/stable/), [isort](https://pycqa.github.io/isort/), [ssort](https://github.com/bwhmather/ssort), and [flake8](https://flake8.pycqa.org/en/latest/). From 6ebf41947badf0d088aef15308d63bf1ade4fd9c Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Sat, 13 Apr 2024 10:27:59 +0100 Subject: [PATCH 20/33] Add github badges --- docs/_templates/badges.html | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 docs/_templates/badges.html diff --git a/docs/_templates/badges.html b/docs/_templates/badges.html new file mode 100644 index 00000000..fe141b7c --- /dev/null +++ b/docs/_templates/badges.html @@ -0,0 +1,6 @@ +
+ Star +
+ + From 73feb3315ae544aca1badf2ba6dbc86f732d9510 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Sat, 13 Apr 2024 14:33:38 +0100 Subject: [PATCH 21/33] More configuration --- docs/Makefile | 2 +- docs/conf.py | 57 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/docs/Makefile b/docs/Makefile index 07aa069e..24e2a024 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -4,7 +4,7 @@ SOURCEDIR = . BUILDDIR = _build html: - sphinx-apidoc -o api/ ../momentGW --force --separate + sphinx-apidoc -o api/ -f -e -M ../momentGW sphinx-build -M html . _build clean: diff --git a/docs/conf.py b/docs/conf.py index 756a8570..0f7901b9 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -3,6 +3,8 @@ import os import sys +from momentGW.base import Base + sys.path.insert(0, os.path.abspath("../")) project = "momentGW" @@ -10,13 +12,64 @@ author = "Oliver J. Backhouse" extensions = [ - "sphinx_mdinclude", - "sphinx.ext.mathjax", "sphinx.ext.autodoc", + "sphinx.ext.intersphinx", + "sphinx.ext.githubpages", + "sphinx.ext.mathjax", + "sphinx.ext.viewcode", + "sphinx_mdinclude", "numpydoc", ] +templates_path = ["_templates"] + +autodoc_default_options = { + "show-inheritance": True, + "members": True, + "private-members": False, + "special-members": True, + "undoc-members": False, + "member-order": "groupwise", + "typehints": "description", +} + +def autodoc_skip_member(app, what, name, obj, skip, options): + """Rule to skip members. + """ + return None + +numpydoc_show_class_members = False +numpydoc_show_inherited_class_members = True +numpydoc_class_members_toctree = False + +highlight_language = "python3" +intersphinx_mapping = {"python": ("https://docs.python.org/3", None)} source_suffix = [".rst", ".md"] master_doc = "index" html_theme = "alabaster" +html_theme_options = { + "fixed_sidebar": True, + "badge_branch": "master", + "github_user": "BoothGroup", + "github_repo": "momentGW", + "github_button": False, + "extra_nav_links": { + "GitHub": "https://github.com/BoothGroup/momentGW", + "Report Issues": "https://github.com/BoothGroup/momentGW/issues", + }, +} +html_sidebars = { + "**": [ + "about.html", + "badges.html", + "navigation.html", + "relations.html", + "searchbox.html", + ] +} + +def setup(app): + """Setup function for Sphinx. + """ + app.connect("autodoc-skip-member", autodoc_skip_member) From 5de4f5d6d1a1e66f17c7138d77b45329fea5b048 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Sat, 13 Apr 2024 15:25:48 +0100 Subject: [PATCH 22/33] Refactor _opts internal to dict --- momentGW/base.py | 79 +++++++++++++++++++++++----------------- momentGW/bse.py | 26 ++++++------- momentGW/evgw.py | 37 +++++++------------ momentGW/fock.py | 39 +++++++++++++++----- momentGW/fsgw.py | 41 ++++++++------------- momentGW/pbc/base.py | 18 ++++----- momentGW/pbc/evgw.py | 2 +- momentGW/pbc/fsgw.py | 7 +--- momentGW/pbc/gw.py | 2 +- momentGW/pbc/qsgw.py | 7 +--- momentGW/pbc/scgw.py | 2 +- momentGW/pbc/uhf/evgw.py | 2 +- momentGW/pbc/uhf/fsgw.py | 7 +--- momentGW/pbc/uhf/gw.py | 2 +- momentGW/pbc/uhf/qsgw.py | 7 +--- momentGW/pbc/uhf/scgw.py | 2 +- momentGW/qsgw.py | 49 +++++++++---------------- momentGW/uhf/evgw.py | 2 +- momentGW/uhf/fsgw.py | 7 +--- momentGW/uhf/qsgw.py | 7 +--- momentGW/uhf/scgw.py | 2 +- momentGW/util.py | 25 +++++++++++++ 22 files changed, 186 insertions(+), 186 deletions(-) diff --git a/momentGW/base.py b/momentGW/base.py index 99bb8796..6076a266 100644 --- a/momentGW/base.py +++ b/momentGW/base.py @@ -2,6 +2,8 @@ Base classes for moment-constrained GW solvers. """ +from collections import OrderedDict + import numpy as np from momentGW import init_logging, logging, mpi_helper, util @@ -10,7 +12,9 @@ class Base: """Base class.""" - _opts = [] + # Options are stored in a dictionary, but can be accessed as + # attributes using the overridden `__getattr__` method + _opts = OrderedDict() def __init__( self, @@ -92,14 +96,14 @@ def _check_modified(val, old): if isinstance(val, dict): # Format each entry of the dictionary keys, vals = zip(*val.items()) if val else ((), ()) - old = getattr(self.__class__, key) + old = self.__class__._opts.get(key, None) keys = [f"{key}.{k}" for k in keys] mods = [old and _check_modified(v, old[k]) for k, v in val.items()] else: # Format the single value keys = [key] vals = [val] - mods = [_check_modified(val, getattr(self.__class__, key))] + mods = [_check_modified(val, self.__class__._opts.get(key, None))] # Loop over entries for key, val, mod in zip(keys, vals, mods): @@ -265,6 +269,25 @@ def mo_occ(self, value): if value is not None: self._mo_occ = mpi_helper.bcast(np.asarray(value)) + def __getattr__(self, key): + """ + Try to get an attribute from the `_opts` dictionary. If it is + not found, raise an AttributeError. + + Parameters + ---------- + key : str + Attribute key. + + Returns + ------- + value : any + Attribute value. + """ + if key in self._opts: + return self._opts[key] + raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{key}'") + class BaseGW(Base): """Base class for moment-constrained GW solvers. @@ -306,39 +329,27 @@ class BaseGW(Base): implementation requires a filepath to import the THC integrals. """ - # --- Default GW options - - diagonal_se = False - polarizability = "drpa" - npoints = 48 - optimise_chempot = False - fock_loop = False - fock_opts = dict( - fock_diis_space=10, - fock_diis_min_space=1, - conv_tol_nelec=1e-6, - conv_tol_rdm1=1e-8, - max_cycle_inner=50, - max_cycle_outer=20, - ) - compression = "ia" - compression_tol = 1e-10 - thc_opts = dict( - file_path=None, + _opts = OrderedDict( + diagonal_se=False, + polarizability="drpa", + npoints=48, + optimise_chempot=False, + fock_loop=False, + fock_opts=OrderedDict( + fock_diis_space=10, + fock_diis_min_space=1, + conv_tol_nelec=1e-6, + conv_tol_rdm1=1e-8, + max_cycle_inner=50, + max_cycle_outer=20, + ), + compression="ia", + compression_tol=1e-10, + thc_opts=OrderedDict( + file_path=None, + ), ) - _opts = [ - "diagonal_se", - "polarizability", - "npoints", - "optimise_chempot", - "fock_loop", - "fock_opts", - "compression", - "compression_tol", - "thc_opts", - ] - def __init__(self, mf, **kwargs): super().__init__(mf, **kwargs) diff --git a/momentGW/bse.py b/momentGW/bse.py index 3fc84cf3..52c06d07 100644 --- a/momentGW/bse.py +++ b/momentGW/bse.py @@ -3,6 +3,8 @@ constraints for molecular systems. """ +from collections import OrderedDict + import numpy as np from dyson import CPGF, MBLGF @@ -70,12 +72,11 @@ class BSE(Base): Default value is `"singlet"`. """ - # --- Default BSE options - - excitation = "singlet" - polarizability = None - - _opts = Base._opts + ["excitation", "polarizability"] + _opts = OrderedDict( + **Base._opts, + excitation="singlet", + polarizability=None, + ) _kernel = kernel @@ -487,13 +488,12 @@ class cpBSE(BSE): Default value is `"singlet"`. """ - # --- Extra cpBSE options - - scale = None - grid = None - eta = 0.1 - - _opts = BSE._opts + ["scale", "grid", "eta"] + _opts = OrderedDict( + **BSE._opts, + scale=None, + grid=None, + eta=0.1, + ) def __init__(self, gw, **kwargs): super().__init__(gw, **kwargs) diff --git a/momentGW/evgw.py b/momentGW/evgw.py index 7a39d6e7..aafe1fc6 100644 --- a/momentGW/evgw.py +++ b/momentGW/evgw.py @@ -3,6 +3,8 @@ constraints for molecular systems. """ +from collections import OrderedDict + import numpy as np from momentGW import logging, util @@ -186,29 +188,18 @@ class evGW(GW): which they are considered zero. Default value is `1e-11`. """ - # --- Extra evGW options - - g0 = False - w0 = False - max_cycle = 50 - conv_tol = 1e-8 - conv_tol_moms = 1e-6 - conv_logical = all - diis_space = 8 - damping = 0.0 - weight_tol = 1e-11 - - _opts = GW._opts + [ - "g0", - "w0", - "max_cycle", - "conv_tol", - "conv_tol_moms", - "conv_logical", - "diis_space", - "damping", - "weight_tol", - ] + _opts = OrderedDict( + **GW._opts, + g0=False, + w0=False, + max_cycle=50, + conv_tol=1e-8, + conv_tol_moms=1e-6, + conv_logical=all, + diis_space=8, + damping=0.0, + weight_tol=1e-11, + ) _kernel = kernel diff --git a/momentGW/fock.py b/momentGW/fock.py index 3bbc8487..1d4c1417 100644 --- a/momentGW/fock.py +++ b/momentGW/fock.py @@ -2,6 +2,8 @@ Fock matrix self-consistent loop. """ +from collections import OrderedDict + import numpy as np import scipy from dyson import Lehmann @@ -146,16 +148,14 @@ def minimize_chempot(se, fock, nelec, occupancy=2, x0=0.0, tol=1e-6, maxiter=200 class BaseFockLoop: """Base class for Fock loops.""" - _opts = [] - - # --- Default Fock loop options - - fock_diis_space = 10 - fock_diis_min_space = 1 - conv_tol_nelec = 1e-6 - conv_tol_rdm1 = 1e-8 - max_cycle_inner = 100 - max_cycle_outer = 20 + _opts = OrderedDict( + fock_diis_space=10, + fock_diis_min_space=1, + conv_tol_nelec=1e-6, + conv_tol_rdm1=1e-8, + max_cycle_inner=100, + max_cycle_outer=20, + ) def __init__(self, gw, gf=None, se=None, **kwargs): # Parameters @@ -396,6 +396,25 @@ def nocc(self): """Get the number of occupied MOs.""" return self.gw.nocc + def __getattr__(self, key): + """ + Try to get an attribute from the `_opts` dictionary. If it is + not found, raise an AttributeError. + + Parameters + ---------- + key : str + Attribute key. + + Returns + ------- + value : any + Attribute value. + """ + if key in self._opts: + return self._opts[key] + raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{key}'") + class FockLoop(BaseFockLoop): """ diff --git a/momentGW/fsgw.py b/momentGW/fsgw.py index da0f9ed7..12fe78b9 100644 --- a/momentGW/fsgw.py +++ b/momentGW/fsgw.py @@ -3,6 +3,8 @@ constraints for molecular systems. """ +from collections import OrderedDict + import numpy as np from momentGW import logging, mpi_helper, util @@ -192,32 +194,19 @@ class fsGW(GW): empty `dict`. """ - # --- Default fsGW options - - fock_loop = True - optimise_chempot = True - - # --- Extra fsGW options - - max_cycle = 50 - conv_tol = 1e-8 - conv_tol_moms = 1e-8 - conv_logical = all - diis_space = 8 - damping = 0.0 - solver = GW - solver_options = {} - - _opts = GW._opts + [ - "max_cycle", - "conv_tol", - "conv_tol_moms", - "conv_logical", - "diis_space", - "damping", - "solver", - "solver_options", - ] + _opts = OrderedDict( + **GW._opts, + max_cycle=50, + conv_tol=1e-8, + conv_tol_moms=1e-8, + conv_logical=all, + diis_space=8, + damping=0.0, + solver=GW, + solver_options={}, + ) + _opts["fock_loop"] = True + _opts["optimise_chempot"] = True _kernel = kernel diff --git a/momentGW/pbc/base.py b/momentGW/pbc/base.py index 4ec417f9..f581d679 100644 --- a/momentGW/pbc/base.py +++ b/momentGW/pbc/base.py @@ -3,6 +3,8 @@ conditions. """ +from collections import OrderedDict + import numpy as np from pyscf.pbc.mp.kmp2 import get_nmo, get_nocc @@ -55,17 +57,11 @@ class BaseKGW(BaseGW): `False`. """ - # --- Default KGW options - - compression = None - - # --- Extra PBC options - - fc = False - - _opts = BaseGW._opts + [ - "fc", - ] + _opts = OrderedDict( + **BaseGW._opts, + fc=False, + ) + _opts["compression"] = None get_nmo = get_nmo get_nocc = get_nocc diff --git a/momentGW/pbc/evgw.py b/momentGW/pbc/evgw.py index e5d34a25..21bf4495 100644 --- a/momentGW/pbc/evgw.py +++ b/momentGW/pbc/evgw.py @@ -83,7 +83,7 @@ class evKGW(KGW, evGW): which they are considered zero. Default value is `1e-11`. """ - _opts = util.list_union(KGW._opts, evGW._opts) + _opts = util.dict_union(KGW._opts, evGW._opts) @property def name(self): diff --git a/momentGW/pbc/fsgw.py b/momentGW/pbc/fsgw.py index 6166bc53..3f9bcb7c 100644 --- a/momentGW/pbc/fsgw.py +++ b/momentGW/pbc/fsgw.py @@ -79,11 +79,8 @@ class fsKGW(KGW, fsGW): empty `dict`. """ - # --- Default fsKGW options - - solver = KGW - - _opts = util.list_union(KGW._opts, fsGW._opts) + _opts = util.dict_union(KGW._opts, fsGW._opts) + _opts["solver"] = KGW project_basis = staticmethod(qsKGW.project_basis) self_energy_to_moments = staticmethod(qsKGW.self_energy_to_moments) diff --git a/momentGW/pbc/gw.py b/momentGW/pbc/gw.py index 13630c3c..6a7f3006 100644 --- a/momentGW/pbc/gw.py +++ b/momentGW/pbc/gw.py @@ -61,7 +61,7 @@ class KGW(BaseKGW, GW): `False`. """ - _opts = util.list_union(BaseKGW._opts, GW._opts) + _opts = util.dict_union(BaseKGW._opts, GW._opts) @property def name(self): diff --git a/momentGW/pbc/qsgw.py b/momentGW/pbc/qsgw.py index 261ad755..02dc5b62 100644 --- a/momentGW/pbc/qsgw.py +++ b/momentGW/pbc/qsgw.py @@ -98,11 +98,8 @@ class qsKGW(KGW, qsGW): empty `dict`. """ - # --- Default qsKGW options - - solver = KGW - - _opts = util.list_union(KGW._opts, qsGW._opts) + _opts = util.dict_union(KGW._opts, qsGW._opts) + _opts["solver"] = KGW check_convergence = evKGW.check_convergence diff --git a/momentGW/pbc/scgw.py b/momentGW/pbc/scgw.py index f88dd5e1..a1cc102c 100644 --- a/momentGW/pbc/scgw.py +++ b/momentGW/pbc/scgw.py @@ -72,7 +72,7 @@ class scKGW(KGW, scGW): Damping parameter. Default value is `0.0`. """ - _opts = util.list_union(KGW._opts, scGW._opts) + _opts = util.dict_union(KGW._opts, scGW._opts) check_convergence = evKGW.check_convergence remove_unphysical_poles = evKGW.remove_unphysical_poles diff --git a/momentGW/pbc/uhf/evgw.py b/momentGW/pbc/uhf/evgw.py index ff46a9a3..a01a250f 100644 --- a/momentGW/pbc/uhf/evgw.py +++ b/momentGW/pbc/uhf/evgw.py @@ -84,7 +84,7 @@ class evKUGW(KUGW, evKGW, evUGW): which they are considered zero. Default value is `1e-11`. """ - _opts = util.list_union(evKGW._opts, evKGW._opts, evUGW._opts) + _opts = util.dict_union(evKGW._opts, evKGW._opts, evUGW._opts) @property def name(self): diff --git a/momentGW/pbc/uhf/fsgw.py b/momentGW/pbc/uhf/fsgw.py index 5dead367..b9a95b67 100644 --- a/momentGW/pbc/uhf/fsgw.py +++ b/momentGW/pbc/uhf/fsgw.py @@ -80,11 +80,8 @@ class fsKUGW(KUGW, fsKGW, fsUGW): empty `dict`. """ - # --- Default fsKUGW options - - solver = KUGW - - _opts = util.list_union(KUGW._opts, fsKGW._opts, fsUGW._opts) + _opts = util.dict_union(KUGW._opts, fsKGW._opts, fsUGW._opts) + _opts["solver"] = KUGW project_basis = staticmethod(qsKUGW.project_basis) self_energy_to_moments = staticmethod(qsKUGW.self_energy_to_moments) diff --git a/momentGW/pbc/uhf/gw.py b/momentGW/pbc/uhf/gw.py index 40f93a24..3f6c6654 100644 --- a/momentGW/pbc/uhf/gw.py +++ b/momentGW/pbc/uhf/gw.py @@ -61,7 +61,7 @@ class KUGW(BaseKUGW, KGW, UGW): `False`. """ - _opts = util.list_union(BaseKUGW._opts, KGW._opts, UGW._opts) + _opts = util.dict_union(BaseKUGW._opts, KGW._opts, UGW._opts) @property def name(self): diff --git a/momentGW/pbc/uhf/qsgw.py b/momentGW/pbc/uhf/qsgw.py index 2a18b189..184387ee 100644 --- a/momentGW/pbc/uhf/qsgw.py +++ b/momentGW/pbc/uhf/qsgw.py @@ -99,11 +99,8 @@ class qsKUGW(KUGW, qsKGW, qsUGW): empty `dict`. """ - # --- Default qsKUGW options - - solver = KUGW - - _opts = util.list_union(KUGW._opts, qsKGW._opts, qsUGW._opts) + _opts = util.dict_union(KUGW._opts, qsKGW._opts, qsUGW._opts) + _opts["solver"] = KUGW check_convergence = evKUGW.check_convergence diff --git a/momentGW/pbc/uhf/scgw.py b/momentGW/pbc/uhf/scgw.py index 9b645598..d438071e 100644 --- a/momentGW/pbc/uhf/scgw.py +++ b/momentGW/pbc/uhf/scgw.py @@ -73,7 +73,7 @@ class scKUGW(KUGW, scKGW, scUGW): Damping parameter. Default value is `0.0`. """ - _opts = util.list_union(scKGW._opts, scKGW._opts, scUGW._opts) + _opts = util.dict_union(scKGW._opts, scKGW._opts, scUGW._opts) check_convergence = evKUGW.check_convergence remove_unphysical_poles = evKUGW.remove_unphysical_poles diff --git a/momentGW/qsgw.py b/momentGW/qsgw.py index d09e806c..dc729e57 100644 --- a/momentGW/qsgw.py +++ b/momentGW/qsgw.py @@ -3,6 +3,8 @@ constraints for molecular systems. """ +from collections import OrderedDict + import numpy as np from pyscf import lib @@ -252,37 +254,22 @@ class qsGW(GW): empty `dict`. """ - # --- Extra qsGW options - - max_cycle = 50 - max_cycle_qp = 50 - conv_tol = 1e-8 - conv_tol_moms = 1e-6 - conv_tol_qp = 1e-8 - conv_logical = all - diis_space = 8 - diis_space_qp = 8 - damping = 0.0 - eta = 1e-1 - srg = 0.0 - solver = GW - solver_options = None - - _opts = GW._opts + [ - "max_cycle", - "max_cycle_qp", - "conv_tol", - "conv_tol_moms", - "conv_tol_qp", - "conv_logical", - "diis_space", - "diis_space_qp", - "damping", - "eta", - "srg", - "solver", - "solver_options", - ] + _opts = OrderedDict( + **GW._opts, + max_cycle=50, + max_cycle_qp=50, + conv_tol=1e-8, + conv_tol_moms=1e-6, + conv_tol_qp=1e-8, + conv_logical=all, + diis_space=8, + diis_space_qp=8, + damping=0.0, + eta=1e-1, + srg=0.0, + solver=GW, + solver_options={}, + ) _kernel = kernel diff --git a/momentGW/uhf/evgw.py b/momentGW/uhf/evgw.py index d3fd84f9..31758313 100644 --- a/momentGW/uhf/evgw.py +++ b/momentGW/uhf/evgw.py @@ -80,7 +80,7 @@ class evUGW(UGW, evGW): which they are considered zero. Default value is `1e-11`. """ - _opts = util.list_union(UGW._opts, evGW._opts) + _opts = util.dict_union(UGW._opts, evGW._opts) @property def name(self): diff --git a/momentGW/uhf/fsgw.py b/momentGW/uhf/fsgw.py index a8f5060b..05c9f6a8 100644 --- a/momentGW/uhf/fsgw.py +++ b/momentGW/uhf/fsgw.py @@ -76,11 +76,8 @@ class fsUGW(UGW, fsGW): empty `dict`. """ - # --- Default fsUGW options - - solver = UGW - - _opts = util.list_union(UGW._opts, fsGW._opts) + _opts = util.dict_union(UGW._opts, fsGW._opts) + _opts["solver"] = UGW project_basis = staticmethod(qsUGW.project_basis) self_energy_to_moments = staticmethod(qsUGW.self_energy_to_moments) diff --git a/momentGW/uhf/qsgw.py b/momentGW/uhf/qsgw.py index 48b62160..04b5a725 100644 --- a/momentGW/uhf/qsgw.py +++ b/momentGW/uhf/qsgw.py @@ -94,11 +94,8 @@ class qsUGW(UGW, qsGW): empty `dict`. """ - # --- Default qsUGW options - - solver = UGW - - _opts = util.list_union(UGW._opts, qsGW._opts) + _opts = util.dict_union(UGW._opts, qsGW._opts) + _opts["solver"] = UGW check_convergence = evUGW.check_convergence diff --git a/momentGW/uhf/scgw.py b/momentGW/uhf/scgw.py index 380ae3e9..cb4c052b 100644 --- a/momentGW/uhf/scgw.py +++ b/momentGW/uhf/scgw.py @@ -68,7 +68,7 @@ class scUGW(UGW, scGW): Damping parameter. Default value is `0.0`. """ - _opts = util.list_union(UGW._opts, scGW._opts) + _opts = util.dict_union(UGW._opts, scGW._opts) check_convergence = evUGW.check_convergence remove_unphysical_poles = evUGW.remove_unphysical_poles diff --git a/momentGW/util.py b/momentGW/util.py index 6c62db0a..7c0ffaf4 100644 --- a/momentGW/util.py +++ b/momentGW/util.py @@ -266,6 +266,31 @@ def list_union(*args): return out +def dict_union(*args): + """ + Find the union of a list of dictionaries, preserving the order + of the first occurrence of each key. + + Parameters + ---------- + args : list of dict + Dictionaries to find the union of. + + Returns + ------- + out : dict + Union of the dictionaries. + """ + cache = set() + out = type(args[0])() if len(args) else {} + for arg in args: + for x in arg: + if x not in cache: + cache.add(x) + out[x] = arg[x] + return out + + def build_1h1p_energies(mo_energy, mo_occ): r""" Construct an array of 1h1p energies where elements are From 81720af36c32c00997d4b8f96c8eb2c19f1dfdfd Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Sat, 13 Apr 2024 15:30:52 +0100 Subject: [PATCH 23/33] Implemented __setattr__ --- momentGW/base.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/momentGW/base.py b/momentGW/base.py index 6076a266..39278c4e 100644 --- a/momentGW/base.py +++ b/momentGW/base.py @@ -272,7 +272,7 @@ def mo_occ(self, value): def __getattr__(self, key): """ Try to get an attribute from the `_opts` dictionary. If it is - not found, raise an AttributeError. + not found, raise an `AttributeError`. Parameters ---------- @@ -288,6 +288,21 @@ def __getattr__(self, key): return self._opts[key] raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{key}'") + def __setattr__(self, key, val): + """ + Try to set an attribute from the `_opts` dictionary. If it is + not found, raise an `AttributeError`. + + Parameters + ---------- + key : str + Attribute key. + """ + if key in self._opts: + self._opts[key] = val + else: + super().__setattr__(key, val) + class BaseGW(Base): """Base class for moment-constrained GW solvers. From 9bfe237b703644a002de3ba155654d08b9bc32a3 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Sat, 13 Apr 2024 16:17:08 +0100 Subject: [PATCH 24/33] Refactor to _defaults with _opts set at object runtime --- momentGW/base.py | 33 ++++++++++++++++----------------- momentGW/bse.py | 8 ++++---- momentGW/evgw.py | 4 ++-- momentGW/fock.py | 28 ++++++++++++++++++++++------ momentGW/fsgw.py | 14 ++++++++------ momentGW/pbc/base.py | 6 +++--- momentGW/pbc/evgw.py | 2 +- momentGW/pbc/fsgw.py | 4 ++-- momentGW/pbc/gw.py | 2 +- momentGW/pbc/qsgw.py | 4 ++-- momentGW/pbc/scgw.py | 2 +- momentGW/pbc/uhf/evgw.py | 2 +- momentGW/pbc/uhf/fsgw.py | 4 ++-- momentGW/pbc/uhf/gw.py | 2 +- momentGW/pbc/uhf/qsgw.py | 4 ++-- momentGW/pbc/uhf/scgw.py | 2 +- momentGW/qsgw.py | 10 ++++++---- momentGW/uhf/evgw.py | 2 +- momentGW/uhf/fsgw.py | 4 ++-- momentGW/uhf/qsgw.py | 4 ++-- momentGW/uhf/scgw.py | 2 +- 21 files changed, 81 insertions(+), 62 deletions(-) diff --git a/momentGW/base.py b/momentGW/base.py index 39278c4e..1c6b811f 100644 --- a/momentGW/base.py +++ b/momentGW/base.py @@ -12,9 +12,8 @@ class Base: """Base class.""" - # Options are stored in a dictionary, but can be accessed as - # attributes using the overridden `__getattr__` method - _opts = OrderedDict() + # Default options + _defaults = OrderedDict() def __init__( self, @@ -24,6 +23,13 @@ def __init__( mo_occ=None, **kwargs, ): + # Options + self._opts = self._defaults.copy() + for key, val in kwargs.items(): + if key not in self._opts: + raise AttributeError(f"{key} is not a valid option for {self.name}") + self._opts[key] = val + # Parameters self._scf = mf self._mo_energy = mo_energy @@ -31,12 +37,6 @@ def __init__( self._mo_occ = mo_occ self.frozen = None - # Options - for key, val in kwargs.items(): - if not hasattr(self, key): - raise AttributeError(f"{key} is not a valid option for {self.name}") - setattr(self, key, val) - # Logging init_logging() @@ -90,20 +90,19 @@ def _check_modified(val, old): return val != old # Loop over options - for key in self._opts: + for key, val in self._opts.items(): if self._opt_is_used(key): - val = getattr(self, key) if isinstance(val, dict): # Format each entry of the dictionary keys, vals = zip(*val.items()) if val else ((), ()) - old = self.__class__._opts.get(key, None) + old = self.__class__._defaults.get(key, None) keys = [f"{key}.{k}" for k in keys] mods = [old and _check_modified(v, old[k]) for k, v in val.items()] else: # Format the single value keys = [key] vals = [val] - mods = [_check_modified(val, self.__class__._opts.get(key, None))] + mods = [_check_modified(val, self._defaults.get(key, None))] # Loop over entries for key, val, mod in zip(keys, vals, mods): @@ -284,9 +283,9 @@ def __getattr__(self, key): value : any Attribute value. """ - if key in self._opts: + if key in self._defaults: return self._opts[key] - raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{key}'") + raise AttributeError def __setattr__(self, key, val): """ @@ -298,7 +297,7 @@ def __setattr__(self, key, val): key : str Attribute key. """ - if key in self._opts: + if key in self._defaults: self._opts[key] = val else: super().__setattr__(key, val) @@ -344,7 +343,7 @@ class BaseGW(Base): implementation requires a filepath to import the THC integrals. """ - _opts = OrderedDict( + _defaults = OrderedDict( diagonal_se=False, polarizability="drpa", npoints=48, diff --git a/momentGW/bse.py b/momentGW/bse.py index 52c06d07..07891ae8 100644 --- a/momentGW/bse.py +++ b/momentGW/bse.py @@ -72,8 +72,8 @@ class BSE(Base): Default value is `"singlet"`. """ - _opts = OrderedDict( - **Base._opts, + _defaults = OrderedDict( + **Base._defaults, excitation="singlet", polarizability=None, ) @@ -488,8 +488,8 @@ class cpBSE(BSE): Default value is `"singlet"`. """ - _opts = OrderedDict( - **BSE._opts, + _defaults = OrderedDict( + **BSE._defaults, scale=None, grid=None, eta=0.1, diff --git a/momentGW/evgw.py b/momentGW/evgw.py index aafe1fc6..6cda563f 100644 --- a/momentGW/evgw.py +++ b/momentGW/evgw.py @@ -188,8 +188,8 @@ class evGW(GW): which they are considered zero. Default value is `1e-11`. """ - _opts = OrderedDict( - **GW._opts, + _defaults = OrderedDict( + **GW._defaults, g0=False, w0=False, max_cycle=50, diff --git a/momentGW/fock.py b/momentGW/fock.py index 1d4c1417..d631aff4 100644 --- a/momentGW/fock.py +++ b/momentGW/fock.py @@ -148,7 +148,7 @@ def minimize_chempot(se, fock, nelec, occupancy=2, x0=0.0, tol=1e-6, maxiter=200 class BaseFockLoop: """Base class for Fock loops.""" - _opts = OrderedDict( + _defaults = OrderedDict( fock_diis_space=10, fock_diis_min_space=1, conv_tol_nelec=1e-6, @@ -162,10 +162,11 @@ def __init__(self, gw, gf=None, se=None, **kwargs): self.gw = gw # Options + self._opts = self._defaults.copy() for key, val in kwargs.items(): - if not hasattr(self, key): + if key not in self._opts: raise AttributeError(f"{key} is not a valid option for {self.name}") - setattr(self, key, val) + self._opts[key] = val # Attributes self._h1e = None @@ -399,7 +400,7 @@ def nocc(self): def __getattr__(self, key): """ Try to get an attribute from the `_opts` dictionary. If it is - not found, raise an AttributeError. + not found, raise an `AttributeError`. Parameters ---------- @@ -411,9 +412,24 @@ def __getattr__(self, key): value : any Attribute value. """ - if key in self._opts: + if key in self._defaults: return self._opts[key] - raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{key}'") + raise AttributeError + + def __setattr__(self, key, val): + """ + Try to set an attribute from the `_opts` dictionary. If it is + not found, raise an `AttributeError`. + + Parameters + ---------- + key : str + Attribute key. + """ + if key in self._defaults: + self._opts[key] = val + else: + super().__setattr__(key, val) class FockLoop(BaseFockLoop): diff --git a/momentGW/fsgw.py b/momentGW/fsgw.py index 12fe78b9..fc6001dc 100644 --- a/momentGW/fsgw.py +++ b/momentGW/fsgw.py @@ -3,6 +3,7 @@ constraints for molecular systems. """ +import copy from collections import OrderedDict import numpy as np @@ -69,8 +70,9 @@ def kernel( # Get the solver solver_options = {} if not gw.solver_options else gw.solver_options.copy() - for key in gw.solver._opts: - solver_options[key] = solver_options.get(key, getattr(gw, key, getattr(gw.solver, key))) + for key in gw.solver._defaults: + if key not in solver_options: + solver_options[key] = copy.deepcopy(gw._opts.get(key, gw.solver._defaults[key])) with logging.with_silent(): subgw = gw.solver(gw._scf, **solver_options) subgw.frozen = gw.frozen @@ -194,8 +196,8 @@ class fsGW(GW): empty `dict`. """ - _opts = OrderedDict( - **GW._opts, + _defaults = OrderedDict( + **GW._defaults, max_cycle=50, conv_tol=1e-8, conv_tol_moms=1e-8, @@ -205,8 +207,8 @@ class fsGW(GW): solver=GW, solver_options={}, ) - _opts["fock_loop"] = True - _opts["optimise_chempot"] = True + _defaults["fock_loop"] = True + _defaults["optimise_chempot"] = True _kernel = kernel diff --git a/momentGW/pbc/base.py b/momentGW/pbc/base.py index f581d679..016b8669 100644 --- a/momentGW/pbc/base.py +++ b/momentGW/pbc/base.py @@ -57,11 +57,11 @@ class BaseKGW(BaseGW): `False`. """ - _opts = OrderedDict( - **BaseGW._opts, + _defaults = OrderedDict( + **BaseGW._defaults, fc=False, ) - _opts["compression"] = None + _defaults["compression"] = None get_nmo = get_nmo get_nocc = get_nocc diff --git a/momentGW/pbc/evgw.py b/momentGW/pbc/evgw.py index 21bf4495..8b4f44ca 100644 --- a/momentGW/pbc/evgw.py +++ b/momentGW/pbc/evgw.py @@ -83,7 +83,7 @@ class evKGW(KGW, evGW): which they are considered zero. Default value is `1e-11`. """ - _opts = util.dict_union(KGW._opts, evGW._opts) + _defaults = util.dict_union(KGW._defaults, evGW._defaults) @property def name(self): diff --git a/momentGW/pbc/fsgw.py b/momentGW/pbc/fsgw.py index 3f9bcb7c..808a8bce 100644 --- a/momentGW/pbc/fsgw.py +++ b/momentGW/pbc/fsgw.py @@ -79,8 +79,8 @@ class fsKGW(KGW, fsGW): empty `dict`. """ - _opts = util.dict_union(KGW._opts, fsGW._opts) - _opts["solver"] = KGW + _defaults = util.dict_union(KGW._defaults, fsGW._defaults) + _defaults["solver"] = KGW project_basis = staticmethod(qsKGW.project_basis) self_energy_to_moments = staticmethod(qsKGW.self_energy_to_moments) diff --git a/momentGW/pbc/gw.py b/momentGW/pbc/gw.py index 6a7f3006..f0991ea6 100644 --- a/momentGW/pbc/gw.py +++ b/momentGW/pbc/gw.py @@ -61,7 +61,7 @@ class KGW(BaseKGW, GW): `False`. """ - _opts = util.dict_union(BaseKGW._opts, GW._opts) + _defaults = util.dict_union(BaseKGW._defaults, GW._defaults) @property def name(self): diff --git a/momentGW/pbc/qsgw.py b/momentGW/pbc/qsgw.py index 02dc5b62..39acf88d 100644 --- a/momentGW/pbc/qsgw.py +++ b/momentGW/pbc/qsgw.py @@ -98,8 +98,8 @@ class qsKGW(KGW, qsGW): empty `dict`. """ - _opts = util.dict_union(KGW._opts, qsGW._opts) - _opts["solver"] = KGW + _defaults = util.dict_union(KGW._defaults, qsGW._defaults) + _defaults["solver"] = KGW check_convergence = evKGW.check_convergence diff --git a/momentGW/pbc/scgw.py b/momentGW/pbc/scgw.py index a1cc102c..862f3f26 100644 --- a/momentGW/pbc/scgw.py +++ b/momentGW/pbc/scgw.py @@ -72,7 +72,7 @@ class scKGW(KGW, scGW): Damping parameter. Default value is `0.0`. """ - _opts = util.dict_union(KGW._opts, scGW._opts) + _defaults = util.dict_union(KGW._defaults, scGW._defaults) check_convergence = evKGW.check_convergence remove_unphysical_poles = evKGW.remove_unphysical_poles diff --git a/momentGW/pbc/uhf/evgw.py b/momentGW/pbc/uhf/evgw.py index a01a250f..52db4a32 100644 --- a/momentGW/pbc/uhf/evgw.py +++ b/momentGW/pbc/uhf/evgw.py @@ -84,7 +84,7 @@ class evKUGW(KUGW, evKGW, evUGW): which they are considered zero. Default value is `1e-11`. """ - _opts = util.dict_union(evKGW._opts, evKGW._opts, evUGW._opts) + _defaults = util.dict_union(evKGW._defaults, evKGW._defaults, evUGW._defaults) @property def name(self): diff --git a/momentGW/pbc/uhf/fsgw.py b/momentGW/pbc/uhf/fsgw.py index b9a95b67..994f5ce9 100644 --- a/momentGW/pbc/uhf/fsgw.py +++ b/momentGW/pbc/uhf/fsgw.py @@ -80,8 +80,8 @@ class fsKUGW(KUGW, fsKGW, fsUGW): empty `dict`. """ - _opts = util.dict_union(KUGW._opts, fsKGW._opts, fsUGW._opts) - _opts["solver"] = KUGW + _defaults = util.dict_union(KUGW._defaults, fsKGW._defaults, fsUGW._defaults) + _defaults["solver"] = KUGW project_basis = staticmethod(qsKUGW.project_basis) self_energy_to_moments = staticmethod(qsKUGW.self_energy_to_moments) diff --git a/momentGW/pbc/uhf/gw.py b/momentGW/pbc/uhf/gw.py index 3f6c6654..646afde9 100644 --- a/momentGW/pbc/uhf/gw.py +++ b/momentGW/pbc/uhf/gw.py @@ -61,7 +61,7 @@ class KUGW(BaseKUGW, KGW, UGW): `False`. """ - _opts = util.dict_union(BaseKUGW._opts, KGW._opts, UGW._opts) + _defaults = util.dict_union(BaseKUGW._defaults, KGW._defaults, UGW._defaults) @property def name(self): diff --git a/momentGW/pbc/uhf/qsgw.py b/momentGW/pbc/uhf/qsgw.py index 184387ee..2aa40bc9 100644 --- a/momentGW/pbc/uhf/qsgw.py +++ b/momentGW/pbc/uhf/qsgw.py @@ -99,8 +99,8 @@ class qsKUGW(KUGW, qsKGW, qsUGW): empty `dict`. """ - _opts = util.dict_union(KUGW._opts, qsKGW._opts, qsUGW._opts) - _opts["solver"] = KUGW + _defaults = util.dict_union(KUGW._defaults, qsKGW._defaults, qsUGW._defaults) + _defaults["solver"] = KUGW check_convergence = evKUGW.check_convergence diff --git a/momentGW/pbc/uhf/scgw.py b/momentGW/pbc/uhf/scgw.py index d438071e..9703e577 100644 --- a/momentGW/pbc/uhf/scgw.py +++ b/momentGW/pbc/uhf/scgw.py @@ -73,7 +73,7 @@ class scKUGW(KUGW, scKGW, scUGW): Damping parameter. Default value is `0.0`. """ - _opts = util.dict_union(scKGW._opts, scKGW._opts, scUGW._opts) + _defaults = util.dict_union(scKGW._defaults, scKGW._defaults, scUGW._defaults) check_convergence = evKUGW.check_convergence remove_unphysical_poles = evKUGW.remove_unphysical_poles diff --git a/momentGW/qsgw.py b/momentGW/qsgw.py index dc729e57..16cb16b6 100644 --- a/momentGW/qsgw.py +++ b/momentGW/qsgw.py @@ -3,6 +3,7 @@ constraints for molecular systems. """ +import copy from collections import OrderedDict import numpy as np @@ -78,8 +79,9 @@ def kernel( # Get the solver solver_options = {} if not gw.solver_options else gw.solver_options.copy() - for key in gw.solver._opts: - solver_options[key] = solver_options.get(key, getattr(gw, key, getattr(gw.solver, key))) + for key in gw.solver._defaults: + if key not in solver_options: + solver_options[key] = copy.deepcopy(gw._opts.get(key, gw.solver._defaults[key])) with logging.with_silent(): subgw = gw.solver(gw._scf, **solver_options) subgw.frozen = gw.frozen @@ -254,8 +256,8 @@ class qsGW(GW): empty `dict`. """ - _opts = OrderedDict( - **GW._opts, + _defaults = OrderedDict( + **GW._defaults, max_cycle=50, max_cycle_qp=50, conv_tol=1e-8, diff --git a/momentGW/uhf/evgw.py b/momentGW/uhf/evgw.py index 31758313..2715c07d 100644 --- a/momentGW/uhf/evgw.py +++ b/momentGW/uhf/evgw.py @@ -80,7 +80,7 @@ class evUGW(UGW, evGW): which they are considered zero. Default value is `1e-11`. """ - _opts = util.dict_union(UGW._opts, evGW._opts) + _defaults = util.dict_union(UGW._defaults, evGW._defaults) @property def name(self): diff --git a/momentGW/uhf/fsgw.py b/momentGW/uhf/fsgw.py index 05c9f6a8..121b1f34 100644 --- a/momentGW/uhf/fsgw.py +++ b/momentGW/uhf/fsgw.py @@ -76,8 +76,8 @@ class fsUGW(UGW, fsGW): empty `dict`. """ - _opts = util.dict_union(UGW._opts, fsGW._opts) - _opts["solver"] = UGW + _defaults = util.dict_union(UGW._defaults, fsGW._defaults) + _defaults["solver"] = UGW project_basis = staticmethod(qsUGW.project_basis) self_energy_to_moments = staticmethod(qsUGW.self_energy_to_moments) diff --git a/momentGW/uhf/qsgw.py b/momentGW/uhf/qsgw.py index 04b5a725..81fa02e0 100644 --- a/momentGW/uhf/qsgw.py +++ b/momentGW/uhf/qsgw.py @@ -94,8 +94,8 @@ class qsUGW(UGW, qsGW): empty `dict`. """ - _opts = util.dict_union(UGW._opts, qsGW._opts) - _opts["solver"] = UGW + _defaults = util.dict_union(UGW._defaults, qsGW._defaults) + _defaults["solver"] = UGW check_convergence = evUGW.check_convergence diff --git a/momentGW/uhf/scgw.py b/momentGW/uhf/scgw.py index cb4c052b..b5098e77 100644 --- a/momentGW/uhf/scgw.py +++ b/momentGW/uhf/scgw.py @@ -68,7 +68,7 @@ class scUGW(UGW, scGW): Damping parameter. Default value is `0.0`. """ - _opts = util.dict_union(UGW._opts, scGW._opts) + _defaults = util.dict_union(UGW._defaults, scGW._defaults) check_convergence = evUGW.check_convergence remove_unphysical_poles = evUGW.remove_unphysical_poles From 6c637675799a2f60118287aecc857419aabdc19c Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Sat, 13 Apr 2024 16:40:09 +0100 Subject: [PATCH 25/33] Fix fsGW options --- momentGW/pbc/fsgw.py | 2 ++ momentGW/pbc/uhf/fsgw.py | 2 ++ momentGW/uhf/fsgw.py | 2 ++ 3 files changed, 6 insertions(+) diff --git a/momentGW/pbc/fsgw.py b/momentGW/pbc/fsgw.py index 808a8bce..4908ce95 100644 --- a/momentGW/pbc/fsgw.py +++ b/momentGW/pbc/fsgw.py @@ -80,6 +80,8 @@ class fsKGW(KGW, fsGW): """ _defaults = util.dict_union(KGW._defaults, fsGW._defaults) + _defaults["fock_loop"] = True + _defaults["optimise_chempot"] = True _defaults["solver"] = KGW project_basis = staticmethod(qsKGW.project_basis) diff --git a/momentGW/pbc/uhf/fsgw.py b/momentGW/pbc/uhf/fsgw.py index 994f5ce9..f01c4501 100644 --- a/momentGW/pbc/uhf/fsgw.py +++ b/momentGW/pbc/uhf/fsgw.py @@ -81,6 +81,8 @@ class fsKUGW(KUGW, fsKGW, fsUGW): """ _defaults = util.dict_union(KUGW._defaults, fsKGW._defaults, fsUGW._defaults) + _defaults["fock_loop"] = True + _defaults["optimise_chempot"] = True _defaults["solver"] = KUGW project_basis = staticmethod(qsKUGW.project_basis) diff --git a/momentGW/uhf/fsgw.py b/momentGW/uhf/fsgw.py index 121b1f34..a9cc5a33 100644 --- a/momentGW/uhf/fsgw.py +++ b/momentGW/uhf/fsgw.py @@ -77,6 +77,8 @@ class fsUGW(UGW, fsGW): """ _defaults = util.dict_union(UGW._defaults, fsGW._defaults) + _defaults["fock_loop"] = True + _defaults["optimise_chempot"] = True _defaults["solver"] = UGW project_basis = staticmethod(qsUGW.project_basis) From 8bb2bb276cbe3c06841ce82a0be5c00048050c93 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Sat, 13 Apr 2024 16:42:27 +0100 Subject: [PATCH 26/33] Make frozen a keyword argument --- momentGW/base.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/momentGW/base.py b/momentGW/base.py index 1c6b811f..e26bffbc 100644 --- a/momentGW/base.py +++ b/momentGW/base.py @@ -21,6 +21,7 @@ def __init__( mo_energy=None, mo_coeff=None, mo_occ=None, + frozen=None, **kwargs, ): # Options @@ -35,7 +36,7 @@ def __init__( self._mo_energy = mo_energy self._mo_coeff = mo_coeff self._mo_occ = mo_occ - self.frozen = None + self.frozen = frozen # Logging init_logging() From b2c267b9769540b7d372912967a2fe3899b23451 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Sat, 13 Apr 2024 19:34:53 +0100 Subject: [PATCH 27/33] Now showing inherited members --- docs/conf.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 0f7901b9..9efdc142 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -3,8 +3,6 @@ import os import sys -from momentGW.base import Base - sys.path.insert(0, os.path.abspath("../")) project = "momentGW" @@ -27,7 +25,8 @@ "show-inheritance": True, "members": True, "private-members": False, - "special-members": True, + "special-members": False, + "inherited-members": True, "undoc-members": False, "member-order": "groupwise", "typehints": "description", From e109fdb9925fad2fec6519d50d384697f2c6ad9b Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Sat, 13 Apr 2024 19:36:09 +0100 Subject: [PATCH 28/33] Remove leftover pyscf size functions --- momentGW/pbc/base.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/momentGW/pbc/base.py b/momentGW/pbc/base.py index 016b8669..2282ba94 100644 --- a/momentGW/pbc/base.py +++ b/momentGW/pbc/base.py @@ -6,7 +6,6 @@ from collections import OrderedDict import numpy as np -from pyscf.pbc.mp.kmp2 import get_nmo, get_nocc from momentGW import logging from momentGW.base import Base, BaseGW @@ -63,9 +62,6 @@ class BaseKGW(BaseGW): ) _defaults["compression"] = None - get_nmo = get_nmo - get_nocc = get_nocc - def __init__(self, mf, **kwargs): super().__init__(mf, **kwargs) From 2b6122668064e33633e43912679994f8c636a348 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Sun, 14 Apr 2024 11:03:42 +0100 Subject: [PATCH 29/33] RTD themes --- docs/conf.py | 18 ++++-------------- pyproject.toml | 1 + 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 9efdc142..4e7d7086 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -16,19 +16,20 @@ "sphinx.ext.mathjax", "sphinx.ext.viewcode", "sphinx_mdinclude", + "sphinx_rtd_theme", "numpydoc", ] templates_path = ["_templates"] autodoc_default_options = { - "show-inheritance": True, "members": True, + "member-order": "bysource", + "show-inheritance": True, "private-members": False, "special-members": False, "inherited-members": True, "undoc-members": False, - "member-order": "groupwise", "typehints": "description", } @@ -46,18 +47,7 @@ def autodoc_skip_member(app, what, name, obj, skip, options): source_suffix = [".rst", ".md"] master_doc = "index" -html_theme = "alabaster" -html_theme_options = { - "fixed_sidebar": True, - "badge_branch": "master", - "github_user": "BoothGroup", - "github_repo": "momentGW", - "github_button": False, - "extra_nav_links": { - "GitHub": "https://github.com/BoothGroup/momentGW", - "Report Issues": "https://github.com/BoothGroup/momentGW/issues", - }, -} +html_theme = "sphinx_rtd_theme" html_sidebars = { "**": [ "about.html", diff --git a/pyproject.toml b/pyproject.toml index a7921e67..ff1fe19d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,6 +56,7 @@ dev = [ "pytest-env>=1.1.0", "sphinx>=4.0.0", "sphinx-mdinclude>=0.5.0", + "sphinx_rtd_theme>=1.0.0", "numpydoc>=1.1.0", ] mpi = [ From b8969fca9df7dbaefb7390a5abeb71e859215ed8 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Sun, 14 Apr 2024 12:35:55 +0100 Subject: [PATCH 30/33] jinja2 templates for API docs --- docs/Makefile | 14 ++- docs/_templates/autoapi/base/base.rst | 7 ++ docs/_templates/autoapi/index.rst | 15 +++ docs/_templates/autoapi/python/attribute.rst | 1 + docs/_templates/autoapi/python/class.rst | 60 +++++++++++ docs/_templates/autoapi/python/data.rst | 37 +++++++ docs/_templates/autoapi/python/exception.rst | 1 + docs/_templates/autoapi/python/function.rst | 15 +++ docs/_templates/autoapi/python/method.rst | 19 ++++ docs/_templates/autoapi/python/module.rst | 104 +++++++++++++++++++ docs/_templates/autoapi/python/package.rst | 1 + docs/_templates/autoapi/python/property.rst | 15 +++ docs/api.rst | 7 -- docs/conf.py | 38 +++---- docs/index.rst | 7 +- 15 files changed, 306 insertions(+), 35 deletions(-) create mode 100644 docs/_templates/autoapi/base/base.rst create mode 100644 docs/_templates/autoapi/index.rst create mode 100644 docs/_templates/autoapi/python/attribute.rst create mode 100644 docs/_templates/autoapi/python/class.rst create mode 100644 docs/_templates/autoapi/python/data.rst create mode 100644 docs/_templates/autoapi/python/exception.rst create mode 100644 docs/_templates/autoapi/python/function.rst create mode 100644 docs/_templates/autoapi/python/method.rst create mode 100644 docs/_templates/autoapi/python/module.rst create mode 100644 docs/_templates/autoapi/python/package.rst create mode 100644 docs/_templates/autoapi/python/property.rst delete mode 100644 docs/api.rst diff --git a/docs/Makefile b/docs/Makefile index 24e2a024..85158a06 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -4,10 +4,18 @@ SOURCEDIR = . BUILDDIR = _build html: - sphinx-apidoc -o api/ -f -e -M ../momentGW sphinx-build -M html . _build +postprocess: + # Post-processing generated files: + # If there is a line with a "Duplicate implicit target name" error, remove it: + for file in `find _build/html -name "*.html"`; do \ + sed -i '/Duplicate implicit target name/d' $$file; \ + done + +docs: html postprocess + clean: - rm -rf _build api + rm -rf _build autoapi -.PHONY: html +.PHONY: html postprocess clean diff --git a/docs/_templates/autoapi/base/base.rst b/docs/_templates/autoapi/base/base.rst new file mode 100644 index 00000000..45c8dd7f --- /dev/null +++ b/docs/_templates/autoapi/base/base.rst @@ -0,0 +1,7 @@ +.. {{ obj.type }}:: {{ obj.name }} + + {% if summary %} + + {{ obj.summary }} + + {% endif %} diff --git a/docs/_templates/autoapi/index.rst b/docs/_templates/autoapi/index.rst new file mode 100644 index 00000000..95d0ad89 --- /dev/null +++ b/docs/_templates/autoapi/index.rst @@ -0,0 +1,15 @@ +API Reference +============= + +This page contains auto-generated API reference documentation [#f1]_. + +.. toctree:: + :titlesonly: + + {% for page in pages %} + {% if page.top_level_object and page.display %} + {{ page.include_path }} + {% endif %} + {% endfor %} + +.. [#f1] Created with `sphinx-autoapi `_ diff --git a/docs/_templates/autoapi/python/attribute.rst b/docs/_templates/autoapi/python/attribute.rst new file mode 100644 index 00000000..ebaba555 --- /dev/null +++ b/docs/_templates/autoapi/python/attribute.rst @@ -0,0 +1 @@ +{% extends "python/data.rst" %} diff --git a/docs/_templates/autoapi/python/class.rst b/docs/_templates/autoapi/python/class.rst new file mode 100644 index 00000000..a584dcd6 --- /dev/null +++ b/docs/_templates/autoapi/python/class.rst @@ -0,0 +1,60 @@ +{% if obj.display %} +.. py:{{ obj.type }}:: {{ obj.short_name }}{% if obj.args %}({{ obj.args }}){% endif %} + +{% for (args, return_annotation) in obj.overloads %} + {{ " " * (obj.type | length) }} {{ obj.short_name }}{% if args %}({{ args }}){% endif %} + +{% endfor %} + + + {% if obj.bases %} + {% if "show-inheritance" in autoapi_options %} + Bases: {% for base in obj.bases %}{{ base|link_objs }}{% if not loop.last %}, {% endif %}{% endfor %} + {% endif %} + + + {% if "show-inheritance-diagram" in autoapi_options and obj.bases != ["object"] %} + .. autoapi-inheritance-diagram:: {{ obj.obj["full_name"] }} + :parts: 1 + {% if "private-members" in autoapi_options %} + :private-bases: + {% endif %} + + {% endif %} + {% endif %} + {% if obj.docstring %} + {{ obj.docstring|indent(3) }} + {% endif %} + {% if "inherited-members" in autoapi_options %} + {% set visible_classes = obj.classes|selectattr("display")|list %} + {% else %} + {% set visible_classes = obj.classes|rejectattr("inherited")|selectattr("display")|list %} + {% endif %} + {% for klass in visible_classes %} + {{ klass.render()|indent(3) }} + {% endfor %} + {% if "inherited-members" in autoapi_options %} + {% set visible_properties = obj.properties|selectattr("display")|list %} + {% else %} + {% set visible_properties = obj.properties|rejectattr("inherited")|selectattr("display")|list %} + {% endif %} + {% for property in visible_properties %} + {{ property.render()|indent(3) }} + {% endfor %} + {% if "inherited-members" in autoapi_options %} + {% set visible_attributes = obj.attributes|selectattr("display")|list %} + {% else %} + {% set visible_attributes = obj.attributes|rejectattr("inherited")|selectattr("display")|list %} + {% endif %} + {% for attribute in visible_attributes %} + {{ attribute.render()|indent(3) }} + {% endfor %} + {% if "inherited-members" in autoapi_options %} + {% set visible_methods = obj.methods|selectattr("display")|list %} + {% else %} + {% set visible_methods = obj.methods|rejectattr("inherited")|selectattr("display")|list %} + {% endif %} + {% for method in visible_methods %} + {{ method.render()|indent(3) }} + {% endfor %} +{% endif %} diff --git a/docs/_templates/autoapi/python/data.rst b/docs/_templates/autoapi/python/data.rst new file mode 100644 index 00000000..3d12b2d0 --- /dev/null +++ b/docs/_templates/autoapi/python/data.rst @@ -0,0 +1,37 @@ +{% if obj.display %} +.. py:{{ obj.type }}:: {{ obj.name }} + {%- if obj.annotation is not none %} + + :type: {%- if obj.annotation %} {{ obj.annotation }}{%- endif %} + + {%- endif %} + + {%- if obj.value is not none %} + + :value: {% if obj.value is string and obj.value.splitlines()|count > 1 -%} + Multiline-String + + .. raw:: html + +
Show Value + + .. code-block:: python + + """{{ obj.value|indent(width=8,blank=true) }}""" + + .. raw:: html + +
+ + {%- else -%} + {%- if obj.value is string -%} + {{ "%r" % obj.value|string|truncate(100) }} + {%- else -%} + {{ obj.value|string|truncate(100) }} + {%- endif -%} + {%- endif %} + {%- endif %} + + + {{ obj.docstring|indent(3) }} +{% endif %} diff --git a/docs/_templates/autoapi/python/exception.rst b/docs/_templates/autoapi/python/exception.rst new file mode 100644 index 00000000..92f3d38f --- /dev/null +++ b/docs/_templates/autoapi/python/exception.rst @@ -0,0 +1 @@ +{% extends "python/class.rst" %} diff --git a/docs/_templates/autoapi/python/function.rst b/docs/_templates/autoapi/python/function.rst new file mode 100644 index 00000000..778ba9a8 --- /dev/null +++ b/docs/_templates/autoapi/python/function.rst @@ -0,0 +1,15 @@ +{% if obj.display %} +.. py:function:: {{ obj.short_name }}({{ obj.args }}){% if obj.return_annotation is not none %} -> {{ obj.return_annotation }}{% endif %} + +{% for (args, return_annotation) in obj.overloads %} + {{ obj.short_name }}({{ args }}){% if return_annotation is not none %} -> {{ return_annotation }}{% endif %} + +{% endfor %} + {% for property in obj.properties %} + :{{ property }}: + {% endfor %} + + {% if obj.docstring %} + {{ obj.docstring|indent(3) }} + {% endif %} +{% endif %} diff --git a/docs/_templates/autoapi/python/method.rst b/docs/_templates/autoapi/python/method.rst new file mode 100644 index 00000000..f50a1bd6 --- /dev/null +++ b/docs/_templates/autoapi/python/method.rst @@ -0,0 +1,19 @@ +{%- if obj.display %} +.. py:method:: {{ obj.short_name }}({{ obj.args }}){% if obj.return_annotation is not none %} -> {{ obj.return_annotation }}{% endif %} + +{% for (args, return_annotation) in obj.overloads %} + {{ obj.short_name }}({{ args }}){% if return_annotation is not none %} -> {{ return_annotation }}{% endif %} + +{% endfor %} + {% if obj.properties %} + {% for property in obj.properties %} + :{{ property }}: + {% endfor %} + + {% else %} + + {% endif %} + {% if obj.docstring %} + {{ obj.docstring|indent(3) }} + {% endif %} +{% endif %} diff --git a/docs/_templates/autoapi/python/module.rst b/docs/_templates/autoapi/python/module.rst new file mode 100644 index 00000000..ed0eb092 --- /dev/null +++ b/docs/_templates/autoapi/python/module.rst @@ -0,0 +1,104 @@ +{% if not obj.display %} +:orphan: + +{% endif %} +:py:mod:`{{ obj.name }}` +=========={{ "=" * obj.name|length }} + +.. py:module:: {{ obj.name }} + +{% if obj.docstring %} +.. autoapi-nested-parse:: + + {{ obj.docstring|indent(3) }} + +{% endif %} + +{% block subpackages %} +{% set visible_subpackages = obj.subpackages|selectattr("display")|list %} +{% if visible_subpackages %} + +{% endif %} +{% endblock %} +{% block submodules %} +{% set visible_submodules = obj.submodules|selectattr("display")|list %} +{% if visible_submodules %} +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + +{% for submodule in visible_submodules %} + {{ submodule.short_name }}/index.rst +{% endfor %} + + +{% endif %} +{% endblock %} +{% block content %} +{% if obj.all is not none %} +{% set visible_children = obj.children|selectattr("short_name", "in", obj.all)|list %} +{% elif obj.type is equalto("package") %} +{% set visible_children = obj.children|selectattr("display")|list %} +{% else %} +{% set visible_children = obj.children|selectattr("display")|rejectattr("imported")|list %} +{% endif %} +{% if visible_children %} +{{ obj.type|title }} Contents +{{ "-" * obj.type|length }}--------- + +{% set visible_classes = visible_children|selectattr("type", "equalto", "class")|list %} +{% set visible_functions = visible_children|selectattr("type", "equalto", "function")|list %} +{% set visible_attributes = visible_children|selectattr("type", "equalto", "data")|list %} +{% if "show-module-summary" in autoapi_options and (visible_classes or visible_functions) %} +{% block classes scoped %} +{% if visible_classes %} +Classes +~~~~~~~ + +.. autoapisummary:: + +{% for klass in visible_classes %} + {{ klass.id }} +{% endfor %} + + +{% endif %} +{% endblock %} + +{% block functions scoped %} +{% if visible_functions %} +Functions +~~~~~~~~~ + +.. autoapisummary:: + +{% for function in visible_functions %} + {{ function.id }} +{% endfor %} + + +{% endif %} +{% endblock %} + +{% block attributes scoped %} +{% if visible_attributes %} +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + +{% for attribute in visible_attributes %} + {{ attribute.id }} +{% endfor %} + + +{% endif %} +{% endblock %} +{% endif %} +{% for obj_item in visible_children %} +{{ obj_item.render()|indent(0) }} +{% endfor %} +{% endif %} +{% endblock %} diff --git a/docs/_templates/autoapi/python/package.rst b/docs/_templates/autoapi/python/package.rst new file mode 100644 index 00000000..fb9a6496 --- /dev/null +++ b/docs/_templates/autoapi/python/package.rst @@ -0,0 +1 @@ +{% extends "python/module.rst" %} diff --git a/docs/_templates/autoapi/python/property.rst b/docs/_templates/autoapi/python/property.rst new file mode 100644 index 00000000..70af2423 --- /dev/null +++ b/docs/_templates/autoapi/python/property.rst @@ -0,0 +1,15 @@ +{%- if obj.display %} +.. py:property:: {{ obj.short_name }} + {% if obj.annotation %} + :type: {{ obj.annotation }} + {% endif %} + {% if obj.properties %} + {% for property in obj.properties %} + :{{ property }}: + {% endfor %} + {% endif %} + + {% if obj.docstring %} + {{ obj.docstring|indent(3) }} + {% endif %} +{% endif %} diff --git a/docs/api.rst b/docs/api.rst deleted file mode 100644 index 72380494..00000000 --- a/docs/api.rst +++ /dev/null @@ -1,7 +0,0 @@ -API Documentation -================= - -.. toctree:: - :maxdepth: 3 - - api/modules diff --git a/docs/conf.py b/docs/conf.py index 4e7d7086..54b4482c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -10,37 +10,29 @@ author = "Oliver J. Backhouse" extensions = [ - "sphinx.ext.autodoc", "sphinx.ext.intersphinx", "sphinx.ext.githubpages", "sphinx.ext.mathjax", - "sphinx.ext.viewcode", "sphinx_mdinclude", "sphinx_rtd_theme", - "numpydoc", + "autoapi.extension", + "sphinx.ext.napoleon", ] templates_path = ["_templates"] -autodoc_default_options = { - "members": True, - "member-order": "bysource", - "show-inheritance": True, - "private-members": False, - "special-members": False, - "inherited-members": True, - "undoc-members": False, - "typehints": "description", -} - -def autodoc_skip_member(app, what, name, obj, skip, options): - """Rule to skip members. - """ - return None - -numpydoc_show_class_members = False -numpydoc_show_inherited_class_members = True -numpydoc_class_members_toctree = False +autoapi_dirs = ["../momentGW"] +autoapi_options = [ + "members", + "inherited-members", + "show-inheritance", +] +autoapi_member_order = "bysource" +autoapi_add_toctree_entry = False +autoapi_python_use_implicit_namespaces = True +autoapi_own_page_level = "class" +autoapi_keep_files = True +autoapi_template_dir = "_templates/autoapi" highlight_language = "python3" intersphinx_mapping = {"python": ("https://docs.python.org/3", None)} @@ -61,4 +53,4 @@ def autodoc_skip_member(app, what, name, obj, skip, options): def setup(app): """Setup function for Sphinx. """ - app.connect("autodoc-skip-member", autodoc_skip_member) + pass diff --git a/docs/index.rst b/docs/index.rst index 39ed5b6f..2932dd98 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,8 +1,11 @@ .. toctree:: - :maxdepth: 1 + :maxdepth: 2 :hidden: - api + autoapi/momentGW/index.rst + autoapi/momentGW/uhf/index.rst + autoapi/momentGW/pbc/index.rst + autoapi/momentGW/pbc/uhf/index.rst .. mdinclude:: ../README.md From dd2aeeeb2cde5c7e275e330f88387739b59b97d1 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Sun, 14 Apr 2024 12:36:41 +0100 Subject: [PATCH 31/33] Don't keep reST files --- docs/conf.py | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 54b4482c..c508a646 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -31,7 +31,6 @@ autoapi_add_toctree_entry = False autoapi_python_use_implicit_namespaces = True autoapi_own_page_level = "class" -autoapi_keep_files = True autoapi_template_dir = "_templates/autoapi" highlight_language = "python3" From ab50f3b0c98da7eff0e9c9d30ef8b9bb028e068d Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Sun, 14 Apr 2024 13:29:29 +0100 Subject: [PATCH 32/33] Change author and copyright to Booth Group --- docs/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index c508a646..dc83cab6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -6,8 +6,8 @@ sys.path.insert(0, os.path.abspath("../")) project = "momentGW" -copyright = "2024, Oliver J. Backhouse" -author = "Oliver J. Backhouse" +copyright = "2024, Booth Group" +author = "Booth Group" extensions = [ "sphinx.ext.intersphinx", From 55e8d3f2eb8bab15079e6462e344608fb153d261 Mon Sep 17 00:00:00 2001 From: Oliver Backhouse Date: Sun, 14 Apr 2024 13:39:31 +0100 Subject: [PATCH 33/33] Add missing dev dep --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ff1fe19d..34061f5c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,7 +57,7 @@ dev = [ "sphinx>=4.0.0", "sphinx-mdinclude>=0.5.0", "sphinx_rtd_theme>=1.0.0", - "numpydoc>=1.1.0", + "sphinx-autoapi>=1.8.0", ] mpi = [ "mpi4py>=3.1.0",