Source code for firecrown.models.cluster.integrator.numcosmo_integrator
"""The NumCosmo integrator module.
This module holds the NumCosmo implementation of the integrator classes
"""
from enum import Enum
from typing import Callable, Optional
import numpy as np
import numpy.typing as npt
from numcosmo_py import Ncm
from firecrown.models.cluster.integrator.integrator import Integrator
[docs]class NumCosmoIntegralMethod(Enum):
"""The available NumCosmo integration methods."""
P = Ncm.IntegralNDMethod.P
P_V = Ncm.IntegralNDMethod.P_V
H = Ncm.IntegralNDMethod.H
H_V = Ncm.IntegralNDMethod.H_V
[docs]class NumCosmoIntegrator(Integrator):
"""The NumCosmo implementation of the Integrator base class."""
def __init__(
self,
method: Optional[NumCosmoIntegralMethod] = None,
relative_tolerance: float = 1e-4,
absolute_tolerance: float = 1e-12,
) -> None:
super().__init__()
self.method = method or NumCosmoIntegralMethod.P_V
self._relative_tolerance = relative_tolerance
self._absolute_tolerance = absolute_tolerance
[docs] def integrate(
self,
func_to_integrate: Callable[
[npt.NDArray[np.float64], npt.NDArray[np.float64]], npt.NDArray[np.float64]
],
) -> float:
"""Integrate the provided integrand argument with NumCosmo."""
Ncm.cfg_init()
int_nd = CountsIntegralND(
len(self.integral_bounds), func_to_integrate, self.extra_args
)
int_nd.set_method(self.method.value)
int_nd.set_reltol(self._relative_tolerance)
int_nd.set_abstol(self._absolute_tolerance)
res = Ncm.Vector.new(1)
err = Ncm.Vector.new(1)
bl, bu = zip(*self.integral_bounds)
int_nd.eval(Ncm.Vector.new_array(bl), Ncm.Vector.new_array(bu), res, err)
return res.get(0)
[docs]class CountsIntegralND(Ncm.IntegralND):
"""Integral subclass used to compute the integrals using NumCosmo."""
def __init__(
self,
dim: int,
fun: Callable[
[npt.NDArray[np.float64], npt.NDArray[np.float64]], npt.NDArray[np.float64]
],
args: npt.NDArray[np.float64],
) -> None:
super().__init__()
self.dim = dim
self.fun = fun
self.extra_args = args
# pylint: disable-next=arguments-differ
[docs] def do_get_dimensions(self) -> tuple[int, int]:
"""Returns the dimensionality of the integral."""
return self.dim, 1
# pylint: disable-next=arguments-differ
[docs] def do_integrand(
self,
x_vec: Ncm.Vector,
dim: int,
npoints: int,
_fdim: int,
fval_vec: Ncm.Vector,
) -> None:
"""Called by NumCosmo to evaluate the integrand."""
x = np.array(x_vec.dup_array()).reshape(npoints, dim)
fval_vec.set_array(list(self.fun(x, self.extra_args)))