Skip to content

Commit

Permalink
Merge pull request #348 from libAtoms/err_calc_stress_virial_voigt
Browse files Browse the repository at this point in the history
Convert virial/stress to Voigt-6 when computing error table
  • Loading branch information
bernstei authored Dec 4, 2024
2 parents 5b08766 + 19f30be commit c1f3bad
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 10 deletions.
36 changes: 30 additions & 6 deletions .github/workflows/pytests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [ "3.9" ]
python-version: [ "3.10" ]
max-parallel: 5
env:
coverage-on-version: "3.9"
coverage-on-version: "3.10"
use-mpi: True
PIP_CONSTRAINT: pip_constraint.txt
defaults:
Expand All @@ -42,13 +42,15 @@ jobs:
run: |
echo "numpy<2" >> $PIP_CONSTRAINT
python3 -m pip install wheel setuptools numpy scipy click matplotlib pyyaml spglib rdkit==2024.3.3 flake8 pytest pytest-cov requests
python3 -c "import numpy; print('numpy version', numpy.__version__)"
- name: Install latest ASE from pypi
run: |
echo PIP_CONSTRAINT $PIP_CONSTRAINT
python3 -m pip install ase
echo -n "ASE VERSION "
python3 -c "import ase; print(ase.__file__, ase.__version__)"
python3 -c "import numpy; print('numpy version', numpy.__version__)"
- name: Install intel-oneapi-mkl for phono3py
run: |
Expand All @@ -61,6 +63,7 @@ jobs:
sudo apt update
sudo apt install intel-oneapi-mkl
sudo apt install intel-oneapi-mkl-devel
python3 -c "import numpy; print('numpy version', numpy.__version__)"
- name: Install phono3py from source
run: |
Expand Down Expand Up @@ -90,16 +93,22 @@ jobs:
cd phono3py
python3 -m pip install -e . -vvv
cd ..
python3 -c "import numpy; print('numpy version', numpy.__version__)"
- name: Install Quippy from PyPI
run: python3 -m pip install quippy-ase
run: |
python3 -m pip install quippy-ase
python3 -c "import numpy; print('numpy version', numpy.__version__)"
- name: Install xTB (before things that need pandas like MACE and wfl, since it will break pandas-numpy compatibility by downgrading numpy)
run: |
# force compatible numpy version
conda install 'numpy<2'
conda install -c conda-forge xtb-python
python3 -m pip install typing-extensions
# install pandas now to encourage compatible numpy version after conda regressed it
python3 -m pip install pandas
python3 -c "import numpy; print('numpy version', numpy.__version__)"
- name: MACE
run: |
Expand Down Expand Up @@ -136,9 +145,11 @@ jobs:
fi
echo "found torch version ${torch_version}+cpu, installing"
python3 -m pip install torch==${torch_version}+cpu -f https://download.pytorch.org/whl/torch_stable.html
python3 -c "import numpy; print('numpy version', numpy.__version__)"
echo "installing mace"
python3 -m pip install git+https://github.com/ACEsuit/mace.git@main
python3 -c "import mace; print(mace.__file__)"
python3 -c "import mace; print('mace file', mace.__file__)"
python3 -c "import numpy; print('numpy version', numpy.__version__)"
- name: Julia and ace fit
run: |
Expand All @@ -148,19 +159,24 @@ jobs:
# note that this hardwires a particular compatible ACE1pack version
echo 'using Pkg; pkg"registry add https://github.com/JuliaRegistries/General"; pkg"registry add https://github.com/JuliaMolSim/MolSim.git"; pkg"add [email protected], ACE1, JuLIP, IPFitting, ASE"' > ace1pack_install.jl
${PWD}/julia-1.8.1/bin/julia ace1pack_install.jl
python3 -c "import numpy; print('numpy version', numpy.__version__)"
- name: Install wfl (expyre and universalSOAP are dependencies)
run: python3 -m pip install .
run: |
python3 -m pip install .
python3 -c "import numpy; print('numpy version', numpy.__version__)"
- name: Install Quantum Espresso
run: |
sudo apt-get install --no-install-recommends quantum-espresso
python3 -c "import numpy; print('numpy version', numpy.__version__)"
- name: Install MOPAC
run: |
wget http://openmopac.net/mopac-22.1.1-linux.tar.gz
wget https://github.com/openmopac/mopac/releases/download/v22.1.1/mopac-22.1.1-linux.tar.gz
tar -xzvf mopac-22.1.1-linux.tar.gz
echo $GITHUB_WORKSPACE/mopac-22.1.1-linux/bin >> $GITHUB_PATH
python3 -c "import numpy; print('numpy version', numpy.__version__)"
- name: Install buildcell
run: |
Expand All @@ -172,6 +188,7 @@ jobs:
mkdir -p $HOME/bin
cp src/buildcell/src/buildcell $HOME/bin/
cd ..
python3 -c "import numpy; print('numpy version', numpy.__version__)"
- name: Add buildcell to system path
run: |
Expand All @@ -183,6 +200,7 @@ jobs:
# this can eaily be turned off if needed
conda install -c conda-forge mpi4py openmpi pytest-mpi
python3 -m pip install mpipool
python3 -c "import numpy; print('numpy version', numpy.__version__)"
- name: Install and configure slurm and ExPyRe
run: |
Expand All @@ -206,6 +224,7 @@ jobs:
sinfo -s --long
mkdir $HOME/.expyre
cp .github/workflows_assets/config.json $HOME/.expyre
python3 -c "import numpy; print('numpy version', numpy.__version__)"
- name: Set up pw.x for running in wfl
run: |
Expand All @@ -221,6 +240,7 @@ jobs:
echo 'post-espresso $HOME/.config/ase/config.ini'
cat $HOME/.config/ase/config.ini
python3 -c "import numpy; print('numpy version', numpy.__version__)"
- name: Lint with flake8
run: |
Expand All @@ -234,6 +254,8 @@ jobs:
run: |
rm -rf $HOME/pytest_plain
mkdir $HOME/pytest_plain
# attempt to work around mkl/numpy issue
export MKL_THREADING_LAYER=GNU
#
export EXPYRE_PYTEST_SYSTEMS=github
export WFL_PYTEST_BUILDCELL=$HOME/bin/buildcell
Expand All @@ -247,6 +269,8 @@ jobs:
run: |
rm -rf $HOME/pytest_cov
mkdir $HOME/pytest_cov
# attempt to work around mkl/numpy issue
export MKL_THREADING_LAYER=GNU
#
export EXPYRE_PYTEST_SYSTEMS=github
export WFL_PYTEST_BUILDCELL=$HOME/bin/buildcell
Expand Down
12 changes: 12 additions & 0 deletions tests/test_error.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import pytest
from ase.atoms import Atoms
from ase.calculators.lj import LennardJones
from ase.stress import voigt_6_to_full_3x3_stress
from pytest import approx

