Implementing periodic boundary conditions with kim-api (kimpy)

Hi, I am trying to build my own atomistic simulator using kimpy. To begin with, I have been able to compute the quantities such as partial energy and partial forces using kimpy. However, I have done this only for a finite set of atoms. Now, I wish to extend my simulator for an infinite set of atoms, i.e., with periodic boundary conditions. For this, as I understand, my neighbour list function will have to be modified to check for neighbours in the neighbouring boxes.

My questions are:

  1. What should my neighbour list data structure look like? Keeping in mind that it shouldn’t just have the neighbours that are inside the simulation box but also the ones that are outside in the neighbouring boxes. Also, it must be compatible with kim-api.

  2. How are the quantities such as energy and forces computed by kim-api in the presence of periodic boundary conditions?

Is there anything else that I need to take care of? I will be grateful for any advice.

Thanks

Hi,

kimpy currently allows two types of neighbor list.

The first one is shipped together with kimpy. It is implemented in C++ and has a Python wrapper. An example usage is in the ASE KIM calculator.

The second approach allows you to use python objects. As you said, the data structure of the neighbor list object and the get_neigh function should conform to some predefined pattern to be compatible with the kim api. See this for an example, where the ASE raw neighbor list is wrapped as a neighbor list for kim.

In both cases, compute_args.set_callback registers the neighbor list object and get_neigh function; that’s where the data structure is checked.

The way PBCs are dealt with in kim-api is the same as in LAMMPS. Briefly, the atoms within the box are called contributing atoms, and their periodic images (called non-contributing atoms) outside the box needs to be provided by a simulator to satisfy the PBCs (for example, created via the create_padding function from the kimpy neighbor list). The total energy will be the sum of the energies of contributing atoms, and the force on an atom (either contributing or non-contributing) will be the negative derivative of this total energy w.r.t. the coords of the atom.

Note, the forces are partial forces, and the forces on non-contributing atoms need to be added back to their corresponding contributing atoms to get the total force on atoms in the box. See this kim-api doc page for more information.

1 Like

Hi Dr. Wen,

I have a follow-up query on this.

As written in the kim-api documentation partialEnergy is the sum of partialParticleEnergies of the contributing atoms (partialParticle Energy of the non contributing atoms is taken to be zero).

Is this true for any potential? I have noticed that it isn’t. Consider the following two cases:

  1. Case 1: When LJ potential is used, I find this to be true. So when i sum the partialParticleEnergy for only the contributing atoms, as expected, it comes out to be equal to partialEnergy (that i get from KIM).
  2. Case 2: However, when Tersoff potential is used, I get non-zero partialParticleEnergy for non-contributing atoms. So when i sum the partialParticleEnergy of only the contributing atoms, the sum doesn’t come out to be equal to the partialEnergy. It should have according to the kim-api doc. Surprisingly, when I sum the partialParticleEnergy of all atoms (contributing and non-contributing), the sum comes out to be equal to the partialEnergy.

Could you clarify why this may be happening? Or am I missing something here?

Thanks