Commit 49b3b1cd authored by Paul Erhart's avatar Paul Erhart

Update CI script

parent f659ce05
image: registry.gitlab.com/materials-modeling/hiphive:latest
image: registry.gitlab.com/materials-modeling/hiphive/ci:latest
before_script:
- INSTDIR=$PWD/opt/lib/python
- export PYTHONPATH=$INSTDIR:$PYTHONPATH
build_linux:
stage: build
tags:
- linux
script:
- INSTDIR=$PWD/opt/lib/python
- mkdir -p $INSTDIR
- export PYTHONPATH=$INSTDIR:$PYTHONPATH
- python3 ./setup.py install --home=$PWD/opt
artifacts:
expire_in: 14 days
paths:
- opt/
expire_in: 14 days
run_tests:
basic_tests:
stage: test
dependencies:
- build_linux
tags:
- linux
dependencies:
- build_linux
script:
- export PATH=${PATH}:${HOME}/.local/bin
# Python path used throughout
- INSTDIR=$PWD/opt/lib/python
- export PYTHONPATH=$INSTDIR:$PYTHONPATH
# run tests via coverage
- xdoctest hiphive
- coverage run tests/main.py
- coverage report -m --omit=hiphive/calculators/numba_calc.py
# generate html version of detailed coverage report
- coverage html --omit=hiphive/calculators/numba_calc.py
coverage: '/TOTAL.+ ([0-9]{1,3}%)/'
artifacts:
expire_in: 14 days
paths:
- htmlcov
expire_in: 14 days
test_benchmarks_tutorial:
test_examples:
stage: test
only:
- schedules
......@@ -47,16 +46,14 @@ test_benchmarks_tutorial:
dependencies:
- build_linux
script:
- export PATH=${PATH}:${HOME}/.local/bin
- INSTDIR=$PWD/opt/lib/python
- export PYTHONPATH=$INSTDIR:$PYTHONPATH
- pwd=`pwd`
- |
for dir in `find examples/ -name '*.py' | xargs dirname | sort -uk1 | grep -v compare_fcs_phono3py` ; do
for dir in $(find examples/ -name '*.py' | xargs dirname | sort -uk1 | grep -v compare_fcs_phono3py) ; do
echo "dir= $dir"
cd $pwd
cd $dir
for file in `ls *.py | sort -gk1` ; do
for file in $(ls *.py | sort -gk1) ; do
echo "Running $file -- `date`"
python3 $file
echo "Finished running $file -- `date`"
......@@ -65,20 +62,35 @@ test_benchmarks_tutorial:
done
run_flake8:
style_check:
stage: test
tags:
- linux
script:
- export PATH=${PATH}:${HOME}/.local/bin
- flake8 doc/ examples/ hiphive/ tests/
test_documentation:
stage: test
dependencies:
- build_linux
script:
- mkdir public
- sphinx-build -b doctest -W doc/source/ public/
- sphinx-build -W doc/source/ public/
except:
- master
artifacts:
expire_in: 1 days
paths:
- public
pages:
stage: deploy
dependencies:
- build_linux
- run_tests
- basic_tests
script:
# prepare homepage
- mkdir -p public/dev
......@@ -94,7 +106,7 @@ pages:
# code coverage report
- cp -dr htmlcov/ public/coverage/
# build user guide
- sphinx-build doc/source/ public/
- sphinx-build -W doc/source/ public/
# make tests and examples downloadable
- cd examples
- find tutorial/ -print | zip ../public/tutorial.zip [email protected]
......@@ -111,7 +123,7 @@ pages:
# build user guide
- sed -i "s/version = ''/version = '$tag'/" doc/source/conf.py
- cat doc/source/conf.py
- sphinx-build doc/source/ public/dev/
- sphinx-build -W doc/source/ public/dev/
# make tests and examples downloadable
- cd examples
- find tutorial/ -print | zip ../public/dev/tutorial.zip [email protected]
......
# Base image
FROM python:3.5
FROM python:3.6
# Base packages
RUN \
......@@ -8,46 +8,53 @@ RUN \
apt-get install -qy graphviz zip
# Set up Python3 packages via pip
RUN pip3 install --upgrade \
pip \
setuptools
RUN \
pip3 install --upgrade \
pip \
setuptools
# Install entrypoints "manually" to ensure a sufficiently recent version is
# available for flake8 since the version from python3-dev/pip is too old.
RUN pip3 install --upgrade --user \
entrypoints
RUN pip3 install --upgrade \
coverage \
flake8
RUN \
pip3 install --upgrade \
entrypoints \
&& \
pip3 install --upgrade \
coverage \
flake8 \
xdoctest
# Packages needed for hiphive
RUN pip3 install --upgrade \
h5py \
numba \
numpy \
sympy
RUN pip3 install --upgrade \
ase \
scikit-learn \
scipy \
spglib
RUN \
pip3 install --upgrade \
h5py \
numba \
numpy \
sympy \
&& \
pip3 install --upgrade \
ase \
scikit-learn \
scipy \
spglib
# Packages for building documentation
RUN pip3 install --upgrade \
sphinx_autodoc_typehints \
sphinx-rtd-theme \
sphinx_sitemap \
sphinxcontrib-bibtex \
cloud_sptheme
RUN \
pip3 install --upgrade \
sphinx_autodoc_typehints \
sphinx-rtd-theme \
sphinx_sitemap \
sphinxcontrib-bibtex \
cloud_sptheme
# Packages needed for phono3py compilation
RUN apt-get install -qy liblapack-dev liblapacke-dev libopenblas-dev
# Packages for running examples
RUN pip3 install --upgrade \
pandas \
phonopy==1.13.2 \
phono3py==1.13.3.27
RUN \
pip3 install --upgrade \
pandas \
phonopy==1.13.2 \
phono3py==1.13.3.27
CMD /bin/bash
......@@ -37,18 +37,18 @@ Optimization and machine learning
<https://scikit-learn.org/stable/modules/linear_model.html#automatic-relevance-determination-ard>`_
[PedVarGra11]_
Compressive sensing
compressive sensing
`Compressive sensing (CS)
<https://en.wikipedia.org/wiki/Compressed_sensing>`_, also known as
compressive sampling, is an efficient method for constructing sparse
solutions for linear systems.
CV
Cross validation
cross validation
`Cross validation (CV)
<https://en.wikipedia.org/wiki/Cross-validation_(statistics)>`_
is commonly employed to evaluated the transferability and accuracy of
linear problems.
is commonly employed to evaluated the transferability and accuracy of
linear problems.
LASSO
The `least absolute shrinkage and selection operator (LASSO)
......@@ -56,13 +56,13 @@ Optimization and machine learning
performing variable selection and regularization in problems in
statistics and machine learning.
Kernel ridge regression
kernel ridge regression
`Kernel ridge regression (KRR) <http://scikit-
learn.org/stable/modules/kernel_ridge.html>`_ combines `ridge
regression <https://en.wikipedia.org/wiki/Tikhonov_regularization>`_
with the `kernel trick <https://en.wikipedia.org/wiki/Kernel_method>`_.
Regularization
regularization
`Regularization
<https://en.wikipedia.org/wiki/Regularization_(mathematics)>`_,
is commonly used in machine learning to combat overfitting and
......@@ -86,29 +86,29 @@ Crystal symmetry and clusters
=============================
.. glossary::
Crystal symmetry operation
crystal symmetry operation
A crystal symmetry operation for a specific lattice means that the
lattice is invariant under this operation. An operation comprises
translational and rotational components.
Cluster
cluster
A cluster is defined as a set of points on a lattice.
Cluster size
cluster size
The size of a cluster (commonly refered to as the cluster radius) is
defined as the average distance to the geometrical center of the cluster.
Cluster space
cluster space
The set of clusters into which a structure can be decomposed.
Cutoff
cutoff
Cutoffs define the longest allowed distance between two atoms in a
cluster for each order.
Orbit
orbit
An orbit is defined as a set of symmetry equivalent clusters
Orientation family
orientation family
An orientation family is a subgroup to an orbit, which contains those
clusters that are oriented identically in the lattice.
......@@ -117,13 +117,13 @@ Force constants
===============
.. glossary::
Irreducible parameters
irreducible parameters
Many elements of the force constant matrices are related to each other
by symmetry operations. The irreducible set up of parameters is
obtained by applying all symmetry operations allowed by the space group
of the ideal lattice and the sum rules.
Sum rules
sum rules
In order for a force constant potential to fulfill translational
invariance certain constraints are imposed on the force constants.
These constraints are commonly referred to as sum rules.
......@@ -66,12 +66,12 @@ class ClusterSpace:
third order terms up to a distance of 4 A.
>>> from ase.build import bulk
>>> from hiphive import ClusterSpace
>>> prim = bulk('W')
>>> cs = ClusterSpace(prim, [5.0, 4.0])
"""
# TODO: This class probably need some more documentation and a reference to
# the thesis
# TODO: This class probably needs some more documentation
# TODO: Fix doc for n-body cutoff
def __init__(self, prototype_structure, cutoffs, config=None,
......
......@@ -47,12 +47,13 @@ def relate_structures(reference, target, symprec=1e-5):
The rotation and translation in Cartesian coordinates will map the
reference structure onto the target
Aligning reference with target can be achieved via the transformations
>>> R, T = relate_structures(atoms_ref, atoms_target)
>>> atoms_ref_rotated = rotate_atoms(atoms_ref, R)
>>> atoms_ref_rotated.translate(T)
>>> atoms_ref_rotated.wrap()
>>> atoms_ref_rotated == atoms_target
Aligning reference with target can be achieved via the transformations::
R, T = relate_structures(atoms_ref, atoms_target)
atoms_ref_rotated = rotate_atoms(atoms_ref, R)
atoms_ref_rotated.translate(T)
atoms_ref_rotated.wrap()
atoms_ref_rotated == atoms_target
Parameters
----------
......
......@@ -4,8 +4,14 @@ constant information of a super cell object.
"""
import math
import pickle
from typing import IO, Tuple, Union
import numpy as np
from ase import Atoms
from scipy.sparse import coo_matrix, vstack
from .cluster_space import ClusterSpace
from .core.atoms import Atom, atom_to_spos, spos_to_atom
from .core.structure_alignment import align_supercell
......@@ -13,11 +19,10 @@ from .core.orbits import Orbit, OrientationFamily
from .core.tensors import (rotation_to_cart_coord,
rotate_tensor_precalc, rotation_tensor_as_matrix)
from .core.utilities import Progress, BiMap
from .force_constants import SortedForceConstants
from .force_constants import ForceConstants, SortedForceConstants
from .input_output.logging_tools import logger
from .calculators.numba_calc import (clusters_force_contribution,
cluster_force_contribution)
from scipy.sparse import coo_matrix, vstack
logger = logger.getChild('fcm')
......@@ -30,12 +35,12 @@ class ForceConstantModel:
Parameters
----------
atoms : ase.Atoms
atoms
configuration to which the cluster space is to be applied
cs : ClusterSpace
cs
a cluster space compatible with the structure of the atoms
"""
def __init__(self, atoms, cs):
def __init__(self, atoms: Atoms, cs: ClusterSpace):
self.atoms = atoms.copy()
self.orbits = []
......@@ -44,7 +49,7 @@ class ForceConstantModel:
self._populate_orbits(atoms)
# TODO: refactor
def _populate_orbits(self, atoms):
def _populate_orbits(self, atoms: Atoms):
"""Map the orbits from the underlying force constant potential onto the
supercell structure associated with this force constant model.
......@@ -169,12 +174,12 @@ class ForceConstantModel:
if isinstance(cs, ClusterSpace):
self._parameters = np.zeros(self.cs.n_dofs)
def get_force_constants(self):
def get_force_constants(self) -> SortedForceConstants:
"""Returns the force constants of the super cell.
Returns
-------
force constants : ForceConstants
force constants
complete set of force constants
"""
......@@ -190,12 +195,12 @@ class ForceConstantModel:
return SortedForceConstants(fc_dict, self.atoms)
@property
def parameters(self):
def parameters(self) -> np.ndarray:
""" list(float): parameters """
return self._parameters
@parameters.setter
def parameters(self, parameters):
def parameters(self, parameters: np.ndarray) -> None:
self._parameters = parameters
mapped_parameters = self.cs._map_parameters(parameters)
p = 0
......@@ -217,14 +222,14 @@ class ForceConstantModel:
of.force_constant += et * a
p += len(orb.eigentensors)
def get_forces(self, displacements):
def get_forces(self, displacements: np.ndarray) -> np.ndarray:
""" Returns the forces in the system given displacements.
The parameters of the model must be set to get any result.
Parameters
----------
displacements : numpy.ndarray
displacements
displacements of each atom in the supercell (`N, 3` array)
"""
F = np.zeros(displacements.shape)
......@@ -248,14 +253,14 @@ class ForceConstantModel:
cluster, f, F)
return F
def get_fit_matrix(self, displacements):
def get_fit_matrix(self, displacements: np.ndarray) -> np.ndarray:
""" Returns the matrix used to fit the parameters.
Represents the linear relation between the parameters and the forces.
Parameters
----------
displacements : numpy.ndarrya
displacements
displacements of each atom in the supercell (`(N, 3)` array)
"""
......@@ -288,7 +293,7 @@ class ForceConstantModel:
bar.close()
return M
def get_fcs_sensing(self, fcs):
def get_fcs_sensing(self, fcs: ForceConstants) -> Tuple[np.ndarray, np.ndarray]:
""" Creates a fit matrix from force constants directly.
If the underlying cluster space can completely span the force constants
......@@ -297,21 +302,18 @@ class ForceConstantModel:
naively incorporate only one force constant per orbit into the sensing
matrix.
The parameters can be extracted using e.g. least squares from numpy
The parameters can be extracted using e.g. least squares from numpy::
>>> parameters = np.linalg.lstsq(*fcm.get_fcs_sensing(fcs))[0]
parameters = np.linalg.lstsq(*fcm.get_fcs_sensing(fcs))[0]
Parameters
----------
fcs: ForceConstants
Must be compatible with the ideal structure of the model
fcs
force constants that are compatible with the ideal structure of the model
Returns
-------
M : np.array
The sensing matrix
F : np.array
The flattened, irreducible force constants
a tuple comprising the sensing matrix and the flattened, irreducible force constants
"""
M, F = [], []
et_index = 0
......@@ -335,18 +337,17 @@ class ForceConstantModel:
return M, F
@staticmethod
def read(f):
def read(f: Union[str, IO]):
"""Reads a force constant model from file.
Parameters
----------
f : str or file object
name of input file (str) or stream to load from (file object)
f
name of input file (`str`) or stream to load from (`IO`)
Returns
-------
ForceConstantModel
the original object as stored in the file
the force constant model object as stored in the file
"""
if isinstance(f, str):
with open(f, 'rb') as fobj:
......@@ -354,13 +355,13 @@ class ForceConstantModel:
else:
return pickle.load(f)
def write(self, f):
def write(self, f: Union[str, IO]) -> None:
"""Writes a force constant model to file.
Parameters
----------
f : str or file object
name of input file (str) or stream to write to (file object)
f
name of input file (`str`) or stream to write to (`IO`)
"""
if isinstance(f, str):
with open(f, 'wb') as fobj:
......
......@@ -116,11 +116,14 @@ def prepare_structures(structures: List[Atoms],
Example
-------
>>> db = connect('dft_training_structures.db')
>>> training_structures = [row.toatoms() for row in db.select()]
>>> training_structures = prepare_structures(training_structures, atoms_ideal)
>>> for s in training_structures:
>>> sc.add_structure(s)
The following example illustrates the use of this function::
db = connect('dft_training_structures.db')
training_structures = [row.toatoms() for row in db.select()]
training_structures = prepare_structures(training_structures, atoms_ideal)
for s in training_structures:
sc.add_structure(s)
Parameters
----------
......
......@@ -4,8 +4,8 @@ import re
import sys
from setuptools import setup, find_packages
if sys.version_info < (3, 5, 0, 'final', 0):
raise SystemExit('Python 3.5 or later is required!')
if sys.version_info < (3, 6, 0, 'final', 0):
raise SystemExit('Python 3.6 or later is required!')
with open('README.rst', encoding='utf-8') as fd:
long_description = fd.read()
......@@ -45,9 +45,9 @@ setup(name=name,
'Operating System :: OS Independent',
'Programming Language :: Python :: 3 :: Only',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Intended Audience :: Science/Research',
'License :: OSI Approved :: MIT License',
'Topic :: Scientific/Engineering :: Physics'])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment