Kppvol, kppa, reciprocal_density and pra

Hi,

I got confused about kppvol, kppa and reciprocal_density, which are used in pymatgen.
kppvol is an input argument of the below automatic_density_by_vol

 def automatic_density_by_vol(structure, kppvol, force_gamma=False):
    """
    Returns an automatic Kpoint object based on a structure and a kpoint
    density per inverse Angstrom^3 of reciprocal cell.

    Algorithm:
        Same as automatic_density()

    Args:
        structure (Structure): Input structure
        kppvol (int): Grid density per Angstrom^(-3) of reciprocal cell
        force_gamma (bool): Force a gamma centered mesh

    Returns:
        Kpoints
    """
    vol = structure.lattice.reciprocal_lattice.volume
    kppa = kppvol * vol * structure.num_sites
    return Kpoints.automatic_density(structure, kppa, force_gamma=force_gamma)

kppa is the input arguement of automatic_density

def automatic_density(structure, kppa, force_gamma=False):
“”"
Returns an automatic Kpoint object based on a structure and a kpoint
density. Uses Gamma centered meshes for hexagonal cells and
Monkhorst-Pack grids otherwise.
Algorithm:
Uses a simple approach scaling the number of divisions along each
reciprocal lattice vector proportional to its length.
Args:
structure (Structure): Input structure
kppa (int): Grid density
force_gamma (bool): Force a gamma centered mesh (default is to
use gamma only for hexagonal cells or odd meshes)

    Returns:
        Kpoints
    """
    comment = "pymatgen v%s with grid density = %.0f / number of atoms" % (__version__, kppa)
    if math.fabs((math.floor(kppa ** (1 / 3) + 0.5)) ** 3 - kppa) < 1:
        kppa += kppa * 0.01

    latt = structure.lattice
    lengths = latt.abc
    ngrid = kppa / structure.num_sites
    mult = (ngrid * lengths[0] * lengths[1] * lengths[2]) ** (1 / 3)

    num_div = [int(math.floor(max(mult / l, 1))) for l in lengths]

    is_hexagonal = latt.is_hexagonal()

    has_odd = any([i % 2 == 1 for i in num_div])
    if has_odd or is_hexagonal or force_gamma:
        style = Kpoints.supported_modes.Gamma
    else:
        style = Kpoints.supported_modes.Monkhorst

    return Kpoints(comment, 0, style, [num_div], [0, 0, 0])

reciprocal_density is the input argument of MPStaticSet. In the documentation, it is explained as follows:

reciprocal_density (int): For static calculations, we usually set the reciprocal density by volume. This is a convenience arg to change that, rather than using user_kpoints_settings. Defaults to 100, which is ~50% more than that of standard relaxation calculations.

I have read the document and definition many times, but still have a few questoins as below. Appreciate it if you can help me out with them!
Question 1: In automatic_density_by_vol, kppa = kppvol * vol * structure.num_sites, where the number of atoms is multiplied. But why is kppa still per atom as shown in variable comment in atuomatic_density: comment = 'pymatgen v%s with grid density=%.0f/atom' % (__version__, kppa)? variable comment says that kppa is grid density. In the document of automatic_density_by_vol, However, kppvol is explained as Grid density per Angstrom^(-2) of reciprocal cell. So should it be kppa=kppvol * vol instead?

Question 2: in automatic_density, variable ngrid is introduced: ngrid=kppa / structure.num_sites. Should it be ngrid=kppa*struture.num_sites to cancel the unit of per atom?

Question 3: In the official document of Materials Project, it is documented that total energies are calculated using a k-point mesh of 1000 per reciprocal atom (pra). Does it mean the variable reciprocal_density of MPStaticSet equals 1000?

Question 4: Is the variable reciprocal_density of MPStaticSet exactly the variable kppvol of automatic_density_by_vol?

Thanks very much for your help!
Merry Christmas!

Best regards,
Yang Tong