Source code for deepqmc.loss.energy

from functools import partial

import jax

from ..hamil import MolecularHamiltonian
from ..parallel import all_device_mean
from ..types import (
    Energy,
    KeyArray,
    ParametrizedWaveFunction,
    Params,
    PhysicalConfiguration,
    Stats,
    Weight,
)
from ..utils import batched_vmap, masked_mean


[docs] def compute_local_energy( rng: KeyArray, hamil: MolecularHamiltonian, ansatz: ParametrizedWaveFunction, params: Params, phys_conf: PhysicalConfiguration, batch_size: int | None = None, ) -> tuple[Energy, Stats]: r"""Compute a batch of local energies. Args: rng (~deepqmc.types.KeyArray): rng key to use for the generation of the ECP quadratures. hamil (~deepqmc.hamil.MolecularHamiltonian): the Hamiltonian of the system. ansatz (~deepqmc.types.ParametrizedWaveFunction): the parametrized wave function. params (~deepqmc.types.Params): the current parameters of the Ansatz. phys_conf (~deepqmc.types.PhysicalConfiguration): a batch of input to the Ansatz. Returns: Tuple[~deepqmc.types.Energy, ~deepqmc.types.Stats]: a tuple of local energy and statistics. """ rng = jax.random.split(rng, phys_conf.batch_shape) electron_axis_mapper = ( jax.vmap if batch_size is None else partial(batched_vmap, batch_size=batch_size // jax.device_count()) ) local_energy, hamil_stats = jax.vmap( # molecule_batch jax.vmap( # electronic_state electron_axis_mapper( hamil.local_energy(ansatz), in_axes=(0, None, 0) ) # electron_batch ), (0, None, 0), )(rng, params, phys_conf) stats = jax.tree.map(lambda x: x.mean(axis=-1), hamil_stats) return local_energy, stats
[docs] def compute_mean_energy(local_energy: Energy, weight: Weight) -> tuple[Energy, Stats]: r"""Compute the mean of a batch of local energies. Args: local_energy (~deepqmc.types.Energy): the batch of local energies. weight (~deepqmc.types.Weight): the weight of each sample in the batch. Returns: Tuple[~deepqmc.types.Energy, ~deepqmc.types.Stats]: a tuple of mean energy and statistics. """ return all_device_mean(local_energy * weight), {}
[docs] def compute_mean_energy_tangent( local_energy: Energy, weight: Weight, log_psi_tangent: jax.Array, gradient_mask: jax.Array, ) -> jax.Array: r"""Compute the tangent of the mean energy with respect to the Ansatz parameters. Args: local_energy (~deepqmc.types.Energy): a batch of local energies. weight (~deepqmc.types.Weight): the weights of each sample in the batch. log_psi_tangent (~jax.Array): the jvp of the WF values with respect to the Ansatz parameters. gradient_mask (~jax.Array): a boolean samplewise mask to apply to the gradients. Returns: ~jax.Array: the jvp of the mean energy with respect to the Ansatz parameters. """ per_mol_state_mean_energy = all_device_mean( local_energy * weight, axis=-1, keepdims=True ) local_energy_tangent = ( (local_energy - per_mol_state_mean_energy) * log_psi_tangent * weight ) mean_energy_tangent = masked_mean(local_energy_tangent, gradient_mask) return mean_energy_tangent