diff --git a/source/conf.py b/source/conf.py index b6713a324..418149cd7 100644 --- a/source/conf.py +++ b/source/conf.py @@ -29,7 +29,7 @@ "pyscfdocext", "myst_parser", "sphinx_design", -# "gallery_directive", + "gallery_directive", ] bibtex_bibfiles = ['user/ref.bib'] myst_update_mathjax = False diff --git a/source/develop/agf2_developer.rst b/source/contributor/agf2_developer.rst similarity index 100% rename from source/develop/agf2_developer.rst rename to source/contributor/agf2_developer.rst diff --git a/source/develop/ao2mo_developer.rst b/source/contributor/ao2mo_developer.rst similarity index 100% rename from source/develop/ao2mo_developer.rst rename to source/contributor/ao2mo_developer.rst diff --git a/source/develop/cc_developer.rst b/source/contributor/cc_developer.rst similarity index 100% rename from source/develop/cc_developer.rst rename to source/contributor/cc_developer.rst diff --git a/source/develop/ci_developer.rst b/source/contributor/ci_developer.rst similarity index 100% rename from source/develop/ci_developer.rst rename to source/contributor/ci_developer.rst diff --git a/source/develop/cisd.rst b/source/contributor/cisd.rst similarity index 100% rename from source/develop/cisd.rst rename to source/contributor/cisd.rst diff --git a/source/code-rule.rst b/source/contributor/code-standard.rst similarity index 100% rename from source/code-rule.rst rename to source/contributor/code-standard.rst diff --git a/source/develop/df_developer.rst b/source/contributor/df_developer.rst similarity index 100% rename from source/develop/df_developer.rst rename to source/contributor/df_developer.rst diff --git a/source/develop/dft_developer.rst b/source/contributor/dft_developer.rst similarity index 100% rename from source/develop/dft_developer.rst rename to source/contributor/dft_developer.rst diff --git a/source/develop/eph_developer.rst b/source/contributor/eph_developer.rst similarity index 100% rename from source/develop/eph_developer.rst rename to source/contributor/eph_developer.rst diff --git a/source/develop/fci_developer.rst b/source/contributor/fci_developer.rst similarity index 100% rename from source/develop/fci_developer.rst rename to source/contributor/fci_developer.rst diff --git a/source/develop/gto_developer.rst b/source/contributor/gto_developer.rst similarity index 100% rename from source/develop/gto_developer.rst rename to source/contributor/gto_developer.rst diff --git a/source/contributor/index.md b/source/contributor/index.md new file mode 100644 index 000000000..531375beb --- /dev/null +++ b/source/contributor/index.md @@ -0,0 +1,11 @@ +# Contributor Guide + +A more complete Contributor Guide for PySCF is planned for the future. + +```{toctree} +:caption: Style guide +:maxdepth: 1 + +code-standard +``` + diff --git a/source/develop/mcscf_developer.rst b/source/contributor/mcscf_developer.rst similarity index 100% rename from source/develop/mcscf_developer.rst rename to source/contributor/mcscf_developer.rst diff --git a/source/develop/pbc_developer.rst b/source/contributor/pbc_developer.rst similarity index 100% rename from source/develop/pbc_developer.rst rename to source/contributor/pbc_developer.rst diff --git a/source/develop/scf_developer.rst b/source/contributor/scf_developer.rst similarity index 100% rename from source/develop/scf_developer.rst rename to source/contributor/scf_developer.rst diff --git a/source/develop/soscf_developer.rst b/source/contributor/soscf_developer.rst similarity index 100% rename from source/develop/soscf_developer.rst rename to source/contributor/soscf_developer.rst diff --git a/source/develop/table.png b/source/contributor/table.png similarity index 100% rename from source/develop/table.png rename to source/contributor/table.png diff --git a/source/develop/tdscf_developer.rst b/source/contributor/tdscf_developer.rst similarity index 100% rename from source/develop/tdscf_developer.rst rename to source/contributor/tdscf_developer.rst diff --git a/source/index.md b/source/index.md new file mode 100644 index 000000000..211bf83c8 --- /dev/null +++ b/source/index.md @@ -0,0 +1,49 @@ +--- +html_theme.sidebar_secondary.remove: true +--- + +# Quantum chemistry with Python + + +```{gallery-grid} +:grid-columns: 1 2 2 3 + +- header: "{fab}`python;pst-color-primary` Primarily Python" + content: "Easy to read and write, for quick development with fewer mistakes." +- header: "{fas}`bolt;pst-color-primary` Fast" + content: "Uses NumPy, SciPy, and custom C/C++ code." +- header: "{fa}`code-branch;pst-color-primary` Free and open-source" + content: "Accessible and community-driven. Distributed on [GitHub](https://github.com/pyscf/pyscf) under the [Apache-2.0](https://github.com/pyscf/pyscf/tree/master?tab=Apache-2.0-1-ov-file#readme) license." +- header: "{fas}`gears;pst-color-primary` Modular" + content: "Easily integrated into complex workflows or other software packages." +- header: "{fa}`list-ul;pst-color-primary` Comprehensive" + content: "Extensive collection of electronic structure methods, for molecules and periodic solids." +- header: "{fas}`lightbulb;pst-color-primary` Extensible" + content: "See the list of [Extensions](user/extensions) to PySCF." +``` + + + + +```{toctree} +:hidden: + +quickstart +user/index +contributor/index +About +``` diff --git a/source/index.rst b/source/index.rst deleted file mode 100644 index 9b73c36ae..000000000 --- a/source/index.rst +++ /dev/null @@ -1,58 +0,0 @@ -.. PySCF - -Home -**** - -.. image:: ../logo/pyscf-logo.png - :width: 400 - -The Python-based Simulations of Chemistry Framework (PySCF) is an open-source -collection of electronic structure modules powered by Python. The package -provides a simple, lightweight, and efficient platform for quantum chemistry -calculations and methodology development. -PySCF can be used to simulate the properties of molecules, crystals, and -custom Hamiltonians using mean-field and post-mean-field methods. -To ensure ease of extensibility, almost all of the features in PySCF are -implemented in Python, while computationally critical parts are -implemented and optimized in C. Using this combined Python/C -implementation, the package is as efficient as the best existing C or Fortran -based quantum chemistry programs. -In addition to its core libraries, PySCF supports a rich -ecosystem of :ref:`installing_extproj`. - -.. MPI versions of some routines, additional quantum chemistry methods and analysis, interface with quantum computing toolkits *etc*. See :ref:`installing_extproj`. - -.. For installation instructions, see the :ref:`install` page. - -.. For a guide to performing a variety of calculations with PySCF, see the :ref:`quickstart` guide. - - -.. COMMENTED OUT FOR NOW -.. Install -.. User Guide -.. Developer Guide -.. API Docs -.. Blog -.. Modules -.. about.md - -.. toctree:: - :hidden: - :maxdepth: 1 - - Install - Quickstart - User Guide - Developer Guide - API - About - -.. You can also download the `PDF version `_ of this manual. - - -.. Indices and tables -.. ================== -.. -.. * :ref:`genindex` -.. * :ref:`modindex` -.. * :ref:`search` diff --git a/source/tools/extensions/gallery_directive.py b/source/tools/extensions/gallery_directive.py new file mode 100644 index 000000000..ab275335c --- /dev/null +++ b/source/tools/extensions/gallery_directive.py @@ -0,0 +1,145 @@ +"""A directive to generate a gallery of images from structured data. + +Generating a gallery of images that are all the same size is a common +pattern in documentation, and this can be cumbersome if the gallery is +generated programmatically. This directive wraps this particular use-case +in a helper-directive to generate it with a single YAML configuration file. + +It currently exists for maintainers of the pydata-sphinx-theme, +but might be abstracted into a standalone package if it proves useful. +""" + +from pathlib import Path +from typing import Any, ClassVar, Dict, List + +from docutils import nodes +from docutils.parsers.rst import directives +from sphinx.application import Sphinx +from sphinx.util import logging +from sphinx.util.docutils import SphinxDirective +from yaml import safe_load + +logger = logging.getLogger(__name__) + + +TEMPLATE_GRID = """ +`````{{grid}} {columns} +{options} + +{content} + +````` +""" + +GRID_CARD = """ +````{{grid-item-card}} {title} +{options} + +{content} +```` +""" + + +class GalleryGridDirective(SphinxDirective): + """A directive to show a gallery of images and links in a Bootstrap grid. + + The grid can be generated from a YAML file that contains a list of items, or + from the content of the directive (also formatted in YAML). Use the parameter + "class-card" to add an additional CSS class to all cards. When specifying the grid + items, you can use all parameters from "grid-item-card" directive to customize + individual cards + ["image", "header", "content", "title"]. + + Danger: + This directive can only be used in the context of a Myst documentation page as + the templates use Markdown flavored formatting. + """ + + name = "gallery-grid" + has_content = True + required_arguments = 0 + optional_arguments = 1 + final_argument_whitespace = True + option_spec: ClassVar[dict[str, Any]] = { + # A class to be added to the resulting container + "grid-columns": directives.unchanged, + "class-container": directives.unchanged, + "class-card": directives.unchanged, + } + + def run(self) -> List[nodes.Node]: + """Create the gallery grid.""" + if self.arguments: + # If an argument is given, assume it's a path to a YAML file + # Parse it and load it into the directive content + path_data_rel = Path(self.arguments[0]) + path_doc, _ = self.get_source_info() + path_doc = Path(path_doc).parent + path_data = (path_doc / path_data_rel).resolve() + if not path_data.exists(): + logger.info(f"Could not find grid data at {path_data}.") + nodes.text("No grid data found at {path_data}.") + return + yaml_string = path_data.read_text() + else: + yaml_string = "\n".join(self.content) + + # Use all the element with an img-bottom key as sites to show + # and generate a card item for each of them + grid_items = [] + for item in safe_load(yaml_string): + # remove parameters that are not needed for the card options + title = item.pop("title", "") + + # build the content of the card using some extra parameters + header = f"{item.pop('header')} \n^^^ \n" if "header" in item else "" + image = f"![image]({item.pop('image')}) \n" if "image" in item else "" + content = f"{item.pop('content')} \n" if "content" in item else "" + + # optional parameter that influence all cards + if "class-card" in self.options: + item["class-card"] = self.options["class-card"] + + loc_options_str = "\n".join(f":{k}: {v}" for k, v in item.items()) + " \n" + + card = GRID_CARD.format( + options=loc_options_str, content=header + image + content, title=title + ) + grid_items.append(card) + + # Parse the template with Sphinx Design to create an output container + # Prep the options for the template grid + class_ = "gallery-directive" + f' {self.options.get("class-container", "")}' + options = {"gutter": 2, "class-container": class_} + options_str = "\n".join(f":{k}: {v}" for k, v in options.items()) + + # Create the directive string for the grid + grid_directive = TEMPLATE_GRID.format( + columns=self.options.get("grid-columns", "1 2 3 4"), + options=options_str, + content="\n".join(grid_items), + ) + + # Parse content as a directive so Sphinx Design processes it + container = nodes.container() + self.state.nested_parse([grid_directive], 0, container) + + # Sphinx Design outputs a container too, so just use that + return [container.children[0]] + + +def setup(app: Sphinx) -> Dict[str, Any]: + """Add custom configuration to sphinx app. + + Args: + app: the Sphinx application + + Returns: + the 2 parallel parameters set to ``True``. + """ + app.add_directive("gallery-grid", GalleryGridDirective) + + return { + "parallel_read_safe": True, + "parallel_write_safe": True, + } + diff --git a/source/user.rst b/source/user.rst deleted file mode 100644 index eabb61f0a..000000000 --- a/source/user.rst +++ /dev/null @@ -1,38 +0,0 @@ -.. _theory: - -User Guide -********** - -A variety of electronic structure methods are implemented in the PySCF package. -Many of them can also be used for solid-state calculations with periodic boundary conditions. -This User Guide introduces the basic theories of these methods and demonstrates their main -functionalities. - - -.. toctree:: - :maxdepth: 1 - - user/gto.rst - user/scf.rst - user/dft.rst - user/mp.rst - user/gw.rst - user/ci.rst - user/cc.rst - user/adc.rst - user/agf2.rst - user/mcscf.rst - user/mrpt.rst - user/tddft.rst - user/solvent.rst - user/qmmm.rst - user/md.rst - user/df.rst - user/pbc.rst - user/eph.rst - user/lo.rst - user/sgx.rst - user/geomopt.rst - user/gpu.rst - user/reference.rst - diff --git a/source/user/extensions.md b/source/user/extensions.md new file mode 100644 index 000000000..bd8baa32e --- /dev/null +++ b/source/user/extensions.md @@ -0,0 +1,106 @@ +# Extensions + +Due to its flexibility and modular nature, many extensions have been developed +based on PySCF. As a courtesy, repositories for some of these extensions are +hosted by the [PySCF organization's GitHub](https://github.com/pyscf). However, +the PySCF organization provides no support for these extensions, nor a +guarantee of future compatibility. Questions should be addressed to the authors +of the extension, and issues can be raised on the GitHub repository of the +extension. + +Once an extension module has been correctly installed (see [How to install +extensions](#how-to-install-extensions)), you can use it as a regular submodule +of PySCF, e.g., +```python +import pyscf +from pyscf.semiempirical import MINDO3 +mol = pyscf.M(atom='N 0 0 0; N 0 0 1') +MINDO3(mol).run() +``` + + A list of PySCF extensions is given below. + +| Project | URL | +| --------------- | ------------------------------------------- | +| cas_ac0 | https://github.com/CQCL/pyscf-ac0 | +| cornell-shci | https://github.com/pyscf/cornell-shci | +| dftd3 | https://github.com/pyscf/dftd3 | +| dmrgscf | https://github.com/pyscf/dmrgscf | +| doci | https://github.com/pyscf/doci | +| fciqmc | https://github.com/pyscf/fciqmc | +| icmpspt | https://github.com/pyscf/icmpspt | +| mbd | https://github.com/pyscf/mbd | +| naive-hci | https://github.com/pyscf/naive-hci | +| nao | https://github.com/pyscf/nao | +| qsdopt | https://github.com/pyscf/qsdopt | +| rt | https://github.com/pyscf/rt | +| semiempirical | https://github.com/pyscf/semiempirical | +| shciscf | https://github.com/pyscf/shciscf | +| zquatev | https://github.com/sunqm/zquatev | +| tblis | https://github.com/pyscf/pyscf-tblis | + +## How to install extensions + +Many extension modules (e.g., the semiempirical module) can be +installed using pip's extra dependency mechanism, +```bash +pip install pyscf[semiempirical] +``` + +Although not recommended, all extension modules can be installed, +```bash +pip install pyscf[all] +``` + +## How to install extensions (advanced) + +Based on the technique of namespace packages specified in [PEP +420](https://www.python.org/dev/peps/pep-0420/>), PySCF has developed a couple +of methods to install the extension modules. + +### Pip command + +For pip version newer than 19.0, projects hosted on GitHub can be installed on +the command line, +```bash +pip install git+https://github.com/pyscf/semiempirical +``` + +A particular release on GitHub can be installed with the release URL you can +look up on GitHub, +```bash +pip install https://github.com/pyscf/semiempirical/archive/v0.1.0.tar.gz +``` + +### Pip command for local paths + +If you wish to load an extension module developed in a local directory, you can +use the local install mode of pip. Use of a Python virtual environment is +recommended to avoid polluting the system default Python runtime environment, +for example, +```bash +python -m venv /home/abc/pyscf-local-env +source /home/abc/pyscf-local-env/bin/activate +git clone https://github.com/pyscf/semiempirical /home/abc/semiempirical +pip install -e /home/abc/semiempirical +``` + +### Environment variable `PYSCF_EXT_PATH` + +You can place the location of each extension module (or a file that contains +these locations) in this environment variable. The PySCF library will parse the +paths defined in this environment variable, and load the relevant submodules. +For example, +```bash +git clone https://github.com/pyscf/semiempirical /home/abc/semiempirical +git clone https://github.com/pyscf/doci /home/abc/doci +git clone https://github.com/pyscf/dftd3 /home/abc/dftd3 +echo /home/abc/doci > /home/abc/.pyscf_ext_modules +echo /home/abc/dftd3 >> /home/abc/.pyscf_ext_modules +export PYSCF_EXT_PATH=/home/abc/semiempirical:/home/abc/.pyscf_ext_modules +``` + +Using this definition of `PYSCF_EXT_PATH`, the three extension +submodules (semiempirical, doci, dftd3) are loaded when PySCF is +imported, and you don't have to use a Python virtual environment. + diff --git a/source/user/index.md b/source/user/index.md new file mode 100644 index 000000000..51401aca0 --- /dev/null +++ b/source/user/index.md @@ -0,0 +1,62 @@ +# User Guide + +A variety of electronic structure methods are implemented in the PySCF package. +Many of them can also be used for solid-state calculations with periodic +boundary conditions. This User Guide introduces the basic theories of these +methods and demonstrates their main functionalities. + +```{toctree} +:caption: Getting started +:maxdepth: 1 + +install +using +``` + +```{toctree} +:caption: Building molecules and crystals +:maxdepth: 1 + +gto +pbcgto +``` + +```{toctree} +:caption: Electronic structure methods +:maxdepth: 1 + +scf +dft.rst +mp.rst +gw.rst +ci.rst +cc.rst +adc.rst +agf2.rst +mcscf.rst +mrpt.rst +tddft.rst +``` + +```{toctree} +:caption: Other functionalities +:maxdepth: 1 + +solvent.rst +qmmm.rst +md.rst +df.rst +pbc.rst +eph.rst +lo.rst +sgx.rst +geomopt.rst +gpu.rst +``` + +```{toctree} +:caption: Extensions +:maxdepth: 1 + +extensions +``` diff --git a/source/user/pbcgto.md b/source/user/pbcgto.md new file mode 100644 index 000000000..3bd467cf0 --- /dev/null +++ b/source/user/pbcgto.md @@ -0,0 +1,220 @@ +# Crystal structure + +**Module**: `pyscf.pbc.gto` + +**Examples**: [pyscf/examples/pbc](https://github.com/pyscf/pyscf/tree/master/examples/pbc) + +## Building a crystal + +Periodic crystals are built using the `pbc.gto.Cell` class, +which is very similar to the `gto.Mole` class, +```python +from pyscf.pbc import gto +cell = gto.Cell() +cell.atom = '''H 0 0 0; H 1 1 1''' +cell.basis = 'gth-dzvp' +cell.pseudo = 'gth-lda' +cell.a = numpy.eye(3) * 2 +cell.build() +``` + +The other equivalent ways to build a molecule introduced in [Molecular +structure](gto), including the shortcut functions `pbc.gto.M()` or `pyscf.M()`, +also apply here, +```python +from pyscf.pbc import gto +cell = gto.Cell() +cell.build( + atom = '''H 0 0 0; H 1 1 1''', + basis = 'gth-dzvp', + pseudo = 'gth-lda', + a = numpy.eye(3) * 2) +``` +```python +from pyscf.pbc import gto +cell = gto.M( + atom = '''H 0 0 0; H 1 1 1''', + basis = 'gth-dzvp', + pseudo = 'gth-lda', + a = numpy.eye(3) * 2) +``` +```python +import pyscf +cell = pyscf.M( + atom = '''H 0 0 0; H 1 1 1''', + basis = 'gth-dzvp', + pseudo = 'gth-lda', + a = numpy.eye(3) * 2) +``` + +## Geometry and lattice vectors + +The `Cell.atom` attribute defines the positions of the atoms inside the unit cell, and +the additional parameter `Cell.a` defines the lattice vectors. +The format of `Cell.a` is array-like, +```python +cell.a = numpy.eye(3) * 2 +cell.a = [[2,0,0],[0,2,0],[0,0,2]] +``` + +Each row of the 3-by-3 matrix of `Cell.a` represents a lattice vector +in Cartesian coordinates, with the same unit as the input `atom` parameter +(and controllable by the `unit` attribute). + +:::{warning} + +The input lattice vectors should form a right-handed coordinate system, as +otherwise some integrals may be computed incorrectly in PySCF. +PySCF will print a warning if the lattice vectors do not form a right-handed +coordinate system. + +::: + +## Basis set and pseudopotentials + +PySCF uses crystalline Gaussian-type orbitals as basis functions for periodic +calculations. The predefined basis sets and ECPs for molecular calculations +can be used in periodic calculations as well. + +As described more in [](link), many PBC calculations require the use of +ECPs (or pseudopotentials, as they are more commonly called in periodic codes). +In addition to molecular ECPs, PySCF includes GTH pseudopotentials, +which have been parameterized for use with HF or different DFT functionals, +```python +cell.pseudo = 'gth-hf' +cell.pseudo = 'gth-lda' # an alias for 'gth-pade' +cell.pseudo = 'gth-pbe' +``` +The GTH pseudopotentials should always be used with corresponding valence basis sets, +```python +cell.basis = 'gth-szv' # or gth-dzv, gth-dzvp, gth-tzvp +``` + +Lists of all available GTH pseudopotentials and basis sets are available in +[pbc/gto/pseudo](https://github.com/pyscf/pyscf/tree/master/pyscf/pbc/gto/pseudo) +and [pbc/gto/basis](https://github.com/pyscf/pyscf/tree/master/pyscf/pbc/gto/basis). + +:::{note} + +GTH basis sets and pseudopotentials are not available for all atoms of the periodic table. + +::: + +## K-points + +The k-points to be used in solid calculations can be obtained through the +`Cell.make_kpts` method, by specifying the number of k-points +in each lattice vector direction, +```python +kpts = cell.make_kpts([1,2,2]) +print(kpts.shape) +# (4,3) +``` +By default, this will return the shifted Monkhorst-Pack mesh that includes +the Gamma point. To get the non-shifted Monkhorst-Pack mesh, +```python +kpts = cell.make_kpts([1,2,2], with_gamma_point=False) +``` + +To get a shifted Monkhorst-pack mesh centered at a specific point, +```python +kpts = cell.make_kpts([1,2,2], scaled_center=[0.,0.25,0.25]) +``` +where `scaled_center` is defined in the units of reciprocal lattice vectors. + +The obtained k-points are used as input for crystalline electronic structure calculations, +```python +from pyscf.pbc import scf +kpts = cell.make_kpts([2,2,2]) +kmf = scf.KRHF(cell, kpts=kpts) +e_hf = kmf.kernel() +``` + +Calculations with k-points always return the energy per unit cell. + +## Spin + +Because k-point sampling formally represents a calculation on a supercell, +the attribute `Cell.spin` indicates the number of unpaired electrons in the +supercell (**not** in the unit cell). For example, in a calculation with +a 2x2x2 k-point mesh, `cell.spin = 1` leads to one unpaired electron in the +supercell (not eight). + +## Low-dimensional systems + +The PySCF `pbc` module also supports low-dimensional periodic systems. You can initialize +the attribute `Cell.dimension` to specify the dimension of the system, +```python +cell.dimension = 2 +cell.a = numpy.eye(3) * 2 +cell.build() +``` + +When `Cell.dimension` is smaller than 3, a vacuum of infinite size will be +applied in certain direction(s). For example, when `Cell.dimension = 2`, +the z-direction will be treated as infinitely large and the xy-plane +constitutes the periodic surface. When `Cell.dimension = 1`, the y and z axes +are treated as vacuum and thus the system is a wire in the x direction. +When `Cell.dimension = 0`, all three directions are treated as vacuum, and this is +equivalent to a molecular system. + +## Other parameters + +The `Cell.precision` attribute determines the integral accuracy, and its +default value is `1e-8` hartree. When calling the `cell.build()` method, +some parameters are set automatically based on the value of `precision`, including + + * `mesh` - length-3 list or 1x3 array of int + + - The numbers of grid points in the FFT-mesh in each direction. + + * `ke_cutoff` - float + + - Kinetic energy cutoff of the plane waves in FFTDF + + * `rcut` - float + + - Cutoff radius (in Bohr) of the lattice summation in the integral evaluation + +Other attributes of the `Mole` class such as `verbose`, +`max_memory`, etc., have the same meanings in the `Cell` class. + +:::{note} + +Currently, point group symmetries for crystals are not supported. + +::: + +## Accessing AO integrals + +Periodic AO integrals can be evaluated using the `Cell.pbc_intor` function, +```python +overlap = cell.pbc_intor('int1e_ovlp') +kin = cell.pbc_intor('int1e_kin') +``` + +By default, the `Cell.pbc_intor` function only returns integrals at the +Gamma point. If k-points are specified, it will return the integrals at each +k-point, +```python +kpts = cell.make_kpts([2,2,2]) +overlap = cell.pbc_intor('int1e_ovlp', kpts=kpts) +``` + +:::{note} + +The `Cell.pbc_intor` function can only be used to evaluate periodic short-range +integrals. PBC density fitting methods have to be used to compute the integrals for +long-range operators such as the electron-nuclear attraction and the electron-electron +repulsion integrals. + +::: + +The electron repulsion integrals can be evaluated with the periodic density fitting +methods, +```python +from pyscf.pbc import df +eri = df.DF(cell).get_eri() +``` +See [Periodic density fitting](pbc/df) for more details. +