From e717b8998c9612e3a1944bc0d1efe6c5ff12aa34 Mon Sep 17 00:00:00 2001 From: julpe Date: Thu, 2 Jul 2026 14:18:21 +0200 Subject: [PATCH] Changes for memory efficiency and streamlined deepcopy into separate copy method. Also fixed Eliashberg equation for multi-orbital systems. --- .github/dependabot.yml | 4 + .github/workflows/CI.yml | 6 +- .github/workflows/Docs.yml | 42 +++ .github/workflows/Lint.yml | 38 +++ CONTRIBUTING.md | 14 +- README.md | 2 +- codecov.yml | 2 +- dgamore/DGAmore.py | 54 +++- dgamore/__init__.py | 3 +- dgamore/brillouin_zone.py | 4 +- dgamore/bubble_gen.py | 2 +- dgamore/config.py | 6 +- dgamore/config_parser.py | 3 +- dgamore/dga_config.yaml | 4 +- dgamore/dga_io.py | 2 +- dgamore/dga_logger.py | 2 +- dgamore/dmft_interface.py | 2 +- dgamore/eliashberg_solver.py | 151 ++++++--- dgamore/four_point.py | 64 +++- dgamore/gap_function.py | 2 +- dgamore/greens_function.py | 15 +- dgamore/hamiltonian.py | 2 +- dgamore/interaction.py | 16 +- dgamore/lambda_correction.py | 2 +- dgamore/local_four_point.py | 20 +- dgamore/local_n_point.py | 7 +- dgamore/local_sde.py | 28 +- dgamore/local_two_point.py | 6 +- dgamore/matsubara_frequencies.py | 2 +- dgamore/max_ent.py | 35 ++- dgamore/memory_estimator.py | 28 +- dgamore/mpi_utils.py | 46 ++- dgamore/n_point_base.py | 42 ++- dgamore/nonlocal_sde.py | 296 ++++++++++++++---- dgamore/plotting.py | 4 +- dgamore/self_energy.py | 13 +- dgamore/symmetrize_new.py | 8 +- dgamore/symmetry_reduction.py | 9 +- dgamore/two_point.py | 6 +- docs/conf.py | 2 +- docs/configuration.rst | 10 +- docs/contributing.rst | 14 +- docs/installation.rst | 4 +- docs/usage.rst | 14 +- pyproject.toml | 12 +- setup.py | 7 +- tests/__init__.py | 3 +- tests/conftest.py | 49 ++- tests/test_autodetect_memory.py | 79 ++++- tests/test_brillouin_zone.py | 6 +- tests/test_bubble_gen.py | 32 +- .../end_2_end/vrg_q_dens_right_rank_0.npy | Bin 0 -> 645248 bytes .../end_2_end/vrg_q_magn_right_rank_0.npy | Bin 0 -> 645248 bytes tests/test_eliashberg_end_to_end.py | 36 +-- tests/test_eliashberg_solver.py | 133 +++++++- tests/test_four_point.py | 120 ++++++- tests/test_greens_function.py | 4 +- tests/test_hamiltonian.py | 2 +- tests/test_interaction.py | 56 ++-- tests/test_lambda_correction.py | 2 +- tests/test_local_four_point.py | 154 ++++----- tests/test_local_n_point.py | 36 +-- tests/test_local_sde.py | 2 +- tests/test_local_sde_end_to_end.py | 4 +- tests/test_local_two_point.py | 2 +- tests/test_max_ent.py | 67 +++- tests/test_memory_estimator.py | 31 +- tests/test_mixing.py | 30 +- tests/test_mpi_utils.py | 96 +++++- tests/test_n_point_base.py | 9 +- tests/test_nonlocal_sde.py | 95 +++++- tests/test_nonlocal_sde_end_to_end.py | 2 +- tests/test_self_energy.py | 14 +- tests/test_symmetrize.py | 2 +- tests/test_symmetry_reduction.py | 26 +- 75 files changed, 1644 insertions(+), 503 deletions(-) create mode 100644 .github/workflows/Docs.yml create mode 100644 .github/workflows/Lint.yml create mode 100644 tests/test_data/end_2_end/vrg_q_dens_right_rank_0.npy create mode 100644 tests/test_data/end_2_end/vrg_q_magn_right_rank_0.npy diff --git a/.github/dependabot.yml b/.github/dependabot.yml index d60f0707..828d8797 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,3 +5,7 @@ updates: directory: "/" # Location of package manifests schedule: interval: "monthly" + - package-ecosystem: "pip" + directory: "/" # root requirements.txt (docs/requirements.txt is intentionally pinned, left out) + schedule: + interval: "monthly" diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index ac4a887e..2b71a259 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -10,6 +10,10 @@ on: permissions: contents: read +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: test: name: Test on ${{ matrix.os }} / Python ${{ matrix.python-version }} @@ -57,7 +61,7 @@ jobs: # 7. Run tests with coverage - name: Run tests run: | - pytest tests --runslow --cov=dgamore --cov-report=term-missing --cov-report=xml -vv + pytest tests --runslow --cov=dgamore --cov-report=term-missing --cov-report=xml --cov-fail-under=85 -vv # pytest tests --runslow --cov=dgamore --cov-report=xml --cov-report=term # 8. Upload coverage to Codecov (requires CODECOV_TOKEN for private repos) diff --git a/.github/workflows/Docs.yml b/.github/workflows/Docs.yml new file mode 100644 index 00000000..06c4eb7f --- /dev/null +++ b/.github/workflows/Docs.yml @@ -0,0 +1,42 @@ +name: Docs + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + name: Build docs (Sphinx) + runs-on: ubuntu-latest + steps: + # 1. Checkout repository + - name: Checkout code + uses: actions/checkout@v6 + + # 2. Set up Python (mirrors the Read the Docs build: Python 3.13) + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.13" + cache: 'pip' + + # 3. Install documentation dependencies (mpi4py and cupy are mocked in conf.py) + - name: Install documentation dependencies + run: | + python -m pip install --upgrade pip + pip install -r docs/requirements.txt + + # 4. Build HTML docs; -W turns warnings into errors, --keep-going reports them all + - name: Build HTML documentation + run: | + sphinx-build -W --keep-going -b html docs docs/_build/html diff --git a/.github/workflows/Lint.yml b/.github/workflows/Lint.yml new file mode 100644 index 00000000..54eda63b --- /dev/null +++ b/.github/workflows/Lint.yml @@ -0,0 +1,38 @@ +name: Lint + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + black: + name: Black format check + runs-on: ubuntu-latest + steps: + # 1. Checkout repository + - name: Checkout code + uses: actions/checkout@v6 + + # 2. Set up Python + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.12" + + # 3. Install Black (pinned; keep local Black matching this version) + - name: Install Black + run: pip install black==26.5.1 + + # 4. Verify formatting (line-length also read from [tool.black] in pyproject.toml) + - name: Check formatting + run: black --check --line-length 120 . diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2f6ad8ea..e056aa73 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -69,16 +69,18 @@ When you would like to contribute code, the following workflow keeps things smoo ```bash pytest tests # fast suite (skips tests marked slow) pytest tests --runslow # full suite, as run in CI - pytest tests --runslow --cov=dgamore --cov-report=term-missing # with coverage + pytest tests --runslow --cov=dgamore --cov-report=term-missing --cov-fail-under=85 # coverage, as CI runs it ``` 5. **Open a pull request** against the `main` branch, with a short description of what you changed and why. If your pull request is related to an existing issue, mentioning it helps connect the two. -A continuous integration pipeline runs the full test suite on every pull request, across Python 3.12 to 3.14 on both -Linux and macOS. This is there to catch regressions, not to be a gatekeeper, so please do not worry if something turns -red on the first try; it is a normal part of the process, and we are glad to help you get it passing. A coverage tool -also checks that the overall test coverage stays above 85%, so adding tests for your changes is the best way to keep it -healthy. +A continuous integration pipeline runs on every pull request. It checks that the code is Black-formatted, then runs the +full test suite across Python 3.12 to 3.14 on both Linux and macOS. This is there to catch regressions, not to be a +gatekeeper, so please do not worry if something turns red on the first try; it is a normal part of the process, and we +are glad to help you get it passing. The pipeline also requires the overall test coverage to stay at **at least 85%**, +and the build fails if it drops below that threshold. Beyond the overall figure, the new or changed code in a pull +request (the *patch*) must itself be covered to **at least 85%**, so please add tests for what you write rather than +relying on the rest of the code base to carry the average. ## Coding style diff --git a/README.md b/README.md index 93ae57be..1b805177 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Configure a run by editing your configuration file, then execute the routine wit holding it and `-c` to name it (defaults: the repository directory and [dga_config.yaml](dgamore/dga_config.yaml)): ```bash -mpiexec -np 8 DGAmore.py -p /configs/ -c my_config.yaml # or: DGAmore.py for a single-core test run +mpiexec -np 8 DGAmore -p /configs/ -c my_config.yaml # or: DGAmore for a single-core test run ``` See the [installation](https://dgamore.readthedocs.io/en/latest/installation.html) and diff --git a/codecov.yml b/codecov.yml index 0b6f1c3b..171d14be 100644 --- a/codecov.yml +++ b/codecov.yml @@ -26,7 +26,7 @@ coverage: default: target: 85% threshold: 0% - informational: true + informational: false comment: layout: "reach, diff, flags, files" behavior: default diff --git a/dgamore/DGAmore.py b/dgamore/DGAmore.py index 5e31a821..faa9e821 100644 --- a/dgamore/DGAmore.py +++ b/dgamore/DGAmore.py @@ -2,11 +2,11 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems """ -Main entry point and top-level driver of a DGAmore run (installed on the PATH as ``DGAmore.py``). The -:func:`execute_dga_routine` orchestrates the full pipeline: parse the config, load the DMFT input, run the local +Main entry point and top-level driver of a DGAmore run (installed on the PATH as ``DGAmore``). The +:func:`main` orchestrates the full pipeline: parse the config, load the DMFT input, run the local Schwinger-Dyson step per inequivalent atom and assemble the full multi-band quantities, run the non-local ladder DGA self-energy, optionally analytically continue to real frequencies, and optionally solve the Eliashberg equation -- saving and plotting results along the way. Rank 0 owns the file I/O, local assembly and plotting; the @@ -16,7 +16,11 @@ import itertools as it import logging import os -from copy import deepcopy + +# OpenMPI: exclude the UCX one-sided (RMA) component before MPI is initialised. On some OpenMPI 5.x builds it fails its +# own component-query and prints a benign "OSC UCX component priority set inside component query failed" warning when +# the per-node shared-memory giwk window is created. +os.environ.setdefault("OMPI_MCA_osc", "^ucx") import matplotlib.pyplot as plt import numpy as np @@ -42,7 +46,7 @@ logging.getLogger("matplotlib").setLevel(logging.WARNING) -def execute_dga_routine(): +def main(): """ Runs the complete DGA pipeline end to end: config parsing and folder setup, DMFT input loading, the local Schwinger-Dyson step (per inequivalent atom, assembled into full multi-band quantities), the non-local @@ -224,7 +228,7 @@ def write_to_full_4pt_quantity(obj_full, obj_ineq: LocalFourPoint, sl: slice): :return: The full object with this atom's block filled in. """ if obj_full is None: - obj_full = deepcopy(obj_ineq) + obj_full = obj_ineq.copy() obj_full.mat = np.zeros( (config.sys.n_bands,) * 4 + obj_ineq.current_shape[4:], dtype=obj_ineq.mat.dtype ) @@ -246,7 +250,7 @@ def write_to_full_2pt_quantity( :return: The full object with this atom's block filled in. """ if obj_full is None: - obj_full = deepcopy(obj_ineq) + obj_full = obj_ineq.copy() obj_full.mat = np.zeros( ((1, 1, 1) + (config.sys.n_bands,) * 2 if has_momentum else (config.sys.n_bands,) * 2) + (obj_ineq.current_shape[-1],), @@ -581,13 +585,27 @@ def autodetect_memory_settings(comm: MPI.Comm) -> None: construct_fq_cheap=config.eliashberg.construct_fq_cheap, ) - def node_total(distributed: float, single: float, n_ranks: int) -> float: - """Memory held on a node with ``n_ranks`` ranks at a branch's peak (see :func:`autodetect_memory_settings`).""" - return n_ranks * (baseline + distributed) + single + # giwk_full is deduplicated to one copy per node through the whole non-local self-energy section when + # config.memory.use_shared_memory_giwk is on (the node root builds it, the others map it read-only; it is re-shared + # at the smaller core-box window after the bubble). + giwk_shared_credit = ( + memory_estimator.giwk_baseline_bytes(config.lattice.q_grid.nk_tot, config.sys.n_bands, niv_cut) + if config.memory.use_shared_memory_giwk + else 0.0 + ) + giwk_shared_branches = {"chi0q", "chiq_aux", "sde"} + + def node_total(distributed: float, single: float, n_ranks: int, giwk_shared: bool = False) -> float: + """Memory held on a node with ``n_ranks`` ranks at a branch's peak (see :func:`autodetect_memory_settings`). + When ``giwk_shared``, the replicated ``giwk_full`` is counted once per node instead of once per rank.""" + total = n_ranks * (baseline + distributed) + single + if giwk_shared: + total -= (n_ranks - 1) * giwk_shared_credit + return total - def fits_everywhere(distributed: float, single: float) -> bool: + def fits_everywhere(distributed: float, single: float, giwk_shared: bool = False) -> bool: """Whether a transient (per-rank ``distributed`` + one-off ``single``) fits the 90% budget on every node.""" - return all(node_total(distributed, single, r) <= avail * 0.9 for r, avail in nodes.values()) + return all(node_total(distributed, single, r, giwk_shared) <= avail * 0.9 for r, avail in nodes.values()) flag_to_key = { "save_memory_for_chi0q": "chi0q", @@ -613,17 +631,19 @@ def fits_everywhere(distributed: float, single: float) -> bool: continue bp = peaks[key] label = key_to_label[key] - if not fits_everywhere(bp.on_distributed, bp.on_single): - worst = max(node_total(bp.on_distributed, bp.on_single, r) for r, _ in nodes.values()) + # giwk is deduplicated per node across the whole SDE section, so credit those branches (not the eliashberg ones). + giwk_shared = key in giwk_shared_branches and config.memory.use_shared_memory_giwk + if not fits_everywhere(bp.on_distributed, bp.on_single, giwk_shared): + worst = max(node_total(bp.on_distributed, bp.on_single, r, giwk_shared) for r, _ in nodes.values()) raise MemoryError( f"Even the most memory-lean path for '{label}' needs {worst / 1024**3:.3f} GB on a node, which " f"exceeds 90% of that node's available memory. Use more nodes, fewer ranks per node, a smaller " f"frequency box or k-grid." ) - autodetect_on = not fits_everywhere(bp.off_distributed, bp.off_single) + autodetect_on = not fits_everywhere(bp.off_distributed, bp.off_single, giwk_shared) final = bool(getattr(config.memory, attr)) or autodetect_on setattr(config.memory, attr, final) - worst_off = max(node_total(bp.off_distributed, bp.off_single, r) for r, _ in nodes.values()) + worst_off = max(node_total(bp.off_distributed, bp.off_single, r, giwk_shared) for r, _ in nodes.values()) logger.info( f"{label}: fast-path node total {worst_off / 1024**3:.3f} GB -> " f"memory saving {'enabled' if final else 'disabled'}." @@ -702,4 +722,4 @@ def configure_matplotlib(): if __name__ == "__main__": - execute_dga_routine() + main() diff --git a/dgamore/__init__.py b/dgamore/__init__.py index 09901cb1..5c1a04f0 100644 --- a/dgamore/__init__.py +++ b/dgamore/__init__.py @@ -1,6 +1,5 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems - diff --git a/dgamore/brillouin_zone.py b/dgamore/brillouin_zone.py index 75f7bcec..b2a45925 100644 --- a/dgamore/brillouin_zone.py +++ b/dgamore/brillouin_zone.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems """ @@ -361,7 +361,7 @@ def get_lattice_symmetries_from_string(symmetry_string: str | tuple | list) -> l # Sentinel object returned by get_lattice_symmetries_from_string for "auto". -# Identity-checked, so it must be a unique singleton — a small dedicated object. +# Identity-checked, so it must be a unique singleton - a small dedicated object. class _AutoSymmetriesSentinel: """Marker indicating that lattice symmetries are to be detected automatically from a Hamiltonian, via KGrid.specify_auto_symmetries().""" diff --git a/dgamore/bubble_gen.py b/dgamore/bubble_gen.py index cbec3614..29faad64 100644 --- a/dgamore/bubble_gen.py +++ b/dgamore/bubble_gen.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems r""" Generalized bare susceptibilities (the "bubbles"). :class:`BubbleGenerator` builds the products of two Green's diff --git a/dgamore/config.py b/dgamore/config.py index 8745d6f4..42622017 100644 --- a/dgamore/config.py +++ b/dgamore/config.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems """ Global configuration singleton. This module holds the process-wide mutable state of a DGAmore run as module-level @@ -278,6 +278,9 @@ class MemoryConfig: :ivar bool save_memory_for_sde: Use the q-loop self-energy contraction instead of the FFT one. :ivar bool save_memory_for_fq: Use the per-q full-vertex construction in the Eliashberg step. :ivar bool save_memory_for_lanczos: Use the frequency-distributed Lanczos solver. + :ivar bool use_shared_memory_giwk: Store the replicated full-grid Green's function ``giwk_full`` in one MPI + shared-memory window per node (computed only by the node root) instead of one private copy per rank. Enabled + by default; disable it if cross-socket (NUMA) reads of the shared buffer outweigh the memory saving. """ def __init__(self): @@ -286,6 +289,7 @@ def __init__(self): self.save_memory_for_sde: bool = False self.save_memory_for_fq: bool = False self.save_memory_for_lanczos: bool = False + self.use_shared_memory_giwk: bool = True class AnaContConfig: diff --git a/dgamore/config_parser.py b/dgamore/config_parser.py index dc040ae1..952232cb 100644 --- a/dgamore/config_parser.py +++ b/dgamore/config_parser.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems """ YAML configuration parsing. :class:`ConfigParser` reads the run's YAML config (rank 0), broadcasts it to all MPI @@ -326,6 +326,7 @@ def _build_memory_config(self, config_file): conf.save_memory_for_sde = self._try_parse(section, "save_memory_for_sde", conf.save_memory_for_sde) conf.save_memory_for_fq = self._try_parse(section, "save_memory_for_fq", conf.save_memory_for_fq) conf.save_memory_for_lanczos = self._try_parse(section, "save_memory_for_lanczos", conf.save_memory_for_lanczos) + conf.use_shared_memory_giwk = self._try_parse(section, "use_shared_memory_giwk", conf.use_shared_memory_giwk) return conf diff --git a/dgamore/dga_config.yaml b/dgamore/dga_config.yaml index 6f443665..a9196113 100644 --- a/dgamore/dga_config.yaml +++ b/dgamore/dga_config.yaml @@ -96,4 +96,6 @@ memory: # less memory intensive, but it will increase runtime. save_memory_for_lanczos: False # If True, the code will perform the Lanczos algorithm with the pairing vertex for # the Eliashberg calculation in a more memory efficient way. This will reduce memory usage but increase runtime - # due to required MPI communication in each Lanczos step. \ No newline at end of file + # due to required MPI communication in each Lanczos step. + use_shared_memory_giwk: True # If True (default), the full-grid lattice Green's function is stored once per node in + # an MPI shared-memory window (computed only by the node's first rank) \ No newline at end of file diff --git a/dgamore/dga_io.py b/dgamore/dga_io.py index a8561279..d57e21ed 100644 --- a/dgamore/dga_io.py +++ b/dgamore/dga_io.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems """ High-level DMFT input loading and run setup. This module ties the DMFT interface, the global config and the lattice diff --git a/dgamore/dga_logger.py b/dgamore/dga_logger.py index 5cc6036e..6146ce9a 100644 --- a/dgamore/dga_logger.py +++ b/dgamore/dga_logger.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems """ MPI-aware logging. :class:`DgaLogger` timestamps messages and, by default, only emits them on the root rank so diff --git a/dgamore/dmft_interface.py b/dgamore/dmft_interface.py index 06162121..3f766ca3 100644 --- a/dgamore/dmft_interface.py +++ b/dgamore/dmft_interface.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems """ DMFT input interface. :class:`DMFTInterface` is the abstract contract for reading the quantities a DGA run needs diff --git a/dgamore/eliashberg_solver.py b/dgamore/eliashberg_solver.py index 32c22cfd..b25b88ce 100644 --- a/dgamore/eliashberg_solver.py +++ b/dgamore/eliashberg_solver.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems r""" Linearized Eliashberg equation solver. Starting from the ladder-DGA full vertex (saved per channel by the @@ -133,7 +133,7 @@ def create_full_vertex_q_r( f_q_r = nonlocal_sde.create_auxiliary_chi_r_q(gamma_r, gchi0_q_inv, u_loc, v_nonloc) logger.info(f"Non-Local auxiliary susceptibility ({gamma_r.channel.value}) calculated.") - f_q_r = config.sys.beta**2 * (gchi0_q_inv - gchi0_q_inv @ f_q_r @ gchi0_q_inv) + f_q_r = (gchi0_q_inv - gchi0_q_inv @ f_q_r @ gchi0_q_inv).scale(config.sys.beta**2) gchi0_q_inv.free() if not config.eliashberg.save_fq: @@ -143,14 +143,14 @@ def create_full_vertex_q_r( logger.info(f"Calculated first part of full {gamma_r.channel.value} vertex.") - vrg_q_r = FourPoint.load( + vrg_q_r_left = FourPoint.load( os.path.join(config.output.eliashberg_path, f"vrg_q_{gamma_r.channel.value}_rank_{mpi_dist.my_rank}.npy"), channel=gamma_r.channel, num_vn_dimensions=1, ) if config.eliashberg.construct_fq_cheap: - vrg_q_r = vrg_q_r.cut_niv(niv_pp) + vrg_q_r_left = vrg_q_r_left.cut_niv(niv_pp) gchi_aux_q_r_sum = FourPoint.load( os.path.join( @@ -162,10 +162,22 @@ def create_full_vertex_q_r( logger.info(f"Loaded vrg_q_{gamma_r.channel.value} and gchi_aux_q_{gamma_r.channel.value}_sum from files.") u = u_loc.as_channel(gamma_r.channel) + v_nonloc.as_channel(gamma_r.channel) - f_q_r_2 = u @ (vrg_q_r * vrg_q_r) - u @ gchi_aux_q_r_sum @ u @ (vrg_q_r * vrg_q_r) - vrg_q_r.free() + f_q_r_2 = vrg_q_r_left @ u - vrg_q_r_left @ (u @ gchi_aux_q_r_sum @ u) + vrg_q_r_left.free() gchi_aux_q_r_sum.free() + vrg_q_r_right = FourPoint.load( + os.path.join(config.output.eliashberg_path, f"vrg_q_{gamma_r.channel.value}_right_rank_{mpi_dist.my_rank}.npy"), + channel=gamma_r.channel, + num_vn_dimensions=1, + ) + + if config.eliashberg.construct_fq_cheap: + vrg_q_r_right = vrg_q_r_right.cut_niv(niv_pp) + + f_q_r_2 = f_q_r_2 * vrg_q_r_right + vrg_q_r_right.free() + if not config.eliashberg.save_fq: f_q_r_2 = transform_vertex_q_frequencies_w0(f_q_r_2, niv_pp) f_q_r += f_q_r_2 @@ -178,6 +190,7 @@ def create_full_vertex_q_r( delete_files( config.output.eliashberg_path, f"vrg_q_{gamma_r.channel.value}_rank_{mpi_dist.my_rank}.npy", + f"vrg_q_{gamma_r.channel.value}_right_rank_{mpi_dist.my_rank}.npy", f"gchi_aux_q_{gamma_r.channel.value}_sum_rank_{mpi_dist.my_rank}.npy", ) @@ -226,7 +239,8 @@ def create_full_vertex_q_r_v2( v_nonloc: Interaction, gamma_r: LocalFourPoint, gchi0_q_inv: FourPoint, - vrg_q_r: FourPoint, + vrg_q_r_left: FourPoint, + vrg_q_r_right: FourPoint, gchi_aux_q_r_sum: FourPoint, niv_pp: int, q_index: int, @@ -239,28 +253,28 @@ def create_full_vertex_q_r_v2( :param v_nonloc: The non-local interaction :math:`V^{q}`. :param gamma_r: The local irreducible vertex :math:`\Gamma_{r}` for this channel. :param gchi0_q_inv: The inverse bare bubble :math:`(\chi_0^q)^{-1}` over all rank-local q-points. - :param vrg_q_r: The momentum-dependent three-leg vertex :math:`\gamma^q_{r}`. + :param vrg_q_r_left: The momentum-dependent three-leg vertex :math:`\gamma^q_{r}`. + :param vrg_q_r_right: The momentum-dependent "right-side" three-leg vertex :math:`\gamma^q_{r}`. :param gchi_aux_q_r_sum: The summed auxiliary susceptibility :math:`\sum_{\nu'}\chi^{*;q}_{r}`. :param niv_pp: Number of positive fermionic frequencies of the pp vertex. :param q_index: Index of the q-point (into the rank-local list) to compute. :return: The full ladder vertex :math:`F^{q}_{r}` for that q-point as a :class:`FourPoint`. """ gchi0_q_inv_idx = gchi0_q_inv.filter_q_index(q_index) - vrg_q_r_idx = vrg_q_r.filter_q_index(q_index) + vrg_q_r_left_idx = vrg_q_r_left.filter_q_index(q_index) + vrg_q_r_right_idx = vrg_q_r_right.filter_q_index(q_index) gchi_aux_q_r_sum_idx = gchi_aux_q_r_sum.filter_q_index(q_index) v_nonloc_idx = v_nonloc.filter_q_index(q_index) u = u_loc.as_channel(gamma_r.channel) + v_nonloc_idx.as_channel(gamma_r.channel) f_q_r_idx = nonlocal_sde.create_auxiliary_chi_r_q(gamma_r, gchi0_q_inv_idx, u_loc, v_nonloc_idx) - f_q_r_idx = ( - config.sys.beta**2 * (gchi0_q_inv_idx - gchi0_q_inv_idx @ f_q_r_idx @ gchi0_q_inv_idx) - + u @ (vrg_q_r_idx * vrg_q_r_idx) - - u @ gchi_aux_q_r_sum_idx @ u @ (vrg_q_r_idx * vrg_q_r_idx) - ) + f_q_r_idx = (gchi0_q_inv_idx - gchi0_q_inv_idx @ f_q_r_idx @ gchi0_q_inv_idx).scale(config.sys.beta**2) + ( + vrg_q_r_left_idx @ u - vrg_q_r_left_idx @ (u @ gchi_aux_q_r_sum_idx @ u) + ) * vrg_q_r_right_idx gchi0_q_inv_idx.free() - vrg_q_r_idx.free() + vrg_q_r_left_idx.free() gchi_aux_q_r_sum_idx.free() if not config.eliashberg.save_fq: @@ -292,12 +306,20 @@ def create_full_vertex_q_r_pp_w0_v2( ) logger.info(f"Loaded gchi0_q_inv from file.") - vrg_q_r = FourPoint.load( + vrg_q_r_left = FourPoint.load( os.path.join(config.output.eliashberg_path, f"vrg_q_{gamma_r.channel.value}_rank_{mpi_dist_irrk.my_rank}.npy"), channel=gamma_r.channel, num_vn_dimensions=1, ) + vrg_q_r_right = FourPoint.load( + os.path.join( + config.output.eliashberg_path, f"vrg_q_{gamma_r.channel.value}_right_rank_{mpi_dist_irrk.my_rank}.npy" + ), + channel=gamma_r.channel, + num_vn_dimensions=1, + ) + gchi_aux_q_r_sum = FourPoint.load( os.path.join( config.output.eliashberg_path, f"gchi_aux_q_{gamma_r.channel.value}_sum_rank_{mpi_dist_irrk.my_rank}.npy" @@ -309,7 +331,8 @@ def create_full_vertex_q_r_pp_w0_v2( if config.eliashberg.construct_fq_cheap: gamma_r = gamma_r.cut_niv(niv_pp) gchi0_q_inv = gchi0_q_inv.cut_niv(niv_pp) - vrg_q_r = vrg_q_r.cut_niv(niv_pp) + vrg_q_r_left = vrg_q_r_left.cut_niv(niv_pp) + vrg_q_r_right = vrg_q_r_right.cut_niv(niv_pp) logger.info(f"Loaded vrg_q_{gamma_r.channel.value} and gchi_aux_q_{gamma_r.channel.value}_sum from files.") @@ -335,13 +358,14 @@ def create_full_vertex_q_r_pp_w0_v2( for idx, q in enumerate(my_irr_q_list): f_q_r_mat[idx] = create_full_vertex_q_r_v2( - u_loc, v_nonloc, gamma_r, gchi0_q_inv, vrg_q_r, gchi_aux_q_r_sum, niv_pp, idx + u_loc, v_nonloc, gamma_r, gchi0_q_inv, vrg_q_r_left, vrg_q_r_right, gchi_aux_q_r_sum, niv_pp, idx ).mat logger.info(f"Full ladder-vertex ({gamma_r.channel.value}) calculated.") gchi0_q_inv.free() - vrg_q_r.free() + vrg_q_r_left.free() + vrg_q_r_right.free() gchi_aux_q_r_sum.free() delete_files( @@ -387,7 +411,7 @@ def create_local_ud_diagrams_pp_w0(g_dmft: GreensFunction) -> tuple[LocalFourPoi """ gchi_dens_loc = LocalFourPoint.load(os.path.join(config.output.output_path, f"gchi_dens_loc.npy"), SpinChannel.DENS) gchi_magn_loc = LocalFourPoint.load(os.path.join(config.output.output_path, f"gchi_magn_loc.npy"), SpinChannel.MAGN) - gchi_ud_loc = 0.5 * (gchi_dens_loc - gchi_magn_loc).set_channel(SpinChannel.UD) + gchi_ud_loc = (gchi_dens_loc - gchi_magn_loc).set_channel(SpinChannel.UD).scale(0.5) gchi_ud_loc_pp_w0 = gchi_ud_loc.change_frequency_notation_ph_to_pp_w0() del gchi_dens_loc, gchi_magn_loc, gchi_ud_loc @@ -397,15 +421,15 @@ def create_local_ud_diagrams_pp_w0(g_dmft: GreensFunction) -> tuple[LocalFourPoi .flip_frequency_axis(-1, False) ) - gamma_ud_loc_pp_w0 = config.sys.beta**2 * ( - (gchi_ud_loc_pp_w0 - gchi0_loc_pp_w0).invert() + gchi0_loc_pp_w0.invert() + gamma_ud_loc_pp_w0 = ((gchi_ud_loc_pp_w0 - gchi0_loc_pp_w0).invert() + gchi0_loc_pp_w0.invert()).scale( + config.sys.beta**2 ) gamma_ud_loc_pp_w0.save(output_dir=config.output.eliashberg_path, name="gamma_ud_loc_pp_w0") f_dens_loc = LocalFourPoint.load(os.path.join(config.output.output_path, f"f_dens_loc.npy"), SpinChannel.DENS) f_magn_loc = LocalFourPoint.load(os.path.join(config.output.output_path, f"f_magn_loc.npy"), SpinChannel.MAGN) - f_ud_loc = 0.5 * (f_dens_loc - f_magn_loc).set_channel(SpinChannel.UD) + f_ud_loc = (f_dens_loc - f_magn_loc).set_channel(SpinChannel.UD).scale(0.5) f_ud_loc_pp_w0 = f_ud_loc.change_frequency_notation_ph_to_pp_w0() del f_dens_loc, f_magn_loc, f_ud_loc @@ -579,9 +603,12 @@ def solve_eliashberg_lanczos( # is freed right after its matmul-layout copy is built (peak stays ~1 vertex, not 3), and the flipped-term sign is # folded in place. chi0_mm = _chi0_to_matmul_layout(gchi0_q0_pp.mat) - gamma_mm = _gamma_to_matmul_layout(gamma_r_pp.mat) + # The pairing vertex arrives in the w2dynamics G2 leg order (c cdag c cdag), whereas the contraction in + # _apply_gamma_pp expects the TRIQS order (cdag c cdag c), see + # https://triqs.github.io/tprf/latest/theory/eliashberg.html + gamma_mm = _gamma_to_matmul_layout(gamma_r_pp.permute_orbitals("abcd->badc", False).mat) gamma_r_pp.free() - gamma_flipped_mm = _gamma_to_matmul_layout(gamma_pp_flipped.mat) + gamma_flipped_mm = _gamma_to_matmul_layout(gamma_pp_flipped.permute_orbitals("abcd->badc", False).mat) gamma_pp_flipped.free() gamma_flipped_mm *= sign @@ -698,9 +725,13 @@ def solve_eliashberg_lanczos_v2( # pairing vertices materialized once per rank. Each einsum-layout source is freed right after its matmul-layout copy # is built (peak stays ~1 vertex, not 3), and the flipped-term sign is folded in place. chi0_mm = _chi0_to_matmul_layout(gchi0_q0_pp.mat) if mpi_dist_v.comm.rank == root else None - gamma_mm = _gamma_to_matmul_layout(gamma_r_pp.mat) + # The pairing vertex arrives in the w2dynamics G2 leg order (c cdag c cdag), whereas the contraction in + # _apply_gamma_pp expects the TRIQS order (cdag c cdag c). The two differ by the "abcd->badc" swap + # (o1<->o2, o3<->o4); applying it to both the direct and the flipped vertex makes the gap's creation legs + # contract with the vertex's creation legs. This is a no-op for a single band. + gamma_mm = _gamma_to_matmul_layout(gamma_r_pp.permute_orbitals("abcd->badc", False).mat) gamma_r_pp.free() - gamma_flipped_mm = _gamma_to_matmul_layout(gamma_r_pp_flipped.mat) + gamma_flipped_mm = _gamma_to_matmul_layout(gamma_r_pp_flipped.permute_orbitals("abcd->badc", False).mat) gamma_r_pp_flipped.free() gamma_flipped_mm *= sign @@ -776,6 +807,47 @@ def mv(gap: np.ndarray): return lambdas, gaps +def dispatch_full_vertex_calculation( + channel: SpinChannel, u_loc: LocalInteraction, v_nonloc: Interaction, niv_pp: int, mpi_dist: MpiDistributor +) -> FourPoint: + r""" + Loads the local irreducible vertex for ``channel`` and builds the full ladder pp vertex, dispatching between + the memory-lean and the regular construction routine based on the memory configuration. Please note that + Eq. (4.43) in my master's thesis is wrong. The correct formula is + :math:`F^{q\nu\nu'}_{r;abcd}=F^{(1);q\nu\nu'}_{r;abcd}+F^{(2);q\nu\nu'}_{r;abcd}`, with + :math:`F^{(1);q\nu\nu'}_{r;abcd} = \beta^2\Big[(\chi_{0;abcd}^{q\nu\nu'})^{-1}- + (\chi_{0;abef}^{q\nu\nu_1})^{-1}\chi_{r;fehg}^{*;q\nu_1\nu_2}(\chi_{0;ghcd}^{q\nu_2\nu'})^{-1}\Big]` and + :math:`F^{(2);q\nu\nu'}_{r;abcd} = \gamma^{q\nu}_{r;abef}\Big(\mathbb{1}_{feji} - + \mathcal{U}^{q}_{r;fehg}\chi^{q}_{r;ghji}\Big)\mathcal{U}^{q}_{r;ijkl}\tilde\gamma^{q\nu'}_{r;lkcd}`, + where + :math:`\tilde\gamma_{r;abcd}^{q\nu}=\beta (\sum_{\nu'} \chi^{*;q\nu'\nu}_{r;ablm}) (\chi^{q\nu}_{0;mlcd})^{-1} + =\beta (\sum_{\nu'} \chi^{*;q\nu\nu'}_{r;mlba}) (\chi^{q\nu}_{0;mlcd})^{-1}`, i.e. the sum over the first + frequency argument equals the sum over the last one only up to the orbital reversal dictated by + time-reversal symmetry, see :meth:`~dgamore.nonlocal_sde.create_vrg_r_q_right`. No explicit factors of + :math:`\beta` appear in :math:`F^{(2)}` because they are absorbed into the stored objects: + :math:`\chi^{q}_{r}` is the (:math:`U`-dressed, shell- (and sometimes :math:`\lambda`-corrected)) physical + susceptibility normalized as :math:`\frac{1}{\beta^2}\sum_{\nu\nu'}\chi^{q\nu\nu'}_{r}`, and the three-leg + vertices carry the net normalization :math:`\gamma^{q\nu}_{r} = (\chi^{q\nu}_{0})^{-1}\sum_{\nu'} + \chi^{*;q\nu\nu'}_{r}` (the explicit :math:`\beta` in their construction cancels the :math:`1/\beta` of the + fused frequency sum), such that :math:`\gamma^{q\nu}_{r} \to \mathbb{1}` for :math:`\nu \to \infty`. + + :param channel: The spin channel (density or magnetic). + :param u_loc: The bare local interaction :math:`U`. + :param v_nonloc: The non-local interaction :math:`V^{q}`. + :param niv_pp: Number of positive fermionic frequencies of the pp vertex. + :param mpi_dist: MPI distributor over the irreducible BZ q-points. + :return: The full ladder pp vertex :math:`F^{q}_{r}` as a :class:`FourPoint`. + """ + gamma_r = LocalFourPoint.load(os.path.join(config.output.output_path, f"gamma_{channel.value}_loc.npy"), channel) + if config.memory.save_memory_for_fq: + f_q_r = create_full_vertex_q_r_pp_w0_v2(u_loc, v_nonloc, gamma_r, niv_pp, mpi_dist) + else: + f_q_r = create_full_vertex_q_r_pp_w0(u_loc, v_nonloc, gamma_r, niv_pp, mpi_dist) + gamma_r.free() + mpi_dist.barrier() + return f_q_r + + def solve( giwk_dga: GreensFunction, g_dmft: GreensFunction, u_loc: LocalInteraction, v_nonloc: Interaction, comm: MPI.Comm ): @@ -805,29 +877,6 @@ def solve( niv_pp = min(config.box.niw_core // 2, config.box.niv_core // 2) - def dispatch_full_vertex_calculation(channel, u, v, niv, mpi_dist) -> FourPoint: - r""" - Loads the local irreducible vertex for ``channel`` and builds the full ladder pp vertex, dispatching between - the memory-lean and the regular construction routine based on the memory configuration. - - :param channel: The spin channel (density or magnetic). - :param u: The bare local interaction :math:`U`. - :param v: The non-local interaction :math:`V^{q}`. - :param niv: Number of positive fermionic frequencies of the pp vertex. - :param mpi_dist: MPI distributor over the irreducible BZ q-points. - :return: The full ladder pp vertex :math:`F^{q}_{r}` as a :class:`FourPoint`. - """ - gamma_r = LocalFourPoint.load( - os.path.join(config.output.output_path, f"gamma_{channel.value}_loc.npy"), channel - ) - if config.memory.save_memory_for_fq: - f_q_r = create_full_vertex_q_r_pp_w0_v2(u, v, gamma_r, niv, mpi_dist) - else: - f_q_r = create_full_vertex_q_r_pp_w0(u, v, gamma_r, niv, mpi_dist) - gamma_r.free() - mpi_dist.barrier() - return f_q_r - f_dens_pp = dispatch_full_vertex_calculation(SpinChannel.DENS, u_loc, v_nonloc, niv_pp, mpi_dist_irrk) f_magn_pp = dispatch_full_vertex_calculation(SpinChannel.MAGN, u_loc, v_nonloc, niv_pp, mpi_dist_irrk) @@ -861,7 +910,7 @@ def dispatch_full_vertex_calculation(channel, u, v, niv, mpi_dist) -> FourPoint: # different from the regular pp f_dens_loc = LocalFourPoint.load(os.path.join(config.output.output_path, f"f_dens_loc.npy"), SpinChannel.DENS) f_magn_loc = LocalFourPoint.load(os.path.join(config.output.output_path, f"f_magn_loc.npy"), SpinChannel.MAGN) - f_ud_loc = 0.5 * (f_dens_loc - f_magn_loc).set_channel(SpinChannel.UD) + f_ud_loc = (f_dens_loc - f_magn_loc).set_channel(SpinChannel.UD).scale(0.5) f_ud_loc_transf_w0 = transform_vertex_loc_frequencies_w0(f_ud_loc, niv_pp) del f_dens_loc, f_magn_loc, f_ud_loc diff --git a/dgamore/four_point.py b/dgamore/four_point.py index ee8acc9a..a9f372f2 100644 --- a/dgamore/four_point.py +++ b/dgamore/four_point.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems r""" Momentum-dependent four-point objects. :class:`FourPoint` extends :class:`LocalFourPoint` with one momentum axis @@ -13,7 +13,6 @@ """ import gc -from copy import deepcopy import numpy as np @@ -90,7 +89,7 @@ def __rsub__(self, other) -> "FourPoint": """ Reflected operator form of :meth:`sub` (``B - A``), returning ``-(A - B)``. See :meth:`sub`. """ - return -self.sub(other) + return self.sub(other).scale(-1.0) def __mul__(self, other) -> "FourPoint": """ @@ -371,7 +370,7 @@ def permute_orbitals(self, permutation: str = "abcd->abcd", copy: bool = True) - return self if copy: - return deepcopy(self).permute_orbitals(permutation, copy=False) + return self.copy().permute_orbitals(permutation, copy=False) permutation = ( f"i{split[0]}...->i{split[1]}..." @@ -392,18 +391,20 @@ def map_to_full_bz(self, grid: KGrid, nq: tuple = None): """ return self._map_to_full_bz(grid, 4, nq) - def add(self, other) -> "FourPoint": + def add(self, other, copy: bool = True) -> "FourPoint": """ Adds ``other`` to this object (operator ``+``); see :meth:`_add` for the accepted operands and the niw-range handling. :param other: A :class:`FourPoint`, :class:`LocalFourPoint`, :class:`Interaction`, :class:`LocalInteraction`, numpy array, or number. - :return: A new :class:`FourPoint` holding the sum. + :param copy: If True (default), return a new :class:`FourPoint`; if False, accumulate into ``self`` in place + (only supported when ``other`` is a conforming :class:`FourPoint`, see :meth:`_add`). + :return: A new :class:`FourPoint` holding the sum (or ``self`` when ``copy=False``). """ - return self._add(other) + return self._add(other, copy=copy) - def _add(self, other, subtract: bool = False) -> "FourPoint": + def _add(self, other, subtract: bool = False, copy: bool = True) -> "FourPoint": """ Helper method that allows for addition of FourPoint objects and other FourPoint, LocalFourPoint, Interaction or LocalInteraction objects. Additions with numpy arrays, floats, ints or complex numbers are also supported. @@ -414,8 +415,16 @@ def _add(self, other, subtract: bool = False) -> "FourPoint": :param other: A :class:`FourPoint`, :class:`LocalFourPoint`, :class:`Interaction`, :class:`LocalInteraction`, numpy array, or number. Local operands are broadcast over the momentum axis. :param subtract: If True, subtract ``other`` instead of adding it (used by :meth:`sub` to avoid a negated copy). - :return: A new :class:`FourPoint` (in the half niw range for the vertex-vertex case). - :raises ValueError: If ``other`` has an unsupported type. + :param copy: If True (default), return a new :class:`FourPoint`; if False, accumulate the result into + ``self.mat`` in place and return ``self`` (no out-of-place result block). The in-place branch is only + supported between two :class:`FourPoint` objects whose fermionic frequency dimensions already match (it + refuses to diagonally extend ``self``), which is the self-energy-kernel accumulation case in + :mod:`dgamore.nonlocal_sde`. + :return: A new :class:`FourPoint` (in the half niw range for the vertex-vertex case), or ``self`` when + ``copy=False``. + :raises ValueError: If ``other`` has an unsupported type, or ``copy=False`` would have to diagonally extend + ``self``. + :raises NotImplementedError: If ``copy=False`` and ``other`` is not a :class:`FourPoint`. """ if not isinstance( other, (FourPoint, LocalFourPoint, Interaction, LocalInteraction, np.ndarray, float, int, complex) @@ -424,6 +433,11 @@ def _add(self, other, subtract: bool = False) -> "FourPoint": op = np.subtract if subtract else np.add + if not copy and not isinstance(other, FourPoint): + raise NotImplementedError( + "In-place addition/subtraction (copy=False) is only supported between two FourPoint objects." + ) + if isinstance(other, (np.ndarray, float, int, complex)): return FourPoint( op(self.mat, other), @@ -491,6 +505,23 @@ def _add(self, other, subtract: bool = False) -> "FourPoint": other = self._align_q_dimensions_for_operations(other) other, self_extended, other_extended = self._align_frequency_dimensions_for_operation(other) + if not copy: + if self_extended: + raise ValueError( + "In-place addition/subtraction (copy=False) cannot diagonally extend 'self'; both operands " + "must have the same number of fermionic frequency dimensions." + ) + # accumulate into self in place: no out-of-place result block (and the caller folds any scalar prefactor + # via FourPoint.scale, so no negated/scaled copy of ``other`` either). + op(self.mat, other.mat, out=self.mat) + self.channel = channel + self._full_niw_range = False + self.update_original_shape() + if other_full_niw_range: + other = other.to_full_niw_range() + self._revert_frequency_dimensions_after_operation(other, other_extended, False) + return self + result = FourPoint( op(self.mat, other.mat), channel, @@ -511,7 +542,7 @@ def _add(self, other, subtract: bool = False) -> "FourPoint": other = self._revert_frequency_dimensions_after_operation(other, other_extended, self_extended) return result - def sub(self, other) -> "FourPoint": + def sub(self, other, copy: bool = True) -> "FourPoint": """ Helper method that allows for subtraction of FourPoint objects and other FourPoint, LocalFourPoint, Interaction or LocalInteraction objects. Subtractions with numpy arrays, floats, ints or complex numbers are also supported. @@ -521,10 +552,13 @@ def sub(self, other) -> "FourPoint": :param other: A :class:`FourPoint`, :class:`LocalFourPoint`, :class:`Interaction`, :class:`LocalInteraction`, numpy array, or number. - :return: The difference, implemented as ``self._add(other, subtract=True)`` (see :meth:`_add`). + :param copy: If True (default), return a new :class:`FourPoint`; if False, subtract into ``self`` in place + and return ``self`` (only supported when ``other`` is a conforming :class:`FourPoint`, see :meth:`_add`). + :return: The difference, implemented as ``self._add(other, subtract=True)`` (see :meth:`_add`), or ``self`` + when ``copy=False``. :raises ValueError: Propagated from :meth:`_add` for unsupported operands. """ - return self._add(other, subtract=True) + return self._add(other, subtract=True, copy=copy) def mul(self, other) -> "FourPoint": r""" @@ -543,7 +577,7 @@ def mul(self, other) -> "FourPoint": raise ValueError("Multiplication only supported with numbers, numpy arrays or FourPoint objects.") if not isinstance(other, FourPoint): - copy = deepcopy(self) + copy = self.copy() copy.mat *= other return copy @@ -696,7 +730,7 @@ def invert(self, copy: bool = True): """ if copy: - return deepcopy(self).invert(copy=False) + return self.copy().invert(copy=False) self.to_half_niw_range() if self.num_vn_dimensions == 1: diff --git a/dgamore/gap_function.py b/dgamore/gap_function.py index 916c50ff..ab5bf3be 100644 --- a/dgamore/gap_function.py +++ b/dgamore/gap_function.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems r""" The superconducting gap function :math:`\Delta`, i.e. the eigenvector of the linearized Eliashberg equation. diff --git a/dgamore/greens_function.py b/dgamore/greens_function.py index 7e38e605..59969edd 100644 --- a/dgamore/greens_function.py +++ b/dgamore/greens_function.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems r""" Single-particle Green's function. :class:`GreensFunction` builds the momentum-dependent interacting Green's @@ -99,7 +99,12 @@ def root_fun( def update_mu( - mu0: float, target_filling: float, ek: np.ndarray, sigma_mat: np.ndarray, beta: float, smom0: np.ndarray, + mu0: float, + target_filling: float, + ek: np.ndarray, + sigma_mat: np.ndarray, + beta: float, + smom0: np.ndarray, logger=None, ) -> float: r""" @@ -137,7 +142,7 @@ class GreensFunction(TwoPoint): \varepsilon_{ab}(k) - \Sigma_{ab}(k, \nu)]^{-1}`. Built from a :class:`SelfEnergy`, the band dispersion :math:`\varepsilon(k)` and the chemical potential :math:`\mu`; on top of the two-point orbital bookkeeping inherited from :class:`LocalTwoPoint` it adds the Dyson construction (local and momentum-resolved) and the - derived quantities — filling, occupation matrices, kinetic and (Galitskii-Migdal) potential energy — all using + derived quantities - filling, occupation matrices, kinetic and (Galitskii-Migdal) potential energy - all using moment-corrected asymptotic Matsubara sums so the finite frequency box does not bias the result. """ @@ -245,7 +250,9 @@ def get_g_full(siw: SelfEnergy, mu: float, ek: np.ndarray, beta: float): return GreensFunction(mat, siw, ek, siw.full_niv_range, False, False, nk=ek.shape[:3], beta=beta, mu=mu) @staticmethod - def create_g_loc(siw: SelfEnergy, ek: np.ndarray, beta: float, mu: float, calc_filling: bool = True) -> "GreensFunction": + def create_g_loc( + siw: SelfEnergy, ek: np.ndarray, beta: float, mu: float, calc_filling: bool = True + ) -> "GreensFunction": r""" Builds a local (k-summed) Green's function from a self-energy and band dispersion. diff --git a/dgamore/hamiltonian.py b/dgamore/hamiltonian.py index 2d573330..48cb4965 100644 --- a/dgamore/hamiltonian.py +++ b/dgamore/hamiltonian.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems r""" Lattice model setup. :class:`Hamiltonian` assembles the (multi-orbital) Hubbard model: the real-space hopping diff --git a/dgamore/interaction.py b/dgamore/interaction.py index acc695a7..1b430152 100644 --- a/dgamore/interaction.py +++ b/dgamore/interaction.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems r""" Interaction tensors. :class:`LocalInteraction` wraps the momentum-independent (Hubbard/Kanamori) interaction @@ -10,8 +10,6 @@ equations. """ -from copy import deepcopy - import numpy as np from dgamore.n_point_base import IHaveMat, IHaveChannel, IAmNonLocal, SpinChannel @@ -55,7 +53,7 @@ def permute_orbitals(self, permutation: str = "abcd->abcd") -> "LocalInteraction raise ValueError("Invalid permutation.") if split[0] == split[1]: - return deepcopy(self) + return self.copy() return LocalInteraction(np.einsum(permutation, self.mat, optimize=True), self.channel) @@ -69,7 +67,7 @@ def as_channel(self, channel: SpinChannel) -> "LocalInteraction": :return: A new :class:`LocalInteraction` in the requested channel. :raises ValueError: If the object is already in a (non-``NONE``) channel, or the target channel is unsupported. """ - copy = deepcopy(self) + copy = self.copy() if copy.channel == channel: return copy @@ -139,7 +137,7 @@ def pow(self, power) -> "LocalInteraction": """ if power <= 0: raise ValueError("Exponentiation of Interaction objects only supports positive powers greater than zero.") - result = deepcopy(self) + result = self.copy() for _ in range(1, power): result = LocalInteraction(result.times("abcd,dcef->abef", self), self.channel) return result @@ -228,7 +226,7 @@ def permute_orbitals(self, permutation: str = "abcd->abcd") -> "Interaction": raise ValueError("Invalid permutation.") if split[0] == split[1]: - return deepcopy(self) + return self.copy() permutation = f"...{split[0]}->...{split[1]}" return Interaction( @@ -245,7 +243,7 @@ def as_channel(self, channel: SpinChannel) -> "Interaction": :return: A new :class:`Interaction` in the requested channel. :raises ValueError: If the object is already in a (non-``NONE``) channel, or the target channel is unsupported. """ - copy = deepcopy(self) + copy = self.copy() if copy.channel == channel: return copy @@ -325,7 +323,7 @@ def pow(self, power) -> "Interaction": if power <= 0: raise ValueError("Exponentiation of Interaction objects only supports positive powers greater than zero.") is_self_compressed = self.has_compressed_q_dimension - result = deepcopy(self).compress_q_dimension() + result = self.copy().compress_q_dimension() for _ in range(1, power): result = Interaction(result.times("qabcd,qdcef->qabef", self), self.channel, self.nq, True) return result if is_self_compressed else result.decompress_q_dimension() diff --git a/dgamore/lambda_correction.py b/dgamore/lambda_correction.py index f065e870..c6fa5e79 100644 --- a/dgamore/lambda_correction.py +++ b/dgamore/lambda_correction.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems r""" Moriya :math:`\lambda`-correction of the physical susceptibility. The non-local susceptibility is shifted by a diff --git a/dgamore/local_four_point.py b/dgamore/local_four_point.py index 7e774031..b91e897f 100644 --- a/dgamore/local_four_point.py +++ b/dgamore/local_four_point.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems r""" Local (momentum-independent) four-point objects. :class:`LocalFourPoint` wraps a single array carrying four @@ -12,8 +12,6 @@ matrix layout used for inversion and matrix products. Notation mirrors the thesis (Chapters 3 & 4). """ -from copy import deepcopy - import numpy as np from dgamore.interaction import LocalInteraction, Interaction @@ -82,7 +80,7 @@ def __rsub__(self, other): """ Reflected operator form of :meth:`sub` (``B - A``), returning ``-(A - B)``. See :meth:`sub`. """ - return -self.sub(other) + return self.sub(other).scale(-1.0) def __mul__(self, other): """ @@ -141,7 +139,7 @@ def pow(self, power: int, identity): return self.invert() ** abs(power) result = identity - base = deepcopy(self) + base = self.copy() # Exponentiation by squaring while power > 0: @@ -370,7 +368,7 @@ def invert(self, copy: bool = True): """ if copy: - return deepcopy(self).invert(copy=False) + return self.copy().invert(copy=False) self.to_half_niw_range().to_compound_indices() self.mat = np.linalg.inv(self.mat) @@ -490,7 +488,7 @@ def mul(self, other): raise ValueError("Multiplication only supported with numbers, numpy arrays or LocalFourPoint objects.") if not isinstance(other, LocalFourPoint): - copy = deepcopy(self) + copy = self.copy() copy.mat *= other return copy @@ -664,7 +662,7 @@ def permute_orbitals(self, permutation: str = "abcd->abcd", copy: bool = True) - raise ValueError("Invalid permutation.") if copy: - return deepcopy(self).permute_orbitals(permutation, copy=False) + return self.copy().permute_orbitals(permutation, copy=False) permutation = f"{split[0]}...->{split[1]}..." self.mat = np.einsum(permutation, self.mat, optimize=True) @@ -724,7 +722,7 @@ def change_frequency_notation_ph_to_pp_w0(self): if self.num_wn_dimensions != 1 or self.num_vn_dimensions not in (1, 2): raise ValueError("Object must have 1 bosonic and 1 or 2 fermionic frequency dimensions.") - copy = deepcopy(self) + copy = self.copy() if copy.frequency_notation == FrequencyNotation.PP: return copy @@ -749,7 +747,7 @@ def create_wn_dimension(self): if self.num_wn_dimensions != 0: raise ValueError("Object already has bosonic frequency dimensions.") - copy = deepcopy(self) + copy = self.copy() # insert bosonic axis immediately before the last vn axes copy.mat = np.expand_dims(copy.mat, axis=-(copy.num_vn_dimensions + 1)) copy._num_wn_dimensions = 1 @@ -786,7 +784,7 @@ def pad_with_u(self, u: LocalInteraction, niv_pad: int): :return: A new :class:`LocalFourPoint` padded to ``niv_pad``. """ if niv_pad <= self.niv: - return deepcopy(self) + return self.copy() copy = self._clone_without_mat() # Allocate the padded array once and broadcast-fill the shell with ``u`` instead of materializing a full diff --git a/dgamore/local_n_point.py b/dgamore/local_n_point.py index 016b8be6..1fa72494 100644 --- a/dgamore/local_n_point.py +++ b/dgamore/local_n_point.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems """ Base class for all local (momentum-independent) N-point quantities. :class:`LocalNPoint` adds the orbital and @@ -12,7 +12,6 @@ import itertools import os -from copy import deepcopy import numpy as np @@ -435,7 +434,7 @@ def flip_frequency_axis(self, axis: tuple | int, copy: bool = True): raise ValueError(f"Invalid axis {axis}. Possible axes are {axis_possible}.") if copy: - return deepcopy(self).flip_frequency_axis(axis, copy=False) + return self.copy().flip_frequency_axis(axis, copy=False) self.mat = np.flip(self.mat, axis=axis) return self @@ -452,7 +451,7 @@ def swap_fermionic_frequency_axes(self, copy: bool = True): raise ValueError("Cannot swap axes if there are less than two fermionic frequency dimensions.") if copy: - return deepcopy(self).swap_fermionic_frequency_axes(copy=False) + return self.copy().swap_fermionic_frequency_axes(copy=False) self.mat = np.swapaxes(self.mat, -1, -2) return self diff --git a/dgamore/local_sde.py b/dgamore/local_sde.py index e1c16089..b553d2ee 100644 --- a/dgamore/local_sde.py +++ b/dgamore/local_sde.py @@ -1,14 +1,14 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems r""" Local Schwinger-Dyson step. Given the two-particle DMFT Green's functions and the bare interaction, the functions -here build the local vertex hierarchy per spin channel — the generalized susceptibility :math:`\chi_{r}`, the +here build the local vertex hierarchy per spin channel - the generalized susceptibility :math:`\chi_{r}`, the irreducible vertex :math:`\Gamma_{r}` (with the Kitatani shell asymptotics), the auxiliary susceptibility :math:`\chi^{*}_{r}`, the three-leg vertex :math:`\gamma_{r}` (``vrg``), the full vertex :math:`F_{r}`, and the -physical susceptibility — and recompute the local self-energy via the Schwinger-Dyson equation as a sanity check +physical susceptibility - and recompute the local self-energy via the Schwinger-Dyson equation as a sanity check against the DMFT input. Equation numbers refer to the author's master's thesis (Chapter 3). A second set of functions implements the alternative ab-initio DGA formulation. """ @@ -57,7 +57,7 @@ def create_gamma_r(gchi_r: LocalFourPoint, gchi0_inv: LocalFourPoint, beta: floa :param beta: Inverse temperature :math:`\beta`. :return: The irreducible vertex :math:`\Gamma_{r}` as a :class:`LocalFourPoint`. """ - return beta**2 * (gchi_r.invert() - gchi0_inv) + return (gchi_r.invert() - gchi0_inv).scale(beta**2) def create_gamma_r_with_shell_correction( @@ -76,7 +76,7 @@ def create_gamma_r_with_shell_correction( """ chi_tilde_shell = (gchi0.invert() + 1.0 / config.sys.beta**2 * u_loc.as_channel(gchi_r.channel)).invert() chi_tilde_core_inv = chi_tilde_shell.cut_niv(config.box.niv_core).invert() - return config.sys.beta**2 * (gchi_r.invert() - chi_tilde_core_inv) + u_loc.as_channel(gchi_r.channel) + return (gchi_r.invert() - chi_tilde_core_inv).scale(config.sys.beta**2) + u_loc.as_channel(gchi_r.channel) def create_auxiliary_chi(gamma_r: LocalFourPoint, gchi0_inv: LocalFourPoint, u_loc: LocalInteraction) -> LocalFourPoint: @@ -90,7 +90,7 @@ def create_auxiliary_chi(gamma_r: LocalFourPoint, gchi0_inv: LocalFourPoint, u_l :param u_loc: The bare local interaction :math:`U`. :return: The auxiliary susceptibility :math:`\chi^{*}_{r}` as a :class:`LocalFourPoint`. """ - return (gchi0_inv + (gamma_r - u_loc.as_channel(gamma_r.channel)) / config.sys.beta**2).invert() + return (gchi0_inv + (gamma_r - u_loc.as_channel(gamma_r.channel)).scale(1.0 / config.sys.beta**2)).invert() def create_generalized_chi_with_shell_correction( @@ -106,8 +106,8 @@ def create_generalized_chi_with_shell_correction( :param u_loc: The bare local interaction :math:`U`. :return: The shell-corrected physical susceptibility :math:`\chi_{r}^{\omega}` as a :class:`LocalFourPoint`. """ - gchi0_full_sum = 1.0 / config.sys.beta * gchi0.sum_over_all_vn(config.sys.beta) - gchi0_core_sum = 1.0 / config.sys.beta * gchi0.cut_niv(config.box.niv_core).sum_over_all_vn(config.sys.beta) + gchi0_full_sum = gchi0.sum_over_all_vn(config.sys.beta).scale(1.0 / config.sys.beta) + gchi0_core_sum = gchi0.cut_niv(config.box.niv_core).sum_over_all_vn(config.sys.beta).scale(1.0 / config.sys.beta) return ((gchi_aux_sum + gchi0_full_sum - gchi0_core_sum).invert() + u_loc.as_channel(gchi_aux_sum.channel)).invert() @@ -137,7 +137,7 @@ def create_full_vertex(gchi_r: LocalFourPoint, gchi0_inv: LocalFourPoint) -> Loc :param gchi0_inv: The inverse bare bubble :math:`\chi_0^{-1}`. :return: The full vertex :math:`F_{r}` as a :class:`LocalFourPoint`. """ - return config.sys.beta**2 * (gchi0_inv - gchi0_inv @ gchi_r @ gchi0_inv) + return (gchi0_inv - gchi0_inv @ gchi_r @ gchi0_inv).scale(config.sys.beta**2) def create_vrg(gchi_aux: LocalFourPoint, gchi0_inv: LocalFourPoint) -> LocalFourPoint: @@ -151,7 +151,7 @@ def create_vrg(gchi_aux: LocalFourPoint, gchi0_inv: LocalFourPoint) -> LocalFour :return: The three-leg vertex :math:`\gamma_{r}` (``vrg``) as a :class:`LocalFourPoint`. """ gchi_aux_sum = gchi_aux.sum_over_vn(config.sys.beta, axis=(-1,)) - return config.sys.beta * (gchi0_inv @ gchi_aux_sum) + return (gchi0_inv @ gchi_aux_sum).scale(config.sys.beta) def create_vertex_functions( @@ -380,20 +380,20 @@ def perform_local_schwinger_dyson_abinitio_dga( # F_r = -beta^2 * [chi0^(-1) - chi0^(-1) chi_r chi0^(-1)] # gamma_r is NOT the irreducible vertex in channel r but rather the three-point vertex from AbinitioDGA gchi0_inv_core = gchi0_core.invert() - f_dens_loc = -config.sys.beta**2 * (gchi0_inv_core - gchi0_inv_core @ gchi_dens_loc @ gchi0_inv_core) + f_dens_loc = (gchi0_inv_core - gchi0_inv_core @ gchi_dens_loc @ gchi0_inv_core).scale(-config.sys.beta**2) logger.info("Local full vertex F^wvv' (dens) calculated.") - f_magn_loc = -config.sys.beta**2 * (gchi0_inv_core - gchi0_inv_core @ gchi_magn_loc @ gchi0_inv_core) + f_magn_loc = (gchi0_inv_core - gchi0_inv_core @ gchi_magn_loc @ gchi0_inv_core).scale(-config.sys.beta**2) logger.info("Local full vertex F^wvv' (magn) calculated.") del gchi0_inv_core # f_dens_loc_with_asympt = create_asympt_f(gchi_dens_loc, gchi_magn_loc, gchi_ud_pp_loc_sum, u_loc) # in most equations we need 1 + gamma_r so we add it here - gamma_dens_loc = 1.0 / config.sys.beta * (gchi0_core @ f_dens_loc).sum_over_vn(config.sys.beta, axis=(-2,)) + gamma_dens_loc = (gchi0_core @ f_dens_loc).sum_over_vn(config.sys.beta, axis=(-2,)).scale(1.0 / config.sys.beta) one_plus_gamma_dens_loc = LocalFourPoint.identity_like(gamma_dens_loc) + gamma_dens_loc logger.info("Local three-leg vertex gamma^wv (dens) calculated.") - gamma_magn_loc = 1.0 / config.sys.beta * (gchi0_core @ f_magn_loc).sum_over_vn(config.sys.beta, axis=(-2,)) + gamma_magn_loc = (gchi0_core @ f_magn_loc).sum_over_vn(config.sys.beta, axis=(-2,)).scale(1.0 / config.sys.beta) one_plus_gamma_magn_loc = LocalFourPoint.identity_like(gamma_magn_loc) + gamma_magn_loc logger.info("Local three-leg vertex gamma^wv (magn) calculated.") del gchi0_core, gamma_magn_loc diff --git a/dgamore/local_two_point.py b/dgamore/local_two_point.py index b68a0d9a..f8cd7085 100644 --- a/dgamore/local_two_point.py +++ b/dgamore/local_two_point.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems r""" Base class for the local (momentum-independent) two-point quantities. :class:`LocalTwoPoint` wraps a single array @@ -12,8 +12,6 @@ single momentum dimension on top (just as :class:`FourPoint` extends :class:`LocalFourPoint`). """ -from copy import deepcopy - import numpy as np from dgamore.local_n_point import LocalNPoint @@ -69,7 +67,7 @@ def permute_orbitals(self, permutation: str = "ab->ab") -> "LocalTwoPoint": if split[0] == split[1]: return self - copy = deepcopy(self) + copy = self.copy() copy.mat = np.einsum(f"{split[0]}...->{split[1]}...", copy.mat, optimize=True) return copy diff --git a/dgamore/matsubara_frequencies.py b/dgamore/matsubara_frequencies.py index 3f703948..edfbafdc 100644 --- a/dgamore/matsubara_frequencies.py +++ b/dgamore/matsubara_frequencies.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems """ Helpers for Matsubara frequency arithmetic. :class:`MFHelper` builds the integer index grids and the diff --git a/dgamore/max_ent.py b/dgamore/max_ent.py index ba5896bb..a2472c1a 100644 --- a/dgamore/max_ent.py +++ b/dgamore/max_ent.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems r""" Analytic continuation of imaginary-frequency quantities to the real axis via the maximum-entropy method. This @@ -11,8 +11,11 @@ irreducible BZ. """ +import contextlib import gc +import io import os +import warnings import numpy as np from mpi4py import MPI @@ -85,9 +88,7 @@ def perform_maxent_giwk(giwk: GreensFunction, name: str, comm: MPI.Comm): irrq_list = config.lattice.k_grid.get_irrq_list() - mpi_dist = MpiDistributor( - ntasks=len(irrq_list), comm=comm, name="Maxent_G", output_path=config.output.output_path - ) + mpi_dist = MpiDistributor(ntasks=len(irrq_list), comm=comm, name="Maxent_G", output_path=config.output.output_path) giwk_maxent = giwk_maxent.reduce_q(irrq_list) logger.info("Scattering Green's function in the IBZ to all ranks.") @@ -108,17 +109,33 @@ def perform_maxent_giwk(giwk: GreensFunction, name: str, comm: MPI.Comm): for band in range(config.sys.n_bands): logger.info(f"Processing analytic continuation of band {band+1}.") for k in range(giwk_maxent.mat.shape[0]): + # Capture the vendored solver's stdout so its print() diagnostics go through the logger instead of + # leaking to the output; re-logged (prefixed) below whether the continuation succeeds or fails. + captured_output = io.StringIO() try: - probl_maxent = AnalyticContinuationProblem( - im_axis=wn, re_axis=w, im_data=giwk_maxent[k, band, band], beta=config.sys.beta - ) - result = probl_maxent.solve(model=model, stdev=stdev)[0] - spectral_function[k, band] = result.A_opt.astype(np.float32) + with warnings.catch_warnings(), contextlib.redirect_stdout(captured_output): + # Escalate numpy/scipy RuntimeWarnings (divide/invalid/overflow) to exceptions so a numerically + # broken continuation falls through to the A(k, w) = 0 fallback below (its own errors are caught too). + warnings.simplefilter("error", RuntimeWarning) + probl_maxent = AnalyticContinuationProblem( + im_axis=wn, re_axis=w, im_data=giwk_maxent[k, band, band], beta=config.sys.beta + ) + result = probl_maxent.solve(model=model, stdev=stdev)[0] + spectral_function[k, band] = result.A_opt.astype(np.float32) del probl_maxent, result gc.collect() except Exception: + kpt = tuple(int(c) for c in irrq_list[mpi_dist.my_tasks[k]]) + logger.info( + f"Failed to determine analytic continuation of k={kpt} (band {band + 1}), " + f"setting A(k={kpt}, w) = 0.0." + ) spectral_function[k, band] = 0.0 + finally: + for message in captured_output.getvalue().splitlines(): + if message.strip(): + logger.info(f"ana_cont: {message}") mpi_dist.comm.barrier() logger.info(f"Completed analytic continuation of band {band+1}.") spectral_function = mpi_dist.gather(spectral_function) diff --git a/dgamore/memory_estimator.py b/dgamore/memory_estimator.py index c34d48fb..ab69680a 100644 --- a/dgamore/memory_estimator.py +++ b/dgamore/memory_estimator.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems """ Pure, side-effect-free estimator of the peak host-memory of the memory-sensitive DGAmore operations. Each @@ -111,6 +111,25 @@ def _giwk_rspace(nk_tot: int, nb: int, nv: int) -> int: return nk_tot * nb**2 * nv +def giwk_baseline_bytes(nk_tot: int, n_bands: int, niv_cut: int, overhead: float = OVERHEAD_FACTOR) -> float: + """ + Returns the per-rank bytes of the replicated full-grid Green's function ``giwk_full`` at the ``niv_cut`` window - + exactly half of the persistent ``baseline`` (``giwk_full`` and ``sigma_old`` have the same size). This is the part + of the baseline that ``config.memory.use_shared_memory_giwk`` deduplicates to a single copy per node. The driver + credits it to the whole non-local self-energy section (the ``chi0q``, ``chiq_aux`` and ``sde`` branches), across + which ``giwk_full`` stays one copy per node (it is re-shared at the smaller core-box window after the bubble in + ``nonlocal_sde.calculate_self_energy_q``). Using the full ``niv_cut`` window for the post-bubble branches, where the + resident giwk is actually the smaller core box, keeps the credit conservative there. + + :param nk_tot: Total number of momentum points (full BZ). + :param n_bands: Number of bands. + :param niv_cut: Half width of the fermionic window ``giwk_full`` is kept at through the kernel/SDE section. + :param overhead: Global multiplicative factor accounting for un-modeled transient arrays. + :return: The per-rank ``giwk_full`` baseline in bytes. + """ + return DTYPE_BYTES * overhead * _giwk_rspace(nk_tot, n_bands, 2 * niv_cut) + + def estimate_peaks( *, n_bands: int, @@ -175,7 +194,12 @@ def estimate_peaks( # stay live on every rank -- giwk_full and sigma_old, both kept at niv_cut through the SDE (giwk's shell window is # needed by the self-energy contraction; sigma_old keeps its DMFT shell for the mixing/residual). See # nonlocal_sde.calculate_self_energy_q. The remaining self-energies (sigma_dmft, sigma_dmft_full, delta_sigma) are - # local (a single k-point) and negligible. + # local (a single k-point) and negligible. This baseline counts giwk_full per rank; when + # config.memory.use_shared_memory_giwk is set the driver credits the deduplicated giwk copies back via + # giwk_baseline_bytes for the SDE-section branches (chi0q, chiq_aux, sde), across which giwk_full stays one copy per + # node (re-shared at the smaller core-box window after the bubble); the eliashberg branches keep this conservative + # per-rank giwk term. This estimator stays side-effect-free and ranks-per-node-agnostic; the node-total assembly + # and the sharing credit live in the driver. baseline = scale * 2 * _giwk_rspace(nk_tot, nb, 2 * niv_cut) peaks: dict[str, BranchPeak] = {} diff --git a/dgamore/mpi_utils.py b/dgamore/mpi_utils.py index 58d4dc3e..25503456 100644 --- a/dgamore/mpi_utils.py +++ b/dgamore/mpi_utils.py @@ -1,10 +1,10 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems """ -Multiprocessing (MPI) utilities for the non-local step — a single module covering everything parallel: +Multiprocessing (MPI) utilities for the non-local step - a single module covering everything parallel: * low-level **message-chunking primitives** (``send_rows`` / ``recv_rows_into`` / ``recv_rows_alloc`` / ``bcast_rows`` / ``bcast_rows_into`` / ``send_bytes`` / ``recv_bytes`` and the ``row_chunks`` / ``chunk_step`` @@ -37,12 +37,50 @@ from dgamore import symmetry_reduction from dgamore.brillouin_zone import KGrid from dgamore.four_point import FourPoint +from dgamore.n_point_base import DTYPE # Canonical 2 GB MPI per-message limit. The chunking helpers below take it as an explicit ``limit`` argument so the # established test hook of monkeypatching ``mpi_utils.MAX_MPI_BYTES`` to force the chunked path keeps working. MAX_MPI_BYTES = 2**31 - 1 +def build_node_shared_array(node_comm, compute_fn, dtype=DTYPE): + r""" + Build an array once per node and expose it to every rank on that node through a single MPI shared-memory window, + so a large replicated quantity (e.g. the full-grid Green's function ``giwk_full``) is stored **once per node + instead of once per rank** and computed only on the node root. + + ``compute_fn`` is called **only on the node-local root rank** (rank 0 of ``node_comm``) and must return the fully + built numpy array; the other ranks do not call it. Its result is copied into a shared-memory segment allocated by + the root, and every rank receives a numpy view of that same physical buffer (read-only by convention - only the + root writes it). ``node_comm`` must be a node-local communicator, e.g. ``comm.Split_type(MPI.COMM_TYPE_SHARED)``. + + When the node holds a single rank the shared window is pointless, so the freshly computed private array is + returned unchanged with ``win = None`` (this also keeps single-rank / mock communicators working). The caller + owns the returned window and must free it (``win.Free()``) once all ranks are done reading the array. + + :param node_comm: The node-local (shared-memory) communicator. + :param compute_fn: Zero-argument callable returning the array; invoked only on the node root. + :param dtype: Storage dtype of the shared buffer (defaults to the global ``DTYPE``, complex64). + :return: The tuple ``(array, win)`` - the (shared) numpy array on every rank and the MPI window (``None`` for a + single-rank node). + """ + is_root = node_comm.Get_rank() == 0 + local = compute_fn() if is_root else None + if node_comm.Get_size() == 1: + return local, None + shape = node_comm.bcast(local.shape if is_root else None) + itemsize = np.dtype(dtype).itemsize + nbytes = int(np.prod(shape)) * itemsize if is_root else 0 + win = MPI.Win.Allocate_shared(nbytes, itemsize, comm=node_comm) + buf, _ = win.Shared_query(0) + shared = np.ndarray(buffer=buf, dtype=dtype, shape=shape) + if is_root: + shared[...] = local + node_comm.Barrier() + return shared, win + + # ==================================================================================================================== # Message-chunking primitives (split a transfer's leading axis below the 2 GB MPI per-message limit). # ==================================================================================================================== @@ -658,7 +696,7 @@ def bcast_npoint(self, obj, root: int = 0): """ Broadcasts an N-point-like object (one exposing a ``.mat`` numpy array) from ``root`` to all ranks. The large ``.mat`` is broadcast as raw sub-2 GB chunks (so there is no multi-gigabyte pickle blob and no >2 GB message), - while the rest of the object travels as a small pickled metadata blob — the broadcast analogue of + while the rest of the object travels as a small pickled metadata blob - the broadcast analogue of :meth:`send_to_rank`/:meth:`recv_from_rank`. Prefer this over :meth:`bcast` for large objects such as a full-BZ self-energy or gap function, both to respect the 2 GB limit and to avoid the full in-memory pickle copy. @@ -692,7 +730,7 @@ def allreduce(self, rank_result=None) -> np.ndarray: ``Allreduce`` is collective, so the chunk schedule must be identical on every rank. That holds here because the reduced arrays are always equally shaped across ranks (the callers reduce full, replicated quantities such as - the full-k-space self-energy / Fock term — each rank holds a partial sum of the *same* array), so every rank + the full-k-space self-energy / Fock term - each rank holds a partial sum of the *same* array), so every rank derives the same chunk boundaries. The single-chunk case is byte-for-byte the previous behavior. :param rank_result: This rank's contribution; reduced in place. Must have the same shape on every rank. diff --git a/dgamore/n_point_base.py b/dgamore/n_point_base.py index 5dbad618..251bffb4 100644 --- a/dgamore/n_point_base.py +++ b/dgamore/n_point_base.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems """ Foundational mixins for every physical quantity in the code. :class:`IHaveMat` owns the underlying numpy array @@ -159,6 +159,16 @@ def memory_usage_in_gb(self) -> float: """ return self.mat.nbytes / (1024**3) + def copy(self) -> "IHaveMat": + """ + Returns an independent deep copy of the object -- a thin wrapper around :func:`copy.deepcopy` used in place of + a bare ``deepcopy(obj)`` throughout the package. Mutating the returned object (including its ``mat``) does not + affect the original. + + :return: A deep copy of ``self``. + """ + return deepcopy(self) + def __mul__(self, other) -> "IHaveMat": """ Multiplies the object by a scalar number, returning a new (deep-copied) object. @@ -170,7 +180,7 @@ def __mul__(self, other) -> "IHaveMat": if not isinstance(other, (int, float, complex)): raise ValueError("Multiplication only supported with numbers.") - copy = deepcopy(self) + copy = self.copy() copy.mat *= other return copy @@ -203,6 +213,26 @@ def __truediv__(self, other) -> "IHaveMat": raise ValueError("Division only supported with numbers.") return self.__mul__(1.0 / other) + def scale(self, factor, copy: bool = False) -> "IHaveMat": + """ + Multiplies the matrix by a scalar. The in-place branch (``copy=False``, the default here) mutates and + returns ``self`` without allocating a copy -- the memory-lean counterpart of the non-destructive + ``*``/:meth:`__mul__` operator (which already covers the copying case). Used to fold a scalar prefactor + into an in-place accumulation (e.g. the self-energy-kernel assembly in :mod:`dgamore.nonlocal_sde`) + without a throwaway scaled copy. ``copy=True`` returns a scaled deep copy and leaves ``self`` untouched. + + :param factor: A scalar (int, float or complex) to multiply with. + :param copy: If True, return a scaled deep copy; if False (default), scale ``self.mat`` in place. + :return: The scaled object (``self`` when ``copy=False``). + :raises ValueError: If ``factor`` is not a number. + """ + if not isinstance(factor, (int, float, complex)): + raise ValueError("Multiplication only supported with numbers.") + if copy: + return self.copy().scale(factor, copy=False) + self.mat *= factor + return self + def __getitem__(self, item): """ Indexing shortcut: ``obj[item]`` is equivalent to ``obj.mat[item]``. @@ -291,7 +321,7 @@ def _clone_without_mat(self): mat = self._mat self._mat = None try: - clone = deepcopy(self) + clone = self.copy() finally: self._mat = mat return clone @@ -705,7 +735,7 @@ def interpolate_q_grid(self, nq_new: tuple[int, int, int], copy: bool = True): :return: The re-gridded object in the same momentum-compression state as the input. :raises ValueError: If a target size is not a positive integer, or the object is compressed but not full-BZ. """ - copy = deepcopy(self) if copy else self + copy = self.copy() if copy else self nq_new = tuple(int(n) for n in nq_new) if any(n < 1 for n in nq_new): @@ -807,7 +837,7 @@ def fft(self, copy: bool = True): :return: The Fourier-transformed object, in the same momentum-compression state as the input. """ if copy: - return deepcopy(self).fft(copy=False) + return self.copy().fft(copy=False) compress = False if self.has_compressed_q_dimension: @@ -826,7 +856,7 @@ def ifft(self, copy: bool = True): :return: The inverse-Fourier-transformed object, in the same momentum-compression state as the input. """ if copy: - return deepcopy(self).ifft(copy=False) + return self.copy().ifft(copy=False) compress = False if self.has_compressed_q_dimension: diff --git a/dgamore/nonlocal_sde.py b/dgamore/nonlocal_sde.py index b98b1bc5..b705271b 100644 --- a/dgamore/nonlocal_sde.py +++ b/dgamore/nonlocal_sde.py @@ -1,10 +1,10 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems r""" -Non-local ladder DGA step — the parallel-heavy core of the code. Starting from the local irreducible vertex +Non-local ladder DGA step - the parallel-heavy core of the code. Starting from the local irreducible vertex :math:`\Gamma_{r}` and the bare interaction, the functions here build, per momentum :math:`q` and spin channel, the bubble :math:`\chi_0^q`, the auxiliary susceptibility :math:`\chi^{*;q}_{r}`, the three-leg vertex :math:`\gamma^q_{r}`, the physical susceptibility :math:`\chi^q_{r}` (with shell and optional @@ -18,7 +18,6 @@ import glob import os import re -from copy import deepcopy import mpi4py.MPI as MPI import numpy as np @@ -220,7 +219,28 @@ def create_vrg_r_q(gchi_aux_q_r_sum: FourPoint, gchi0_q_inv: FourPoint) -> FourP :param gchi0_q_inv: The inverse bare bubble :math:`(\chi_0^q)^{-1}` (core box). :return: The three-leg vertex :math:`\gamma^q_{r}` (``vrg``) as a :class:`FourPoint`. """ - return config.sys.beta * (gchi0_q_inv @ gchi_aux_q_r_sum) + return (gchi0_q_inv @ gchi_aux_q_r_sum).scale(config.sys.beta) + + +def create_vrg_r_q_right(gchi_aux_q_r_sum: FourPoint, gchi0_q_inv: FourPoint) -> FourPoint: + r""" + Returns the momentum-dependent right-sided three-leg vertex, i.e. the counterpart of :meth:`create_vrg_r_q` + (Eq. (3.63) in my master's thesis) with the summed frequency argument of :math:`\chi^{*}` and the position of + :math:`(\chi_0)^{-1}` swapped. It thus reads + :math:`\tilde{\gamma}_{r;abcd}^{q\nu} = \beta (\sum_{\nu'} \chi^{*;q\nu'\nu}_{r;ablm}) (\chi^{q\nu}_{0;mlcd})^{-1}`. + Notice that the sum runs over the *first* frequency argument, whereas only the sum over the last frequency is + available (see :meth:`FourPoint.invert_and_sum_over_last_vn`). The two are related by the time-reversal symmetry + :math:`\chi^{*;q\nu\nu'}_{r;abcd} = \chi^{*;q\nu'\nu}_{r;dcba}` (enforced on the DMFT two-particle Green's + function via :meth:`LocalFourPoint.symmetrize_v_vp` and inherited by all vertices built from it), which carries + an orbital reversal along with the frequency swap: + :math:`\sum_{\nu'} \chi^{*;q\nu'\nu}_{r;ablm} = \sum_{\nu'} \chi^{*;q\nu\nu'}_{r;mlba}`. Hence the last-frequency + sum enters with the orbital permutation ``"abcd->dcba"`` applied. + + :param gchi_aux_q_r_sum: The frequency-summed auxiliary susceptibility :math:`\sum_{\nu'}\chi^{*;q}_{r}`. + :param gchi0_q_inv: The inverse bare bubble :math:`(\chi_0^q)^{-1}` (core box). + :return: The right-sided three-leg vertex :math:`\tilde{\gamma}^q_{r}` (``vrg_right``) as a :class:`FourPoint`. + """ + return (gchi_aux_q_r_sum.permute_orbitals("abcd->dcba") @ gchi0_q_inv).scale(config.sys.beta) def create_generalized_chi_q_with_shell_correction( @@ -288,7 +308,7 @@ def calculate_kernel_r_q( kernel = vrg_q_r - vrg_q_r @ u_r @ gchi_aux_q_r_sum if vrg_q_r.channel == SpinChannel.MAGN: - kernel -= 2.0 / 3.0 * FourPoint.identity_like(kernel) + kernel.sub(FourPoint.identity_like(kernel).scale(2.0 / 3.0), copy=False) return u_r @ kernel @@ -334,7 +354,7 @@ def fit_oz_spin(q_grid: KGrid, mat: np.ndarray): initial_guess = (mat.max(), 2.0) return opt.curve_fit(oz_spin_w0, q_grid, mat, p0=initial_guess)[0] - chi = deepcopy(chi_phys_q_r) + chi = chi_phys_q_r.copy() chi_mat = chi.map_to_full_bz(config.lattice.q_grid).to_half_niw_range().take_first_wn().mat.real orb_shape = (config.sys.n_bands,) * 4 oz_coeffs = np.zeros(orb_shape + (2,), dtype=float) @@ -431,6 +451,14 @@ def calculate_sigma_kernel_r_q( ) logger.info(f"Non-Local auxiliary susceptibility ({gchi_aux_q_r_sum.channel.value}) calculated.") + if config.eliashberg.perform_eliashberg: + vrg_q_r_right = create_vrg_r_q_right(gchi_aux_q_r_sum, gchi0_q_inv) + vrg_q_r_right.save( + name=f"vrg_q_{vrg_q_r_right.channel.value}_right_rank_{mpi_dist_irrq.comm.rank}", + output_dir=config.output.eliashberg_path, + ) + vrg_q_r_right.free() + vrg_q_r = create_vrg_r_q(gchi_aux_q_r_sum, gchi0_q_inv) logger.info(f"Non-local three-leg vertex gamma^wv ({vrg_q_r.channel.value}) done.") @@ -867,13 +895,11 @@ def select_sigma_fft_device(mpi_distributor: MpiDistributor) -> bool: :param mpi_distributor: MPI distributor providing the per-rank GPU choice. :return: True if the GPU implementation should be used, False to fall back to the CPU implementation. """ - cp = None try: import cupy as cp except ImportError: return False # CuPy not installed -> CPU - n_gpus = 0 try: n_gpus = cp.cuda.runtime.getDeviceCount() except cp.cuda.runtime.CUDARuntimeError: @@ -929,6 +955,51 @@ def _map_kernel_to_full_bz( return mpi_utils.exchange_and_map_irrbz_fullbz(kernel, mpi_dist_irrk, mpi_dist_fullbz) +def _run_fft_sde_pass( + kernel_src: FourPoint, + mpi_dist_irrk: MpiDistributor, + mpi_dist_fullbz: MpiDistributor, + giwk_full: GreensFunction, + niw_index_w_pairs: list[tuple[int, int]], + use_gpu: bool, + negative_w: bool, +) -> SelfEnergy: + r""" + Runs one bosonic-frequency FFT self-energy pass: maps the (small) irreducible-BZ kernel to the full BZ + (consuming ``kernel_src``), optionally builds its time-reversed negative-:math:`\omega` block, contracts the + requested ``niw_index_w_pairs`` via :func:`calculate_sigma_from_kernel_fft`, and frees the full-BZ kernel. Both + passes of :func:`calculate_self_energy_q` go through this helper: the caller hands the positive pass a + :meth:`~dgamore.n_point_base.IHaveMat.copy` of the irreducible kernel (so it survives for the negative pass) and + the negative pass the original (which this consumes), so only a single full-BZ niw half is ever resident. + + :param kernel_src: The irreducible-BZ kernel for this pass; consumed by the full-BZ map (mutated or replaced). + :param mpi_dist_irrk: MPI distributor over the irreducible BZ q-points. + :param mpi_dist_fullbz: MPI distributor over the full BZ q-points. + :param giwk_full: The momentum-dependent :class:`GreensFunction`. + :param niw_index_w_pairs: The ``(kernel_w_index, w)`` pairs to contract (see + :func:`calculate_sigma_from_kernel_fft_cpu`). + :param use_gpu: Whether to run the GPU implementation (as decided by :func:`select_sigma_fft_device`). + :param negative_w: If True, build the negative-:math:`\omega` block via + :meth:`LocalNPoint.to_negative_niw_range` before contracting (the negative pass) and trim the kernel peak + back to the OS on free; if False, contract the mapped kernel directly (the positive pass). + :return: The rank-local R-space :class:`SelfEnergy` of this pass. + """ + # ``_map_kernel_to_full_bz`` may mutate-and-return its argument or return a fresh object, so free the source + # only when a distinct object came back. + kernel_full = _map_kernel_to_full_bz(kernel_src, mpi_dist_irrk, mpi_dist_fullbz) + if kernel_full is not kernel_src: + kernel_src.free() + + if negative_w: + kernel_neg = kernel_full.to_negative_niw_range() + kernel_full.free() # release the full-BZ positive copy as soon as the negative block is built + kernel_full = kernel_neg + + sigma = calculate_sigma_from_kernel_fft(mpi_dist_irrk, kernel_full, giwk_full, niw_index_w_pairs, use_gpu) + kernel_full.free(trim=negative_w) # coarse per-iteration trim on the last (negative) pass + return sigma + + def get_starting_sigma(default_sigma: SelfEnergy) -> tuple[SelfEnergy, int]: """ Tries to retrieve the last calculated self-energy from a previous self-consistency calculation as a starting point @@ -1043,6 +1114,104 @@ def _get_top_n_files(path: str, pattern: str, regex: re.Pattern) -> list[tuple[i return sigmas +def _build_giwk_full(comm: MPI.Comm, sigma: SelfEnergy, mu: float, ek: np.ndarray, beta: float) -> tuple: + r""" + Builds the full-grid Green's function :math:`G(k, \nu)`, optionally deduplicated across the MPI ranks that share + a physical node. With ``config.memory.use_shared_memory_giwk`` set (the default), the Dyson inversion runs only on + each node's root rank and the result is placed in one MPI shared-memory window per node, so ``giwk_full`` occupies + a single physical buffer per node instead of one private copy per rank (see + :func:`dgamore.mpi_utils.build_node_shared_array`). Otherwise every rank builds its own copy. The node topology is + discovered at runtime via ``comm.Split_type(MPI.COMM_TYPE_SHARED)`` (nothing about the cluster is hard-coded). + + :param comm: The (world) MPI communicator. + :param sigma: The self-energy :math:`\Sigma` entering the Dyson equation. + :param mu: Chemical potential :math:`\mu`. + :param ek: Band dispersion :math:`\varepsilon(k)`. + :param beta: Inverse temperature :math:`\beta`. + :return: The tuple ``(giwk_full, win, node_comm)``; ``win`` and ``node_comm`` are ``None`` on the non-shared path + and must otherwise be released with :func:`_release_shared_giwk` once ``giwk_full`` has been cut to its private + core box (the shared buffer is read-only and must not be freed while any rank still reads it). + """ + if not config.memory.use_shared_memory_giwk: + return GreensFunction.get_g_full(sigma, mu, ek, beta), None, None + + node_comm = comm.Split_type(MPI.COMM_TYPE_SHARED) + giwk_mat, win = mpi_utils.build_node_shared_array( + node_comm, lambda: GreensFunction.get_g_full(sigma, mu, ek, beta).mat + ) + giwk_full = GreensFunction( + giwk_mat, sigma, ek, sigma.full_niv_range, False, False, nk=ek.shape[:3], beta=beta, mu=mu + ) + return giwk_full, win, node_comm + + +def _release_shared_giwk(win, node_comm) -> None: + r""" + Releases the shared-memory window and node communicator allocated by :func:`_build_giwk_full`, once all node ranks + have finished reading ``giwk_full`` (i.e. after it has been cut to a private copy). The barrier guarantees no rank + is still reading the shared buffer when it is freed. A no-op when node-sharing was not used. + + :param win: The MPI shared-memory window (or ``None``). + :param node_comm: The node-local communicator (or ``None``). + :return: None. + """ + if node_comm is None: + return + node_comm.Barrier() + if win is not None: + win.Free() + node_comm.Free() + + +def _cut_and_reshare_giwk(giwk_full: GreensFunction, win, node_comm, niv: int) -> tuple: + r""" + Cuts ``giwk_full`` to the :math:`[-niv, niv)` core box. When ``giwk_full`` is node-shared (``node_comm`` is not + ``None``), the node root cuts the shared full-niv Green's function into a **new, smaller per-node shared window** + and every rank maps that; the caller then frees the old (large) full-niv window via :func:`_free_shared_window`. + This keeps the deduplicated ``giwk_full`` at one copy per node through the whole self-energy step, not just the + bubble. Without sharing it is a plain per-rank cut. + + :param giwk_full: The full-niv Green's function (possibly backed by a shared window). + :param win: The shared-memory window backing ``giwk_full`` (unused here; freed by the caller afterwards). + :param node_comm: The node-local communicator (or ``None`` on the non-shared path). + :param niv: Half width of the target fermionic core box. + :return: The tuple ``(giwk_cut, cut_win)``; ``cut_win`` is ``None`` on the non-shared or single-rank-node path. + """ + if node_comm is None: + return giwk_full.cut_niv(niv), None + + node_comm.Barrier() # every rank has finished reading the full-niv window (the bubble) + cut_mat, cut_win = mpi_utils.build_node_shared_array(node_comm, lambda: giwk_full.cut_niv(niv).mat) + giwk_cut = GreensFunction( + cut_mat, + giwk_full._sigma, + giwk_full._ek, + giwk_full.full_niv_range, + False, + False, + nk=giwk_full._ek.shape[:3], + beta=giwk_full._beta, + mu=giwk_full._mu, + ) + return giwk_cut, cut_win + + +def _free_shared_window(win, node_comm) -> None: + r""" + Frees a shared-memory window while keeping its node communicator alive - the communicator is reused for the cut + ``giwk_full`` window and released later by :func:`_release_shared_giwk`. A barrier guarantees no rank is still + reading the window's buffer. A no-op when there is no window. + + :param win: The MPI shared-memory window (or ``None``). + :param node_comm: The node-local communicator (or ``None``). + :return: None. + """ + if node_comm is None or win is None: + return + node_comm.Barrier() + win.Free() + + def calculate_self_energy_q( comm: MPI.Comm, u_loc: LocalInteraction, v_nonloc: Interaction, sigma_dmft: SelfEnergy, sigma_local: SelfEnergy ) -> SelfEnergy: @@ -1056,7 +1225,7 @@ def calculate_self_energy_q( :param u_loc: The bare local interaction :math:`U`. :param v_nonloc: The non-local interaction :math:`V^{q}`. :param sigma_dmft: The DMFT self-energy (used as the starting point and for the shell/tail correction). - :param sigma_local: The locally recomputed self-energy (used for the double-counting :math:`\Delta\Sigma`). + :param sigma_local: The locally recomputed self-energy (used for smoothing out the DGA :class:`SelfEnergy`). :return: The converged (or last-iteration) momentum-dependent DGA :class:`SelfEnergy`. """ logger = config.logger @@ -1086,7 +1255,7 @@ def calculate_self_energy_q( mu_history = _init_mu_history(starting_iter) niv_cut = min(config.box.niw_core + config.box.niv_full + 10, config.box.niv_dmft) - sigma_dmft_full = deepcopy(sigma_dmft) + sigma_dmft_full = sigma_dmft.copy() if comm.rank == 0: giwk_full_dmft = GreensFunction.get_g_full( @@ -1115,7 +1284,7 @@ def calculate_self_energy_q( delta_sigma = sigma_dmft.cut_niv(config.box.niv_core) - sigma_local.cut_niv(config.box.niv_core) - v_nonloc_full = deepcopy(v_nonloc) + v_nonloc_full = v_nonloc.copy() v_nonloc = v_nonloc.reduce_q(my_irr_q_list) for current_iter in range(starting_iter + 1, starting_iter + config.self_consistency.max_iter + 1): @@ -1127,8 +1296,8 @@ def calculate_self_energy_q( fock = mpi_dist_fullbz.allreduce(fock) logger.info("Calculated Hartree and Fock terms.") - giwk_full = GreensFunction.get_g_full( - sigma_old, mu_history[-1], config.lattice.hamiltonian.get_ek(), config.sys.beta + giwk_full, giwk_win, giwk_node_comm = _build_giwk_full( + comm, sigma_old, mu_history[-1], config.lattice.hamiltonian.get_ek(), config.sys.beta ) logger.log_memory_usage("giwk", giwk_full, comm.size) @@ -1159,27 +1328,31 @@ def calculate_self_energy_q( gchi0_q.save(name=f"gchi0_q_rank_{comm.rank}", output_dir=config.output.output_path) logger.log_memory_usage("Gchi0_q_full", gchi0_q, comm.size) - giwk_full = giwk_full.cut_niv(config.box.niv_core + config.box.niw_core) + # Cut giwk to the core box for the self-energy step. When node-shared, the node root cuts into a new, smaller + # per-node window and the large full-niv window is freed; the cut giwk stays one copy per node through the SDE. + old_giwk_win = giwk_win + giwk_full, giwk_win = _cut_and_reshare_giwk( + giwk_full, giwk_win, giwk_node_comm, config.box.niv_core + config.box.niw_core + ) + _free_shared_window(old_giwk_win, giwk_node_comm) - # sigma_old is not read again until the mixing step at the end of the iteration, and its shell - # [niv_core, niv_cut) is always the (k-independent) DMFT self-energy. Shrink the full-grid sigma_old to its core - # here -- freeing the broadcast shell through the kernel/SDE/fq peak -- and reconstruct the shell from sigma_dmft - # just before mixing, which restores it to niv_cut bit-for-bit. sigma_old = sigma_old.cut_niv(config.box.niv_core) - f_dc_loc = 2 * LocalFourPoint.load(os.path.join(config.output.output_path, "f_magn_loc.npy")).permute_orbitals( - "abcd->cbad" + f_dc_loc = ( + LocalFourPoint.load(os.path.join(config.output.output_path, "f_magn_loc.npy")) + .permute_orbitals("abcd->cbad") + .scale(2.0) ) - kernel = -calculate_sigma_dc_kernel(f_dc_loc, gchi0_q, u_loc) + kernel = calculate_sigma_dc_kernel(f_dc_loc, gchi0_q, u_loc).scale(-1.0) f_dc_loc.free() logger.info("Calculated double-counting kernel.") - gchi0_q_full_sum = 1.0 / config.sys.beta * gchi0_q.sum_over_all_vn(config.sys.beta) + gchi0_q_full_sum = gchi0_q.sum_over_all_vn(config.sys.beta).scale(1.0 / config.sys.beta) gchi0_q_core = gchi0_q.cut_niv(config.box.niv_core) gchi0_q.free() logger.log_memory_usage("Gchi0_q_core", gchi0_q_core, comm.size) - gchi0_q_core_inv = deepcopy(gchi0_q_core).invert(False) + gchi0_q_core_inv = gchi0_q_core.copy().invert(False) logger.log_memory_usage("Gchi0_q_inv", gchi0_q_core_inv, comm.size) if current_iter == 1: @@ -1188,14 +1361,17 @@ def calculate_self_energy_q( if config.eliashberg.perform_eliashberg: gchi0_q_core_inv.save(name=f"gchi0_q_inv_rank_{comm.rank}", output_dir=config.output.eliashberg_path) - gchi0_q_core_sum = 1.0 / config.sys.beta * gchi0_q_core.sum_over_all_vn(config.sys.beta) + gchi0_q_core_sum = gchi0_q_core.sum_over_all_vn(config.sys.beta).scale(1.0 / config.sys.beta) gchi0_q_core.free() gamma_dens = LocalFourPoint.load( os.path.join(config.output.output_path, "gamma_dens_loc.npy"), SpinChannel.DENS ) - kernel += calculate_sigma_kernel_r_q( - gamma_dens, gchi0_q_core_inv, gchi0_q_full_sum, gchi0_q_core_sum, u_loc, v_nonloc, mpi_dist_irrk + kernel.add( + calculate_sigma_kernel_r_q( + gamma_dens, gchi0_q_core_inv, gchi0_q_full_sum, gchi0_q_core_sum, u_loc, v_nonloc, mpi_dist_irrk + ), + copy=False, ) gamma_dens.free() mpi_dist_irrk.barrier() @@ -1204,8 +1380,11 @@ def calculate_self_energy_q( gamma_magn = LocalFourPoint.load( os.path.join(config.output.output_path, "gamma_magn_loc.npy"), SpinChannel.MAGN ) - kernel += 3 * calculate_sigma_kernel_r_q( - gamma_magn, gchi0_q_core_inv, gchi0_q_full_sum, gchi0_q_core_sum, u_loc, v_nonloc, mpi_dist_irrk + kernel.add( + calculate_sigma_kernel_r_q( + gamma_magn, gchi0_q_core_inv, gchi0_q_full_sum, gchi0_q_core_sum, u_loc, v_nonloc, mpi_dist_irrk + ).scale(3.0), + copy=False, ) gchi0_q_core_inv.free() gchi0_q_full_sum.free() @@ -1213,7 +1392,7 @@ def calculate_self_energy_q( gamma_magn.free() logger.info("Calculated kernel for magnetic channel.") - logger.info("Started calculation of DGA self-energy.") + logger.info("Starting calculation of DGA self-energy.") if config.memory.save_memory_for_sde: # q-loop path: the kernel is mapped to the full BZ once (the full niw range is handled inside the q-loop). @@ -1224,43 +1403,30 @@ def calculate_self_energy_q( sigma_new.mat = mpi_dist_fullbz.allreduce(sigma_new.mat) else: # FFT path: split the bosonic-frequency sum into a positive- and a negative-w pass so the full-BZ - # kernel is only ever materialized over half the niw range AND only one niw half exists at a time. The - # small irreducible-BZ kernel is kept and mapped to the full BZ separately for each pass; the negative - # block's time-reversal is applied *after* the irreducible->full-BZ unfold (not before). The unfold applies - # a per-k orbital rotation U (complex for multi-band) plus an optional conjugation (see - # :meth:`IAmNonLocal._map_to_full_bz`), and ``to_negative_niw_range`` conjugates the data, so it must see - # the already-unfolded kernel (conj of U*..U^T), exactly as the q-loop path and the original single-pass - # implementation did. Flipping the irreducible-BZ kernel first would leave U un-conjugated and corrupt - # sigma on the symmetry-folded q-points. + # kernel is only ever materialized over half the niw range AND only one niw half exists at a time. niw = config.box.niw_core kernel_irr = kernel # the (small) irreducible-BZ positive-w kernel, mapped to the full BZ once per pass - # Decide CPU/GPU (and select the GPU) once, so the detection is not logged for each of the two passes. + # Decide CPU/GPU (and select the GPU) once use_gpu = select_sigma_fft_device(mpi_dist_fullbz) - # positive pass: map a copy of the irr-BZ kernel to the full BZ and contract w = 0..+niw. The deep copy - # keeps ``kernel_irr`` (small) intact for the negative pass, which maps it again -- so only a single - # full-BZ niw half is ever resident. ``_map_kernel_to_full_bz`` may either mutate-and-return its argument - # or return a fresh object, so free the source copy only when a distinct object came back. - kernel_pos_irr = deepcopy(kernel_irr) - kernel_pos = _map_kernel_to_full_bz(kernel_pos_irr, mpi_dist_irrk, mpi_dist_fullbz) - if kernel_pos is not kernel_pos_irr: - kernel_pos_irr.free() - sigma_new = calculate_sigma_from_kernel_fft( - mpi_dist_irrk, kernel_pos, giwk_full, [(i, i) for i in range(niw + 1)], use_gpu + sigma_new = _run_fft_sde_pass( + kernel_irr.copy(), + mpi_dist_irrk, + mpi_dist_fullbz, + giwk_full, + [(i, i) for i in range(niw + 1)], + use_gpu, + negative_w=False, ) - kernel_pos.free() - - # negative pass: map the irr-BZ kernel to the full BZ, time-reverse the full-BZ result (w = 0, -1, ..., - # -niw), and contract w = -1..-niw (skip the w=0 duplicate). - kernel_neg_full = _map_kernel_to_full_bz(kernel_irr, mpi_dist_irrk, mpi_dist_fullbz) - if kernel_neg_full is not kernel_irr: - kernel_irr.free() # the irr-BZ kernel is no longer needed once the full-BZ negative source exists - kernel_neg = kernel_neg_full.to_negative_niw_range() - kernel_neg_full.free() # release the full-BZ positive copy as soon as the negative block is built - sigma_neg = calculate_sigma_from_kernel_fft( - mpi_dist_irrk, kernel_neg, giwk_full, [(i, -i) for i in range(1, niw + 1)], use_gpu + sigma_neg = _run_fft_sde_pass( + kernel_irr, + mpi_dist_irrk, + mpi_dist_fullbz, + giwk_full, + [(i, -i) for i in range(1, niw + 1)], + use_gpu, + negative_w=True, ) - kernel_neg.free(trim=True) # coarse per-iteration trim: return the full-BZ kernel peak to the OS sigma_new.mat += sigma_neg.mat # accumulate the rank-local R-space partial self-energies (in place) sigma_neg.free() @@ -1273,6 +1439,12 @@ def calculate_self_energy_q( logger.info("Self-energy calculated from kernel.") logger.log_memory_usage("Non-local sigma", sigma_new, comm.size) + # giwk's momentum-space data is no longer needed (only its dispersion ek is used below); drop the shared view + # on every rank, then release the per-node cut-giwk window and its node communicator. + if giwk_win is not None: + giwk_full.mat = None + _release_shared_giwk(giwk_win, giwk_node_comm) + sigma_new = sigma_new + hartree + fock logger.info("Full non-local self-energy calculated.") @@ -1283,8 +1455,6 @@ def calculate_self_energy_q( # delta_sigma = sigma_dmft.cut_niv(config.box.niv_core) - sigma_new.q_mean().cut_niv(config.box.niv_core) logger.info("Applying mixing strategy to the self-energy.") - # Restore sigma_old's DMFT shell (cut after the bubble for memory) so the mixing and the residual below see the - # full niv_cut self-energy exactly as before. sigma_old = sigma_old.concatenate_self_energies(sigma_dmft) sigma_new = apply_mixing_strategy(sigma_new, sigma_old, sigma_dmft, current_iter) @@ -1315,7 +1485,7 @@ def calculate_self_energy_q( logger.info(f"Updated mu from {old_mu} to {config.sys.mu}.") if comm.rank == 0: - sigma_occ = deepcopy(sigma_new).concatenate_self_energies(sigma_dmft_full) + sigma_occ = sigma_new.copy().concatenate_self_energies(sigma_dmft_full) giwk_occ = giwk_full.get_g_full( sigma_occ, config.sys.mu, config.lattice.hamiltonian.get_ek(), config.sys.beta ) diff --git a/dgamore/plotting.py b/dgamore/plotting.py index 5fd61325..4d972d6c 100644 --- a/dgamore/plotting.py +++ b/dgamore/plotting.py @@ -1,10 +1,10 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems """ -All matplotlib plotting helpers. These functions produce the diagnostic and result figures of a run — local +All matplotlib plotting helpers. These functions produce the diagnostic and result figures of a run - local self-energy / susceptibility checks, frequency-resolved four-point maps, momentum-space two-point maps (with optional Fermi-surface markers), the superconducting gap function, and the analytically continued spectral function along a high-symmetry path. Each routine saves and/or shows its figure. All plotting is gated behind diff --git a/dgamore/self_energy.py b/dgamore/self_energy.py index 58dbd801..b3316df1 100644 --- a/dgamore/self_energy.py +++ b/dgamore/self_energy.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems r""" Single-particle self-energy. :class:`SelfEnergy` wraps the (possibly momentum-dependent) self-energy @@ -12,7 +12,6 @@ """ import itertools as it -from copy import deepcopy import numpy as np from scipy.interpolate import PchipInterpolator, interp1d @@ -118,14 +117,14 @@ def create_with_asympt_up_to_core(self) -> "SelfEnergy": asympt = self._get_asympt(niv=self.niv) if self._niv_core == self.niv: - return deepcopy(self) + return self.copy() if asympt.niv == 0: - return deepcopy(self) + return self.copy() copy = self.cut_niv(self._niv_core) if copy is self: # ``cut_niv`` was a no-op (``_niv_core >= self.niv``); deep-copy so the operation stays non-destructive. - copy = deepcopy(self) + copy = self.copy() copy.mat = np.concatenate( (asympt.mat[..., : asympt.niv - copy.niv], copy.mat, asympt.mat[..., asympt.niv + copy.niv :]), axis=-1 ) @@ -141,7 +140,7 @@ def append_asympt(self, niv: int): """ asympt = self._get_asympt(niv) if niv <= self.niv: - return deepcopy(self) + return self.copy() # ``np.concatenate`` allocates the result and only reads ``self.mat``, so clone the metadata without # duplicating the array first. copy = self._clone_without_mat() @@ -267,7 +266,7 @@ def fit_polynomial(self, n_fit: int = 4, degree: int = 3, niv_core: int = 0) -> :return: A new :class:`SelfEnergy` holding the polynomial fit, in the full fermionic frequency range. """ if n_fit == 0: - return deepcopy(self) + return self.copy() if n_fit > self.niv or n_fit < 0: n_fit = niv_core + 200 diff --git a/dgamore/symmetrize_new.py b/dgamore/symmetrize_new.py index a50cbf2d..339cbe4b 100644 --- a/dgamore/symmetrize_new.py +++ b/dgamore/symmetrize_new.py @@ -2,7 +2,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems r""" Standalone preprocessing script (a second installed console script) that converts a w2dynamics worm-sampled @@ -362,7 +362,7 @@ def complete(text, state): return None -if __name__ == "__main__": +def main(): default_filename = "Vertex.hdf5" default_output_filename = "g4iw_sym.hdf5" @@ -441,3 +441,7 @@ def complete(text, state): print(f"{len(ineq_numbers)} inequivalent atom(s) written to {output_filename}.") print("Done!") exit() + + +if __name__ == "__main__": + main() diff --git a/dgamore/symmetry_reduction.py b/dgamore/symmetry_reduction.py index 215349ec..a46fa659 100644 --- a/dgamore/symmetry_reduction.py +++ b/dgamore/symmetry_reduction.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems """ @@ -58,7 +58,6 @@ import itertools import string - # ============================================================================ # Spatial ops on a discrete reciprocal grid # ============================================================================ @@ -475,7 +474,7 @@ def _discover_symmetries(H, atol, verbose=False): M_all = _enumerate_integer_matrices() M_candidates = [M for M in M_all if _M_preserves_grid(M, nk)] - # Dedupe M's by their grid action — when N_i = 1 for some axis, many M's + # Dedupe M's by their grid action - when N_i = 1 for some axis, many M's # produce the same k-grid index map. Use a tuple of (hash, length) plus # confirmation against stored representatives to avoid keeping nktot-sized # bytes for every distinct M (which costs ~nktot bytes per entry; for cubic @@ -566,7 +565,7 @@ def _canon_U_bytes(U): for conj in (False, True): # Quick dedup: if for this (idx_q, sigma, conj) we already have # an op, only one U is enough (the U is determined up to the - # group's commutant — finding more here is redundant for the IBZ). + # group's commutant - finding more here is redundant for the IBZ). # But we keep distinct U's because they're truly different group elts. if Hg is None: Hg = H_flat[idx_q].reshape(nx, ny, nz, norb, norb) @@ -952,7 +951,7 @@ def expand_tensor(T_ibz, kind="kb", sigma_power=1): # For every FBZ point k (in (nx,ny,nz) layout): # T_full(k) = sigma_k * U_k T(rep(k))^[*conj_k] U_k^dagger (per orbital index pair) # where rep(k) is given by pos_in_irrk[k_flat] -> position in irrk_ind. - "pos_in_irrk": pos_in_irrk, # shape (nktot,), int — irrk_inv equivalent + "pos_in_irrk": pos_in_irrk, # shape (nktot,), int - irrk_inv equivalent "Us": Us, # shape (nx, ny, nz, norb, norb), complex "sigmas": sigmas, # shape (nx, ny, nz), float (+/-1) "conjs": conjs, # shape (nx, ny, nz), bool diff --git a/dgamore/two_point.py b/dgamore/two_point.py index aa3f9303..94b16f42 100644 --- a/dgamore/two_point.py +++ b/dgamore/two_point.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems r""" Momentum-dependent two-point objects. :class:`TwoPoint` extends :class:`LocalTwoPoint` with one momentum axis @@ -11,8 +11,6 @@ :class:`LocalFourPoint`. """ -from copy import deepcopy - import numpy as np from dgamore.brillouin_zone import KGrid @@ -65,7 +63,7 @@ def permute_orbitals(self, permutation: str = "ab->ab") -> "TwoPoint": if split[0] == split[1]: return self - copy = deepcopy(self) + copy = self.copy() permutation = ( ( diff --git a/docs/conf.py b/docs/conf.py index ed1d6c64..feefc1d4 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -21,7 +21,7 @@ # Native/optional dependencies that need not (and on a docs runner cannot easily) be installed to build the docs. # autodoc only needs to *import* the package; mocking these keeps the docs build light and runner-agnostic. -autodoc_mock_imports = ["mpi4py", "cupy"] +autodoc_mock_imports = ["mpi4py", "cupy", "psutil"] # Cross-reference the standard library and the scientific stack. intersphinx_mapping = { diff --git a/docs/configuration.rst b/docs/configuration.rst index 3c92c356..0e7998f1 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -288,8 +288,9 @@ equations. This section therefore exposes more memory-efficient algorithms for f save_memory_for_sde: False # bool save_memory_for_fq: False # bool save_memory_for_lanczos: False # bool + use_shared_memory_giwk: True # bool -These switches control, in turn, the construction of the bare bubble susceptibility, of the auxiliary +The first five switches control, in turn, the construction of the bare bubble susceptibility, of the auxiliary susceptibility entering the Schwinger-Dyson equation, of the Schwinger-Dyson equation itself, of the full ladder vertices for the Eliashberg equation, and of the Lanczos algorithm. Enabling any of them increases the runtime substantially because of the additional Python-level looping and MPI communication. Under the hood, the bubble and the @@ -313,3 +314,10 @@ only enable additional switches, never turn off one that was requested. Converse variant of a required step does not fit on some node, the run stops immediately with a ``MemoryError`` that recommends using more nodes, fewer ranks per node, or a smaller frequency box or momentum grid, rather than failing unpredictably partway through. + +The final switch, ``use_shared_memory_giwk``, is of a different kind and is enabled by default. The full-grid lattice +Green's function is identical on every rank, yet each rank would normally rebuild and store its own copy, so a node +running many ranks holds that (large) array many times over. When this switch is on, the ranks that share a physical +node instead keep a single copy in one MPI shared-memory window: the Dyson inversion is performed only by that node's +first rank and the others map the same buffer read-only. The node topology is discovered automatically at runtime, so +nothing about the cluster needs to be configured. diff --git a/docs/contributing.rst b/docs/contributing.rst index e9a02786..4f49f050 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -81,16 +81,18 @@ When you would like to contribute code, the following workflow keeps things smoo pytest tests # fast suite (skips tests marked slow) pytest tests --runslow # full suite, as run in CI - pytest tests --runslow --cov=dgamore --cov-report=term-missing # with coverage + pytest tests --runslow --cov=dgamore --cov-report=term-missing --cov-fail-under=85 # coverage, as CI runs it 5. **Open a pull request** against the ``main`` branch, with a short description of what you changed and why. If your pull request is related to an existing issue, mentioning it helps connect the two. -A continuous integration pipeline runs the full test suite on every pull request, across Python 3.12 to 3.14 on both -Linux and macOS. This is there to catch regressions, not to be a gatekeeper, so please do not worry if something turns -red on the first try; it is a normal part of the process, and we are glad to help you get it passing. A coverage tool -also checks that the overall test coverage stays above eighty-five percent, so adding tests for your changes is the -best way to keep it healthy. +A continuous integration pipeline runs on every pull request. It checks that the code is Black-formatted, then runs the +full test suite across Python 3.12 to 3.14 on both Linux and macOS. This is there to catch regressions, not to be a +gatekeeper, so please do not worry if something turns red on the first try; it is a normal part of the process, and we +are glad to help you get it passing. The pipeline also requires the overall test coverage to stay at **at least +eighty-five percent**, and the build fails if it drops below that threshold. Beyond the overall figure, the new or +changed code in a pull request (the *patch*) must itself be covered to **at least eighty-five percent**, so please add +tests for what you write rather than relying on the rest of the code base to carry the average. Coding style ------------ diff --git a/docs/installation.rst b/docs/installation.rst index 732769f0..a91947f4 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -47,8 +47,8 @@ The editable install is recommended for development, as it lets you modify the s pick up upstream changes simply by pulling the latest version. Please make sure no older cached versions of the dependencies are reused, as this can lead to installation problems. -Installing the package also places the entry point ``DGAmore.py`` on your ``PATH``, so you can launch a run from -anywhere without specifying its full path. To verify the installation, you can optionally install ``pytest`` and run +Installing the package also places the entry points ``DGAmore`` and ``symmetrize`` on your ``PATH``, so you can +launch a run from anywhere without specifying its full path. To verify the installation, you can optionally install ``pytest`` and run the test suite: .. code-block:: bash diff --git a/docs/usage.rst b/docs/usage.rst index 1503ec3f..88312691 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -7,7 +7,7 @@ Preparing the input DGAmore takes as input the result of a DMFT calculation, which currently must be produced with w2dynamics, a continuous-time quantum Monte Carlo solver based on the hybridisation expansion. A w2dynamics run yields both the one-particle quantities and a two-particle output containing the four-point Green's functions. The two-particle -output first has to be converted into the format DGAmore expects. This is done by running the ``symmetrize_new.py`` +output first has to be converted into the format DGAmore expects. This is done by running the ``symmetrize`` script, which is installed alongside the main entry point; it prompts for the input and output file names and writes only the density and magnetic spin components of the two-particle Green's function to the output file. The original, unsymmetrised vertex file is not needed afterwards. @@ -20,19 +20,19 @@ additional file specifying the local and non-local interaction can be provided. Running a calculation --------------------- -The main entry point of the program is ``DGAmore.py``. Because it is added to the Python environment as a standalone +The main entry point of the program is ``DGAmore``. Because it is added to the Python environment as a standalone executable, it can be invoked by name without its full path. For single-core execution, which is mainly intended for testing, run: .. code-block:: bash - DGAmore.py + DGAmore For a parallel run with MPI, use: .. code-block:: bash - mpiexec -np DGAmore.py + mpiexec -np DGAmore Instead of ``mpiexec`` you may also use ``mpirun`` or, on SLURM-based clusters, ``srun``. The number of processes ```` should be chosen according to the problem size and the available resources; note that increasing the @@ -46,7 +46,7 @@ processes and loads the configuration file ``my_config.yaml`` from ``/configs/`` .. code-block:: bash - mpiexec -np 8 DGAmore.py -p /configs/ -c my_config.yaml + mpiexec -np 8 DGAmore -p /configs/ -c my_config.yaml On a SLURM-based cluster, a typical job submission script looks as follows: @@ -71,10 +71,10 @@ On a SLURM-based cluster, a typical job submission script looks as follows: export OMP_NUM_THREADS=1 # Recommended on SLURM-based clusters: - srun DGAmore.py -p "" -c ".yaml" + srun DGAmore -p "" -c ".yaml" # Alternatively, with mpirun or mpiexec: - mpirun -np $SLURM_NTASKS DGAmore.py -p "" -c ".yaml" + mpirun -np $SLURM_NTASKS DGAmore -p "" -c ".yaml" The ``-o`` and ``-e`` options set the files for the job output and errors; here both are written to the same file, but separate files may be used instead. The results of a completed run are written to a subdirectory of the output diff --git a/pyproject.toml b/pyproject.toml index 11f37678..b66bdcc3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,4 +3,14 @@ requires = ["setuptools", "wheel"] build-backend = "setuptools.build_meta" [tool.black] -line-length = 120 \ No newline at end of file +line-length = 120 + +[tool.coverage.run] +omit = [ + "*/DGAmore.py", + "*/plotting.py", + "*/config_parser.py", + "*/symmetrize_new.py", + "*/ana_cont.py", + "*/dmft_interface.py", +] \ No newline at end of file diff --git a/setup.py b/setup.py index 886e28cb..3b8a465e 100644 --- a/setup.py +++ b/setup.py @@ -22,6 +22,11 @@ "Operating System :: POSIX", "Operating System :: POSIX :: Linux", ], - scripts=["dgamore/DGAmore.py", "dgamore/symmetrize_new.py"], + entry_points={ + "console_scripts": [ + "DGAmore = dgamore.DGAmore:main", + "symmetrize = dgamore.symmetrize_new:main", + ], + }, python_requires=">=3.12", ) diff --git a/tests/__init__.py b/tests/__init__.py index 09901cb1..5c1a04f0 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,6 +1,5 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems - diff --git a/tests/conftest.py b/tests/conftest.py index eed89f4c..e0f271e5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems import logging @@ -179,8 +179,10 @@ def allreduce_numpy(sendbuf, recvbuf, op=None): comm_mock.Bcast.side_effect = bcast_numpy comm_mock.Allreduce.side_effect = allreduce_numpy - # Split should return itself + # Split / Split_type return the single-rank comm itself; Free is a no-op comm_mock.Split.return_value = comm_mock + comm_mock.Split_type.return_value = comm_mock + comm_mock.Free.return_value = None return comm_mock @@ -235,15 +237,17 @@ def _assign(buf, data): class Comm: - def __init__(self, size=1): - self._size = int(size) + def __init__(self, size=1, members=None): + self._members = tuple(members) if members is not None else tuple(range(int(size))) + self._size = len(self._members) self._barrier = _threading.Barrier(self._size) if self._size > 1 else None self._inboxes = [dict() for _ in range(self._size)] self._lock = _threading.Lock() self._store = [None] * self._size + self._split_cache = {} def Get_rank(self): - return getattr(_tls, "rank", 0) + return self._members.index(getattr(_tls, "rank", 0)) def Get_size(self): return self._size @@ -265,6 +269,21 @@ def abort_barrier(self): if self._barrier is not None: self._barrier.abort() + def Split_type(self, split_type, key=0, info=None): + # Group the ranks by hostname (COMM_TYPE_SHARED -> one sub-communicator per node). Threads share memory, so + # same-node ranks receive the SAME cached Comm instance and therefore a shared barrier/store, which is what + # makes the shared-memory window below genuinely shared. + host = getattr(_tls, "hostname", "node0") + hosts = list(self._collective(host)) + group = tuple(self._members[i] for i in range(self._size) if hosts[i] == host) + with self._lock: + if host not in self._split_cache: + self._split_cache[host] = Comm(members=group) + return self._split_cache[host] + + def Free(self): + pass + def _collective(self, contribution): r = self.rank self._bw() @@ -356,13 +375,33 @@ def Irecv(self, buf, source, tag=0): return _Request(lambda: _assign(buf, self._queue(self.rank, (source, tag)).get(timeout=_QUEUE_TIMEOUT))) +class Win: + # Minimal MPI shared-memory window over the threaded fake Comm. Because threads share an address space, the node + # root (local rank 0) allocates one bytearray and every rank of the (node) communicator receives the SAME object + # via bcast, so a numpy view over it is genuinely shared - writes by the root are visible to all. + @staticmethod + def Allocate_shared(size, disp_unit=1, info=None, comm=None): + win = Win() + buf = bytearray(int(size)) if comm.Get_rank() == 0 else None + win._buf = comm.bcast(buf, root=0) + return win + + def Shared_query(self, rank): + return self._buf, 1 + + def Free(self): + self._buf = None + + COMM_WORLD = Comm(1) FAKE_MPI = _types.SimpleNamespace( Comm=Comm, Request=Request, + Win=Win, IN_PLACE=IN_PLACE, REQUEST_NULL=REQUEST_NULL, + COMM_TYPE_SHARED=1, COMM_WORLD=COMM_WORLD, Get_processor_name=Get_processor_name, ) diff --git a/tests/test_autodetect_memory.py b/tests/test_autodetect_memory.py index 73fd9cc0..462d832c 100644 --- a/tests/test_autodetect_memory.py +++ b/tests/test_autodetect_memory.py @@ -9,7 +9,7 @@ import dgamore.config as config import dgamore.DGAmore as dgamore_main -from dgamore.memory_estimator import estimate_peaks +from dgamore.memory_estimator import BranchPeak, estimate_peaks, giwk_baseline_bytes from tests.conftest import create_comm_mock # the q-grid / box parameters the fake_system fixture installs, so tests can reproduce the driver's estimate @@ -171,3 +171,80 @@ def spy(**kwargs): dgamore_main.autodetect_memory_settings(_mock_comm()) assert captured["save_fq"] is True assert captured["construct_fq_cheap"] is True + + +def test_memory_config_shares_giwk_by_default(): + """The node-shared giwk optimization is enabled by default (disable-able for the NUMA case).""" + assert config.MemoryConfig().use_shared_memory_giwk is True + + +def test_shared_giwk_credits_the_bubble_branch_node_total(fake_system, monkeypatch): + """use_shared_memory_giwk subtracts the deduplicated giwk copies from the chi0q (bubble) node total, so the fast + FFT bubble fits at a budget where the replicated estimate would force the lean path on.""" + fake_system(1) # installs the fixture config; the real budget is set per-branch below + r = 4 + giwk_half = giwk_baseline_bytes(config.lattice.q_grid.nk_tot, config.sys.n_bands, FIXTURE_PARAMS["niv_cut"]) + baseline = 2.0 * giwk_half + big = 50.0 * baseline # chi0q fast is a single-rank transient and the binding branch; its lean path is tiny + tiny = BranchPeak(off_distributed=0.0, off_single=0.0, on_distributed=0.0, on_single=0.0) + peaks = { + "chi0q": BranchPeak(off_distributed=0.0, off_single=big, on_distributed=0.0, on_single=0.0), + "chiq_aux": tiny, + "sde": tiny, + } + monkeypatch.setattr(dgamore_main.memory_estimator, "estimate_peaks", lambda **kw: (baseline, peaks)) + + uncredited = r * baseline + big # r*(baseline+off_distributed) + off_single, off_distributed == 0 + budget = uncredited - 0.5 * (r - 1) * giwk_half # between the credited (r->1 giwk) total and the uncredited one + ranks = lambda obj: [obj] * r + + config.memory.use_shared_memory_giwk = True + config.memory.save_memory_for_chi0q = False + monkeypatch.setattr(dgamore_main.psutil, "virtual_memory", lambda: SimpleNamespace(available=int(budget / 0.9))) + dgamore_main.autodetect_memory_settings(_mock_comm(size=r, allgather=ranks)) + assert config.memory.save_memory_for_chi0q is False # credited fast bubble fits + + config.memory.use_shared_memory_giwk = False + config.memory.save_memory_for_chi0q = False + dgamore_main.autodetect_memory_settings(_mock_comm(size=r, allgather=ranks)) + assert config.memory.save_memory_for_chi0q is True # uncredited fast bubble overflows -> lean forced on + + +def test_shared_giwk_credits_a_non_bubble_sde_branch(fake_system, monkeypatch): + """The giwk credit applies to every SDE-section branch, not just the bubble: the heavy chiq_aux fast path fits + with sharing where the replicated estimate would force it onto the lean per-q path.""" + fake_system(1) + r = 4 + giwk_half = giwk_baseline_bytes(config.lattice.q_grid.nk_tot, config.sys.n_bands, FIXTURE_PARAMS["niv_cut"]) + baseline = 2.0 * giwk_half + big = 50.0 * baseline # chiq_aux fast is the binding branch (distributed); its lean path is trivially small here + tiny = BranchPeak(off_distributed=0.0, off_single=0.0, on_distributed=0.0, on_single=0.0) + peaks = { + "chi0q": tiny, + "chiq_aux": BranchPeak(off_distributed=big, off_single=0.0, on_distributed=0.0, on_single=0.0), + "sde": tiny, + } + monkeypatch.setattr(dgamore_main.memory_estimator, "estimate_peaks", lambda **kw: (baseline, peaks)) + + uncredited = r * (baseline + big) # off_single == 0 + budget = uncredited - 0.5 * (r - 1) * giwk_half # between the credited (giwk r->1) and the uncredited total + ranks = lambda obj: [obj] * r + + config.memory.use_shared_memory_giwk = True + config.memory.save_memory_for_chiq_aux = False + monkeypatch.setattr(dgamore_main.psutil, "virtual_memory", lambda: SimpleNamespace(available=int(budget / 0.9))) + dgamore_main.autodetect_memory_settings(_mock_comm(size=r, allgather=ranks)) + assert config.memory.save_memory_for_chiq_aux is False # credited fast path fits + + config.memory.use_shared_memory_giwk = False + config.memory.save_memory_for_chiq_aux = False + dgamore_main.autodetect_memory_settings(_mock_comm(size=r, allgather=ranks)) + assert config.memory.save_memory_for_chiq_aux is True # uncredited fast path overflows -> lean forced on + + +def test_dgamore_excludes_osc_ucx_before_mpi_init(): + """DGAmore defaults OMPI_MCA_osc to '^ucx' before importing mpi4py, muting the benign osc/ucx shared-window warning + with no user configuration; the ordering (set before MPI_Init) is what makes it take effect.""" + src = open(dgamore_main.__file__, encoding="utf-8").read() + assert 'os.environ.setdefault("OMPI_MCA_osc", "^ucx")' in src + assert src.index('os.environ.setdefault("OMPI_MCA_osc", "^ucx")') < src.index("from mpi4py import MPI") diff --git a/tests/test_brillouin_zone.py b/tests/test_brillouin_zone.py index 089f4246..42ae8f7a 100644 --- a/tests/test_brillouin_zone.py +++ b/tests/test_brillouin_zone.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems from unittest.mock import patch @@ -488,7 +488,7 @@ def test_k_axis_normalized_positions_and_length(): # distances between consecutive points: [1, 1, 1] -> cumulative [1,2,3] # k_axis_pos = [0,1,2,3] -> normalized by 3 -> [0, 1/3, 2/3, 1] expected = np.array([0.0, 1.0 / 3.0, 2.0 / 3.0, 1.0]) - assert np.allclose(kp.k_axis, expected, rtol=1e-12, atol=1e-12) + assert np.allclose(kp.k_axis, expected, atol=1e-12) assert kp.k_axis.size == kp.nk_tot @@ -608,7 +608,7 @@ def test_get_lattice_symmetries_from_string_auto_is_case_insensitive(): def _make_small_real_cubic_h(nx=4, ny=4, nz=4, nb=1): - """A simple real, Hermitian, cubic-symmetric H on a small grid — convenient for + """A simple real, Hermitian, cubic-symmetric H on a small grid - convenient for testing auto-detection. With a single band the orbital action is trivial; the discovered symmetry is the spatial cubic group (8 ops for nx=ny=nz with all-axes inversions + permutations).""" diff --git a/tests/test_bubble_gen.py b/tests/test_bubble_gen.py index 923b7eb6..137ec7ab 100644 --- a/tests/test_bubble_gen.py +++ b/tests/test_bubble_gen.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems """ Parity tests for :class:`dgamore.bubble_gen.BubbleGenerator`. Each test compares the produced bubble against an @@ -59,7 +59,7 @@ def test_create_generalized_chi0_matches_reference(): ref[a, b, c, d, iw, iv] = -beta * gl * gr assert res.mat.shape == ref.shape - assert np.allclose(res.mat, ref, atol=1e-4, rtol=1e-4) + assert np.allclose(res.mat, ref, atol=1e-4) def test_create_generalized_chi0_q_matches_reference(): @@ -90,7 +90,7 @@ def test_create_generalized_chi0_q_matches_reference(): assert res.mat.shape == ref.shape assert res.has_compressed_q_dimension is True - assert np.allclose(res.mat, ref, atol=1e-4, rtol=1e-4) + assert np.allclose(res.mat, ref, atol=1e-4) def test_create_generalized_chi0_q_no_copy_of_full_green_function(): @@ -125,7 +125,7 @@ def test_create_generalized_chi0_pp_w0_matches_reference(): assert res.mat.shape == ref.shape assert res.frequency_notation == FrequencyNotation.PP - assert np.allclose(res.mat, ref, atol=1e-4, rtol=1e-4) + assert np.allclose(res.mat, ref, atol=1e-4) def test_create_generalized_chi0_pp_w0_does_not_mutate_input(): @@ -158,7 +158,7 @@ def test_create_generalized_chi0_q_pp_w0_matches_reference(): assert res.mat.shape == ref.shape assert res.frequency_notation == FrequencyNotation.PP - assert np.allclose(res.mat, ref, atol=1e-4, rtol=1e-4) + assert np.allclose(res.mat, ref, atol=1e-4) def test_create_generalized_chi0_q_pp_w0_does_not_mutate_input(): @@ -168,3 +168,25 @@ def test_create_generalized_chi0_q_pp_w0_does_not_mutate_input(): g_before = g.mat.copy() BubbleGenerator.create_generalized_chi0_q_pp_w0(g, niv_pp, bz.KGrid(nk, symmetries=[])) assert np.array_equal(g.mat, g_before) + + +def test_momentum_pp_bubble_is_local_pp_bubble_in_acbd_layout(): + """Momentum pp bubble equals the local pp bubble permuted 'abcd->acbd' (up to the -beta the momentum form omits).""" + nb, niv_pp, beta = 2, 3, 2.0 + nk = (2, 2, 1) + config.lattice.nk = nk + q_grid = bz.KGrid(nk, symmetries=[]) + rng = np.random.default_rng(11) + nvg = niv_pp + 2 + # asymmetric G_ij != G_ji obeying the physical conjugation symmetry G_ij(-nu) = conj(G_ji(nu)) + half = rng.standard_normal((nb, nb, nvg)) + 1j * rng.standard_normal((nb, nb, nvg)) + gloc = np.empty((nb, nb, 2 * nvg), dtype=np.complex64) + gloc[:, :, nvg:] = half + gloc[:, :, :nvg] = np.conj(np.swapaxes(half, 0, 1))[:, :, ::-1] + g_loc = GreensFunction(gloc) + g_mom = GreensFunction( + np.broadcast_to(gloc, (*nk, nb, nb, 2 * nvg)).copy(), has_compressed_q_dimension=False, nk=nk + ) + local_acbd = BubbleGenerator.create_generalized_chi0_pp_w0(g_loc, niv_pp, beta).permute_orbitals("abcd->acbd") + momentum = BubbleGenerator.create_generalized_chi0_q_pp_w0(g_mom, niv_pp, q_grid).decompress_q_dimension() + assert np.allclose(momentum.mat, local_acbd.mat[..., 0, :][None, None, None] / (-beta), atol=1e-4) diff --git a/tests/test_data/end_2_end/vrg_q_dens_right_rank_0.npy b/tests/test_data/end_2_end/vrg_q_dens_right_rank_0.npy new file mode 100644 index 0000000000000000000000000000000000000000..4c8b653e1bbc7fb44d302e21dc6db1234347de57 GIT binary patch literal 645248 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�u4C2CrkE2)=BB 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 Iyu#?rOpW5N36k%(_nxK#{h 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 Vs&xB!1sn`2xcD`v5O;Yj`+pVHOQQe) literal 0 HcmV?d00001 diff --git a/tests/test_eliashberg_end_to_end.py b/tests/test_eliashberg_end_to_end.py index c74273ce..22fc3f69 100644 --- a/tests/test_eliashberg_end_to_end.py +++ b/tests/test_eliashberg_end_to_end.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems import os @@ -63,16 +63,13 @@ def Waitall(reqs): yield folder, comm_mock -@pytest.mark.parametrize( - "niw_core, niv_core, niv_shell, save_fq, save_memory", - [(20, 20, 10, True, True), (20, 20, 10, False, True), (20, 20, 10, True, False), (20, 20, 10, False, False)], -) -def test_eliashberg_equation_without_local_part(setup, niw_core, niv_core, niv_shell, save_fq, save_memory): +@pytest.mark.parametrize("save_fq, save_memory", [(True, True), (False, True), (True, False), (False, False)]) +def test_eliashberg_equation_without_local_part(setup, save_fq, save_memory): folder, comm_mock = setup - config.box.niw_core = niw_core - config.box.niv_core = niv_core - config.box.niv_shell = niv_shell + config.box.niw_core = 20 + config.box.niv_core = 20 + config.box.niv_shell = 10 g_dmft, s_dmft, g2_dens, g2_magn = tuple(x[0] for x in dga_io.load_from_dmft_file_and_update_config()) @@ -94,20 +91,17 @@ def test_eliashberg_equation_without_local_part(setup, niw_core, niv_core, niv_s lambdas_sing, lambdas_trip, gaps_sing, gaps_trip = eliashberg_solver.solve( g_dga, g_dmft, u_loc, v_nonloc, comm_mock ) - assert np.allclose(lambdas_sing, np.array([16.00998764, 15.8037398, 14.97882938, 14.68343997]), atol=1e-4) - assert np.allclose(lambdas_trip, np.array([6.70800075, 6.70799438, 6.45388298, 6.45387878]), atol=1e-4) + assert np.allclose(lambdas_sing, np.array([16.00752, 15.802559, 14.981937, 14.684908]), atol=1e-2) + assert np.allclose(lambdas_trip, np.array([6.7059956, 6.705986, 6.456438, 6.4564347]), atol=1e-2) -@pytest.mark.parametrize( - "niw_core, niv_core, niv_shell, save_fq, save_memory", - [(20, 20, 10, True, True), (20, 20, 10, False, True), (20, 20, 10, True, False), (20, 20, 10, False, False)], -) -def test_eliashberg_equation_with_local_part(setup, niw_core, niv_core, niv_shell, save_fq, save_memory): +@pytest.mark.parametrize("save_fq, save_memory", [(True, True), (False, True), (True, False), (False, False)]) +def test_eliashberg_equation_with_local_part(setup, save_fq, save_memory): folder, comm_mock = setup - config.box.niw_core = niw_core - config.box.niv_core = niv_core - config.box.niv_shell = niv_shell + config.box.niw_core = 20 + config.box.niv_core = 20 + config.box.niv_shell = 10 g_dmft, s_dmft, g2_dens, g2_magn = tuple(x[0] for x in dga_io.load_from_dmft_file_and_update_config()) @@ -129,5 +123,5 @@ def test_eliashberg_equation_with_local_part(setup, niw_core, niv_core, niv_shel lambdas_sing, lambdas_trip, gaps_sing, gaps_trip = eliashberg_solver.solve( g_dga, g_dmft, u_loc, v_nonloc, comm_mock ) - assert np.allclose(lambdas_sing, np.array([15.80373144, 14.68344285, 12.59292746, 10.81764214]), atol=1e-4) - assert np.allclose(lambdas_trip, np.array([6.70800083, 6.70799431, 6.45388305, 6.45387905]), atol=1e-4) + assert np.allclose(lambdas_sing, np.array([15.802556, 14.68491, 12.591037, 10.81988]), atol=1e-2) + assert np.allclose(lambdas_trip, np.array([6.706, 6.7059937, 6.456441, 6.45644]), atol=1e-2) diff --git a/tests/test_eliashberg_solver.py b/tests/test_eliashberg_solver.py index 56c06b86..b9606a09 100644 --- a/tests/test_eliashberg_solver.py +++ b/tests/test_eliashberg_solver.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems import numpy as np @@ -13,6 +13,8 @@ _chi0_to_matmul_layout, _gamma_to_matmul_layout, ) +from dgamore.four_point import FourPoint +from dgamore.n_point_base import FrequencyNotation, SpinChannel def test_apply_gchi0_pp_matches_einsum(): @@ -26,7 +28,7 @@ def test_apply_gchi0_pp_matches_einsum(): ref = np.einsum("xyzabcdv,xyzcdv->xyzabv", chi0, gap, optimize=True) got = _apply_gchi0_pp(_chi0_to_matmul_layout(chi0), gap.ravel(), o) assert got.shape == ref.shape - assert np.allclose(got, ref, rtol=1e-10) + assert np.allclose(got, ref, atol=1e-10) @pytest.mark.parametrize("nv", [6, 3]) @@ -40,4 +42,129 @@ def test_apply_gamma_pp_matches_einsum(nv): ref = np.einsum("xyzacbdvp,xyzcdp->xyzabv", gamma, gap_gg, optimize=True) got = _apply_gamma_pp(_gamma_to_matmul_layout(gamma), gap_gg, o) assert got.shape == ref.shape - assert np.allclose(got, ref, rtol=1e-10) + assert np.allclose(got, ref, atol=1e-10) + + +@pytest.mark.parametrize("o", [2, 1]) +def test_pairing_vertex_contraction_uses_triqs_leg_order(o): + """The 'abcd->badc' permute makes the vertex contraction implement Delta_ab = sum_cd Gamma_cadb X_cd (TRIQS leg + order); the raw w2dynamics-order layout only agrees for a single band.""" + rng = np.random.default_rng(3) + nq, nv = (2, 2, 1), 4 + shape = (*nq, o, o, o, o, nv, nv) + gamma = (rng.standard_normal(shape) + 1j * rng.standard_normal(shape)).astype(np.complex64) + x = (rng.standard_normal((*nq, o, o, nv)) + 1j * rng.standard_normal((*nq, o, o, nv))).astype(np.complex64) + ref = np.einsum("xyzcadbvp,xyzcdp->xyzabv", gamma, x, optimize=True) + badc = FourPoint( + gamma.copy(), SpinChannel.SING, nq, 0, 2, True, True, False, FrequencyNotation.PP + ).permute_orbitals("abcd->badc") + fixed = _apply_gamma_pp(_gamma_to_matmul_layout(badc.mat), x, o) + raw = _apply_gamma_pp(_gamma_to_matmul_layout(gamma), x, o) + assert np.allclose(fixed, ref, atol=1e-4) + assert (o == 1) == np.allclose(raw, ref, atol=1e-4) + + +def _graded_orbital_symmetrization(gamma: np.ndarray, generators: list[tuple[tuple[int, ...], int]]) -> np.ndarray: + """Averages a rank-4 orbital tensor over the group generated by the given (permutation, character) pairs. With all + characters +1 this is a plain symmetrization; a character -1 makes the vertex odd under that permutation.""" + group = {(0, 1, 2, 3): 1.0} + changed = True + while changed: + changed = False + for p, s in list(group.items()): + for q, sq in generators: + composition = tuple(p[q[i]] for i in range(4)) + if composition not in group: + group[composition] = s * sq + changed = True + return sum(s * np.transpose(gamma, p) for p, s in group.items()) / len(group) + + +def _matvec_direct_term_single_slice( + gamma: np.ndarray, g_plus: np.ndarray, g_minus: np.ndarray, gap: np.ndarray, n_bands: int +) -> np.ndarray: + """Applies the direct term of the Eliashberg matvec for a single momentum/frequency slice, exactly as in + :func:`solve_eliashberg_lanczos`: bare pp bubble times gap (see :func:`_apply_gchi0_pp`), then the + ``"abcd->badc"``-permuted pairing vertex contraction (see :func:`_apply_gamma_pp`).""" + chi0 = np.einsum("ad,bc->abcd", g_plus, g_minus)[None, None, None, ..., None] + gap_gg = _apply_gchi0_pp(_chi0_to_matmul_layout(chi0), gap[None, None, None, ..., None].ravel(), n_bands) + vertex = FourPoint( + gamma[None, None, None, ..., None, None].copy(), + SpinChannel.SING, + (1, 1, 1), + 0, + 2, + True, + True, + False, + FrequencyNotation.PP, + ).permute_orbitals("abcd->badc") + return _apply_gamma_pp(_gamma_to_matmul_layout(vertex.mat), gap_gg, n_bands)[0, 0, 0, :, :, 0] + + +@pytest.mark.parametrize("channel", [SpinChannel.SING, SpinChannel.TRIP]) +def test_matvec_direct_term_matches_thesis_eq_4_40_on_physical_sector(channel): + """On the physical symmetry class -- pairing vertex with its particle-swap (1432, 3214) and static time-reversal + (dcba) symmetries, G(k) symmetric (time reversal plus inversion) and the gap in the SPOT sector (Delta = +/- + Delta^T for singlet/triplet) -- the matvec direct term is identical to Eq. (4.40) of the thesis and preserves the + sector. For a generic (unsymmetrized) vertex the two wirings differ, so the equivalence is a property of the + symmetry class, not of the contraction pattern.""" + rng = np.random.default_rng(4) + o = 3 + sign = 1 if channel == SpinChannel.SING else -1 + + gamma = (rng.standard_normal((o,) * 4) + 1j * rng.standard_normal((o,) * 4)).astype(np.complex64) + gamma_sym = _graded_orbital_symmetrization(gamma, [((0, 3, 2, 1), sign), ((2, 1, 0, 3), sign), ((3, 2, 1, 0), 1)]) + + g_k = rng.standard_normal((o, o)) + 1j * rng.standard_normal((o, o)) + g_k = (0.5 * (g_k + g_k.T)).astype(np.complex64) # TR + inversion: G(k) = G(k)^T = G(-k) + + for _ in range(4): + gap = rng.standard_normal((o, o)) + 1j * rng.standard_normal((o, o)) + gap = (0.5 * (gap + sign * gap.T)).astype(np.complex64) # SPOT-allowed static sector + + got = _matvec_direct_term_single_slice(gamma_sym, g_k, g_k, gap, o) + ref = np.einsum("xbya,ad,cb,dc->xy", gamma_sym, g_k, g_k, gap, optimize=True) + assert np.allclose(got, ref, atol=1e-4) + assert np.allclose(got, sign * got.T, atol=1e-4) + + got_generic = _matvec_direct_term_single_slice(gamma, g_k, g_k, gap, o) + ref_generic = np.einsum("xbya,ad,cb,dc->xy", gamma, g_k, g_k, gap, optimize=True) + assert not np.allclose(got_generic, ref_generic, atol=1e-4) + + +@pytest.mark.parametrize("o", [2, 1]) +def test_badc_permute_is_noop_for_swap_and_tr_symmetric_pairing_vertex(o): + """'abcd->badc' composes from the physical vertex symmetries (badc = dcba composed with cdab), so for a pairing + vertex carrying the particle-swap (1432, 3214) and static time-reversal (dcba) symmetries the w2dynamics and TRIQS + leg orders give identical contractions for any gap; for a generic tensor they differ (except for a single band).""" + rng = np.random.default_rng(5) + nq, nv = (1, 1, 1), 1 + + gamma = (rng.standard_normal((o,) * 4) + 1j * rng.standard_normal((o,) * 4)).astype(np.complex64) + gamma_sym = _graded_orbital_symmetrization(gamma, [((0, 3, 2, 1), 1), ((2, 1, 0, 3), 1), ((3, 2, 1, 0), 1)]) + x = (rng.standard_normal((*nq, o, o, nv)) + 1j * rng.standard_normal((*nq, o, o, nv))).astype(np.complex64) + + def contract(mat): + padded = mat[None, None, None, ..., None, None].copy() + return _apply_gamma_pp(_gamma_to_matmul_layout(padded), x, o) + + def badc(mat): + return ( + FourPoint( + mat[None, None, None, ..., None, None].copy(), + SpinChannel.SING, + nq, + 0, + 2, + True, + True, + False, + FrequencyNotation.PP, + ) + .permute_orbitals("abcd->badc") + .mat[0, 0, 0, :, :, :, :, 0, 0] + ) + + assert np.allclose(contract(badc(gamma_sym)), contract(gamma_sym), atol=1e-4) + assert (o == 1) == np.allclose(contract(badc(gamma)), contract(gamma), atol=1e-4) diff --git a/tests/test_four_point.py b/tests/test_four_point.py index d33325a1..c5238afa 100644 --- a/tests/test_four_point.py +++ b/tests/test_four_point.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems from copy import deepcopy @@ -126,6 +126,116 @@ def test_mul_with_scalar_and_array(small_fourpoint): assert np.allclose(res2.mat, fp.mat * 2.0) +def test_scale_in_place_multiplies_and_returns_self(small_fourpoint): + """scale(factor) multiplies mat in place (copy=False default), returns self, and stays complex64.""" + fp = small_fourpoint + before = fp.mat.copy() + out = fp.scale(3.0) + assert out is fp + assert np.array_equal(fp.mat, (before * 3.0).astype(np.complex64)) + assert fp.mat.dtype == np.complex64 + + +def test_scale_copy_true_leaves_original_untouched(small_fourpoint): + """scale(factor, copy=True) returns a new scaled object and leaves self unchanged.""" + fp = small_fourpoint + before = fp.mat.copy() + out = fp.scale(-2.0, copy=True) + assert out is not fp + assert np.array_equal(out.mat, (before * -2.0).astype(np.complex64)) + assert np.array_equal(fp.mat, before) + + +def test_scale_rejects_non_scalar(small_fourpoint): + """scale only accepts numbers (mirrors __mul__).""" + with pytest.raises(ValueError): + small_fourpoint.scale(np.ones(3)) + + +def test_copy_returns_independent_deep_copy(small_fourpoint): + """copy() returns a new, independent deep copy whose mutation does not affect the original.""" + fp = small_fourpoint + c = fp.copy() + assert c is not fp + assert c.mat is not fp.mat + assert np.array_equal(c.mat, fp.mat) + before = fp.mat.copy() + c.mat[...] = 0.0 + assert np.array_equal(fp.mat, before) + + +def _kernel_block(rng, channel, num_vn=1): + """Builds a half-niw, compressed-q FourPoint matching the self-energy-kernel layout (num_vn 1 or 2).""" + nq = (4, 4, 1) + qtot, o, niw, niv = 16, 2, 3, 3 + shape = (qtot, o, o, o, o, niw + 1) + (2 * niv,) * num_vn + mat = rng.standard_normal(shape) + 1j * rng.standard_normal(shape) + return FourPoint(mat, channel, nq, 1, num_vn, False, True, True, FrequencyNotation.PH) + + +def test_add_inplace_equals_out_of_place_and_returns_self(rng): + """add(other, copy=False) accumulates into self in place, returns self, bit-equal to self + other.""" + a, b = _kernel_block(rng, SpinChannel.NONE), _kernel_block(rng, SpinChannel.DENS) + ref = deepcopy(a) + deepcopy(b) + out = a.add(b, copy=False) + assert out is a + assert np.array_equal(a.mat, ref.mat) + assert a.channel == ref.channel == SpinChannel.DENS + + +def test_sub_inplace_equals_out_of_place_and_returns_self(rng): + """sub(other, copy=False) subtracts into self in place, returns self, bit-equal to self - other.""" + a, b = _kernel_block(rng, SpinChannel.DENS), _kernel_block(rng, SpinChannel.MAGN) + ref = deepcopy(a) - deepcopy(b) + out = a.sub(b, copy=False) + assert out is a + assert np.array_equal(a.mat, ref.mat) + + +def test_add_inplace_with_scaled_other_matches_reference(rng): + """The kernel-accumulation idiom k.add(other.scale(3), copy=False) equals k + 3 * other.""" + a, b = _kernel_block(rng, SpinChannel.NONE), _kernel_block(rng, SpinChannel.MAGN) + ref = deepcopy(a) + 3 * deepcopy(b) + a.add(b.scale(3.0), copy=False) + assert np.array_equal(a.mat, ref.mat) + + +def test_add_copy_true_is_nondestructive(rng): + """add(other) (copy=True default) returns a new object and leaves self unchanged (unchanged behavior).""" + a, b = _kernel_block(rng, SpinChannel.DENS), _kernel_block(rng, SpinChannel.DENS) + before = a.mat.copy() + out = a.add(b) + assert out is not a + assert np.array_equal(a.mat, before) + + +def test_add_inplace_rejects_non_fourpoint(rng): + """copy=False is only defined between two FourPoints; a scalar/array/interaction operand raises.""" + a = _kernel_block(rng, SpinChannel.DENS) + with pytest.raises(NotImplementedError): + a.add(2.0, copy=False) + + +def test_add_inplace_rejects_vn_extension(rng): + """copy=False refuses to diagonally extend self (num_vn=1 += num_vn=2), which would allocate a larger array.""" + a, b = _kernel_block(rng, SpinChannel.NONE, num_vn=1), _kernel_block(rng, SpinChannel.DENS, num_vn=2) + with pytest.raises(ValueError): + a.add(b, copy=False) + + +def test_add_inplace_reverts_other_niw_range(rng): + """copy=False converts a full-niw other to half for the op, then restores its range (non-destructive to other).""" + nq, qtot, o, niw, niv = (4, 4, 1), 16, 2, 3, 3 + a = _kernel_block(rng, SpinChannel.DENS) # half niw range + full_shape = (qtot, o, o, o, o, 2 * niw + 1, 2 * niv) + full_mat = rng.standard_normal(full_shape) + 1j * rng.standard_normal(full_shape) + b = FourPoint(full_mat, SpinChannel.MAGN, nq, 1, 1, True, True, True, FrequencyNotation.PH) + ref = deepcopy(a) + deepcopy(b) + a.add(b, copy=False) + assert np.array_equal(a.mat, ref.mat) + assert b.full_niw_range + + def test_add_with_localinteraction_and_interaction(rng): """A FourPoint adds a LocalInteraction and a momentum-dependent Interaction, preserving its shape.""" nq = (4, 4, 1) @@ -246,7 +356,7 @@ def test_sum_over_vn_reduces_dims(small_fourpoint): sl = fp.mat[0, 0, 0, 0, 0, 0, :, :, :] expect = (1 / beta) * np.sum(sl, axis=-1) got = out.mat[0, 0, 0, 0, 0, 0, :, :] - assert np.allclose(got, expect, rtol=1e-6, atol=1e-6) + assert np.allclose(got, expect, atol=1e-6) def test_sum_over_vn_raises_on_too_many_axes(small_fourpoint): @@ -565,7 +675,7 @@ def test_invert_and_sum_methods_agree_on_decompressed_fp(small_fourpoint): assert out1._num_vn_dimensions == 1 assert out2._num_vn_dimensions == 1 assert out1.current_shape == out2.current_shape - assert np.allclose(out1.mat, out2.mat, rtol=1e-6, atol=1e-8) + assert np.allclose(out1.mat, out2.mat, atol=1e-6) def test_invert_and_sum_methods_agree_on_compressed_fp(small_fourpoint_compressed): @@ -580,7 +690,7 @@ def test_invert_and_sum_methods_agree_on_compressed_fp(small_fourpoint_compresse assert out1._num_vn_dimensions == 1 assert out2._num_vn_dimensions == 1 assert out1.current_shape == out2.current_shape - assert np.allclose(out1.mat, out2.mat, rtol=1e-6, atol=1e-8) + assert np.allclose(out1.mat, out2.mat, atol=1e-6) def test_invert_and_sum_scales_with_beta(small_fourpoint_compressed): @@ -594,7 +704,7 @@ def test_invert_and_sum_scales_with_beta(small_fourpoint_compressed): out_beta2 = deepcopy(fp).invert_and_sum_over_last_vn_v2(beta2) scale = beta1 / beta2 - assert np.allclose(out_beta2.mat, out_beta1.mat * scale, rtol=1e-8, atol=1e-10) + assert np.allclose(out_beta2.mat, out_beta1.mat * scale, atol=1e-8) def test_invert_and_sum_v1_scales_with_beta(small_fourpoint_compressed): diff --git a/tests/test_greens_function.py b/tests/test_greens_function.py index e9b15786..bc29f9bc 100644 --- a/tests/test_greens_function.py +++ b/tests/test_greens_function.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems from unittest.mock import MagicMock @@ -234,7 +234,7 @@ def test_get_epot_e_corr_einsum_matches_transposed_product_reference(): dsigma = g._sigma.decompress_q_dimension().mat - smom0[..., None] e_corr_ref = (dsigma * g.decompress_q_dimension().transpose_orbitals().mat).sum().real / beta e_corr_new = np.einsum("...abv,...bav->...", dsigma, g.decompress_q_dimension().mat).sum().real / beta - assert np.allclose(e_corr_new, e_corr_ref, rtol=1e-5) + assert np.allclose(e_corr_new, e_corr_ref, atol=1e-5) assert np.isfinite(g.get_epot()) diff --git a/tests/test_hamiltonian.py b/tests/test_hamiltonian.py index ea56ee69..c2ed321b 100644 --- a/tests/test_hamiltonian.py +++ b/tests/test_hamiltonian.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems import os diff --git a/tests/test_interaction.py b/tests/test_interaction.py index 5cadd282..9ffc9f76 100644 --- a/tests/test_interaction.py +++ b/tests/test_interaction.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems import pytest @@ -18,7 +18,7 @@ def test_localinteraction_adds_correctly(): interaction1 = LocalInteraction(mat1) interaction2 = LocalInteraction(mat2) result = interaction1 + interaction2 - assert np.allclose(result.mat, mat1 + mat2, rtol=1e-2) + assert np.allclose(result.mat, mat1 + mat2, atol=1e-2) def test_localinteraction_handles_identity_permutation(): @@ -26,7 +26,7 @@ def test_localinteraction_handles_identity_permutation(): mat = np.array([[1, 2], [3, 4]]) interaction = LocalInteraction(mat) result = interaction.permute_orbitals("abcd->abcd") - assert np.allclose(result.mat, mat, rtol=1e-2) + assert np.allclose(result.mat, mat, atol=1e-2) def test_localinteraction_raises_error_on_invalid_permutation(): @@ -58,7 +58,7 @@ def test_transforms_to_correct_channel(channel, expected_mat): """LocalInteraction.as_channel builds the dens/magn/sing/trip combinations.""" interaction = LocalInteraction(u_loc, SpinChannel.NONE) result = interaction.as_channel(channel) - assert np.allclose(result.mat, expected_mat, rtol=1e-2) + assert np.allclose(result.mat, expected_mat, atol=1e-2) assert result.channel == channel @@ -67,7 +67,7 @@ def test_interaction_exponentiates_correctly(): mat = np.array(np.random.rand(2, 2, 2, 2)) interaction = LocalInteraction(mat) result = interaction**2 - assert np.allclose(result.mat, np.einsum("abcd,dcef->abef", mat, mat, optimize=True), rtol=1e-2) + assert np.allclose(result.mat, np.einsum("abcd,dcef->abef", mat, mat, optimize=True), atol=1e-2) def test_interaction_raises_error_on_invalid_exponentiation(): @@ -92,7 +92,7 @@ def test_localinteraction_rsub_has_correct_sign(): u = LocalInteraction(mat) other = np.zeros_like(mat) result = u.__rsub__(other) # directly call __rsub__ to test B - A = C - assert np.allclose(result.mat, -mat, rtol=1e-2) + assert np.allclose(result.mat, -mat, atol=1e-2) def test_interaction_handles_channel_transformation(): @@ -100,7 +100,7 @@ def test_interaction_handles_channel_transformation(): mat = np.array([[1, 2], [3, 4]]) interaction = Interaction(mat, SpinChannel.NONE) result = interaction.as_channel(SpinChannel.DENS) - assert np.allclose(result.mat, 2 * mat, rtol=1e-2) + assert np.allclose(result.mat, 2 * mat, atol=1e-2) def test_interaction_raises_error_on_invalid_channel_transformation(): @@ -133,7 +133,7 @@ def test_permute_orbitals_returns_same_object_for_identity_permutation(n): mat = np.random.rand(16, n, n, n, n) interaction = Interaction(mat) result = interaction.permute_orbitals("abcd->abcd") - assert np.allclose(result.mat, interaction.mat, rtol=1e-2) + assert np.allclose(result.mat, interaction.mat, atol=1e-2) @pytest.mark.parametrize("n", [1, 2, 3]) @@ -143,7 +143,7 @@ def test_permute_orbitals_applies_correct_permutation_with_compressed_q_dimensio interaction = Interaction(mat, has_compressed_q_dimension=True) result = interaction.permute_orbitals("abcd->adcb") expected = np.einsum("...abcd->...adcb", mat, optimize=True) - assert np.allclose(result.mat, expected, rtol=1e-2) + assert np.allclose(result.mat, expected, atol=1e-2) @pytest.mark.parametrize("n", [1, 2, 3]) @@ -153,7 +153,7 @@ def test_permute_orbitals_applies_correct_permutation_with_decompressed_q_dimens interaction = Interaction(mat, has_compressed_q_dimension=False) result = interaction.permute_orbitals("abcd->adcb") expected = np.einsum("...abcd->...adcb", mat, optimize=True) - assert np.allclose(result.mat, expected, rtol=1e-2) + assert np.allclose(result.mat, expected, atol=1e-2) @pytest.mark.parametrize("n", [1, 2, 3]) @@ -179,7 +179,7 @@ def test_interaction_handles_compressed_q_dimension_exponentiation(): interaction = Interaction(mat, has_compressed_q_dimension=True) result = interaction**2 assert result.mat.shape == mat.shape - assert np.allclose(result.mat, np.einsum("qabcd,qdcef->qabef", mat, mat, optimize=True), rtol=1e-2) + assert np.allclose(result.mat, np.einsum("qabcd,qdcef->qabef", mat, mat, optimize=True), atol=1e-2) def test_raises_error_when_exponentiating_with_invalid_power(): @@ -196,7 +196,7 @@ def test_transforms_to_dens_channel_correctly(n): mat = np.random.rand(4, n, n, n, n) interaction = Interaction(mat, SpinChannel.NONE) result = interaction.as_channel(SpinChannel.DENS) - assert np.allclose(result.mat, 2 * interaction.mat, rtol=1e-2) + assert np.allclose(result.mat, 2 * interaction.mat, atol=1e-2) assert result.channel == SpinChannel.DENS @@ -206,7 +206,7 @@ def test_transforms_to_magn_channel_correctly(n): mat = np.random.rand(4, n, n, n, n) interaction = Interaction(mat, SpinChannel.NONE) result = interaction.as_channel(SpinChannel.MAGN) - assert np.allclose(result.mat, 0 * interaction.mat, rtol=1e-2) + assert np.allclose(result.mat, 0 * interaction.mat, atol=1e-2) assert result.channel == SpinChannel.MAGN @@ -216,7 +216,7 @@ def test_transforms_to_sing_channel_correctly(n): mat = np.random.rand(4, n, n, n, n) interaction = Interaction(mat, SpinChannel.NONE) result = interaction.as_channel(SpinChannel.SING) - assert np.allclose(result.mat, interaction.mat, rtol=1e-2) + assert np.allclose(result.mat, interaction.mat, atol=1e-2) assert result.channel == SpinChannel.SING @@ -226,7 +226,7 @@ def test_transforms_to_trip_channel_correctly(n): mat = np.random.rand(4, n, n, n, n) interaction = Interaction(mat, SpinChannel.NONE) result = interaction.as_channel(SpinChannel.TRIP) - assert np.allclose(result.mat, interaction.mat, rtol=1e-2) + assert np.allclose(result.mat, interaction.mat, atol=1e-2) assert result.channel == SpinChannel.TRIP @@ -246,7 +246,7 @@ def test_adds_interaction_with_numpy_array_correctly(n): mat2 = np.random.rand(16, n, n, n, n) interaction = Interaction(mat1, has_compressed_q_dimension=True) result = interaction + mat2 - assert np.allclose(result.mat, mat1 + mat2, rtol=1e-2) + assert np.allclose(result.mat, mat1 + mat2, atol=1e-2) @pytest.mark.parametrize("n", [1, 2, 3]) @@ -257,7 +257,7 @@ def test_adds_two_interactions_correctly_1(n): interaction1 = Interaction(mat1, has_compressed_q_dimension=True) interaction2 = Interaction(mat2, has_compressed_q_dimension=True) result = interaction1 + interaction2 - assert np.allclose(result.mat, mat1 + mat2, rtol=1e-2) + assert np.allclose(result.mat, mat1 + mat2, atol=1e-2) @pytest.mark.parametrize("n", [1, 2, 3]) @@ -268,7 +268,7 @@ def test_adds_two_interactions_correctly_2(n): interaction1 = Interaction(mat1, has_compressed_q_dimension=True) interaction2 = Interaction(mat2, has_compressed_q_dimension=False) result = interaction1 + interaction2 - assert np.allclose(result.mat, mat1 + mat2, rtol=1e-2) + assert np.allclose(result.mat, mat1 + mat2, atol=1e-2) @pytest.mark.parametrize("n", [1, 2, 3]) @@ -279,7 +279,7 @@ def test_adds_two_interactions_correctly_3(n): interaction1 = Interaction(mat1, has_compressed_q_dimension=False) interaction2 = Interaction(mat2, has_compressed_q_dimension=True) result = interaction1 + interaction2 - assert np.allclose(result.mat, mat1 + mat2, rtol=1e-2) + assert np.allclose(result.mat, mat1 + mat2, atol=1e-2) @pytest.mark.parametrize("n", [1, 2, 3]) @@ -291,7 +291,7 @@ def test_adds_interaction_with_localinteraction_correctly_if_decompressed(n): local_interaction = LocalInteraction(mat2) result = interaction + local_interaction expected = mat1 + mat2[None, ...] - assert np.allclose(result.mat, expected, rtol=1e-2) + assert np.allclose(result.mat, expected, atol=1e-2) @pytest.mark.parametrize("n", [1, 2, 3]) @@ -303,7 +303,7 @@ def test_adds_interaction_with_localinteraction_correctly_if_compressed(n): local_interaction = LocalInteraction(mat2) result = interaction + local_interaction expected = mat1 + mat2[None, ...] - assert np.allclose(result.mat, expected, rtol=1e-2) + assert np.allclose(result.mat, expected, atol=1e-2) @pytest.mark.parametrize("n", [1, 2]) @@ -319,7 +319,7 @@ def test_adds_localinteraction_on_left_with_interaction_returns_interaction(n): assert isinstance(result, Interaction) assert result.has_compressed_q_dimension assert result.current_shape == v_mat.shape - assert np.allclose(result.mat, u_mat[None, ...] + v_mat, rtol=1e-2) + assert np.allclose(result.mat, u_mat[None, ...] + v_mat, atol=1e-2) @pytest.mark.parametrize("n", [1, 2]) @@ -335,7 +335,7 @@ def test_subtracts_interaction_from_localinteraction_on_left_returns_interaction assert isinstance(result, Interaction) assert result.has_compressed_q_dimension assert result.current_shape == v_mat.shape - assert np.allclose(result.mat, u_mat[None, ...] - v_mat, rtol=1e-2) + assert np.allclose(result.mat, u_mat[None, ...] - v_mat, atol=1e-2) def test_adds_two_interactions_using_operator_correctly(): @@ -345,7 +345,7 @@ def test_adds_two_interactions_using_operator_correctly(): interaction1 = Interaction(mat1) interaction2 = Interaction(mat2) result = interaction1 + interaction2 - assert np.allclose(result.mat, mat1 + mat2, rtol=1e-2) + assert np.allclose(result.mat, mat1 + mat2, atol=1e-2) def test_adds_interaction_and_numpy_array_using_operator_correctly(): @@ -354,7 +354,7 @@ def test_adds_interaction_and_numpy_array_using_operator_correctly(): mat2 = np.random.rand(4, 4, 2, 2) interaction = Interaction(mat1) result = interaction + mat2 - assert np.allclose(result.mat, mat1 + mat2, rtol=1e-2) + assert np.allclose(result.mat, mat1 + mat2, atol=1e-2) def test_subtracts_two_interactions_using_operator_correctly(): @@ -364,7 +364,7 @@ def test_subtracts_two_interactions_using_operator_correctly(): interaction1 = Interaction(mat1) interaction2 = Interaction(mat2) result = interaction1 - interaction2 - assert np.allclose(result.mat, mat1 - mat2, rtol=1e-2) + assert np.allclose(result.mat, mat1 - mat2, atol=1e-2) def test_subtracts_interaction_and_numpy_array_using_operator_correctly(): @@ -373,7 +373,7 @@ def test_subtracts_interaction_and_numpy_array_using_operator_correctly(): mat2 = np.random.rand(4, 4, 2, 2) interaction = Interaction(mat1) result = interaction - mat2 - assert np.allclose(result.mat, mat1 - mat2, rtol=1e-2) + assert np.allclose(result.mat, mat1 - mat2, atol=1e-2) def test_raises_error_when_adding_unsupported_type(): @@ -390,4 +390,4 @@ def test_nonlocal_interaction_rsub_has_correct_sign(): v = Interaction(mat, SpinChannel.NONE, (1, 1, 1), has_compressed_q_dimension=True) other = np.zeros_like(mat) result = v.__rsub__(other) # directly call __rsub__ to test B - A = C - assert np.allclose(result.mat, -mat, rtol=1e-2) + assert np.allclose(result.mat, -mat, atol=1e-2) diff --git a/tests/test_lambda_correction.py b/tests/test_lambda_correction.py index 76a0f571..71fda4f3 100644 --- a/tests/test_lambda_correction.py +++ b/tests/test_lambda_correction.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems import os diff --git a/tests/test_local_four_point.py b/tests/test_local_four_point.py index 10a01a0c..d277cb22 100644 --- a/tests/test_local_four_point.py +++ b/tests/test_local_four_point.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems from unittest.mock import patch, MagicMock @@ -25,7 +25,7 @@ def test_exponentiation_with_positive_power_1(n): expected = obj for _ in range(n - 1): expected = expected @ obj - assert np.allclose(result.mat, expected.mat, rtol=1e-4) + assert np.allclose(result.mat, expected.mat, atol=1e-4) @pytest.mark.parametrize("n", [1, 2, 3]) @@ -38,7 +38,7 @@ def test_exponentiation_with_positive_power_2(n): expected = obj for _ in range(n - 1): expected = expected @ obj - assert np.allclose(result.mat, expected.mat, rtol=1e-4) + assert np.allclose(result.mat, expected.mat, atol=1e-4) def test_exponentiation_with_zero_power_returns_identity_1(): @@ -47,7 +47,7 @@ def test_exponentiation_with_zero_power_returns_identity_1(): obj = LocalFourPoint(mat, channel=SpinChannel.NONE, num_vn_dimensions=1) identity = LocalFourPoint.identity_like(obj) result = obj.pow(0, identity) - assert np.allclose(result.mat, identity.mat, rtol=1e-4) + assert np.allclose(result.mat, identity.mat, atol=1e-4) def test_exponentiation_with_zero_power_returns_identity_2(): @@ -56,7 +56,7 @@ def test_exponentiation_with_zero_power_returns_identity_2(): obj = LocalFourPoint(mat, channel=SpinChannel.NONE, num_vn_dimensions=2) identity = LocalFourPoint.identity_like(obj) result = obj.pow(0, identity) - assert np.allclose(result.mat, identity.mat, rtol=1e-4) + assert np.allclose(result.mat, identity.mat, atol=1e-4) @pytest.mark.parametrize("n", [1, 2, 3]) @@ -69,7 +69,7 @@ def test_exponentiation_with_negative_power_1(n): expected = obj.invert() for _ in range(n - 1): expected = expected @ obj.invert() - assert np.allclose(result.mat, expected.mat, rtol=1e-4) + assert np.allclose(result.mat, expected.mat, atol=1e-4) @pytest.mark.parametrize("n", [1, 2, 3]) @@ -82,7 +82,7 @@ def test_exponentiation_with_negative_power_2(n): expected = obj.invert() for _ in range(n - 1): expected = expected @ obj.invert() - assert np.allclose(result.mat, expected.mat, rtol=1e-2) + assert np.allclose(result.mat, expected.mat, atol=1e-2) def test_exponentiation_with_non_integer_power_raises_error(): @@ -100,7 +100,7 @@ def test_symmetrizes_square_matrix_correctly(): obj = LocalFourPoint(mat) result = obj.symmetrize_v_vp() expected = np.array([[[[[[1, 2.5], [2.5, 4]]]]]]) - assert np.allclose(result.mat, expected, rtol=1e-4) + assert np.allclose(result.mat, expected, atol=1e-4) def test_symmetrizes_random_matrix_correctly(): @@ -109,7 +109,7 @@ def test_symmetrizes_random_matrix_correctly(): obj = LocalFourPoint(mat) result = obj.symmetrize_v_vp() expected = 0.5 * (mat + mat.swapaxes(0, 3).swapaxes(1, 2).swapaxes(-1, -2)) - assert np.allclose(result.mat, expected, rtol=1e-4) + assert np.allclose(result.mat, expected, atol=1e-4) def test_take_first_wn_selects_first_entry_and_returns_independent_copy(): @@ -119,7 +119,7 @@ def test_take_first_wn_selects_first_entry_and_returns_independent_copy(): expected = obj.mat[..., 0, :, :].copy() result = obj.take_first_wn() assert result.num_wn_dimensions == 0 - assert np.allclose(result.mat, expected, rtol=1e-4) + assert np.allclose(result.mat, expected, atol=1e-4) result.mat[0, 0, 0, 0, 0, 0] = 12345.0 assert not np.allclose(obj.mat[0, 0, 0, 0, 0, 0, 0], 12345.0) @@ -129,7 +129,7 @@ def test_handles_symmetric_matrix_without_modification(): mat = np.array([[[[[[1, 2], [2, 4]]]]]]) obj = LocalFourPoint(mat) result = obj.symmetrize_v_vp() - assert np.allclose(result.mat, mat, rtol=1e-4) + assert np.allclose(result.mat, mat, atol=1e-4) def test_raises_error_for_non_square_last_two_axes(): @@ -154,7 +154,7 @@ def test_sums_over_orbitals_correctly_1(): obj = LocalFourPoint(mat) result = obj.sum_over_orbitals("abcd->ad") assert result.mat.shape == (2, 2, 5, 3) - assert np.allclose(result.mat, np.sum(mat, axis=(1, 2)), rtol=1e-4) + assert np.allclose(result.mat, np.sum(mat, axis=(1, 2)), atol=1e-4) def test_sums_over_orbitals_correctly_2(): @@ -163,7 +163,7 @@ def test_sums_over_orbitals_correctly_2(): obj = LocalFourPoint(mat) result = obj.sum_over_orbitals("abcd->ad") assert result.mat.shape == (2, 2, 5, 3, 3) - assert np.allclose(result.mat, np.sum(mat, axis=(1, 2)), rtol=1e-4) + assert np.allclose(result.mat, np.sum(mat, axis=(1, 2)), atol=1e-4) def test_raises_error_for_invalid_orbital_contraction_format(): @@ -179,7 +179,7 @@ def test_handles_no_orbital_reduction(): mat = np.random.rand(2, 2, 2, 2, 5, 3, 3) obj = LocalFourPoint(mat) result = obj.sum_over_orbitals("abcd->abcd") - assert np.allclose(result.mat, mat, rtol=1e-4) + assert np.allclose(result.mat, mat, atol=1e-4) def test_reduces_orbital_dimensions_correctly_1(): @@ -188,7 +188,7 @@ def test_reduces_orbital_dimensions_correctly_1(): obj = LocalFourPoint(mat) result = obj.sum_over_orbitals("abcd->a") assert result.mat.shape == (3, 5, 4, 4) - assert np.allclose(result.mat, np.sum(mat, axis=(1, 2, 3)), rtol=1e-4) + assert np.allclose(result.mat, np.sum(mat, axis=(1, 2, 3)), atol=1e-4) def test_reduces_orbital_dimensions_correctly_2(): @@ -197,7 +197,7 @@ def test_reduces_orbital_dimensions_correctly_2(): obj = LocalFourPoint(mat) result = obj.sum_over_orbitals("abcd->ab") assert result.mat.shape == (3, 3, 5, 4, 4) - assert np.allclose(result.mat, np.sum(mat, axis=(2, 3)), rtol=1e-4) + assert np.allclose(result.mat, np.sum(mat, axis=(2, 3)), atol=1e-4) def test_reduces_orbital_dimensions_correctly_3(): @@ -206,7 +206,7 @@ def test_reduces_orbital_dimensions_correctly_3(): obj = LocalFourPoint(mat) result = obj.sum_over_orbitals("abcd->abc") assert result.mat.shape == (3, 3, 3, 5, 4, 4) - assert np.allclose(result.mat, np.sum(mat, axis=(3,)), rtol=1e-4) + assert np.allclose(result.mat, np.sum(mat, axis=(3,)), atol=1e-4) def test_sums_over_single_vn_dimension_correctly_1(): @@ -216,7 +216,7 @@ def test_sums_over_single_vn_dimension_correctly_1(): beta = 10.0 result = obj.sum_over_vn(beta, axis=(-1,)) expected_mat = 1 / beta * np.sum(mat, axis=-1) - assert np.allclose(result.mat, expected_mat, rtol=1e-4) + assert np.allclose(result.mat, expected_mat, atol=1e-4) assert result.num_vn_dimensions == 0 @@ -228,7 +228,7 @@ def test_sums_over_single_vn_dimension_correctly_2(n): beta = 10.0 result = obj.sum_over_vn(beta, axis=(-n,)) expected_mat = 1 / beta * np.sum(mat, axis=(-n,)) - assert np.allclose(result.mat, expected_mat, rtol=1e-4) + assert np.allclose(result.mat, expected_mat, atol=1e-4) assert result.num_vn_dimensions == 1 @@ -239,7 +239,7 @@ def test_sums_over_multiple_vn_dimensions_correctly(): beta = 10.0 result = obj.sum_over_vn(beta, axis=(-2, -1)) expected_mat = 1 / beta**2 * np.sum(mat, axis=(-2, -1)) - assert np.allclose(result.mat, expected_mat, rtol=1e-4) + assert np.allclose(result.mat, expected_mat, atol=1e-4) assert result.num_vn_dimensions == 0 @@ -259,7 +259,7 @@ def test_sums_over_all_vn_with_double_vn_dimensions_correctly(): beta = 10.0 result = obj.sum_over_all_vn(beta) expected_mat = 1 / beta**2 * np.sum(mat, axis=(-2, -1)) - assert np.allclose(result.mat, expected_mat, rtol=1e-4) + assert np.allclose(result.mat, expected_mat, atol=1e-4) assert result.num_vn_dimensions == 0 @@ -270,7 +270,7 @@ def test_sums_over_all_vn_with_single_vn_dimension_correctly(): beta = 10.0 result = obj.sum_over_all_vn(beta) expected_mat = 1 / beta * np.sum(mat, axis=-1) - assert np.allclose(result.mat, expected_mat, rtol=1e-4) + assert np.allclose(result.mat, expected_mat, atol=1e-4) assert result.num_vn_dimensions == 0 @@ -280,7 +280,7 @@ def test_handles_no_vn_dimensions_without_modification_for_sum(): obj = LocalFourPoint(mat, num_vn_dimensions=0) beta = 10.0 result = obj.sum_over_all_vn(beta) - assert np.allclose(result.mat, mat, rtol=1e-4) + assert np.allclose(result.mat, mat, atol=1e-4) assert result.num_vn_dimensions == 0 @@ -291,7 +291,7 @@ def test_contracts_legs_correctly_with_two_vn_dimensions(): beta = 10.0 result = obj.contract_legs(beta) assert result.mat.shape == (2, 2, 5) - assert np.allclose(result.mat, 1.0 / beta**2 * np.einsum("abcdefg->ade", mat), rtol=1e-4) + assert np.allclose(result.mat, 1.0 / beta**2 * np.einsum("abcdefg->ade", mat), atol=1e-4) def test_raises_error_when_contracting_legs_with_invalid_vn_dimensions(): @@ -328,7 +328,7 @@ def test_converts_to_compound_indices_with_no_vn_dimensions(): obj = LocalFourPoint(mat, num_vn_dimensions=0) result = obj.to_compound_indices() assert result.mat.shape == (5, 4, 4) - assert np.allclose(result.mat, mat.transpose(4, 0, 1, 3, 2).reshape(5, 4, 4), rtol=1e-4) + assert np.allclose(result.mat, mat.transpose(4, 0, 1, 3, 2).reshape(5, 4, 4), atol=1e-4) def test_converts_to_compound_indices_with_one_vn_dimension(): @@ -356,7 +356,7 @@ def test_converts_to_compound_indices_with_two_vn_dimensions(): mat = np.random.rand(2, 2, 2, 2, 5, 4, 4) obj = LocalFourPoint(mat, num_vn_dimensions=2) result = obj.to_compound_indices() - assert np.allclose(result.mat, mat.transpose(4, 0, 1, 5, 3, 2, 6).reshape(5, 16, 16), rtol=1e-4) + assert np.allclose(result.mat, mat.transpose(4, 0, 1, 5, 3, 2, 6).reshape(5, 16, 16), atol=1e-4) def test_raises_error_for_missing_bosonic_frequencies(): @@ -372,7 +372,7 @@ def test_handles_already_compound_indices_without_modification(): mat = np.random.rand(5, 4, 4) obj = LocalFourPoint(mat, num_wn_dimensions=1, num_vn_dimensions=2) result = obj.to_compound_indices() - assert np.allclose(result.mat, mat, rtol=1e-4) + assert np.allclose(result.mat, mat, atol=1e-4) @pytest.mark.parametrize( @@ -398,7 +398,7 @@ def test_converts_compound_indices_to_full_indices_correctly_for_one_vn_dimensio result = obj.to_full_indices() assert result.mat.shape == (2, 2, 2, 2, 5, 4, 4) assert result.num_vn_dimensions == 2 - assert np.allclose(mat, result.take_vn_diagonal().mat, rtol=1e-4) + assert np.allclose(mat, result.take_vn_diagonal().mat, atol=1e-4) def test_raises_error_for_invalid_current_shape(): @@ -426,7 +426,7 @@ def test_returns_original_object_when_already_in_full_indices(num_wn_dimensions, obj = LocalFourPoint(mat, num_wn_dimensions=num_wn_dimensions, num_vn_dimensions=num_vn_dimensions) result = obj.to_full_indices() assert result.mat.shape == shape - assert np.allclose(result.mat, mat, rtol=1e-4) + assert np.allclose(result.mat, mat, atol=1e-4) assert result.num_wn_dimensions == num_wn_dimensions assert result.num_vn_dimensions == num_vn_dimensions @@ -440,7 +440,7 @@ def test_handles_diagonal_extraction_for_single_vn_dimension(): assert result.mat.shape == (2, 2, 2, 2, 5, 4) mat = mat.reshape((5,) + (2, 2, 4) * 2).transpose(1, 2, 5, 4, 0, 3, 6).diagonal(axis1=-2, axis2=-1) - assert np.allclose(result.mat, mat, rtol=1e-4) + assert np.allclose(result.mat, mat, atol=1e-4) def test_raises_error_for_invalid_bosonic_frequency_dimensions(): @@ -508,8 +508,8 @@ def test_multiplies_two_objects_with_no_vn_dimensions_correctly(): result2 = obj2 @ obj1 expected1 = np.einsum("abcdw,dcefw->abefw", mat1, mat2, optimize=True) expected2 = np.einsum("abcdw,dcefw->abefw", mat2, mat1, optimize=True) - assert np.allclose(result1.mat, expected1[..., 2:], rtol=1e-4) - assert np.allclose(result2.mat, expected2[..., 2:], rtol=1e-4) + assert np.allclose(result1.mat, expected1[..., 2:], atol=1e-4) + assert np.allclose(result2.mat, expected2[..., 2:], atol=1e-4) def test_multiplies_two_objects_with_one_vn_dimension_correctly(): @@ -522,8 +522,8 @@ def test_multiplies_two_objects_with_one_vn_dimension_correctly(): result2 = obj2 @ obj1 expected1 = np.einsum("abcdwv,dcefwv->abefwv", mat1, mat2, optimize=True) expected2 = np.einsum("abcdwv,dcefwv->abefwv", mat2, mat1, optimize=True) - assert np.allclose(result1.mat, expected1[..., 2:, :], rtol=1e-4) - assert np.allclose(result2.mat, expected2[..., 2:, :], rtol=1e-4) + assert np.allclose(result1.mat, expected1[..., 2:, :], atol=1e-4) + assert np.allclose(result2.mat, expected2[..., 2:, :], atol=1e-4) @pytest.mark.parametrize( @@ -577,8 +577,8 @@ def test_handles_multiplication_with_local_interaction_correctly(): result2 = obj2 @ obj1 expected1 = np.einsum("abcdwvp,dcef->abefwvp", mat1, mat2, optimize=True) expected2 = np.einsum("abcd,dcefwvp->abefwvp", mat2, mat1, optimize=True) - assert np.allclose(result1.mat, expected1, rtol=1e-4) - assert np.allclose(result2.mat, expected2, rtol=1e-4) + assert np.allclose(result1.mat, expected1, atol=1e-4) + assert np.allclose(result2.mat, expected2, atol=1e-4) def test_multiplies_objects_with_mixed_vn_dimensions_correctly(): @@ -591,8 +591,8 @@ def test_multiplies_objects_with_mixed_vn_dimensions_correctly(): result2 = obj2 @ obj1 expected1 = np.einsum("abcdwv,dcefw->abefwv", mat1, mat2, optimize=True) expected2 = np.einsum("abcdw,dcefwv->abefwv", mat2, mat1, optimize=True) - assert np.allclose(result1.mat, expected1[..., 2:, :], rtol=1e-4) - assert np.allclose(result2.mat, expected2[..., 2:, :], rtol=1e-4) + assert np.allclose(result1.mat, expected1[..., 2:, :], atol=1e-4) + assert np.allclose(result2.mat, expected2[..., 2:, :], atol=1e-4) assert result1.num_vn_dimensions == 1 assert result2.num_vn_dimensions == 1 @@ -615,7 +615,7 @@ def test_multiplies_with_scalar_correctly(): scalar = 2.5 result = obj * scalar expected = mat * scalar - assert np.allclose(result.mat, expected, rtol=1e-4) + assert np.allclose(result.mat, expected, atol=1e-4) def test_multiplies_with_numpy_array_correctly(): @@ -625,7 +625,7 @@ def test_multiplies_with_numpy_array_correctly(): array = np.random.rand(2, 2, 2, 2, 5, 4) result = obj * array expected = mat * array - assert np.allclose(result.mat, expected, rtol=1e-4) + assert np.allclose(result.mat, expected, atol=1e-4) def test_raises_error_for_invalid_multiplication_type(): @@ -662,7 +662,7 @@ def test_multiplies_two_objects_with_one_vn_dimension_and_generates_two_vn_dimen obj2 = LocalFourPoint(mat2, num_vn_dimensions=1, full_niw_range=True) result = obj1 * obj2 expected = np.einsum("abcdwv,dcefwp->abefwvp", mat1, mat2, optimize=True) - assert np.allclose(result.mat, expected[..., 10:, :, :], rtol=1e-4) + assert np.allclose(result.mat, expected[..., 10:, :, :], atol=1e-4) def test_converts_to_half_bosonic_range_correctly_1(): @@ -672,7 +672,7 @@ def test_converts_to_half_bosonic_range_correctly_1(): result = obj.to_half_niw_range() assert result is obj assert result.mat.shape == (2, 2, 2, 2, 11) - assert np.allclose(result.mat, np.take(mat, np.arange(10, 21), axis=-1), rtol=1e-4) + assert np.allclose(result.mat, np.take(mat, np.arange(10, 21), axis=-1), atol=1e-4) def test_converts_to_half_bosonic_range_correctly_2(): @@ -682,7 +682,7 @@ def test_converts_to_half_bosonic_range_correctly_2(): result = obj.to_half_niw_range() assert result is obj assert result.mat.shape == (2, 2, 2, 2, 11, 20) - assert np.allclose(result.mat, np.take(mat, np.arange(10, 21), axis=-2), rtol=1e-4) + assert np.allclose(result.mat, np.take(mat, np.arange(10, 21), axis=-2), atol=1e-4) def test_converts_to_half_bosonic_range_correctly_3(): @@ -692,7 +692,7 @@ def test_converts_to_half_bosonic_range_correctly_3(): result = obj.to_half_niw_range() assert result is obj assert result.mat.shape == (2, 2, 2, 2, 11, 10, 10) - assert np.allclose(result.mat, np.take(mat, np.arange(10, 21), axis=-3), rtol=1e-4) + assert np.allclose(result.mat, np.take(mat, np.arange(10, 21), axis=-3), atol=1e-4) def test_to_full_niw_range_to_half_niw_range_should_reproduce_original_1(): @@ -700,7 +700,7 @@ def test_to_full_niw_range_to_half_niw_range_should_reproduce_original_1(): mat = np.random.rand(2, 2, 2, 2, 21) + 1j * np.random.rand(2, 2, 2, 2, 21) obj = LocalFourPoint(mat, num_vn_dimensions=0, full_niw_range=False) obj = obj.to_full_niw_range().to_half_niw_range() - assert np.allclose(obj.mat, mat, rtol=1e-4) + assert np.allclose(obj.mat, mat, atol=1e-4) assert obj.full_niw_range is False assert obj.num_vn_dimensions == 0 @@ -710,7 +710,7 @@ def test_to_full_niw_range_to_half_niw_range_should_reproduce_original_2(): mat = np.random.rand(2, 2, 2, 2, 21, 4) + 1j * np.random.rand(2, 2, 2, 2, 21, 4) obj = LocalFourPoint(mat, num_vn_dimensions=1, full_niw_range=False) obj = obj.to_full_niw_range().to_half_niw_range() - assert np.allclose(obj.mat, mat, rtol=1e-4) + assert np.allclose(obj.mat, mat, atol=1e-4) assert obj.full_niw_range is False assert obj.num_vn_dimensions == 1 @@ -720,7 +720,7 @@ def test_to_full_niw_range_to_half_niw_range_should_reproduce_original_3(): mat = np.random.rand(2, 2, 2, 2, 21, 4, 4) + 1j * np.random.rand(2, 2, 2, 2, 21, 4, 4) obj = LocalFourPoint(mat, num_vn_dimensions=2, full_niw_range=False) obj = obj.to_full_niw_range().to_half_niw_range() - assert np.allclose(obj.mat, mat, rtol=1e-4) + assert np.allclose(obj.mat, mat, atol=1e-4) assert obj.full_niw_range is False assert obj.num_vn_dimensions == 2 @@ -734,7 +734,7 @@ def test_adds_two_local_four_point_objects_correctly(): result = obj1 + obj2 expected = mat1 + mat2 assert result.full_niw_range == False - assert np.allclose(result.mat, expected[..., 10:, :, :], rtol=1e-4) + assert np.allclose(result.mat, expected[..., 10:, :, :], atol=1e-4) def test_adds_two_local_four_point_objects_with_different_vn_dimensions(): @@ -772,12 +772,12 @@ def test_adds_two_local_four_point_objects_with_different_vn_dimensions(): assert result5.full_niw_range is False assert result6.full_niw_range is False - assert np.allclose(result1.mat, (mat1 + mat2_diagonal)[..., 10:, :, :], rtol=1e-4) - assert np.allclose(result2.mat, (mat1 + mat3[..., None, None])[..., 10:, :, :], rtol=1e-4) - assert np.allclose(result3.mat, (mat2 + mat3[..., None])[..., 10:, :], rtol=1e-4) - assert np.allclose(result4.mat, (mat2 + mat2)[..., 10:, :], rtol=1e-4) - assert np.allclose(result5.mat, (mat3 + mat3)[..., 10:], rtol=1e-4) - assert np.allclose(result6.mat, (mat1 + mat1)[..., 10:, :, :], rtol=1e-4) + assert np.allclose(result1.mat, (mat1 + mat2_diagonal)[..., 10:, :, :], atol=1e-4) + assert np.allclose(result2.mat, (mat1 + mat3[..., None, None])[..., 10:, :, :], atol=1e-4) + assert np.allclose(result3.mat, (mat2 + mat3[..., None])[..., 10:, :], atol=1e-4) + assert np.allclose(result4.mat, (mat2 + mat2)[..., 10:, :], atol=1e-4) + assert np.allclose(result5.mat, (mat3 + mat3)[..., 10:], atol=1e-4) + assert np.allclose(result6.mat, (mat1 + mat1)[..., 10:, :, :], atol=1e-4) def test_adds_local_four_point_and_scalar_correctly(): @@ -787,7 +787,7 @@ def test_adds_local_four_point_and_scalar_correctly(): obj = LocalFourPoint(mat, num_vn_dimensions=2) result = obj + scalar expected = mat + scalar - assert np.allclose(result.mat, expected, rtol=1e-4) + assert np.allclose(result.mat, expected, atol=1e-4) def test_adds_local_four_point_and_numpy_array_correctly(): @@ -797,7 +797,7 @@ def test_adds_local_four_point_and_numpy_array_correctly(): obj = LocalFourPoint(mat1, num_vn_dimensions=2) result = obj + mat2 expected = mat1 + mat2 - assert np.allclose(result.mat, expected, rtol=1e-4) + assert np.allclose(result.mat, expected, atol=1e-4) def test_adds_local_four_point_and_local_interaction_correctly(): @@ -808,7 +808,7 @@ def test_adds_local_four_point_and_local_interaction_correctly(): obj2 = LocalInteraction(mat2) result = obj1 + obj2 expected = mat1 + mat2[..., None, None, None] - assert np.allclose(result.mat, expected, rtol=1e-4) + assert np.allclose(result.mat, expected, atol=1e-4) def test_raises_error_for_unsupported_addition_type(): @@ -828,7 +828,7 @@ def test_adds_local_four_point_and_interaction_with_compressed_q_dimension(): result = obj1 + interaction assert isinstance(result, np.ndarray) expected = mat1[None, ...] + mat2[..., None, None, None] - assert np.allclose(result, expected, rtol=1e-4) + assert np.allclose(result, expected, atol=1e-4) assert result.shape[1:] == mat1.shape assert result.shape[0] == 5 @@ -842,7 +842,7 @@ def test_adds_local_four_point_and_interaction_with_decompressed_q_dimension(): result = obj1 + interaction assert isinstance(result, np.ndarray) expected = mat1[None, None, None, ...] + mat2[..., None, None, None] - assert np.allclose(result, expected, rtol=1e-4) + assert np.allclose(result, expected, atol=1e-4) assert result.shape[3:] == mat1.shape assert result.shape[:2] == mat2.shape[:2] @@ -879,7 +879,7 @@ def test_converts_to_full_niw_range_correctly_with_no_vn_dimensions(): result = obj.to_full_niw_range() expected = np.conj(np.flip(np.take(mat, np.arange(1, mat.shape[-1]), axis=-1), axis=-1)) expected = np.concatenate((expected, mat), axis=-1) - assert np.allclose(result.mat, expected, rtol=1e-4) + assert np.allclose(result.mat, expected, atol=1e-4) assert result.full_niw_range is True @@ -890,7 +890,7 @@ def test_converts_to_full_niw_range_correctly_with_one_vn_dimension(): result = obj.to_full_niw_range() expected = np.conj(np.flip(np.take(mat, np.arange(1, mat.shape[-2]), axis=-2), axis=(-2, -1))) expected = np.concatenate((expected, mat), axis=-2) - assert np.allclose(result.mat, expected, rtol=1e-4) + assert np.allclose(result.mat, expected, atol=1e-4) assert result.full_niw_range is True @@ -901,7 +901,7 @@ def test_converts_to_full_niw_range_correctly_with_two_vn_dimensions(): result = obj.to_full_niw_range() expected = np.conj(np.flip(np.take(mat, np.arange(1, mat.shape[-3]), axis=-3), axis=(-3, -2, -1))) expected = np.concatenate((expected, mat), axis=-3) - assert np.allclose(result.mat, expected, rtol=1e-4) + assert np.allclose(result.mat, expected, atol=1e-4) assert result.full_niw_range is True @@ -910,7 +910,7 @@ def test_handles_already_full_niw_range_without_modification(): mat = np.random.rand(2, 2, 2, 2, 21, 4, 4) + 1j * np.random.rand(2, 2, 2, 2, 21, 4, 4) obj = LocalFourPoint(mat, num_vn_dimensions=2, full_niw_range=True) result = obj.to_full_niw_range() - assert np.allclose(result.mat, mat, rtol=1e-4) + assert np.allclose(result.mat, mat, atol=1e-4) assert result.full_niw_range is True @@ -1045,7 +1045,7 @@ def test_neg_dunder_calls_neg(): with patch.object(LocalFourPoint, "__neg__", wraps=obj.__neg__) as mock_neg: result = -obj mock_neg.assert_called() - assert np.allclose(result.mat, -obj.mat, rtol=1e-4) + assert np.allclose(result.mat, -obj.mat, atol=1e-4) @pytest.mark.parametrize("num_vn_dimensions", [0, 1, 2]) @@ -1057,7 +1057,7 @@ def test_creates_bosonic_dimension_when_not_present(num_vn_dimensions): result = obj.create_wn_dimension() assert result.num_wn_dimensions == 1 assert result.mat.shape == (2,) * 4 + (1,) + (4,) * num_vn_dimensions - assert np.allclose(result.mat, np.expand_dims(mat, axis=-(num_vn_dimensions + 1)), rtol=1e-4) + assert np.allclose(result.mat, np.expand_dims(mat, axis=-(num_vn_dimensions + 1)), atol=1e-4) @pytest.mark.parametrize("num_vn_dimensions", [0, 1, 2]) @@ -1079,7 +1079,7 @@ def test_removes_bosonic_dimension_correctly(num_vn_dimensions): result = obj.take_first_wn() assert result.num_wn_dimensions == 0 assert result.mat.shape == (2,) * 4 + (4,) * num_vn_dimensions - assert np.allclose(result.mat, np.take(mat, 0, axis=-(num_vn_dimensions + 1)), rtol=1e-4) + assert np.allclose(result.mat, np.take(mat, 0, axis=-(num_vn_dimensions + 1)), atol=1e-4) @pytest.mark.parametrize("num_vn_dimensions", [0, 1, 2]) @@ -1102,17 +1102,17 @@ def test_pads_with_u_correctly(niv_pad): result = obj.pad_with_u(u, niv_pad) assert result.mat.shape == (2, 2, 2, 2, 11, 2 * niv_pad, 2 * niv_pad) assert result.original_shape == result.mat.shape - assert np.allclose(result.mat[..., niv_pad - 4 : niv_pad + 4, niv_pad - 4 : niv_pad + 4], mat, rtol=1e-4) + assert np.allclose(result.mat[..., niv_pad - 4 : niv_pad + 4, niv_pad - 4 : niv_pad + 4], mat, atol=1e-4) - assert np.allclose(result.mat[..., : niv_pad - 4, :], u_mat[..., None, None, None], rtol=1e-4) - assert np.allclose(result.mat[..., : niv_pad - 4], u_mat[..., None, None, None], rtol=1e-4) - assert np.allclose(result.mat[..., niv_pad + 4 :, :], u_mat[..., None, None, None], rtol=1e-4) - assert np.allclose(result.mat[..., niv_pad + 4 :], u_mat[..., None, None, None], rtol=1e-4) + assert np.allclose(result.mat[..., : niv_pad - 4, :], u_mat[..., None, None, None], atol=1e-4) + assert np.allclose(result.mat[..., : niv_pad - 4], u_mat[..., None, None, None], atol=1e-4) + assert np.allclose(result.mat[..., niv_pad + 4 :, :], u_mat[..., None, None, None], atol=1e-4) + assert np.allclose(result.mat[..., niv_pad + 4 :], u_mat[..., None, None, None], atol=1e-4) - assert np.allclose(result.mat[..., niv_pad + 4 :, : niv_pad - 4], u_mat[..., None, None, None], rtol=1e-4) - assert np.allclose(result.mat[..., : niv_pad - 4, niv_pad + 4 :], u_mat[..., None, None, None], rtol=1e-4) - assert np.allclose(result.mat[..., : niv_pad - 4, : niv_pad - 4], u_mat[..., None, None, None], rtol=1e-4) - assert np.allclose(result.mat[..., niv_pad + 4 :, niv_pad + 4 :], u_mat[..., None, None, None], rtol=1e-4) + assert np.allclose(result.mat[..., niv_pad + 4 :, : niv_pad - 4], u_mat[..., None, None, None], atol=1e-4) + assert np.allclose(result.mat[..., : niv_pad - 4, niv_pad + 4 :], u_mat[..., None, None, None], atol=1e-4) + assert np.allclose(result.mat[..., : niv_pad - 4, : niv_pad - 4], u_mat[..., None, None, None], atol=1e-4) + assert np.allclose(result.mat[..., niv_pad + 4 :, niv_pad + 4 :], u_mat[..., None, None, None], atol=1e-4) @pytest.mark.parametrize("niv", [5, 10, 15]) @@ -1123,7 +1123,7 @@ def test_does_not_pad_when_niv_pad_is_less_or_equal(niv): obj = LocalFourPoint(mat, num_vn_dimensions=2) u = LocalInteraction(u_mat) result = obj.pad_with_u(u, niv) - assert np.allclose(result.mat, mat, rtol=1e-4) + assert np.allclose(result.mat, mat, atol=1e-4) assert result.mat.shape == mat.shape @@ -1145,7 +1145,7 @@ def test_pad_with_u_does_not_mutate_self(): u = LocalInteraction(np.random.rand(2, 2, 2, 2)) obj.pad_with_u(u, 8) assert obj.mat.shape == (2, 2, 2, 2, 5, 8, 8) - assert np.allclose(obj.mat, mat, rtol=1e-4) # source array left untouched + assert np.allclose(obj.mat, mat, atol=1e-4) # source array left untouched def test_symmetrize_orbitals_already_symmetrized(): diff --git a/tests/test_local_n_point.py b/tests/test_local_n_point.py index b1ea3a53..cf9b5f51 100644 --- a/tests/test_local_n_point.py +++ b/tests/test_local_n_point.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems import itertools @@ -245,15 +245,15 @@ def test_extends_correctly_with_one_fermionic_dimension(): result = obj.extend_vn_to_diagonal() assert result is obj assert result.mat.shape == (4, 4, 4, 4, 4) - assert np.allclose(result.mat[..., 0, 0], mat[..., 0], rtol=1e-2) - assert np.allclose(result.mat[..., 0, 1], 0, rtol=1e-2) - assert np.allclose(result.mat[..., 1, 0], 0, rtol=1e-2) - assert np.allclose(result.mat[..., 1, 1], mat[..., 1], rtol=1e-2) - assert np.allclose(result.mat[..., 2, 0], 0, rtol=1e-2) - assert np.allclose(result.mat[..., 0, 2], 0, rtol=1e-2) - assert np.allclose(result.mat[..., 2, 1], 0, rtol=1e-2) - assert np.allclose(result.mat[..., 1, 2], 0, rtol=1e-2) - assert np.allclose(result.mat[..., 2, 2], mat[..., 2], rtol=1e-2) + assert np.allclose(result.mat[..., 0, 0], mat[..., 0], atol=1e-2) + assert np.allclose(result.mat[..., 0, 1], 0, atol=1e-2) + assert np.allclose(result.mat[..., 1, 0], 0, atol=1e-2) + assert np.allclose(result.mat[..., 1, 1], mat[..., 1], atol=1e-2) + assert np.allclose(result.mat[..., 2, 0], 0, atol=1e-2) + assert np.allclose(result.mat[..., 0, 2], 0, atol=1e-2) + assert np.allclose(result.mat[..., 2, 1], 0, atol=1e-2) + assert np.allclose(result.mat[..., 1, 2], 0, atol=1e-2) + assert np.allclose(result.mat[..., 2, 2], mat[..., 2], atol=1e-2) def test_raises_error_when_taking_diagonal_with_no_fermionic_dimensions(): @@ -282,10 +282,10 @@ def test_compresses_correctly_with_two_fermionic_dimensions(): result = obj.take_vn_diagonal() assert result is obj assert result.mat.shape == (4, 4, 4, 4) - assert np.allclose(result.mat[..., 0], 1, rtol=1e-2) - assert np.allclose(result.mat[..., 1], 2, rtol=1e-2) - assert np.allclose(result.mat[..., 2], 3, rtol=1e-2) - assert np.allclose(result.mat[..., 3], 4, rtol=1e-2) + assert np.allclose(result.mat[..., 0], 1, atol=1e-2) + assert np.allclose(result.mat[..., 1], 2, atol=1e-2) + assert np.allclose(result.mat[..., 2], 3, atol=1e-2) + assert np.allclose(result.mat[..., 3], 4, atol=1e-2) def test_flips_matrix_along_valid_single_axis(): @@ -293,7 +293,7 @@ def test_flips_matrix_along_valid_single_axis(): mat = np.zeros((4, 4, 9, 10)) obj = LocalNPoint(mat, 2, 1, 1) result = obj.flip_frequency_axis(axis=(-1,)) - assert np.allclose(result.mat, np.flip(mat, axis=-1), rtol=1e-2) + assert np.allclose(result.mat, np.flip(mat, axis=-1), atol=1e-2) def test_flips_matrix_along_valid_multiple_axes(): @@ -301,7 +301,7 @@ def test_flips_matrix_along_valid_multiple_axes(): mat = np.zeros((4, 4, 9, 10)) obj = LocalNPoint(mat, 2, 1, 1) result = obj.flip_frequency_axis(axis=(-2, -1)) - assert np.allclose(result.mat, np.flip(mat, axis=(-2, -1)), rtol=1e-2) + assert np.allclose(result.mat, np.flip(mat, axis=(-2, -1)), atol=1e-2) def test_raises_error_when_flipping_with_no_frequency_dimensions(): @@ -328,7 +328,7 @@ def test_handles_single_axis_as_integer(): mat = np.zeros((4, 4, 9, 10)) obj = LocalNPoint(mat, 2, 1, 1) result = obj.flip_frequency_axis(axis=-1) - assert np.allclose(result.mat, np.flip(mat, axis=-1), rtol=1e-2) + assert np.allclose(result.mat, np.flip(mat, axis=-1), atol=1e-2) def test_aligns_frequency_dimensions_correctly_when_self_has_one_and_other_has_two_fermionic_dimensions(): @@ -401,7 +401,7 @@ def test_converts_to_half_bosonic_range_correctly(): result = obj.to_half_niw_range() assert result is obj assert result.mat.shape == (4, 4, 11, 20) - assert np.allclose(result.mat, np.take(mat, np.arange(10, 21), axis=-2), rtol=1e-2) + assert np.allclose(result.mat, np.take(mat, np.arange(10, 21), axis=-2), atol=1e-2) def test_returns_self_when_already_in_half_bosonic_range(): diff --git a/tests/test_local_sde.py b/tests/test_local_sde.py index ae1d3a1a..0902f27d 100644 --- a/tests/test_local_sde.py +++ b/tests/test_local_sde.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems import os diff --git a/tests/test_local_sde_end_to_end.py b/tests/test_local_sde_end_to_end.py index 1409d83e..c6ea67aa 100644 --- a/tests/test_local_sde_end_to_end.py +++ b/tests/test_local_sde_end_to_end.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems import logging @@ -195,7 +195,7 @@ def test_calculates_local_sde_correctly(setup, niw_core, niv_core, niv_shell): u_loc = config.lattice.hamiltonian.get_local_u() - (gamma_d, gamma_m, chi_d, chi_m, vrg_d, vrg_m, f_d, f_m, gchi_d, gchi_m, sigma_loc) = ( + gamma_d, gamma_m, chi_d, chi_m, vrg_d, vrg_m, f_d, f_m, gchi_d, gchi_m, sigma_loc = ( local_sde.perform_local_schwinger_dyson(g_dmft, g2_dens, g2_magn, u_loc) ) diff --git a/tests/test_local_two_point.py b/tests/test_local_two_point.py index 645e5ba8..1d4a5331 100644 --- a/tests/test_local_two_point.py +++ b/tests/test_local_two_point.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems """ Tests for the shared two-point base classes :class:`LocalTwoPoint` (momentum-independent) and :class:`TwoPoint` diff --git a/tests/test_max_ent.py b/tests/test_max_ent.py index cd00fba2..a9cd30ed 100644 --- a/tests/test_max_ent.py +++ b/tests/test_max_ent.py @@ -1,9 +1,10 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems +import warnings from types import SimpleNamespace from unittest.mock import MagicMock @@ -230,8 +231,8 @@ def fn(comm, rank): assert np.allclose(spectrum[k], spectrum[flat_rep[k]], atol=1e-6) -def test_perform_maxent_giwk_failed_continuation_yields_zeros(tmp_path, monkeypatch): - """perform_maxent_giwk yields zeros when the analytic continuation raises.""" +def test_perform_maxent_giwk_failed_continuation_logs_kpoint_and_yields_zeros(tmp_path, monkeypatch): + """perform_maxent_giwk logs a per-k-point error (not a stack trace) and yields zeros when continuation raises.""" nk, n_bands, w_count = (4, 4, 1), 2, 6 _setup_maxent_config(tmp_path, nk, n_bands, w_count=w_count, seed=4) mat = _build_giwk_mat(nk, n_bands, niv=4, seed=19) @@ -249,6 +250,66 @@ def fn(comm, rank): _, results = run_parallel(1, fn) assert np.array_equal(results[0], np.zeros_like(results[0])) + # one log per failed (irreducible k-point, band), each naming the k-point and the A=0 fallback + fail_msgs = [ + call.args[0] + for call in config.logger.info.call_args_list + if "Failed to determine analytic continuation of k=" in call.args[0] + ] + assert len(fail_msgs) == config.lattice.k_grid.nk_irr * n_bands + assert all("setting A(k=" in m and "= 0.0" in m for m in fail_msgs) + + +def test_perform_maxent_giwk_reroutes_solver_prints_to_logger(tmp_path, monkeypatch): + """The vendored solver's stdout is captured and re-logged as 'ana_cont: ', not leaked to stdout.""" + nk, n_bands = (4, 4, 1), 1 + _setup_maxent_config(tmp_path, nk, n_bands, seed=6) + mat = _build_giwk_mat(nk, n_bands, niv=4, seed=23) + + class _PrintingProblem: + def __init__(self, *args, **kwargs): + pass + + def solve(self, *args, **kwargs): + print("Fermi fit failed.") + return (SimpleNamespace(A_opt=np.zeros(config.ana_cont.w_count)),) + + monkeypatch.setattr(mpi_utils, "MPI", FAKE_MPI) + monkeypatch.setattr(max_ent, "AnalyticContinuationProblem", _PrintingProblem) + + def fn(comm, rank): + return max_ent.perform_maxent_giwk(GreensFunction(mat.copy(), nk=config.lattice.nk), "TEST", comm) + + run_parallel(1, fn) + info_msgs = [call.args[0] for call in config.logger.info.call_args_list] + assert "ana_cont: Fermi fit failed." in info_msgs + + +def test_perform_maxent_giwk_runtime_warning_is_treated_as_failure(tmp_path, monkeypatch): + """A numpy/scipy RuntimeWarning during the continuation is escalated to a failure: A(k, w) = 0.""" + nk, n_bands = (4, 4, 1), 1 + _setup_maxent_config(tmp_path, nk, n_bands, seed=8) + mat = _build_giwk_mat(nk, n_bands, niv=4, seed=29) + + class _WarningProblem: + def __init__(self, *args, **kwargs): + pass + + def solve(self, *args, **kwargs): + warnings.warn("overflow encountered", RuntimeWarning) + return (SimpleNamespace(A_opt=np.ones(config.ana_cont.w_count)),) + + monkeypatch.setattr(mpi_utils, "MPI", FAKE_MPI) + monkeypatch.setattr(max_ent, "AnalyticContinuationProblem", _WarningProblem) + + def fn(comm, rank): + return max_ent.perform_maxent_giwk(GreensFunction(mat.copy(), nk=config.lattice.nk), "TEST", comm) + + _, results = run_parallel(1, fn) + assert np.array_equal(results[0], np.zeros_like(results[0])) + fail_msgs = [c.args[0] for c in config.logger.info.call_args_list if "Failed to determine" in c.args[0]] + assert len(fail_msgs) == config.lattice.k_grid.nk_irr * n_bands + def test_perform_maxent_giwk_single_band(tmp_path, patch_maxent_mpi): """perform_maxent_giwk reduces to the orbital-diagonal continuation for a single band.""" diff --git a/tests/test_memory_estimator.py b/tests/test_memory_estimator.py index 023adf80..a0dc45bc 100644 --- a/tests/test_memory_estimator.py +++ b/tests/test_memory_estimator.py @@ -168,6 +168,17 @@ def test_baseline_is_giwk_plus_sigma_old_at_their_windows(): assert estimate_peaks(**tiny)[0] == pytest.approx(expected) +def test_giwk_baseline_bytes_is_the_deduplicable_half_of_the_baseline(): + """giwk_baseline_bytes is the giwk_full half of the baseline (giwk_full and sigma_old are equal-sized).""" + from dgamore.memory_estimator import giwk_baseline_bytes + + tiny = dict(BASE, n_bands=2, nk_tot=100, niw_core=5, niv_core=5, niv_full=7, niv_cut=22) + giwk = DTYPE_BYTES * OVERHEAD_FACTOR * (tiny["nk_tot"] * tiny["n_bands"] ** 2 * (2 * tiny["niv_cut"])) + got = giwk_baseline_bytes(tiny["nk_tot"], tiny["n_bands"], tiny["niv_cut"]) + assert got == pytest.approx(giwk) + assert got == pytest.approx(estimate_peaks(**tiny)[0] / 2) + + def test_baseline_depends_on_niv_cut_not_niv_full(): """The baseline tracks niv_cut and is independent of niv_full when niv_cut is fixed.""" assert _baseline(niv_full=40) == pytest.approx(_baseline(niv_full=400)) @@ -184,7 +195,15 @@ def test_chiq_aux_invert_factor_counts_construction_temporary(): def test_chiq_aux_off_block_is_two_rank_local_two_fermion_blocks(): """The chiq_aux off-distributed block equals two rank-local two-fermion blocks.""" p = dict( - n_bands=2, nk_tot=80, nk_irr=20, niw_core=4, niv_core=5, niv_full=6, niv_cut=15, niv_pp=2, n_ranks=4, + n_bands=2, + nk_tot=80, + nk_irr=20, + niw_core=4, + niv_core=5, + niv_full=6, + niv_cut=15, + niv_pp=2, + n_ranks=4, with_eliashberg=False, ) _, peaks = estimate_peaks(**p) @@ -240,7 +259,15 @@ def test_fq_cheap_construction_shrinks_per_q_block(): def test_chi0q_fast_single_counts_two_full_grid_buffers(): """The chi0q fast single-rank peak counts both the multiply buffer and the ifftn output.""" p = dict( - n_bands=2, nk_tot=80, nk_irr=20, niw_core=4, niv_core=5, niv_full=6, niv_cut=15, niv_pp=2, n_ranks=4, + n_bands=2, + nk_tot=80, + nk_irr=20, + niw_core=4, + niv_core=5, + niv_full=6, + niv_cut=15, + niv_pp=2, + n_ranks=4, with_eliashberg=False, ) _, peaks = estimate_peaks(**p) diff --git a/tests/test_mixing.py b/tests/test_mixing.py index 4c8b5664..2c3e7765 100644 --- a/tests/test_mixing.py +++ b/tests/test_mixing.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems from copy import deepcopy @@ -104,7 +104,7 @@ def test_linear_mixing_basic(): with patch_config(strategy="linear", mixing=0.5): result = apply_mixing_strategy(sigma_new, sigma_old, sigma_dmft, current_iter=1) - np.testing.assert_allclose(result.mat, 1.0, atol=1e-5) + assert np.allclose(result.mat, 1.0, atol=1e-5) def test_linear_mixing_alpha_zero(): @@ -116,7 +116,7 @@ def test_linear_mixing_alpha_zero(): with patch_config(strategy="linear", mixing=0.0): result = apply_mixing_strategy(sigma_new, sigma_old, sigma_dmft, current_iter=1) - np.testing.assert_allclose(result.mat, 1.0, atol=1e-5) + assert np.allclose(result.mat, 1.0, atol=1e-5) def test_linear_mixing_alpha_one(): @@ -128,7 +128,7 @@ def test_linear_mixing_alpha_one(): with patch_config(strategy="linear", mixing=1.0): result = apply_mixing_strategy(sigma_new, sigma_old, sigma_dmft, current_iter=1) - np.testing.assert_allclose(result.mat, 5.0, atol=1e-5) + assert np.allclose(result.mat, 5.0, atol=1e-5) def test_linear_mixing_complex(): @@ -140,7 +140,7 @@ def test_linear_mixing_complex(): with patch_config(strategy="linear", mixing=0.5): result = apply_mixing_strategy(sigma_new, sigma_old, sigma_dmft, current_iter=1) - np.testing.assert_allclose(result.mat, 1.0 + 1.0j, atol=1e-5) + assert np.allclose(result.mat, 1.0 + 1.0j, atol=1e-5) def test_linear_mixing_returns_self_energy_instance(): @@ -164,7 +164,7 @@ def test_pulay_falls_back_to_linear_when_iter_too_small(): with patch_config(strategy="pulay", mixing=0.5, n_hist=5): result = apply_mixing_strategy(sigma_new, sigma_old, sigma_dmft, current_iter=3) - np.testing.assert_allclose(result.mat, 1.0, atol=1e-5) + assert np.allclose(result.mat, 1.0, atol=1e-5) def test_pulay_returns_self_energy_instance(): @@ -190,7 +190,7 @@ def test_pulay_converged_fixed_point(): result = run_pulay(sigma_new, sigma_old, sigma_dmft, file_sigmas) niv_dmft = sigma_new.mat.shape[-1] // 2 - np.testing.assert_allclose( + assert np.allclose( result.mat[..., niv_dmft - NIV_CORE : niv_dmft + NIV_CORE], np.full_like(result.mat[..., niv_dmft - NIV_CORE : niv_dmft + NIV_CORE], value), atol=1e-4, @@ -219,7 +219,7 @@ def test_pulay_does_not_mutate_sigma_old(): original_mat = sigma_old.mat.copy() run_pulay(sigma_new, sigma_old, sigma_dmft, file_sigmas) - np.testing.assert_array_equal(sigma_old.mat, original_mat) + assert np.array_equal(sigma_old.mat, original_mat) def test_pulay_tails_come_from_sigma_new(): @@ -232,8 +232,8 @@ def test_pulay_tails_come_from_sigma_new(): result = run_pulay(sigma_new, sigma_old, sigma_dmft, file_sigmas) niv_dmft = sigma_new.mat.shape[-1] // 2 - np.testing.assert_allclose(result.mat[..., : niv_dmft - NIV_CORE], 2.0, atol=1e-5) - np.testing.assert_allclose(result.mat[..., niv_dmft + NIV_CORE :], 2.0, atol=1e-5) + assert np.allclose(result.mat[..., : niv_dmft - NIV_CORE], 2.0, atol=1e-5) + assert np.allclose(result.mat[..., niv_dmft + NIV_CORE :], 2.0, atol=1e-5) def test_pulay_result_shape_matches_sigma_new(): @@ -271,7 +271,7 @@ def test_anderson_falls_back_to_linear_when_iter_too_small(): with patch_config(strategy="anderson", mixing=0.5, n_hist=5): result = apply_mixing_strategy(sigma_new, sigma_old, sigma_dmft, current_iter=3) - np.testing.assert_allclose(result.mat, 1.0, atol=1e-5) + assert np.allclose(result.mat, 1.0, atol=1e-5) def test_anderson_returns_self_energy_instance(): @@ -297,7 +297,7 @@ def test_anderson_converged_fixed_point(): result = run_anderson(sigma_new, sigma_old, sigma_dmft, file_sigmas) niv_dmft = sigma_new.mat.shape[-1] // 2 - np.testing.assert_allclose( + assert np.allclose( result.mat[..., niv_dmft - NIV_CORE : niv_dmft + NIV_CORE], np.full_like(result.mat[..., niv_dmft - NIV_CORE : niv_dmft + NIV_CORE], value), atol=1e-4, @@ -326,7 +326,7 @@ def test_anderson_does_not_mutate_sigma_old(): original_mat = sigma_old.mat.copy() run_anderson(sigma_new, sigma_old, sigma_dmft, file_sigmas) - np.testing.assert_array_equal(sigma_old.mat, original_mat) + assert np.array_equal(sigma_old.mat, original_mat) def test_anderson_tails_come_from_sigma_new(): @@ -339,8 +339,8 @@ def test_anderson_tails_come_from_sigma_new(): result = run_anderson(sigma_new, sigma_old, sigma_dmft, file_sigmas) niv_dmft = sigma_new.mat.shape[-1] // 2 - np.testing.assert_allclose(result.mat[..., : niv_dmft - NIV_CORE], 2.0, atol=1e-5) - np.testing.assert_allclose(result.mat[..., niv_dmft + NIV_CORE :], 2.0, atol=1e-5) + assert np.allclose(result.mat[..., : niv_dmft - NIV_CORE], 2.0, atol=1e-5) + assert np.allclose(result.mat[..., niv_dmft + NIV_CORE :], 2.0, atol=1e-5) def test_anderson_result_shape_matches_sigma_new(): diff --git a/tests/test_mpi_utils.py b/tests/test_mpi_utils.py index 24193a97..0632c30d 100644 --- a/tests/test_mpi_utils.py +++ b/tests/test_mpi_utils.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems import os @@ -1175,3 +1175,97 @@ def test_isend_rows_rejects_non_contiguous(): arr = (np.arange(6 * 2).reshape(6, 2) + 1j).astype(np.complex128).T # F-contiguous view with pytest.raises(ValueError): mu._isend_rows(comm1(), arr, dest=0) + + +def test_build_node_shared_array_single_rank_returns_private_array(): + """A single-rank node short-circuits to a private array (no window) and still computes once.""" + calls = [] + + def fn(comm, rank): + node_comm = comm.Split_type(MPI.COMM_TYPE_SHARED) + + def compute(): + calls.append(rank) + return np.full((2, 3), 5.0, dtype=np.complex64) + + arr, win = mu.build_node_shared_array(node_comm, compute) + return np.array(arr), win + + _, res = run_parallel(1, fn) + assert calls == [0] + assert np.array_equal(res[0][0], np.full((2, 3), 5.0, dtype=np.complex64)) + assert res[0][1] is None + + +def test_build_node_shared_array_computes_once_and_shares_within_node(): + """On one node the root computes once and every rank maps the same populated buffer through a window.""" + calls = [] + + def fn(comm, rank): + node_comm = comm.Split_type(MPI.COMM_TYPE_SHARED) + + def compute(): + calls.append(rank) + return np.full((2, 3), 7.0, dtype=np.complex64) + + arr, win = mu.build_node_shared_array(node_comm, compute) + seen = np.array(arr) + node_comm.Barrier() + if win is not None: + win.Free() + node_comm.Free() + return seen, win is not None + + _, res = run_parallel(4, fn, hostnames=["h", "h", "h", "h"]) + assert calls == [0] + for seen, has_win in res: + assert has_win + assert np.array_equal(seen, np.full((2, 3), 7.0, dtype=np.complex64)) + + +def test_build_node_shared_array_isolates_between_nodes(): + """Two nodes each compute on their own root; ranks see only their own node's buffer.""" + calls = [] + + def fn(comm, rank): + node_comm = comm.Split_type(MPI.COMM_TYPE_SHARED) + + def compute(): + calls.append(rank) + return np.full((3,), float(rank + 1), dtype=np.complex64) + + arr, win = mu.build_node_shared_array(node_comm, compute) + seen = np.array(arr) + node_comm.Barrier() + if win is not None: + win.Free() + node_comm.Free() + return seen + + _, res = run_parallel(4, fn, hostnames=["n0", "n0", "n1", "n1"]) + assert sorted(calls) == [0, 2] # one compute per node root (global ranks 0 and 2) + assert np.array_equal(res[0], np.full((3,), 1.0, dtype=np.complex64)) + assert np.array_equal(res[1], np.full((3,), 1.0, dtype=np.complex64)) + assert np.array_equal(res[2], np.full((3,), 3.0, dtype=np.complex64)) + assert np.array_equal(res[3], np.full((3,), 3.0, dtype=np.complex64)) + + +def test_build_node_shared_array_view_is_live_shared_memory(): + """A write by the root after construction is visible to the other node ranks (a true shared view).""" + + def fn(comm, rank): + node_comm = comm.Split_type(MPI.COMM_TYPE_SHARED) + arr, win = mu.build_node_shared_array(node_comm, lambda: np.zeros((4,), dtype=np.complex64)) + if node_comm.Get_rank() == 0: + arr[:] = np.arange(4) # mutate the shared buffer after it was built + node_comm.Barrier() + seen = np.array(arr) + node_comm.Barrier() + if win is not None: + win.Free() + node_comm.Free() + return seen + + _, res = run_parallel(2, fn, hostnames=["h", "h"]) + for seen in res: + assert np.array_equal(seen, np.arange(4).astype(np.complex64)) diff --git a/tests/test_n_point_base.py b/tests/test_n_point_base.py index 7b689d71..47196fa2 100644 --- a/tests/test_n_point_base.py +++ b/tests/test_n_point_base.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems import os @@ -828,6 +828,7 @@ def test_skip_on_non_posix_or_no_proc(monkeypatch): def test_loads_libc_and_calls_malloc_trim(monkeypatch): """malloc_trim loads libc and calls malloc_trim when available.""" + # simulate posix with /proc and a working ctypes.CDLL returning a libc with malloc_trim class FakeLib: def __init__(self): @@ -855,6 +856,7 @@ def malloc_trim(self, arg): def test_ctypes_cdll_failure_sets_unavailable(monkeypatch): """A ctypes CDLL failure marks malloc_trim unavailable.""" + # simulate posix with /proc but CDLL raises -> should mark unavailable and not raise def failing_cdll(name): raise OSError("no libc") @@ -874,6 +876,7 @@ def failing_cdll(name): def test_malloc_trim_exception_is_suppressed(monkeypatch): """An exception from malloc_trim is suppressed.""" + # simulate libc present but malloc_trim itself raises -> should be suppressed (no exception) class BadLib: def malloc_trim(self, arg): @@ -1316,7 +1319,7 @@ def test_map_to_full_bz_auto_2idx_reconstructs_H_exactly(): def test_map_to_full_bz_auto_2idx_reconstructs_H_for_multiorbital_case(): - """Same as above but with multiple orbitals — exercises the orbital einsum path.""" + """Same as above but with multiple orbitals - exercises the orbital einsum path.""" grid, H = _build_auto_kgrid(nx=4, ny=4, nz=4, nb=2) nb = 2 H_flat = H.reshape(-1, nb, nb) @@ -1483,7 +1486,7 @@ def test_map_to_full_bz_auto_1x1x1_trivial_grid_is_identity(): def test_map_to_full_bz_auto_preserves_dtype(): - """The output matrix has the same dtype as the input (the function does not silently cast within the auto branch — the cast to complex64 happens elsewhere in ``IHaveMat.mat = value``).""" + """The output matrix has the same dtype as the input (the function does not silently cast within the auto branch - the cast to complex64 happens elsewhere in ``IHaveMat.mat = value``).""" grid, H = _build_auto_kgrid(nx=4, ny=4, nz=4, nb=1) H_ibz_64 = H.reshape(-1, 1, 1)[grid.irrk_ind].astype(np.complex64).copy() obj = _DoublePrecisionNonLocal(mat=H_ibz_64, nq=(4, 4, 4), has_compressed_q_dimension=True) diff --git a/tests/test_nonlocal_sde.py b/tests/test_nonlocal_sde.py index 8eeaecdb..77ee0875 100644 --- a/tests/test_nonlocal_sde.py +++ b/tests/test_nonlocal_sde.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems import itertools @@ -12,11 +12,22 @@ import dgamore.config as config import dgamore.nonlocal_sde as nonlocal_sde +from dgamore.greens_function import GreensFunction from dgamore.hamiltonian import Hamiltonian from dgamore.interaction import Interaction from dgamore.local_sde import get_local_hartree_fock from dgamore.n_point_base import SpinChannel -from dgamore.nonlocal_sde import _init_mu_history, get_hartree_fock, perform_ornstein_zernike_fit +from dgamore.nonlocal_sde import ( + _build_giwk_full, + _cut_and_reshare_giwk, + _free_shared_window, + _init_mu_history, + _release_shared_giwk, + get_hartree_fock, + perform_ornstein_zernike_fit, +) +from dgamore.self_energy import SelfEnergy +from tests.conftest import create_comm_mock LOCAL_SDE_DATA = f"{os.path.dirname(os.path.abspath(__file__))}/test_data/local_sde" @@ -91,6 +102,10 @@ def __init__(self, mat: np.ndarray): """Stores the orbital-resolved matrix that the reduction chain returns unchanged.""" self._mat = mat + def copy(self): + """Identity copy; the reduction chain is non-mutating so a fresh wrapper suffices.""" + return _ConstantChi(self._mat) + def map_to_full_bz(self, grid): """Identity unfolding to the full BZ.""" return self @@ -134,3 +149,79 @@ def test_ornstein_zernike_fit_logs_no_warning_when_all_converge(monkeypatch): perform_ornstein_zernike_fit(_ConstantChi(np.ones((2, 2, 1, 2, 2, 2, 2), dtype=np.complex64))) logger.warning.assert_not_called() + + +def _tiny_sigma_and_ek(nb=1, niv=4): + """Builds a minimal single-k self-energy and dispersion for the Dyson build.""" + sigma = SelfEnergy(np.zeros((1, 1, 1, nb, nb, 2 * niv), dtype=np.complex64), calc_smom=False, beta=10.0) + ek = np.zeros((1, 1, 1, nb, nb), dtype=np.complex64) + return sigma, ek + + +def test_build_giwk_full_disabled_matches_direct_dyson_and_skips_split(): + """With node-sharing off, _build_giwk_full is the plain Dyson build and never touches the communicator.""" + config.memory.use_shared_memory_giwk = False + sigma, ek = _tiny_sigma_and_ek() + comm = create_comm_mock() + + giwk, win, node_comm = _build_giwk_full(comm, sigma, 0.3, ek, 10.0) + + assert win is None and node_comm is None + assert comm.Split_type.called is False + assert np.allclose(giwk.mat, GreensFunction.get_g_full(sigma, 0.3, ek, 10.0).mat, atol=1e-6) + + +def test_build_giwk_full_shared_single_rank_matches_direct_dyson(): + """With node-sharing on but a single-rank node, the giwk is bit-parity with the direct Dyson build (no window).""" + config.memory.use_shared_memory_giwk = True + sigma, ek = _tiny_sigma_and_ek() + comm = create_comm_mock() + + giwk, win, node_comm = _build_giwk_full(comm, sigma, 0.3, ek, 10.0) + + assert win is None # a single-rank node needs no shared window + assert np.array_equal(giwk.mat, GreensFunction.get_g_full(sigma, 0.3, ek, 10.0).mat) + _release_shared_giwk(win, node_comm) # must not raise on the single-rank / mock path + + +def test_release_shared_giwk_without_sharing_is_noop(): + """Releasing a non-shared giwk (both handles None) is a safe no-op.""" + _release_shared_giwk(None, None) + + +def test_release_shared_giwk_frees_window_and_communicator(): + """With a window allocated, _release barriers (so no rank still reads), frees the window, then the node comm.""" + win, node_comm = mock.Mock(), mock.Mock() + _release_shared_giwk(win, node_comm) + node_comm.Barrier.assert_called_once() + win.Free.assert_called_once() + node_comm.Free.assert_called_once() + + +def test_free_shared_window_frees_window_but_keeps_communicator(): + """_free_shared_window barriers and frees the window but leaves the node communicator alive (reused for the cut).""" + win, node_comm = mock.Mock(), mock.Mock() + _free_shared_window(win, node_comm) + node_comm.Barrier.assert_called_once() + win.Free.assert_called_once() + node_comm.Free.assert_not_called() + + +def test_cut_and_reshare_giwk_without_sharing_is_a_plain_cut(): + """Without a node communicator, _cut_and_reshare_giwk is a plain per-rank cut and allocates no window.""" + sigma, ek = _tiny_sigma_and_ek(niv=8) + giwk = GreensFunction.get_g_full(sigma, 0.3, ek, 10.0) + cut, win = _cut_and_reshare_giwk(giwk, None, None, 4) + assert win is None + assert cut.niv == 4 + assert np.array_equal(cut.mat, GreensFunction.get_g_full(sigma, 0.3, ek, 10.0).cut_niv(4).mat) + + +def test_cut_and_reshare_giwk_shared_single_rank_matches_plain_cut(): + """With a single-rank node communicator the cut giwk matches the plain cut and needs no window.""" + sigma, ek = _tiny_sigma_and_ek(niv=8) + giwk = GreensFunction.get_g_full(sigma, 0.3, ek, 10.0) + cut, win = _cut_and_reshare_giwk(giwk, None, create_comm_mock(), 4) + assert win is None + assert cut.niv == 4 + assert np.array_equal(cut.mat, GreensFunction.get_g_full(sigma, 0.3, ek, 10.0).cut_niv(4).mat) diff --git a/tests/test_nonlocal_sde_end_to_end.py b/tests/test_nonlocal_sde_end_to_end.py index 328dfb0d..c65b6e96 100644 --- a/tests/test_nonlocal_sde_end_to_end.py +++ b/tests/test_nonlocal_sde_end_to_end.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems import contextlib diff --git a/tests/test_self_energy.py b/tests/test_self_energy.py index ee332023..96055833 100644 --- a/tests/test_self_energy.py +++ b/tests/test_self_energy.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems from unittest.mock import MagicMock @@ -82,8 +82,8 @@ def test_fits_smom_algorithm_correctly_with_dummy_data(has_compressed_q_dimensio ) self_energy.mat = dummy_data # Assign dummy data to the matrix smom0, smom1 = self_energy.fit_smom() - assert np.allclose(smom0, dummy_smom0, rtol=1e-2) - assert np.allclose(smom1, dummy_smom1, rtol=1e-2) + assert np.allclose(smom0, dummy_smom0, atol=1e-2) + assert np.allclose(smom1, dummy_smom1, atol=1e-2) def test_fits_smom_correctly_with_edge_case_data(): @@ -125,7 +125,7 @@ def test_returns_correct_asymptotic_self_energy(custom_niv, n_min): ] asympt = self_energy._get_asympt(niv=niv, n_min=n_min) - assert np.allclose(asympt.mat, asympt_expected, rtol=1e-2) + assert np.allclose(asympt.mat, asympt_expected, atol=1e-2) def test_asympt_returns_self_energy_unchanged_when_core_equals_niv(): @@ -248,7 +248,7 @@ def test_interpolate_returns_same_values_when_beta_and_grid_are_unchanged(): result = self_energy.interpolate(beta_target=beta, niv_target=self_energy.niv) assert result.mat.shape == self_energy.mat.shape - assert np.allclose(result.mat, self_energy.mat, rtol=1e-6, atol=1e-6) + assert np.allclose(result.mat, self_energy.mat, atol=1e-6) def test_interpolate_reproduces_linear_frequency_dependence_on_a_new_grid(): @@ -270,7 +270,7 @@ def test_interpolate_reproduces_linear_frequency_dependence_on_a_new_grid(): expected = np.broadcast_to(expected_signal, result.mat.shape).copy() assert result.mat.shape == expected.shape - assert np.allclose(result.mat, expected, rtol=1e-4, atol=1e-4) + assert np.allclose(result.mat, expected, atol=1e-4) def _build_linear_self_energy(niv_value: int, beta_value: float, has_compressed_q_dimension: bool) -> SelfEnergy: @@ -362,7 +362,7 @@ def test_fits_polynomial_coefficients_correctly_with_default_parameters(): mat = np.full(mat.shape, f_vn + 1j * f_vn) # Dummy data for testing self_energy = _se(mat, nk=nk, has_compressed_q_dimension=False) result = self_energy.fit_polynomial(n_fit=25, degree=2) - assert np.allclose(result.mat[0, 0, 0], f_vn + 1j * f_vn, rtol=1e-2, atol=1e6) + assert np.allclose(result.mat[0, 0, 0], f_vn + 1j * f_vn, atol=1e6) def test_create_with_asympt_up_to_core_does_not_mutate_self(): diff --git a/tests/test_symmetrize.py b/tests/test_symmetrize.py index 5547b29e..cf4b7964 100644 --- a/tests/test_symmetrize.py +++ b/tests/test_symmetrize.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems import pytest diff --git a/tests/test_symmetry_reduction.py b/tests/test_symmetry_reduction.py index d1d1e204..a26c0418 100644 --- a/tests/test_symmetry_reduction.py +++ b/tests/test_symmetry_reduction.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025-2026 Julian Peil # SPDX-License-Identifier: MIT # -# DGAmore — Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & +# DGAmore - Multi-Orbital Ladder Dynamical Vertex Approximation (LDGA) & # Eliashberg Equation Solver for Strongly Correlated Electron Systems import builtins @@ -852,7 +852,7 @@ def test_auto_discovery_finds_smaller_group_for_anisotropic_lattice(): @pytest.mark.slow def test_auto_discovery_matches_legacy_for_12cubed_cubic_hamiltonian(): - """Auto-discovered IBZ partition must match the legacy three_dimensional_cubic partition for a genuinely cubic 3-band Hamiltonian. (12^3 — slower.)""" + """Auto-discovered IBZ partition must match the legacy three_dimensional_cubic partition for a genuinely cubic 3-band Hamiltonian. (12^3 - slower.)""" import dgamore.brillouin_zone as bz fname, shape = "hk_3band_srvo3_cubic_12x12x12.npy", (12, 12, 12, 3, 3) @@ -870,7 +870,7 @@ def test_auto_discovery_matches_legacy_for_12cubed_cubic_hamiltonian(): @pytest.mark.slow def test_auto_discovery_matches_legacy_for_20cubed_cubic_hamiltonian(): - """Same as above for the 20^3 grid. (Even slower — covers the larger-grid path.)""" + """Same as above for the 20^3 grid. (Even slower - covers the larger-grid path.)""" import dgamore.brillouin_zone as bz fname, shape = "hk_3band_srvo3_cubic_20x20x20.npy", (20, 20, 20, 3, 3) @@ -1016,7 +1016,7 @@ def test_get_symmetry_reduction_default_excludes_antiunitary_ops(): """The default behaviour must drop anti-unitary operations; therefore no FBZ point should carry conj=True. This is the safe semantics for frequency- dependent quantities.""" H = _make_real_cubic_h(4, 4, 4, 1) result = sr.get_symmetry_reduction(H, atol=1e-8) - assert result["conjs"].any() == False # noqa: E712 — explicit bool check + assert result["conjs"].any() == False # noqa: E712 - explicit bool check def test_get_symmetry_reduction_include_antiunitary_admits_conj_ops(): @@ -1035,7 +1035,7 @@ def test_get_symmetry_reduction_include_antiunitary_shrinks_or_equals_ibz(): def test_get_symmetry_reduction_include_antiunitary_reconstructs_H_correctly(): - """When anti-unitary ops are included, reconstruction of H itself is still correct (anti-unitary ops are valid symmetries of H — only frequency-dependent objects are affected by the missing freq flip).""" + """When anti-unitary ops are included, reconstruction of H itself is still correct (anti-unitary ops are valid symmetries of H - only frequency-dependent objects are affected by the missing freq flip).""" H = _make_real_cubic_h(4, 4, 4, 1) result = sr.get_symmetry_reduction(H, atol=1e-8, include_antiunitary=True) H_ibz = H.reshape(-1, 1, 1)[result["irrk_ind"]] @@ -1063,7 +1063,7 @@ def test_get_symmetry_reduction_default_yields_no_conjugation_in_expansion(): """Concrete consequence of default ``include_antiunitary=False``: applying ``expand`` to any IBZ payload does NOT conjugate orbital indices anywhere. We verify this by feeding a complex payload built so that conjugation would be detectable (the conjugate differs from the original).""" H = _make_real_cubic_h(4, 4, 4, 1) result = sr.get_symmetry_reduction(H, atol=1e-8) - # Reconstruct H itself — well-defined and exact + # Reconstruct H itself - well-defined and exact H_ibz = H.reshape(-1, 1, 1)[result["irrk_ind"]] H_rec = result["expand"](H_ibz) assert np.allclose(H_rec, H, atol=1e-12) @@ -1203,9 +1203,7 @@ def boom(*a, **k): raise np.linalg.LinAlgError("forced") monkeypatch.setattr(sr.np.linalg, "svd", boom) - out = sr._fix_gauge_degenerate( - np.eye(2, dtype=complex), np.eye(2, dtype=complex), [[0, 1]], Hk, Hg, atol=1e-12 - ) + out = sr._fix_gauge_degenerate(np.eye(2, dtype=complex), np.eye(2, dtype=complex), [[0, 1]], Hk, Hg, atol=1e-12) assert out is None @@ -1227,9 +1225,7 @@ def flaky_svd(a, *args, **kwargs): raise np.linalg.LinAlgError("forced on block") monkeypatch.setattr(sr.np.linalg, "svd", flaky_svd) - out = sr._fix_gauge_degenerate( - np.eye(2, dtype=complex), np.eye(2, dtype=complex), [[0, 1]], Hk, Hg, atol=1e-12 - ) + out = sr._fix_gauge_degenerate(np.eye(2, dtype=complex), np.eye(2, dtype=complex), [[0, 1]], Hk, Hg, atol=1e-12) assert out is None assert state["n"] >= 2 @@ -1332,9 +1328,7 @@ def test_group_element_with_near_zero_U_skips_phase_normalization(): def _rot2(theta): - return np.array( - [[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]], dtype=np.complex128 - ) + return np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]], dtype=np.complex128) def test_apply_auto_orbital_transform_four_orbital_nonidentity_einsum(): @@ -1380,4 +1374,4 @@ def test_apply_auto_orbital_transform_reuses_cached_path_four_dim(): u = us[i] uc = u.conj() exp = np.einsum("ap,bq,cr,ds,pqrs->abcd", u, uc, u, uc, mat[i]) - assert np.allclose(out[i], exp) \ No newline at end of file + assert np.allclose(out[i], exp)