from pprint import pprint
Expand Down Expand Up @@ -103,6 +104,17 @@ def test_err_from_calc(ref_atoms):
assert ref_err_dict['virial/atom/comp']['_ALL_']["count"] == 10 * 6


def test_err_stress_shape(ref_atoms):
ref_atoms_calc = generic_calc(ref_atoms, OutputSpec(), LennardJones(sigma=0.75), output_prefix='calc_')
ref_err_dict, _, _ = ref_err_calc(ref_atoms_calc, ref_property_prefix='REF_', calc_property_prefix='calc_')

for at in ref_atoms_calc:
at.info["REF_stress"] = voigt_6_to_full_3x3_stress(at.info["REF_stress"])
ref_err_dict_shape, _, _ = ref_err_calc(ref_atoms_calc, ref_property_prefix='REF_', calc_property_prefix='calc_')

assert ref_err_dict == ref_err_dict_shape


def test_error_properties(ref_atoms):
ref_atoms_calc = generic_calc(ref_atoms, OutputSpec(), LennardJones(sigma=0.75), output_prefix='calc_')
# both energy and per atom
Expand Down
2 changes: 1 addition & 1 deletion tests/test_md.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ def test_md_attach_logger(cu_slab, tmp_path, monkeypatch):
workdir = Path(os.getcwd())

assert len(atoms_traj) == 602
assert all([Path(workdir / "test_log.item_0").is_file(), Path(workdir / "test_log.item_1").is_file()])
assert all([Path(workdir / "test_log.config_0").is_file(), Path(workdir / "test_log.config_1").is_file()])


def test_md_attach_logger_stdout(cu_slab, tmp_path, monkeypatch, capsys):
Expand Down
23 changes: 21 additions & 2 deletions wfl/fit/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from matplotlib.figure import Figure
from matplotlib.pyplot import get_cmap

from ase.stress import full_3x3_to_voigt_6_stress


def calc(inputs, calc_property_prefix, ref_property_prefix,
config_properties=None, atom_properties=None, category_keys="config_type",
Expand Down Expand Up @@ -83,8 +85,21 @@ def _reshape_normalize(quant, prop, atoms, per_atom):
quant: 2-d array containing reshaped quantity, with leading dimension 1 for per-config
or len(atoms) for per-atom
"""
# convert scalars or lists into arrays
quant = np.asarray(quant)

# fix shape of stress/virial
if prop.startswith("stress") or prop.startswith("virial"):
if prop.split("/")[0] in ["stress", "virial"]:
if quant.shape != (6,):
if quant.shape not in [(9,), (3,3)]:
raise ValueError(f"Prop '{prop}' has unknown shape of quant {quant.shape}")
quant = full_3x3_to_voigt_6_stress(quant.reshape((3, 3)))
elif prop.split("/")[0] in ["stresses", "virials"]:
eff_quant_shape = quant.shape[1:]
if eff_quant_shape != (6,):
if eff_quant_shape not in [(9,), (3,3)]:
raise ValueError(f"Prop '{prop}' has unknown shape of quant {quant.shape}")
quant = [full_3x3_to_voigt_6_stress(q.reshape((3, 3))) for q in quant]
quant = np.asarray(quant)

# Reshape to 2-d, with leading dimension 1 for per-config, and len(atoms) for per-atom.
# This is the right shape to work with later flattening for per-property and norm calculation
Expand Down Expand Up @@ -150,6 +165,10 @@ def _reshape_normalize(quant, prop, atoms, per_atom):

continue

# make a copy so normalization doesn't affect original
ref_quant = np.asarray(ref_quant).copy()
calc_quant = np.asarray(calc_quant).copy()

if virial_from_stress:
# ref quant was actually stress, automatically convert
ref_quant *= -at.get_volume()
Expand Down
2 changes: 1 addition & 1 deletion wfl/fit/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import shlex
import warnings

from ase.constraints import voigt_6_to_full_3x3_stress
from ase.stress import voigt_6_to_full_3x3_stress

from wfl.utils.julia import julia_exec_path

Expand Down

0 comments on commit c1f3bad

Please sign in to comment.