Polarization task in database doesn't play well with pymatgen's get_total_ionic_dipole

Hello,

I’ve been running ferroelectric polarization workflows, and some of them have given incorrect results. The issue is that the calculations aren’t being fit correctly to the polarization branch. I’m still trying to narrow down exactly what the problem is, but the problem is in the calculation of ionic polarization, and here’s what I know so far.

Obtaining ionic polarization directly from [‘calcs_reversed’][0][‘output’][‘outcar’][‘p_ion’] in my database works, this value can be used to create a correct pymatgen Polarization object, which matches well with my manual branch fitting in Excel. (That is, it mostly works, the non-polar calculation isn’t fit correctly)

However, taking the database’s [‘calcs_reversed’][0][‘output’][‘outcar’] and [‘calcs_reversed’][0][‘output’][‘outcar’][‘zval_dict’] and feeding them to pymatgen’s get_total_ionic_dipole method gives very different ionic dipoles. This leads to a bad branch fitting which is nothing like the one I get fitting by hand.

Is there a problem in pymatgen’s get_total_ionic_dipole? I don’t think so, because all the different ways of creating a Polarization object seem to work when I create pymatgen Outcars and Structures directly from my local OUTCARS and POSCARS. It works when I feed my Outcars’ and Structures’ p_ion and p_elect directly to Polarization’s default init(), or when I feed my Outcars and Structures to get_total_ionic_dipole() and put that into the default init(), or when I feed the Outcars and Structures to Polarization.from_outcars_and_structures().

Things only break down when I go through the Atomate database first. It just looks like uploading an OUTCAR or POSCAR to the database changes it in some way which is no longer compatible with get_total_ionic_dipole. I’ll update this thread if I figure out why this happens.

Attached are gzipped OUTCARS and POSCARS, the POTCAR is (La, N, O, Sn_d). Also, the script ‘pymat_polar.py’ which calculates polarization using local files and Pymatgen, while the script ‘fetch_atomate.py’ shows how I am pulling things directly from the database to test. Obviously fetch_atomate.py can’t be run by someone without access to my database, but I can provide the relevant Atomate database files if someone wants to try them.

Thanks

atomate_polar.tar.gz (574 KB)

The problem was traced to a rare bug in Pymatgen’s OUTCAR parser - other people’s results are unlikely to be affected unless the POSCAR had a title line (1st line of the file) with the elements in the wrong order. The Pymatgen method is now updated so that it doesn’t depend on the title line, which has no meaning in VASP. Pseudo_zval bugfix by sthartman · Pull Request #1521 · materialsproject/pymatgen · GitHub

···

On Friday, June 14, 2019 at 7:02:12 PM UTC-5, Steven Hartman wrote:

Hello,

I’ve been running ferroelectric polarization workflows, and some of them have given incorrect results. The issue is that the calculations aren’t being fit correctly to the polarization branch. I’m still trying to narrow down exactly what the problem is, but the problem is in the calculation of ionic polarization, and here’s what I know so far.

Obtaining ionic polarization directly from [‘calcs_reversed’][0][‘output’][‘outcar’][‘p_ion’] in my database works, this value can be used to create a correct pymatgen Polarization object, which matches well with my manual branch fitting in Excel. (That is, it mostly works, the non-polar calculation isn’t fit correctly)

However, taking the database’s [‘calcs_reversed’][0][‘output’][‘outcar’] and [‘calcs_reversed’][0][‘output’][‘outcar’][‘zval_dict’] and feeding them to pymatgen’s get_total_ionic_dipole method gives very different ionic dipoles. This leads to a bad branch fitting which is nothing like the one I get fitting by hand.

Is there a problem in pymatgen’s get_total_ionic_dipole? I don’t think so, because all the different ways of creating a Polarization object seem to work when I create pymatgen Outcars and Structures directly from my local OUTCARS and POSCARS. It works when I feed my Outcars’ and Structures’ p_ion and p_elect directly to Polarization’s default init(), or when I feed my Outcars and Structures to get_total_ionic_dipole() and put that into the default init(), or when I feed the Outcars and Structures to Polarization.from_outcars_and_structures().

Things only break down when I go through the Atomate database first. It just looks like uploading an OUTCAR or POSCAR to the database changes it in some way which is no longer compatible with get_total_ionic_dipole. I’ll update this thread if I figure out why this happens.

Attached are gzipped OUTCARS and POSCARS, the POTCAR is (La, N, O, Sn_d). Also, the script ‘pymat_polar.py’ which calculates polarization using local files and Pymatgen, while the script ‘fetch_atomate.py’ shows how I am pulling things directly from the database to test. Obviously fetch_atomate.py can’t be run by someone without access to my database, but I can provide the relevant Atomate database files if someone wants to try them.

Thanks