import math


def _chunk_size(len_grid, len_protein, n_cores, optimize_to=2147483648):
    """
    Calculates the number of probes per chunk.

    To split the calculation in several cores (processors), the grid of probes
    is divided in chunks. This method takes into account the memory and the
    number of cores to find a good balanced size for the chunks.

    Parameters
    ----------
    len_grid : int
        Number of probes of the grid
    len_protein : int
        Number of amino acids of the protein
    n_cores : int
        Number of cores that will be used in the calculation
    optimize_to : int, optional
        Maximum memory (in bytes) that will be used in the calculation. Defaults
        to 2GB

    Returns
    -------
    int
        Number of probes per chunk

    Notes
    -----
    The maximum memory employed by the calculation could in fact be higher than
    the requested in the `optimize_to`. Before starting the actual biometall
    calculation, there is a process to load in memory the .pdb, so if that .pdb
    is bigger than `optimize_to`, the maximum memory employed will be the size
    of the .pdb instead of the size of the chunks.
    """
    number_of_chunks = math.ceil((56 * len_grid * len_protein * n_cores)/optimize_to)
    if number_of_chunks < n_cores:
        return int(len_grid/n_cores) + 1
    else:
        return int(len_grid/number_of_chunks) + 1