Choosing optimal k-points is a tricky task. In GPAW, one can set them manually, using size or density and following a rule of thumb:

```
calc = GPAW(kpts={'size': (4, 4, 4), 'gamma': True})
# or
calc = GPAW(kpts={'density': 2.5, 'gamma': True})
```

A rule of thumb for choosing the initial

k-point sampling is, that the product,ka, between the number ofk-points,k, in any direction, and the length of the basis vector in this direction,a, should be:

ka~ 30 Å, fordband metalska~ 25 Å, for simple metalska~ 20 Å, for semiconductorska~ 15 Å, for insulatorsRemember that convergence in this parameter should always be checked.

https://wiki.fysik.dtu.dk/gpaw/tutorialsexercises/structureoptimization/surface/surface.html

The corresponding densities (*ka*/2π) are:

*ka*/2π ~ 4.8 Å, for*d*band metals*ka*/2π ~ 4.0 Å, for simple metals*ka*/2π ~ 3.2 Å, for semiconductors*ka*/2π ~ 2.4 Å, for insulators

With the recent update, I can start using kplib (see paper) to choose the optimal generalized k-point grids. The main variable in kplib is min_distance, which is analogous to the density×2π. Read more about the min_distance at muellergroup.jhu.edu/K-Points.html.

Here is an example of my conda environment

```
conda create -n gpaw23 python=3.9
conda activate gpaw23
conda install -c conda-forge cxx-compiler
pip install kplib # from pypi.org/project/kpLib
conda install -c conda-forge gpaw
```

Here is a working example:

```
from ase import Atoms
from ase.parallel import parprint
from gpaw import GPAW, PW
from kpLib import get_kpoints
from pymatgen.io.ase import AseAtomsAdaptor
atoms = Atoms(cell=[[1.608145, -2.785389, 0.0], [1.608145, 2.785389, 0.0], [0.0, 0.0, 5.239962]],
symbols=['Ga', 'Ga', 'N', 'N'],
positions=[[ 1.608145 , -0.92846486, 2.61536983],
[ 1.608145 , 0.92846486, 5.23535083],
[ 1.608145 , -0.92846486, 4.58957792],
[ 1.608145 , 0.92846486, 1.96959692]],
pbc=True)
structure = AseAtomsAdaptor.get_structure(atoms)
kpts_data = get_kpoints(structure, minDistance=30, include_gamma=False)
parprint("Found lattice with kplib: ")
parprint(f"Nominal kpts: {kpts_data['num_total_kpts']}")
parprint(f"Distinct kpts: {kpts_data['num_distinct_kpts']}")
atoms.calc = GPAW(xc='PBE',
mode=PW(400),
kpts=kpts_data['coords'],
symmetry={'point_group': True,
'time_reversal': True,
'symmorphic': False,
'tolerance': 1e-4},
txt='gpaw-out.txt')
energy = atoms.get_total_energy()
parprint(f"Total energy: {energy}")
parprint(f"kpts passed to GPAW: {len(atoms.calc.get_bz_k_points())}")
parprint(f"kpts in GPAW IBZ: {len(atoms.calc.get_ibz_k_points())}")
```