From 3b693de893cfaf6dc226801d2900e3b6ddab386b Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Tue, 14 Nov 2023 12:09:40 +0100 Subject: [PATCH] First version of the documentation --- .ci_support/environment-docs.yml | 19 +++ .readthedocs.yml | 28 +++++ docs/Makefile | 20 +++ docs/make.bat | 35 ++++++ docs/source/conf.py | 34 +++++ docs/source/index.rst | 21 ++++ docs/source/installation.md | 55 +++++++++ docs/source/materialproperties.md | 199 ++++++++++++++++++++++++++++++ docs/source/simulationcodes.md | 97 +++++++++++++++ 9 files changed, 508 insertions(+) create mode 100644 .ci_support/environment-docs.yml create mode 100644 .readthedocs.yml create mode 100644 docs/Makefile create mode 100644 docs/make.bat create mode 100644 docs/source/conf.py create mode 100644 docs/source/index.rst create mode 100644 docs/source/installation.md create mode 100644 docs/source/materialproperties.md create mode 100644 docs/source/simulationcodes.md diff --git a/.ci_support/environment-docs.yml b/.ci_support/environment-docs.yml new file mode 100644 index 00000000..ad5af19e --- /dev/null +++ b/.ci_support/environment-docs.yml @@ -0,0 +1,19 @@ +channels: +- conda-forge +dependencies: + - nbsphinx + - sphinx + - myst-parser + - numpy + - ase =3.22.1 + - coverage + - numpy =1.26.0 + - scipy =1.11.3 + - spglib =2.1.0 + - phonopy =2.20.0 + - structuretoolkit =0.0.11 + - seekpath =2.1.0 + - lammps =2023.08.02 + - pandas =2.1.3 + - pylammpsmpi =0.2.5 + - jinja2 =3.1.2 \ No newline at end of file diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 00000000..b4de3480 --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,28 @@ +# .readthedocs.yml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +build: + os: "ubuntu-20.04" + tools: + python: "mambaforge-4.10" + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: docs/source/conf.py + +# Optionally build your docs in additional formats such as PDF and ePub +formats: [] + +# Install pyiron from conda +conda: + environment: .ci_support/environment-docs.yml + +# Optionally set the version of Python and requirements required to build your docs +python: + install: + - method: pip + path: . \ No newline at end of file diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..d0c3cbf1 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 00000000..dc1312ab --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 00000000..f4b85400 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,34 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = 'atomistics' +copyright = '2023, Jan Janssen' +author = 'Jan Janssen' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = ["myst_parser", 'sphinx.ext.autodoc', 'sphinx.ext.napoleon'] + +templates_path = ['_templates'] +exclude_patterns = [] + + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = 'alabaster' +html_static_path = ['_static'] + + +# -- Generate API documentation ---------------------------------------------- +# https://www.sphinx-doc.org/en/master/man/sphinx-apidoc.html + +from sphinx.ext.apidoc import main +main(['-e', '-o', 'apidoc', '../../atomistics/', '--force']) diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 00000000..c258d66b --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,21 @@ +==================================================================== +atomistics - Interfaces for atomistic simulation codes and workflows +==================================================================== + +:Author: Jan Janssen +:Contact: janssen@mpie.de + +First version of the documentation for the :code:`atomistics` package. + + +Documentation +------------- + +.. toctree:: + :maxdepth: 2 + + installation + simulationcodes + materialproperties + +* :ref:`modindex` \ No newline at end of file diff --git a/docs/source/installation.md b/docs/source/installation.md new file mode 100644 index 00000000..e10e08a3 --- /dev/null +++ b/docs/source/installation.md @@ -0,0 +1,55 @@ +# Installation +## pypi-based Installation +``` +pip install atomistics +``` + +### GPAW +``` +pip install atomistics[gpaw] +``` + +### LAMMPS +``` +pip install atomistics[lammps] +``` + +### Phonopy +``` +pip install atomistics[phonopy] +``` + +## conda-based Installation +``` +conda install -c conda-forge atomistics +``` + +### Ab-init +``` +conda install -c conda-forge abinit +``` + +### GPAW +``` +conda install -c conda-forge gpaw +``` + +### LAMMPS +``` +conda install -c conda-forge lammps pylammpsmpi jinja2 pandas +``` + +### Quantum Espresso +``` +conda install -c conda-forge qe +``` + +### Siesta +``` +conda install -c conda-forge siesta +``` + +### Phonopy +``` +conda install -c phonopy seekpath structuretoolkit +``` \ No newline at end of file diff --git a/docs/source/materialproperties.md b/docs/source/materialproperties.md new file mode 100644 index 00000000..715adeff --- /dev/null +++ b/docs/source/materialproperties.md @@ -0,0 +1,199 @@ +# Materials Properties +Demonstrate the calculation of common material properties with the `atomistics` package. The examples use different +simulation codes, still the examples are not simulation code specific. It is one of the core features of the `atomistics` +package that all simulation workflow to calculate a specific material property can be executed with all simulation codes. + +## Elastic Properties +Calculate the elastic properties for Aluminium using the [GPAW](https://wiki.fysik.dtu.dk/gpaw/) DFT code. + +### Equation of State +Calculate the change of potential energy in dependence of the unit cell volume to identify the minimum as the equilibrium +volume. The energy at the equilibrium volume gives the equilibrium energy and the derivative gives the bulk modulus. +``` +from ase.build import bulk +from atomistics.calculators import evaluate_with_ase +from atomistics.workflows import EnergyVolumeCurveWorkflow +from gpaw import GPAW, PW +import numpy as np + + +calculator = EnergyVolumeCurveWorkflow( + structure=bulk("Al", a=4.05, cubic=True), + num_points=11, + fit_type='polynomial', + fit_order=3, + vol_range=0.05, + axes=['x', 'y', 'z'], + strains=None, +) +task_dict = calculator.generate_structures() +result_dict = evaluate_with_ase( + task_dict=task_dict, + ase_calculator=GPAW( + xc="PBE", + mode=PW(300), + kpts=(3, 3, 3) + ) +) +fit_dict = calculator.analyse_structures(output_dict=result_dict) +print(fit_dict) +``` + +### Elastic Matrix +An alternative approach to calculate the bulk modulus is based on the relation `B = (1/3) (C11 + 2 C12 )`. The bulk +modulus can be calculated based on the sum of the first elastic constant `C11` and twice the second elastic constant `C12` +divided by there. +``` +from ase.build import bulk +from atomistics.calculators import evaluate_with_ase +from atomistics.workflows import ElasticMatrixWorkflow +from gpaw import GPAW, PW +import numpy as np + + +calculator = ElasticMatrixWorkflow( + structure=bulk("Al", a=4.0, cubic=True), + num_of_point=5, + eps_range=0.05, + sqrt_eta=True, + fit_order=2 +) +task_dict = calculator.generate_structures() +result_dict = evaluate_with_ase( + task_dict=task_dict, + ase_calculator=GPAW( + xc="PBE", + mode=PW(300), + kpts=(3, 3, 3) + ) +) +elastic_dict = calculator.analyse_structures(output_dict=result_dict) +print(elastic_dict) +``` + +## Thermal Expansion +Calculate the thermal expansion for a Morse Pair potential using the [LAMMPS](https://www.lammps.org/) molecular dynamics +simulation code. + +Import required software packages: +``` +from ase.build import bulk +from atomistics.calculators.lammps import evaluate_with_lammps, get_potential_dataframe +from atomistics.workflows.evcurve.workflow import EnergyVolumeCurveWorkflow +from atomistics.workflows.quasiharmonic.workflow import QuasiHarmonicWorkflow +from atomistics.shared.thermo.debye import get_debye_model +from atomistics.shared.thermo.thermo import get_thermo_bulk_model +import numpy as np +import pandas +from phonopy.units import VaspToTHz +``` + +Define the Morse Potential: +``` +element = "Al" +alpha = 1.8 +r0 = 2.95 +D0 = 0.5 +cutoff = 9.0 +potential_dataframe = pandas.DataFrame({ + "Config": [[ + "pair_style morse/smooth/linear %f"%cutoff, + "pair_coeff * * %.16f %.16f %.16f"%(D0, alpha, r0) + ]], + "Filename": [[]], + "Model": ["Morse"], + "Name": ["Morse"], + "Species": [["Al"]], +}).iloc[0] +potential_dataframe +``` +### Equation of State +``` +structure = bulk("Al", a=4.05, cubic=True) +workflow = EnergyVolumeCurveWorkflow( + structure=structure, + num_points=11, + fit_type='polynomial', + fit_order=3, + vol_range=0.05, + axes=['x', 'y', 'z'], + strains=None, +) +structure_dict = workflow.generate_structures() +result_dict = evaluate_with_lammps( + task_dict=structure_dict, + potential_dataframe=potential_dataframe +) +fit_dict = workflow.analyse_structures(output_dict=result_dict) +debye_model = get_debye_model(fit_dict=fit_dict, masses=structure.get_masses(), num_steps=50) +T_debye_low, T_debye_high = debye_model.debye_temperature +pes = get_thermo_bulk_model( + temperatures=np.linspace(1, 1500, 200), + debye_model=debye_model, +) +pes.plot_contourf(show_min_erg_path=True) +``` +### Quasi-Harmonic Approximation +``` +calculator = QuasiHarmonicWorkflow( + structure=structure, + num_points=11, + vol_range=0.05, + interaction_range=10, + factor=VaspToTHz, + displacement=0.01, + dos_mesh=20, + primitive_matrix=None, + number_of_snapshots=None, +) +structure_dict = calculator.generate_structures() +result_dict = evaluate_with_lammps( + task_dict=structure_dict, + potential_dataframe=potential_dataframe, +) +eng_internal_dict, mesh_collect_dict, dos_collect_dict = calculator.analyse_structures(output_dict=result_dict) +tp_collect_dict = calculator.get_thermal_properties(t_min=1, t_max=1500, t_step=50, temperatures=None) + +temperatures = tp_collect_dict[1.0]['temperatures'] +temperature_max = max(temperatures) +strain_lst = eng_internal_dict.keys() +volume_lst = calculator.get_volume_lst() +eng_int_lst = np.array(list(eng_internal_dict.values())) + +fit_deg = 4 +vol_best = volume_lst[int(len(volume_lst)/2)] +vol_lst, eng_lst = [], [] +for i, temp in enumerate(temperatures): + free_eng_lst = np.array([tp_collect_dict[s]['free_energy'][i] for s in strain_lst]) + eng_int_lst + p = np.polyfit(volume_lst, free_eng_lst, deg=fit_deg) + extrema = np.roots(np.polyder(p, m=1)).real + vol_select = extrema[np.argmin(np.abs(extrema - vol_best))] + eng_lst.append(np.poly1d(p)(vol_select)) + vol_lst.append(vol_select) + +fig, ax=plt.subplots(1,1) +for i, temp in enumerate(temperatures): + ax.plot(volume_lst, np.array([ + tp_collect_dict[s]['free_energy'][i] + for s in strain_lst + ]) + eng_int_lst, color=cmap(temp/temperature_max)) +ax.set_xlabel("Volume") +ax.set_ylabel("Free energy ($U + F_{vib}$) [eV]") +normalize = matplotlib.colors.Normalize(vmin=np.min(temperatures), vmax=np.max(temperatures)) +scalarmappaple = matplotlib.cm.ScalarMappable(norm=normalize, cmap=cmap) +scalarmappaple.set_array(list(tp_collect_dict.keys())) +cbar = plt.colorbar(scalarmappaple, ax=ax) +cbar.set_label("Temperature") +plt.plot(vol_lst, eng_lst, color="black", linestyle="--") +``` +### Molecular Dynamics +For the pair potential we find good agreement between the three different approximation + +## Phase Diagram +One of the goals of the `atomistics` package is to be able to calculate phase diagrams with ab-initio precision. + +### Quasi-Harmonic Approximation +coming soon + +### Calphy +coming soon \ No newline at end of file diff --git a/docs/source/simulationcodes.md b/docs/source/simulationcodes.md new file mode 100644 index 00000000..797cde1a --- /dev/null +++ b/docs/source/simulationcodes.md @@ -0,0 +1,97 @@ +# Simulation Codes +At the current stage the majority of simulation codes are interfaced using the [Atomic Simulation Environment](https://wiki.fysik.dtu.dk/ase/) + +## Ab init +``` +from ase.calculators.abinit import Abinit +from atomistics.calculators import evaluate_with_ase + +result_dict = evaluate_with_ase( + task_dict={}, + ase_calculator=EMT() +) +``` + +## EMT +``` +from ase.calculators.emt import EMT +from atomistics.calculators import evaluate_with_ase + +result_dict = evaluate_with_ase( + task_dict={}, + ase_calculator=EMT() +) +``` + +## GPAW +``` +from gpaw import GPAW, PW +from atomistics.calculators import evaluate_with_ase + +result_dict = evaluate_with_ase( + task_dict={}, + ase_calculator=GPAW( + xc="PBE", + mode=PW(300), + kpts=(3, 3, 3) + ) +) +``` + +## LAMMPS +``` +from atomistics.calculators import evaluate_with_lammps, get_potential_dataframe + +potential = '1999--Mishin-Y--Al--LAMMPS--ipr1' +resource_path = os.path.join(os.path.dirname(__file__), "static", "lammps") +structure = bulk("Al", cubic=True) +df_pot = get_potential_dataframe( + structure=structure, + resource_path=resource_path +) +df_pot_selected = df_pot[df_pot.Name == potential].iloc[0] + +result_dict = evaluate_with_lammps( + task_dict={}, + potential_dataframe=df_pot_selected, +) +``` + +## Quantum Espresso +``` +from ase.calculators.espresso import Espresso +from atomistics.calculators import evaluate_with_ase + +pseudopotentials = {"Al": "Al.pbe-n-kjpaw_psl.1.0.0.UPF"} +result_dict = evaluate_with_ase( + task_dict={}, + ase_calculator=Espresso( + pseudopotentials=pseudopotentials, + tstress=True, + tprnfor=True, + kpts=(3, 3, 3), + ) +) +``` + +## Siesta +``` +from ase.calculators.siesta import Siesta +from ase.units import Ry +from atomistics.calculators import evaluate_with_ase + +result_dict = evaluate_with_ase( + task_dict={}, + ase_calculator=Siesta( + label="siesta", + xc="PBE", + mesh_cutoff=200 * Ry, + energy_shift=0.01 * Ry, + basis_set="DZ", + kpts=(5, 5, 5), + fdf_arguments={"DM.MixingWeight": 0.1, "MaxSCFIterations": 100}, + pseudo_path=os.path.abspath("tests/static/siesta"), + pseudo_qualifier="", + ) +) +``` \ No newline at end of file