Source code for netket.hilbert.particle

# Copyright 2021 The NetKet Authors - All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from typing import Optional, Union
import numpy as np
from .continuous_hilbert import ContinuousHilbert


[docs] class Particle(ContinuousHilbert): r"""Hilbert space derived from ContinuousHilbert defining N particles in continuous space with or without periodic boundary conditions."""
[docs] def __init__( self, N: Union[int, tuple[int, ...]], L: Optional[tuple[float, ...]] = None, pbc: Optional[Union[bool, tuple[bool, ...]]] = None, *, D: Optional[int] = None, ): """ Constructs new ``Particles`` given specifications of the continuous space they are defined in. Args: N: Number of particles. If int all have the same spin. If Tuple the entry indicates how many particles there are with a certain spin-projection. L: Tuple indicating the maximum of the continuous quantum number(s) in the configurations. Each entry in the tuple corresponds to a different physical dimension. If `np.inf` is used an infinite box is considered and `pbc=False` is mandatory (because what are PBC if there are no boundaries?). If a finite value is given, a minimum value of zero is assumed for the quantum number(s). A particle in a 3D box of size L would take `(L,L,L)`. A rotor model would take e.g. `(2pi,)`. pbc: Tuple or bool indicating whether to use periodic boundary conditions in a given physical dimension. If tuple it must have the same length as domain. If bool the same value is used for all the dimensions defined in domain. D: (Optional) Number of dimensions. Can be specified instead of `L` and `pbc` in order to construct a `Particle` in a $D-$ dimensional infinite box. Equivalent to `Particle(N, L=(np.inf,) * D, pbc=False)`. """ if D is None and L is None: raise ValueError("Must specify at least `L` or `D`.") elif D is not None: if L is not None: raise TypeError( "Cannot specify at the same time `D` and `L`. If you want to use " "an infinite box, just specify D, otherwise specify L." ) L = (np.inf,) * D # Assume 1D if L is a scalar if not hasattr(L, "__len__"): L = (L,) if not hasattr(N, "__len__"): N = (N,) if pbc is None: if np.all(np.isinf(L)): pbc = False else: raise ValueError("`pbc` must be specified if `L` is finite.") if isinstance(pbc, bool): pbc = [pbc] * len(L) if np.any(np.logical_and(np.isinf(L), pbc)): raise ValueError( "Cannot combine periodic boundary conditions and infinite size along the same dimension." ) self._N = sum(N) self._n_per_spin = N super().__init__(L, pbc)
@property def size(self) -> int: return self._N * len(self._extent) @property def n_particles(self) -> int: r"""The number of particles""" return self._N @property def n_per_spin(self) -> tuple[int, ...]: r"""Gives the number of particles in a specific spin projection. The length of this tuple indicates the total spin whereas the position in the tuple indicates the spin projection. Example: (10,5,3) describes 18 particles of total spin 1 where 10 of those have spin-projection -1, 5 have spin-projection 0 and 3 have spin-projection 1. """ return self._n_per_spin @property def _attrs(self): return (self._N, self.extent, self.pbc) def __repr__(self): return f"ContinuousParticle(N={self.n_particles}, " f"d={len(self.extent)})"