diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..a07e6b0ca --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +target/ +**/*.rs.bk +Cargo.lock + +.tox/ +build/ +dist/ +*.egg-info +__pycache__/ diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 000000000..e69de29bb diff --git a/_redirect.html b/_redirect.html new file mode 100644 index 000000000..4f607eaeb --- /dev/null +++ b/_redirect.html @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/index.html b/index.html new file mode 100644 index 000000000..e22946da0 --- /dev/null +++ b/index.html @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/latest/.buildinfo b/latest/.buildinfo new file mode 100644 index 000000000..2768a09a3 --- /dev/null +++ b/latest/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 8b6cf372667946410ccdc2de10046502 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/latest/.doctrees/devdoc/explanations/architecture.doctree b/latest/.doctrees/devdoc/explanations/architecture.doctree new file mode 100644 index 000000000..01c49eb6c Binary files /dev/null and b/latest/.doctrees/devdoc/explanations/architecture.doctree differ diff --git a/latest/.doctrees/devdoc/explanations/index.doctree b/latest/.doctrees/devdoc/explanations/index.doctree new file mode 100644 index 000000000..d6c5ffe83 Binary files /dev/null and b/latest/.doctrees/devdoc/explanations/index.doctree differ diff --git a/latest/.doctrees/devdoc/explanations/interfaces.doctree b/latest/.doctrees/devdoc/explanations/interfaces.doctree new file mode 100644 index 000000000..bba32335e Binary files /dev/null and b/latest/.doctrees/devdoc/explanations/interfaces.doctree differ diff --git a/latest/.doctrees/devdoc/explanations/radial-integral.doctree b/latest/.doctrees/devdoc/explanations/radial-integral.doctree new file mode 100644 index 000000000..95c232cd1 Binary files /dev/null and b/latest/.doctrees/devdoc/explanations/radial-integral.doctree differ diff --git a/latest/.doctrees/devdoc/get-started.doctree b/latest/.doctrees/devdoc/get-started.doctree new file mode 100644 index 000000000..7a50b32db Binary files /dev/null and b/latest/.doctrees/devdoc/get-started.doctree differ diff --git a/latest/.doctrees/devdoc/how-to/index.doctree b/latest/.doctrees/devdoc/how-to/index.doctree new file mode 100644 index 000000000..92fbd8cb1 Binary files /dev/null and b/latest/.doctrees/devdoc/how-to/index.doctree differ diff --git a/latest/.doctrees/devdoc/how-to/new-calculator.doctree b/latest/.doctrees/devdoc/how-to/new-calculator.doctree new file mode 100644 index 000000000..4f4893c21 Binary files /dev/null and b/latest/.doctrees/devdoc/how-to/new-calculator.doctree differ diff --git a/latest/.doctrees/devdoc/how-to/profiling.doctree b/latest/.doctrees/devdoc/how-to/profiling.doctree new file mode 100644 index 000000000..362fe0eb6 Binary files /dev/null and b/latest/.doctrees/devdoc/how-to/profiling.doctree differ diff --git a/latest/.doctrees/devdoc/index.doctree b/latest/.doctrees/devdoc/index.doctree new file mode 100644 index 000000000..e961f3287 Binary files /dev/null and b/latest/.doctrees/devdoc/index.doctree differ diff --git a/latest/.doctrees/environment.pickle b/latest/.doctrees/environment.pickle new file mode 100644 index 000000000..dcce5c8a3 Binary files /dev/null and b/latest/.doctrees/environment.pickle differ diff --git a/latest/.doctrees/examples/compute-soap.doctree b/latest/.doctrees/examples/compute-soap.doctree new file mode 100644 index 000000000..f665231c0 Binary files /dev/null and b/latest/.doctrees/examples/compute-soap.doctree differ diff --git a/latest/.doctrees/examples/first-calculation.doctree b/latest/.doctrees/examples/first-calculation.doctree new file mode 100644 index 000000000..13764970d Binary files /dev/null and b/latest/.doctrees/examples/first-calculation.doctree differ diff --git a/latest/.doctrees/examples/index.doctree b/latest/.doctrees/examples/index.doctree new file mode 100644 index 000000000..7b4196ac3 Binary files /dev/null and b/latest/.doctrees/examples/index.doctree differ diff --git a/latest/.doctrees/examples/keys-selection.doctree b/latest/.doctrees/examples/keys-selection.doctree new file mode 100644 index 000000000..212d73b81 Binary files /dev/null and b/latest/.doctrees/examples/keys-selection.doctree differ diff --git a/latest/.doctrees/examples/long-range-descriptor.doctree b/latest/.doctrees/examples/long-range-descriptor.doctree new file mode 100644 index 000000000..8bb5ef021 Binary files /dev/null and b/latest/.doctrees/examples/long-range-descriptor.doctree differ diff --git a/latest/.doctrees/examples/profiling.doctree b/latest/.doctrees/examples/profiling.doctree new file mode 100644 index 000000000..d223ed484 Binary files /dev/null and b/latest/.doctrees/examples/profiling.doctree differ diff --git a/latest/.doctrees/examples/property-selection.doctree b/latest/.doctrees/examples/property-selection.doctree new file mode 100644 index 000000000..afcf5d758 Binary files /dev/null and b/latest/.doctrees/examples/property-selection.doctree differ diff --git a/latest/.doctrees/examples/sample-selection.doctree b/latest/.doctrees/examples/sample-selection.doctree new file mode 100644 index 000000000..bdef04ddd Binary files /dev/null and b/latest/.doctrees/examples/sample-selection.doctree differ diff --git a/latest/.doctrees/examples/sg_execution_times.doctree b/latest/.doctrees/examples/sg_execution_times.doctree new file mode 100644 index 000000000..b306999d8 Binary files /dev/null and b/latest/.doctrees/examples/sg_execution_times.doctree differ diff --git a/latest/.doctrees/examples/splined-radial-integral.doctree b/latest/.doctrees/examples/splined-radial-integral.doctree new file mode 100644 index 000000000..7fcf9facc Binary files /dev/null and b/latest/.doctrees/examples/splined-radial-integral.doctree differ diff --git a/latest/.doctrees/explanations/concepts.doctree b/latest/.doctrees/explanations/concepts.doctree new file mode 100644 index 000000000..136dabb7a Binary files /dev/null and b/latest/.doctrees/explanations/concepts.doctree differ diff --git a/latest/.doctrees/explanations/index.doctree b/latest/.doctrees/explanations/index.doctree new file mode 100644 index 000000000..b8992b032 Binary files /dev/null and b/latest/.doctrees/explanations/index.doctree differ diff --git a/latest/.doctrees/explanations/rotation_adapted.doctree b/latest/.doctrees/explanations/rotation_adapted.doctree new file mode 100644 index 000000000..a5dbf7e49 Binary files /dev/null and b/latest/.doctrees/explanations/rotation_adapted.doctree differ diff --git a/latest/.doctrees/explanations/soap.doctree b/latest/.doctrees/explanations/soap.doctree new file mode 100644 index 000000000..69e683181 Binary files /dev/null and b/latest/.doctrees/explanations/soap.doctree differ diff --git a/latest/.doctrees/get-started/featomic.doctree b/latest/.doctrees/get-started/featomic.doctree new file mode 100644 index 000000000..49240b7bf Binary files /dev/null and b/latest/.doctrees/get-started/featomic.doctree differ diff --git a/latest/.doctrees/get-started/index.doctree b/latest/.doctrees/get-started/index.doctree new file mode 100644 index 000000000..218ca7777 Binary files /dev/null and b/latest/.doctrees/get-started/index.doctree differ diff --git a/latest/.doctrees/get-started/installation.doctree b/latest/.doctrees/get-started/installation.doctree new file mode 100644 index 000000000..22791f4ab Binary files /dev/null and b/latest/.doctrees/get-started/installation.doctree differ diff --git a/latest/.doctrees/get-started/tutorials.doctree b/latest/.doctrees/get-started/tutorials.doctree new file mode 100644 index 000000000..6db9deb75 Binary files /dev/null and b/latest/.doctrees/get-started/tutorials.doctree differ diff --git a/latest/.doctrees/how-to/computing-soap.doctree b/latest/.doctrees/how-to/computing-soap.doctree new file mode 100644 index 000000000..d2d03d631 Binary files /dev/null and b/latest/.doctrees/how-to/computing-soap.doctree differ diff --git a/latest/.doctrees/how-to/index.doctree b/latest/.doctrees/how-to/index.doctree new file mode 100644 index 000000000..85537edb8 Binary files /dev/null and b/latest/.doctrees/how-to/index.doctree differ diff --git a/latest/.doctrees/how-to/keys-selection.doctree b/latest/.doctrees/how-to/keys-selection.doctree new file mode 100644 index 000000000..aa4adc35b Binary files /dev/null and b/latest/.doctrees/how-to/keys-selection.doctree differ diff --git a/latest/.doctrees/how-to/long-range.doctree b/latest/.doctrees/how-to/long-range.doctree new file mode 100644 index 000000000..136ca4139 Binary files /dev/null and b/latest/.doctrees/how-to/long-range.doctree differ diff --git a/latest/.doctrees/how-to/property-selection.doctree b/latest/.doctrees/how-to/property-selection.doctree new file mode 100644 index 000000000..458618753 Binary files /dev/null and b/latest/.doctrees/how-to/property-selection.doctree differ diff --git a/latest/.doctrees/how-to/sample-selection.doctree b/latest/.doctrees/how-to/sample-selection.doctree new file mode 100644 index 000000000..f8b95f4af Binary files /dev/null and b/latest/.doctrees/how-to/sample-selection.doctree differ diff --git a/latest/.doctrees/how-to/splined-radial-integral.doctree b/latest/.doctrees/how-to/splined-radial-integral.doctree new file mode 100644 index 000000000..d3db53d19 Binary files /dev/null and b/latest/.doctrees/how-to/splined-radial-integral.doctree differ diff --git a/latest/.doctrees/index.doctree b/latest/.doctrees/index.doctree new file mode 100644 index 000000000..c1df8ba93 Binary files /dev/null and b/latest/.doctrees/index.doctree differ diff --git a/latest/.doctrees/references/api/c/calculators.doctree b/latest/.doctrees/references/api/c/calculators.doctree new file mode 100644 index 000000000..8d1d022b9 Binary files /dev/null and b/latest/.doctrees/references/api/c/calculators.doctree differ diff --git a/latest/.doctrees/references/api/c/index.doctree b/latest/.doctrees/references/api/c/index.doctree new file mode 100644 index 000000000..57718171c Binary files /dev/null and b/latest/.doctrees/references/api/c/index.doctree differ diff --git a/latest/.doctrees/references/api/c/misc.doctree b/latest/.doctrees/references/api/c/misc.doctree new file mode 100644 index 000000000..aeae65a55 Binary files /dev/null and b/latest/.doctrees/references/api/c/misc.doctree differ diff --git a/latest/.doctrees/references/api/c/systems.doctree b/latest/.doctrees/references/api/c/systems.doctree new file mode 100644 index 000000000..374005dc0 Binary files /dev/null and b/latest/.doctrees/references/api/c/systems.doctree differ diff --git a/latest/.doctrees/references/api/cxx/calculators.doctree b/latest/.doctrees/references/api/cxx/calculators.doctree new file mode 100644 index 000000000..45e40bc13 Binary files /dev/null and b/latest/.doctrees/references/api/cxx/calculators.doctree differ diff --git a/latest/.doctrees/references/api/cxx/index.doctree b/latest/.doctrees/references/api/cxx/index.doctree new file mode 100644 index 000000000..646bef263 Binary files /dev/null and b/latest/.doctrees/references/api/cxx/index.doctree differ diff --git a/latest/.doctrees/references/api/cxx/misc.doctree b/latest/.doctrees/references/api/cxx/misc.doctree new file mode 100644 index 000000000..3e1ced095 Binary files /dev/null and b/latest/.doctrees/references/api/cxx/misc.doctree differ diff --git a/latest/.doctrees/references/api/cxx/systems.doctree b/latest/.doctrees/references/api/cxx/systems.doctree new file mode 100644 index 000000000..25c4a971e Binary files /dev/null and b/latest/.doctrees/references/api/cxx/systems.doctree differ diff --git a/latest/.doctrees/references/api/index.doctree b/latest/.doctrees/references/api/index.doctree new file mode 100644 index 000000000..fe7706de6 Binary files /dev/null and b/latest/.doctrees/references/api/index.doctree differ diff --git a/latest/.doctrees/references/api/python/basis.doctree b/latest/.doctrees/references/api/python/basis.doctree new file mode 100644 index 000000000..22f441f52 Binary files /dev/null and b/latest/.doctrees/references/api/python/basis.doctree differ diff --git a/latest/.doctrees/references/api/python/calculators.doctree b/latest/.doctrees/references/api/python/calculators.doctree new file mode 100644 index 000000000..532e89865 Binary files /dev/null and b/latest/.doctrees/references/api/python/calculators.doctree differ diff --git a/latest/.doctrees/references/api/python/cutoff.doctree b/latest/.doctrees/references/api/python/cutoff.doctree new file mode 100644 index 000000000..ae0c26078 Binary files /dev/null and b/latest/.doctrees/references/api/python/cutoff.doctree differ diff --git a/latest/.doctrees/references/api/python/density.doctree b/latest/.doctrees/references/api/python/density.doctree new file mode 100644 index 000000000..ade6641cf Binary files /dev/null and b/latest/.doctrees/references/api/python/density.doctree differ diff --git a/latest/.doctrees/references/api/python/index.doctree b/latest/.doctrees/references/api/python/index.doctree new file mode 100644 index 000000000..b80697480 Binary files /dev/null and b/latest/.doctrees/references/api/python/index.doctree differ diff --git a/latest/.doctrees/references/api/python/misc.doctree b/latest/.doctrees/references/api/python/misc.doctree new file mode 100644 index 000000000..415275a60 Binary files /dev/null and b/latest/.doctrees/references/api/python/misc.doctree differ diff --git a/latest/.doctrees/references/api/python/splines.doctree b/latest/.doctrees/references/api/python/splines.doctree new file mode 100644 index 000000000..bec277542 Binary files /dev/null and b/latest/.doctrees/references/api/python/splines.doctree differ diff --git a/latest/.doctrees/references/api/python/systems.doctree b/latest/.doctrees/references/api/python/systems.doctree new file mode 100644 index 000000000..59eebd459 Binary files /dev/null and b/latest/.doctrees/references/api/python/systems.doctree differ diff --git a/latest/.doctrees/references/api/python/utils/clebsch-gordan.doctree b/latest/.doctrees/references/api/python/utils/clebsch-gordan.doctree new file mode 100644 index 000000000..0752b52cd Binary files /dev/null and b/latest/.doctrees/references/api/python/utils/clebsch-gordan.doctree differ diff --git a/latest/.doctrees/references/api/python/utils/index.doctree b/latest/.doctrees/references/api/python/utils/index.doctree new file mode 100644 index 000000000..11f81dd57 Binary files /dev/null and b/latest/.doctrees/references/api/python/utils/index.doctree differ diff --git a/latest/.doctrees/references/api/python/utils/power-spectrum.doctree b/latest/.doctrees/references/api/python/utils/power-spectrum.doctree new file mode 100644 index 000000000..96e6310d6 Binary files /dev/null and b/latest/.doctrees/references/api/python/utils/power-spectrum.doctree differ diff --git a/latest/.doctrees/references/api/rust.doctree b/latest/.doctrees/references/api/rust.doctree new file mode 100644 index 000000000..635c4f116 Binary files /dev/null and b/latest/.doctrees/references/api/rust.doctree differ diff --git a/latest/.doctrees/references/api/torch/calculators.doctree b/latest/.doctrees/references/api/torch/calculators.doctree new file mode 100644 index 000000000..5028ea85b Binary files /dev/null and b/latest/.doctrees/references/api/torch/calculators.doctree differ diff --git a/latest/.doctrees/references/api/torch/cxx/calculators.doctree b/latest/.doctrees/references/api/torch/cxx/calculators.doctree new file mode 100644 index 000000000..6277d2e4d Binary files /dev/null and b/latest/.doctrees/references/api/torch/cxx/calculators.doctree differ diff --git a/latest/.doctrees/references/api/torch/cxx/index.doctree b/latest/.doctrees/references/api/torch/cxx/index.doctree new file mode 100644 index 000000000..b7aacb4f2 Binary files /dev/null and b/latest/.doctrees/references/api/torch/cxx/index.doctree differ diff --git a/latest/.doctrees/references/api/torch/index.doctree b/latest/.doctrees/references/api/torch/index.doctree new file mode 100644 index 000000000..abcfe11ad Binary files /dev/null and b/latest/.doctrees/references/api/torch/index.doctree differ diff --git a/latest/.doctrees/references/api/torch/systems.doctree b/latest/.doctrees/references/api/torch/systems.doctree new file mode 100644 index 000000000..80e748d87 Binary files /dev/null and b/latest/.doctrees/references/api/torch/systems.doctree differ diff --git a/latest/.doctrees/references/api/torch/utils/clebsch-gordan.doctree b/latest/.doctrees/references/api/torch/utils/clebsch-gordan.doctree new file mode 100644 index 000000000..81c2a4ffb Binary files /dev/null and b/latest/.doctrees/references/api/torch/utils/clebsch-gordan.doctree differ diff --git a/latest/.doctrees/references/api/torch/utils/index.doctree b/latest/.doctrees/references/api/torch/utils/index.doctree new file mode 100644 index 000000000..5cdd94bb3 Binary files /dev/null and b/latest/.doctrees/references/api/torch/utils/index.doctree differ diff --git a/latest/.doctrees/references/api/torch/utils/power-spectrum.doctree b/latest/.doctrees/references/api/torch/utils/power-spectrum.doctree new file mode 100644 index 000000000..84040267b Binary files /dev/null and b/latest/.doctrees/references/api/torch/utils/power-spectrum.doctree differ diff --git a/latest/.doctrees/references/calculators/atomic-composition.doctree b/latest/.doctrees/references/calculators/atomic-composition.doctree new file mode 100644 index 000000000..aec52d18a Binary files /dev/null and b/latest/.doctrees/references/calculators/atomic-composition.doctree differ diff --git a/latest/.doctrees/references/calculators/index.doctree b/latest/.doctrees/references/calculators/index.doctree new file mode 100644 index 000000000..b4908232a Binary files /dev/null and b/latest/.doctrees/references/calculators/index.doctree differ diff --git a/latest/.doctrees/references/calculators/lode-spherical-expansion.doctree b/latest/.doctrees/references/calculators/lode-spherical-expansion.doctree new file mode 100644 index 000000000..76e9804e4 Binary files /dev/null and b/latest/.doctrees/references/calculators/lode-spherical-expansion.doctree differ diff --git a/latest/.doctrees/references/calculators/neighbor-list.doctree b/latest/.doctrees/references/calculators/neighbor-list.doctree new file mode 100644 index 000000000..6d2f90bea Binary files /dev/null and b/latest/.doctrees/references/calculators/neighbor-list.doctree differ diff --git a/latest/.doctrees/references/calculators/soap-power-spectrum.doctree b/latest/.doctrees/references/calculators/soap-power-spectrum.doctree new file mode 100644 index 000000000..9eee9ec8b Binary files /dev/null and b/latest/.doctrees/references/calculators/soap-power-spectrum.doctree differ diff --git a/latest/.doctrees/references/calculators/soap-radial-spectrum.doctree b/latest/.doctrees/references/calculators/soap-radial-spectrum.doctree new file mode 100644 index 000000000..8021c22f8 Binary files /dev/null and b/latest/.doctrees/references/calculators/soap-radial-spectrum.doctree differ diff --git a/latest/.doctrees/references/calculators/sorted-distances.doctree b/latest/.doctrees/references/calculators/sorted-distances.doctree new file mode 100644 index 000000000..1201c59fa Binary files /dev/null and b/latest/.doctrees/references/calculators/sorted-distances.doctree differ diff --git a/latest/.doctrees/references/calculators/spherical-expansion-by-pair.doctree b/latest/.doctrees/references/calculators/spherical-expansion-by-pair.doctree new file mode 100644 index 000000000..50753b82d Binary files /dev/null and b/latest/.doctrees/references/calculators/spherical-expansion-by-pair.doctree differ diff --git a/latest/.doctrees/references/calculators/spherical-expansion.doctree b/latest/.doctrees/references/calculators/spherical-expansion.doctree new file mode 100644 index 000000000..c0cd9ac40 Binary files /dev/null and b/latest/.doctrees/references/calculators/spherical-expansion.doctree differ diff --git a/latest/.doctrees/references/index.doctree b/latest/.doctrees/references/index.doctree new file mode 100644 index 000000000..dadce8391 Binary files /dev/null and b/latest/.doctrees/references/index.doctree differ diff --git a/latest/_downloads/081634a43959105f7f41a7682e76d405/property-selection.ipynb b/latest/_downloads/081634a43959105f7f41a7682e76d405/property-selection.ipynb new file mode 100644 index 000000000..b412db67f --- /dev/null +++ b/latest/_downloads/081634a43959105f7f41a7682e76d405/property-selection.ipynb @@ -0,0 +1,248 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# Property Selection\n\n.. start-body\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import chemfiles\nimport numpy as np\nfrom metatensor import Labels, MetatensorError, TensorBlock, TensorMap\nfrom skmatter.feature_selection import FPS\n\nfrom featomic import SoapPowerSpectrum" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First we load the dataset with chemfiles\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "with chemfiles.Trajectory(\"dataset.xyz\") as trajectory:\n frames = [f for f in trajectory]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "and define the hyper parameters of the representation\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "HYPER_PARAMETERS = {\n \"cutoff\": {\n \"radius\": 5.0,\n \"smoothing\": {\"type\": \"ShiftedCosine\", \"width\": 0.5},\n },\n \"density\": {\n \"type\": \"Gaussian\",\n \"width\": 0.3,\n },\n \"basis\": {\n \"type\": \"TensorProduct\",\n \"max_angular\": 4,\n \"radial\": {\"type\": \"Gto\", \"max_radial\": 6},\n },\n}\n\ncalculator = SoapPowerSpectrum(**HYPER_PARAMETERS)\n\ndescriptor = calculator.compute(frames)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The selections for feature can be a set of ``Labels``, in which case the names\nof the labels must be a subset of the names of the properties produced by the\ncalculator. You can see the default set of names with:\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(\"property names:\", descriptor.property_names)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can use a subset of these names to define a selection. In this case, only\nproperties matching the labels in this selection will be used by featomic\n(here, only properties with ``l = 0`` will be used)\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "selection = Labels(\n names=[\"l\"],\n values=np.array([[0]]),\n)\nselected_descriptor = calculator.compute(frames, selected_properties=selection)\n\nselected_descriptor = selected_descriptor.keys_to_samples(\"center_type\")\nselected_descriptor = selected_descriptor.keys_to_properties(\n [\"neighbor_1_type\", \"neighbor_2_type\"]\n)\n\nproperties = selected_descriptor.block().properties" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We expect to get `[0]` as the list of `l` properties\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(f\"we have the following angular components: {np.unique(properties['l'])}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The previous selection method uses the same selection for all blocks. If you\ncan to use different selection for different blocks, you should use a\n``TensorMap`` to create your selection\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "selected_descriptor = calculator.compute(frames, selected_properties=selection)\ndescriptor_for_comparison = calculator.compute(\n frames, selected_properties=selected_descriptor\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The descriptor had 180 properties stored in the first block, the\nselected_descriptor had 36. So ``descriptor_for_comparison`` will also have 36\nproperties.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(\"shape of first block initially:\", descriptor.block(0).values.shape)\nprint(\"shape of first block of reference:\", selected_descriptor.block(0).values.shape)\nprint(\n \"shape of first block after selection:\",\n descriptor_for_comparison.block(0).values.shape,\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The ``TensorMap`` format allows us to select different features within each\nblock, and then construct a general matrix of features. We can select the most\nsignificant features using FPS, which selects features based on the distance\nbetween them. The following code snippet selects the 10 most important\nfeatures in each block, then constructs a TensorMap containing this selection,\nand calculates the final matrix of features for it.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def fps_feature_selection(descriptor, n_to_select):\n \"\"\"\n Select ``n_to_select`` features block by block in the ``descriptor``, using\n Farthest Point Sampling to do the selection; and return a ``TensorMap`` with\n the right structure to be used as properties selection with featomic calculators\n \"\"\"\n blocks = []\n for block in descriptor:\n # create a separate FPS selector for each block\n fps = FPS(n_to_select=n_to_select)\n mask = fps.fit(block.values).get_support()\n selected_properties = Labels(\n names=block.properties.names,\n values=block.properties.values[mask],\n )\n # The only important data here is the properties, so we create empty\n # sets of samples and components.\n blocks.append(\n TensorBlock(\n values=np.empty((1, len(selected_properties))),\n samples=Labels.single(),\n components=[],\n properties=selected_properties,\n )\n )\n\n return TensorMap(descriptor.keys, blocks)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can then apply this function to subselect according to the data contained\nin a descriptor\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "selection = fps_feature_selection(descriptor, n_to_select=10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "and use the selection with featomic, potentially running the calculation on a\ndifferent set of systems\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "selected_descriptor = calculator.compute(frames, selected_properties=selection)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that in this case it is no longer possible to have a single feature\nmatrix, because each block will have its own properties.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "try:\n selected_descriptor.keys_to_samples(\"center_type\")\nexcept MetatensorError as err:\n print(err)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + ".. end-body\n\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/latest/_downloads/157269325187c1e5cc5b17bff969fe70/profiling.py b/latest/_downloads/157269325187c1e5cc5b17bff969fe70/profiling.py new file mode 100644 index 000000000..9253a32cb --- /dev/null +++ b/latest/_downloads/157269325187c1e5cc5b17bff969fe70/profiling.py @@ -0,0 +1,65 @@ +""" +Profiling calculation +===================== + +.. start-body +""" + +import chemfiles + +import featomic +from featomic import SoapPowerSpectrum + + +def compute_soap(path): + """Compute SOAP power spectrum. + + This is the same code as the 'compute-soap' example + """ + with chemfiles.Trajectory(path) as trajectory: + frames = [f for f in trajectory] + + HYPER_PARAMETERS = { + "cutoff": { + "radius": 5.0, + "smoothing": {"type": "ShiftedCosine", "width": 0.5}, + }, + "density": { + "type": "Gaussian", + "width": 0.3, + }, + "basis": { + "type": "TensorProduct", + "max_angular": 4, + "radial": {"type": "Gto", "max_radial": 6}, + }, + } + + calculator = SoapPowerSpectrum(**HYPER_PARAMETERS) + descriptor = calculator.compute(frames, gradients=["positions"]) + descriptor = descriptor.keys_to_samples("center_type") + descriptor = descriptor.keys_to_properties(["neighbor_1_type", "neighbor_2_type"]) + + return descriptor + + +# %% +# +# Run the calculation with profiling enabled. + +with featomic.Profiler() as profiler: + descriptor = compute_soap("dataset.xyz") +# %% +# +# Display the recorded profiling data as table. + +print(profiler.as_short_table()) + +# %% +# +# You can also save this data as json for future usage +print(profiler.as_json()) + +# %% +# +# .. end-body diff --git a/latest/_downloads/1dcd7388f9219fe5f08cc17fa4fa2d0d/property-selection.py b/latest/_downloads/1dcd7388f9219fe5f08cc17fa4fa2d0d/property-selection.py new file mode 100644 index 000000000..e50407f31 --- /dev/null +++ b/latest/_downloads/1dcd7388f9219fe5f08cc17fa4fa2d0d/property-selection.py @@ -0,0 +1,168 @@ +""" +Property Selection +================== + +.. start-body +""" + +import chemfiles +import numpy as np +from metatensor import Labels, MetatensorError, TensorBlock, TensorMap +from skmatter.feature_selection import FPS + +from featomic import SoapPowerSpectrum + + +# %% +# +# First we load the dataset with chemfiles + +with chemfiles.Trajectory("dataset.xyz") as trajectory: + frames = [f for f in trajectory] + +# %% +# +# and define the hyper parameters of the representation + +HYPER_PARAMETERS = { + "cutoff": { + "radius": 5.0, + "smoothing": {"type": "ShiftedCosine", "width": 0.5}, + }, + "density": { + "type": "Gaussian", + "width": 0.3, + }, + "basis": { + "type": "TensorProduct", + "max_angular": 4, + "radial": {"type": "Gto", "max_radial": 6}, + }, +} + +calculator = SoapPowerSpectrum(**HYPER_PARAMETERS) + +descriptor = calculator.compute(frames) + +# %% +# +# The selections for feature can be a set of ``Labels``, in which case the names +# of the labels must be a subset of the names of the properties produced by the +# calculator. You can see the default set of names with: + +print("property names:", descriptor.property_names) + +# %% +# +# We can use a subset of these names to define a selection. In this case, only +# properties matching the labels in this selection will be used by featomic +# (here, only properties with ``l = 0`` will be used) + +selection = Labels( + names=["l"], + values=np.array([[0]]), +) +selected_descriptor = calculator.compute(frames, selected_properties=selection) + +selected_descriptor = selected_descriptor.keys_to_samples("center_type") +selected_descriptor = selected_descriptor.keys_to_properties( + ["neighbor_1_type", "neighbor_2_type"] +) + +properties = selected_descriptor.block().properties + +# %% +# +# We expect to get `[0]` as the list of `l` properties + +print(f"we have the following angular components: {np.unique(properties['l'])}") + +# %% +# +# The previous selection method uses the same selection for all blocks. If you +# can to use different selection for different blocks, you should use a +# ``TensorMap`` to create your selection + +selected_descriptor = calculator.compute(frames, selected_properties=selection) +descriptor_for_comparison = calculator.compute( + frames, selected_properties=selected_descriptor +) + +# %% +# +# The descriptor had 180 properties stored in the first block, the +# selected_descriptor had 36. So ``descriptor_for_comparison`` will also have 36 +# properties. +print("shape of first block initially:", descriptor.block(0).values.shape) +print("shape of first block of reference:", selected_descriptor.block(0).values.shape) +print( + "shape of first block after selection:", + descriptor_for_comparison.block(0).values.shape, +) + +# %% +# +# The ``TensorMap`` format allows us to select different features within each +# block, and then construct a general matrix of features. We can select the most +# significant features using FPS, which selects features based on the distance +# between them. The following code snippet selects the 10 most important +# features in each block, then constructs a TensorMap containing this selection, +# and calculates the final matrix of features for it. + + +def fps_feature_selection(descriptor, n_to_select): + """ + Select ``n_to_select`` features block by block in the ``descriptor``, using + Farthest Point Sampling to do the selection; and return a ``TensorMap`` with + the right structure to be used as properties selection with featomic calculators + """ + blocks = [] + for block in descriptor: + # create a separate FPS selector for each block + fps = FPS(n_to_select=n_to_select) + mask = fps.fit(block.values).get_support() + selected_properties = Labels( + names=block.properties.names, + values=block.properties.values[mask], + ) + # The only important data here is the properties, so we create empty + # sets of samples and components. + blocks.append( + TensorBlock( + values=np.empty((1, len(selected_properties))), + samples=Labels.single(), + components=[], + properties=selected_properties, + ) + ) + + return TensorMap(descriptor.keys, blocks) + + +# %% +# +# We can then apply this function to subselect according to the data contained +# in a descriptor + +selection = fps_feature_selection(descriptor, n_to_select=10) + +# %% +# +# and use the selection with featomic, potentially running the calculation on a +# different set of systems + +selected_descriptor = calculator.compute(frames, selected_properties=selection) + +# %% +# +# Note that in this case it is no longer possible to have a single feature +# matrix, because each block will have its own properties. + +try: + selected_descriptor.keys_to_samples("center_type") +except MetatensorError as err: + print(err) + +# %% +# +# .. end-body diff --git a/latest/_downloads/1fca5afa28681412baa1843c260225ba/sample-selection.py b/latest/_downloads/1fca5afa28681412baa1843c260225ba/sample-selection.py new file mode 100644 index 000000000..6f5226aad --- /dev/null +++ b/latest/_downloads/1fca5afa28681412baa1843c260225ba/sample-selection.py @@ -0,0 +1,142 @@ +""" +Sample Selection +================ + +.. start-body +""" + +import chemfiles +import numpy as np +from metatensor import Labels + +from featomic import SoapPowerSpectrum + + +# %% +# +# First we load the dataset with chemfiles + +with chemfiles.Trajectory("dataset.xyz") as trajectory: + frames = [f for f in trajectory] + +# %% +# +# and define the hyper parameters of the representation + +HYPER_PARAMETERS = { + "cutoff": { + "radius": 5.0, + "smoothing": {"type": "ShiftedCosine", "width": 0.5}, + }, + "density": { + "type": "Gaussian", + "width": 0.3, + }, + "basis": { + "type": "TensorProduct", + "max_angular": 4, + "radial": {"type": "Gto", "max_radial": 6}, + }, +} + +calculator = SoapPowerSpectrum(**HYPER_PARAMETERS) + +descriptor = calculator.compute(frames) + +# %% +# +# The selections for sample can be a set of ``Labels``, in which case the names +# of the labels must be a subset of the names of the samples produced by the +# calculator. You can see the default set of names with: + +print("sample names:", descriptor.sample_names) + +# %% +# +# We can use a subset of these names to define a selection. In this case, only +# samples matching the labels in this selection will be used by featomic (here, +# only atoms from system 0, 2, and 3) + +selection = Labels( + names=["system"], + values=np.array([[0], [2], [3]]), +) + +descriptor_selected = calculator.compute(frames, selected_samples=selection) + +descriptor_selected = descriptor_selected.keys_to_samples("center_type") +descriptor_selected = descriptor_selected.keys_to_properties( + ["neighbor_1_type", "neighbor_2_type"] +) + +samples = descriptor_selected.block().samples + +# %% +# +# The first block should have ``[0, 2, 3]`` as ``samples["system"]`` + +print(f"we have the following systems: {np.unique(samples['system'])}") + +# %% +# +# If we want to select not only based on the system indexes but also atomic +# indexes, we can do the following (here we select atom 0 in the first system +# and atom 1 in the third system): + +selection = Labels( + names=["system", "atom"], + values=np.array([[0, 0], [2, 1]]), +) + +descriptor_selected = calculator.compute(frames, selected_samples=selection) +descriptor_selected = descriptor_selected.keys_to_samples("center_type") +descriptor_selected = descriptor_selected.keys_to_properties( + ["neighbor_1_type", "neighbor_2_type"] +) + +# %% +# +# The values will have 2 rows, since we have two samples: + +print( + "shape of first block of descriptor:", + descriptor_selected.block(0).values.shape, +) + +# %% +# +# The previous selection method uses the same selection for all blocks. If you +# can to use different selection for different blocks, you should use a +# `TensorMap` to create your selection + +descriptor = calculator.compute(frames) +descriptor_selected = calculator.compute(frames, selected_samples=selection) + +# %% +# +# notice how we are passing a TensorMap as the ``selected_samples`` argument: + +print(type(descriptor_selected)) +descriptor_for_comparison = calculator.compute( + frames, selected_samples=descriptor_selected +) + +# %% +# +# The descriptor had 420 samples stored in the first block, +# the ``descriptor_selected`` had 0. So ``descriptor_for_comparison`` +# will also have 0 samples. + +print("shape of first block initially:", descriptor.block(0).values.shape) +print( + "shape of first block of reference:", + descriptor_selected.block(0).values.shape, +) +print( + "shape of first block after selection:", + descriptor_for_comparison.block(0).values.shape, +) + +# %% +# +# .. end-body diff --git a/latest/_downloads/2ec60c786c8a5f204193e244b399a9a4/profiling.zip b/latest/_downloads/2ec60c786c8a5f204193e244b399a9a4/profiling.zip new file mode 100644 index 000000000..7105cea9b Binary files /dev/null and b/latest/_downloads/2ec60c786c8a5f204193e244b399a9a4/profiling.zip differ diff --git a/latest/_downloads/33cbf89244c381c85dfb98b83889ff69/first-calculation.ipynb b/latest/_downloads/33cbf89244c381c85dfb98b83889ff69/first-calculation.ipynb new file mode 100644 index 000000000..a6ea5a0cc --- /dev/null +++ b/latest/_downloads/33cbf89244c381c85dfb98b83889ff69/first-calculation.ipynb @@ -0,0 +1,399 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n\n# First descriptor computation\n\nThis is an introduction to the featomic interface using a molecular crystals\ndataset using the Python interface. If you are interested in another\nprogramming language we recommend you first follow this tutorial and afterward\ntake a look at the how-to guide on `userdoc-how-to-computing-soap`.\n\n## The dataset\n\nThe atomic configurations used in our documentation are a small subset of the\n[ShiftML2 dataset](https://pubs.acs.org/doi/pdf/10.1021/acs.jpcc.2c03854)\ncontaining molecular crystals. There are four crystals - one with each of the\nelements [hydrogen, carbon], [hydrogen, carbon, nitrogen, oxygen], [hydrogen,\ncarbon, nitrogen], or [hydrogen, carbon, oxygen]. Each crystal has 10 structures,\nalso denoted by frames, attributed to it. The first frame of each crystal structure\nis the geometry-optimized frame. The following 9 frames contain atoms that are\nslightly displaced from the geometry-optimized frame. You can obtain the dataset\nfrom our :download:`website <../../static/dataset.xyz>`.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will start by importing all the required packages: the classic numpy;\nchemfiles to load data, and featomic to compute representations. Afterward\nwe will load the dataset using chemfiles.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import chemfiles\nimport numpy as np\n\nfrom featomic import SphericalExpansion\n\n\nwith chemfiles.Trajectory(\"dataset.xyz\") as trajectory:\n frames = [f for f in trajectory]\n\nprint(f\"The dataset contains {len(frames)} frames.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will not explain here how to use chemfiles in detail, as we only use a few\nfunctions. Briefly, :class:`chemfiles.Trajectory` loads structure data in a\nformat featomic can use. If you want to learn more about the possibilities\ntake a look at the [chemfiles documentation](https://chemfiles.org).\n\nLet us now take a look at the first frame of the dataset.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "frame0 = frames[0]\n\nprint(frame0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With ``frame0.atoms`` we get a list of the atoms that make up frame zero.\nThe ``name`` attribute gives us the name of the specified atom.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "elements, counts = np.unique([atom.name for atom in frame0.atoms], return_counts=True)\n\nprint(\n f\"The first frame contains \"\n f\"{counts[0]} {elements[0]}-atoms, \"\n f\"{counts[1]} {elements[1]}-atoms, \"\n f\"{counts[2]} {elements[2]}-atoms and \"\n f\"{counts[3]} {elements[3]}-atoms.\"\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Calculate a descriptor\n\nWe will now calculate an atomic descriptor for this structure using the SOAP\nspherical expansion as introduced by [Bart\u00f3k, Kondor, and Cs\u00e1nyi](http://dx.doi.org/10.1103/PhysRevB.87.184115).\n\nTo do so we define below a set of parameters telling featomic how the\nspherical expansion should be calculated. These parameters are also called\nhyper parameters since they are parameters of the representation, in\nopposition to parameters of machine learning models. Hyper parameters are a\ncrucial part of calculating descriptors. Poorly selected hyper parameters will\nlead to a poor description of your dataset as discussed in the [literature](https://arxiv.org/abs/1502.02127).\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "cutoff = {\n \"radius\": 4.5,\n \"smoothing\": {\"type\": \"ShiftedCosine\", \"width\": 0.5},\n}\n\ndensity = {\n \"type\": \"Gaussian\",\n \"width\": 0.3,\n \"radial_scaling\": {\n \"type\": \"Willatt2018\",\n \"scale\": 2.0,\n \"rate\": 1.0,\n \"exponent\": 4,\n },\n}\n\nbasis = {\n \"type\": \"TensorProduct\",\n \"max_angular\": 5,\n \"radial\": {\"type\": \"Gto\", \"max_radial\": 8},\n}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "After we set the hyper parameters we initialize a\n:class:`featomic.calculators.SphericalExpansion` object with hyper parameters\ndefined above and run the\n:py:func:`featomic.calculators.CalculatorBase.compute()` method.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "calculator = SphericalExpansion(cutoff=cutoff, density=density, basis=basis)\ndescriptor0 = calculator.compute(frame0)\nprint(type(descriptor0))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The descriptor format is a :class:`metatensor.TensorMap` object. Metatensor is\nlike numpy for storing representations of atomistic ML data. Extensive details\non the metatensor are covered in the [corresponding documentation](https://lab-cosmo.github.io/metatensor/).\n\nWe will now have a look at how the data is stored inside\n:class:`metatensor.TensorMap` objects.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(descriptor0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The :class:`metatensor.TensorMap` is structured in several instances of an\n:class:`metatensor.TensorBlock`. To distinguish the block each block is associated\nwith a unique key. For the current example, we have one block for each angular channel\nlabeled by ``o3_lambda``, the central atom type ``center_type`` and\nneighbor atom type labeled by ``neighbor_type``. Different atomic types are\nrepresented using their atomic number, e.g. 1 for hydrogen, 6 for carbon, etc. To\nsummarize, this descriptor contains 112 blocks covering all combinations of the\nangular channels of the central and neighbor atom types in our dataset.\n\nLet us take a look at the second block (at index 1) in detail. This block contains the\ndescriptor for the $l=1$ angular channel for hydrogen-hydrogen pairs.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "block = descriptor0.block(1)\nprint(descriptor0.keys[1])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The descriptor values\n\nThe values of the representation are stored as an array. Each entry in this\narray also has associated unique metadata as each block. For the spherical\nexpansion calculator used in this tutorial the values have three dimensions\nwhich we can verify from the ``.shape`` attribute.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(block.values.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The descriptor values\n\nThe first dimension is denoted by the `samples`, the intermediate dimension by\n`components`, and the last dimension by `properties`. The \"sample dimension\"\nhas a length of eight because we have eight hydrogen atoms in the first frame.\nWe can reveal more detailed metadata information about the sample-dimension\nprinting of the :py:attr:`metatensor.TensorBlock.samples` attribute of the\nblock\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(block.samples)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The result is an :class:`metatensor.TensorMap` instance. It contains in total\neight tuples each with two values. The tuple values are named as follows\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(block.samples.names)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Meaning that the first entry of each tuple indicates the _structure_, which is\n0 for all because we only computed the representation of a single frame. The\nsecond entry of each tuple refers to the index of the _center_ atom.\n\nWe can do a similar investigation for the second dimension: the\n:py:attr:`metatensor.TensorBlock.components`.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(block.components)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here, the components are associated with the angular channels of the\nrepresentation. The size of ``o3_mu`` is $2l + 1$, where\n$l$ is the current ``o3_lambda`` of the block. Here, its\ndimension is three because we are looking at the ``o3_lambda=1``\nblock. You may have noticed that the return value of the last call is a\n:class:`list` of :class:`metatensor.Labels` and not a single ``Labels``\ninstance. The reason is that a block can have several component dimensions as\nwe will see below for the gradients.\n\nThe last value represents the number of radial channels. For the\n:py:attr:`metatensor.TensorBlock.properties` dimension we find an object\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(block.properties)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "containing a tuple of only one value ranging from 0 to 8. The name of this entry is\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(block.properties.names)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "and denoting the radial channels. The range results from our choice of\n``max_radial = 9`` in the hyper parameters above.\n\nAfter looking at the metadata we can investigate the actual data of the\nrepresentation in more details\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(block.values[0, 0, :])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "By using ``[0, 0, :]`` we selected the first hydrogen and the first ``m``\nchannel. As you the output shows the values are floating point numbers between\n``-1.0`` and ``1.0``. Values in this range are reasonable and can be directly\nused as input for a machine learning algorithm.\n\nFeatomic is also able to process more than one structure within one function\ncall. You can process a whole dataset with\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "descriptor_full = calculator.compute(frames)\n\nblock_full = descriptor_full.block(0)\nprint(block_full.values.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the 0th block of the :class:`metatensor.TensorMap` contains not eight but\n420 entries in the first dimensions. This reflects the fact that in total we\nhave 420 hydrogen atoms in the whole dataset.\n\nIf you want to use another calculator instead of\n:class:`featomic.calculators.SphericalExpansion` shown here check out the\n`userdoc-references` section.\n\n## Computing gradients\n\nAdditionally, featomic is also able to calculate gradients on top of the\nvalues. Gradients are useful for constructing an ML potential and running\nsimulations. For example ``gradients`` of the representation with respect to\natomic positions can be calculated by setting the ``gradients`` parameter of\nthe :py:func:`featomic.calculators.CalculatorBase.compute()` method to\n``[\"positions\"]``.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "descriptor_gradients = calculator.compute(frame0, gradients=[\"positions\"])\n\nblock_gradients = descriptor_gradients.block(0)\ngradient_position = block_gradients.gradient(\"positions\")\n\nprint(gradient_position.values.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The calculated descriptor contains the values and in each block the associated\nposition gradients as an :class:`metatensor.block.Gradient` instance. The\nactual values are stored in the ``data`` attribute. Similar to the features\nthe gradient data also has associated metadata. But, compared to the values\nwere we found three dimensions, and gradients have four. Again the first is\ncalled `samples` and the `properties`. The dimensions between the sample and\nproperty dimensions are denoted by `components`.\n\nLooking at the shape in more detail we find that we have 52 samples, which is\nmuch more compared to features where we only have eight samples. This arises\nfrom the fact that we calculate the position gradient for each pair in the\nstructure. For our selected block these are all hydrogen-hydrogen pairs.\nNaively one would come up with ``8 * 8 = 64`` samples, but featomic already\nignores pairs that are outside of the cutoff radius. Their position gradient\nis always zero. The :attr:`metatensor.block.Gradient.samples` attribute shows\nthis in detail.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(gradient_position.samples)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that we have a tuple of three with the names\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(gradient_position.samples.names)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the above output of the Labels instance for example the `(2, 0, 17)` entry\nis missing indicating that this pair is outside of the cutoff.\n\nNow looking at the :attr:`metatensor.block.Gradient.components`\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(gradient_position.components)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "we find two of them. Besides the `o3_mu` component that is also present in the\nfeatures position gradients also have a component indicating the direction of the\ngradient vector.\n\nFinally, the :attr:`metatensor.block.Gradient.properties` dimension is the same as for\nthe values\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(gradient_position.properties)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Featomic can also calculate gradients with respect to the strain (i.e. the virial).\nFor this, you have to add ``\"strain\"`` to the list parsed to the ``gradients``\nparameter of the :py:func:`featomic.calculators.CalculatorBase.compute()` method.\nStrain gradients/virial are useful when computing the stress and the pressure.\n\nIf you want to know about the effect of changing hypers take a look at the next\ntutorial. If you want to solve an explicit problem our `userdoc-how-to` might\nhelp you.\n\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/latest/_downloads/36d886e596f0b08a8c0e4ccbd309a891/long-range-descriptor.py b/latest/_downloads/36d886e596f0b08a8c0e4ccbd309a891/long-range-descriptor.py new file mode 100644 index 000000000..a31191746 --- /dev/null +++ b/latest/_downloads/36d886e596f0b08a8c0e4ccbd309a891/long-range-descriptor.py @@ -0,0 +1,391 @@ +""" +.. _userdoc-tutorials-long-range-descriptor: + +Long-range only LODE descriptor +=============================== + +.. start-body + +We start the example by loading the required packages +""" + +# %% + +import ase +import ase.visualize.plot +import matplotlib.pyplot as plt +import numpy as np +from ase.build import molecule +from metatensor import LabelsEntry, TensorMap + +import featomic +from featomic import LodeSphericalExpansion, SphericalExpansion + + +# %% +# +# **Single water molecule (short range) system** +# +# Our first test system is a single water molecule with a :math:`15\,\mathrm{Å}` +# vacuum layer around it. + + +atoms = molecule("H2O", vacuum=15, pbc=True) + +# %% +# We choose a ``cutoff`` for the projection of the spherical expansion and the +# neighbor search of the real space spherical expansion. + +cutoff = 3 + +# %% +# We can use ase's visualization tools to plot the system and draw a gray circle to +# indicate the ``cutoff`` radius. + +fig, ax = plt.subplots() + +ase.visualize.plot.plot_atoms(atoms) + +cutoff_circle = plt.Circle( + xy=atoms[0].position[:2], + radius=cutoff, + color="gray", + ls="dashed", + fill=False, +) +ax.add_patch(cutoff_circle) + +ax.set_xlabel("Å") +ax.set_ylabel("Å") + +fig.show() + + +# %% +# +# As you can see, for a single water molecule, the ``cutoff`` includes all atoms of +# the system. The combination of the test system and the ``cutoff`` aims to +# demonstrate that the full atomic fingerprint is contained within the ``cutoff``. +# By later subtracting the short-range density from the LODE density, we will observe +# that the difference between them is almost zero, indicating that a single water +# molecule is a short-range system. + + +# %% +# +# For the density, we choose a smeared power law as used in LODE, which does not decay +# exponentially like a :py:class:`Gaussian ` density and is +# therefore suited to describe long-range interactions between atoms. + + +density = featomic.density.SmearedPowerLaw(smearing=1.2, exponent=3) + + +# %% +# +# To visualize this we plot ``density`` together with a Gaussian density +# (``gaussian_density``) with the same ``width`` in a log-log plot. + +radial_positions = np.geomspace(1e-5, 10, num=1000) +gaussian_density = featomic.density.Gaussian(width=density.smearing) + +plt.plot( + radial_positions, + density.compute(radial_positions, derivative=False), + label="SmearedPowerLaw", +) +plt.plot( + radial_positions, + gaussian_density.compute(radial_positions, derivative=False), + label="Gaussian", +) + + +positions_indicator = np.array([3.0, 8.0]) +plt.plot( + positions_indicator, + 2 * positions_indicator ** (-density.exponent), + c="k", + label=f"exponent={density.exponent}", +) + +plt.legend() + +plt.xlim(1e-1, 10) +plt.ylim(1e-3, 5e-1) + +plt.xlabel("radial positions / Å") +plt.ylabel("atomic density") + +plt.xscale("log") +plt.yscale("log") + +# %% +# +# We see that the ``SmearedPowerLaw`` decays with a power law of 3, which is the +# potential exponent we picked above, wile the :py:class:`Gaussian +# ` density decays exponentially and is therefore not suited +# for long-range descriptors. + +# %% +# +# As a projection basis, we don't use the usual :py:class:`Gto ` +# which is commonly used for short range descriptors. Instead, we select the +# :py:class:`Monomials ` which is the optimal radial basis +# for the LODE descriptor as discussed in `Huguenin-Dumittan et al. +# `_ + +by_angular = {} +for angular in range(2): + by_angular[angular] = featomic.basis.Monomials( + radius=cutoff, angular_channel=angular, max_radial=4 + ) + + +basis = featomic.basis.Explicit( + by_angular=by_angular, + # We choose a relatively low spline accuracy (default is ``1e-8``) to achieve quick + # computation of the spline points. You can increase the spline accuracy if + # required, but be aware that the time to compute these points will increase + # significantly! + spline_accuracy=1e-2, +) + +# %% +# +# We now have all building blocks to construct the spline for the real and +# Fourier space spherical expansions. + + +real_space_spliner = featomic.splines.SoapSpliner( + # We don't use a ``smoothing`` function in the cutoff or a ``radial_scaling`` in the + # density to ensure the correct construction of the long-range only descriptor + cutoff=featomic.cutoff.Cutoff(radius=cutoff, smoothing=None), + basis=basis, + density=density, +) +real_space_hypers = real_space_spliner.get_hypers() + +fourier_space_spliner = featomic.splines.LodeSpliner( + basis=basis, + density=density, +) +fourier_space_hypers = fourier_space_spliner.get_hypers() + +# %% +# +# With the splines ready, we now compute the two spherical expansions + + +real_space_calculator = SphericalExpansion(**real_space_hypers) +real_space_expansion = real_space_calculator.compute(atoms) + + +fourier_space_calculator = LodeSphericalExpansion(**fourier_space_hypers) +fourier_space_expansion = fourier_space_calculator.compute(atoms) + +# %% +# As described in the beginning, we now subtract the real space LODE contributions +# from Fourier space to obtain a descriptor that only contains the contributions from +# atoms outside of the ``cutoff``. + + +delta_expansion = fourier_space_expansion - real_space_expansion + + +# %% +# +# You can now use the ``delta_expansion`` as a purely long-range descriptor in +# combination with a short-range descriptor like +# :py:class:`featomic.SphericalExpansion` for your machine learning models. +# +# We now verify that for our test ``atoms`` the LODE spherical expansion only contains +# short-range contributions. To demonstrate this, we densify the +# :py:class:`metatensor.TensorMap` to have only one block per ``"center_type"`` and +# visualize our result. Since we have to perform the densify operation several times in +# this how-to, we define a helper function ``densify_tensormap``. + + +def densify_tensormap(tensor: TensorMap) -> TensorMap: + dense_tensor = tensor.components_to_properties("o3_mu") + dense_tensor = dense_tensor.keys_to_samples("neighbor_type") + dense_tensor = dense_tensor.keys_to_properties(["o3_lambda", "o3_sigma"]) + + return dense_tensor + + +# %% +# We apply the function to the Fourier space spherical expansion +# ``fourier_space_expansion`` and ``subtracted_expansion``. + + +fourier_space_expansion = densify_tensormap(fourier_space_expansion) +delta_expansion = densify_tensormap(delta_expansion) + + +# %% +# Finally, we plot the values of each block for the Fourier Space spherical expansion +# in the upper panel and the difference between the Fourier Space and the real space +# in the lower panel. And since we will do this plot several times we again define a +# small plot function to help us + + +def plot_value_comparison( + key: LabelsEntry, + fourier_space_expansion: TensorMap, + subtracted_expansion: TensorMap, +): + fig, ax = plt.subplots(2, layout="tight") + + values_subtracted = subtracted_expansion[key].values + values_fourier_space = fourier_space_expansion[key].values + + ax[0].set_title(f"center_type={key.values[0]}\n Fourier space sph. expansion") + im = ax[0].matshow(values_fourier_space, vmin=-0.25, vmax=0.5) + ax[0].set_ylabel("sample index") + + ax[1].set_title("Difference between Fourier and real space sph. expansion") + ax[1].matshow(values_subtracted, vmin=-0.25, vmax=0.5) + ax[1].set_ylabel("sample index") + ax[1].set_xlabel("property index") + + fig.colorbar(im, ax=ax[0], orientation="horizontal", fraction=0.1, label="values") + + +# %% +# We first plot the values of the TensorMaps for center_type=1 (hydrogen) + +plot_value_comparison( + fourier_space_expansion.keys[0], fourier_space_expansion, delta_expansion +) + +# %% +# and for center_type=8 (oxygen) + +plot_value_comparison( + fourier_space_expansion.keys[1], fourier_space_expansion, delta_expansion +) + + +# %% +# The plot shows that the spherical expansion for the Fourier space is non-zero while +# the difference between the two expansions is very small. +# +# .. warning:: +# Small residual values may stems from the contribution of the periodic images. You +# can verify and reduce those contributions by either increasing the cell and/or +# increase the ``potential_exponent``. +# +# **Two water molecule (long range) system** +# +# We now add a second water molecule shifted by :math:`3\,\mathrm{Å}` in each +# direction from our first water molecule to show that such a system has non +# negligible long range effects. + + +atoms_shifted = molecule("H2O", vacuum=10, pbc=True) +atoms_shifted.positions = atoms.positions + 3 + +atoms_long_range = atoms + atoms_shifted + + +fig, ax = plt.subplots() + +ase.visualize.plot.plot_atoms(atoms_long_range, ax=ax) + +cutoff_circle = plt.Circle( + xy=atoms[0].position[1:], + radius=cutoff, + color="gray", + ls="dashed", + fill=False, +) + +cutoff_circle_shifted = plt.Circle( + xy=atoms_shifted[0].position[1:], + radius=cutoff, + color="gray", + ls="dashed", + fill=False, +) + +ax.add_patch(cutoff_circle) +ax.add_patch(cutoff_circle_shifted) + +ax.set_xlabel("Å") +ax.set_ylabel("Å") + +fig.show() + + +# %% +# As you can see, the ``cutoff`` radii of the two molecules are completely disjoint. +# Therefore, a short-range model will not able to describe the intermolecular +# interactions between our two molecules. To verify we now again create a long-range +# only descriptor for this system. We use the already defined +# ``real_space_expansion_long_range`` and ``fourier_space_expansion_long_range`` + + +real_space_expansion_long_range = real_space_calculator.compute(atoms_long_range) +fourier_space_expansion_long_range = fourier_space_calculator.compute(atoms_long_range) + +# %% +# We now first verify that the contribution from the short-range descriptors is the +# same as for a single water molecule. Exemplarily, we compare only the first +# (Hydrogen) block of each tensor. + + +print("Single water real space spherical expansion") +print(np.round(real_space_expansion[1].values, 3)) + +print("\nTwo water real space spherical expansion") +print(np.round(real_space_expansion_long_range[1].values, 3)) + +# %% +# Since the values of the block are the same, we can conclude that there is no +# information shared between the two molecules and that the short-range descriptor is +# not able to distinguish the system with only one or two water molecules. Note that +# the different number of `samples` in ``real_space_expansion_long_range`` reflects +# the fact that the second system has more atoms then the first. +# +# As above, we construct a long-range only descriptor and densify the result for +# plotting the values. + + +delta_expansion_long_range = ( + fourier_space_expansion_long_range - real_space_expansion_long_range +) + +fourier_space_expansion_long_range = densify_tensormap( + fourier_space_expansion_long_range +) +delta_expansion_long_range = densify_tensormap(delta_expansion_long_range) + + +# %% +# As above, we plot the values of the spherical expansions for the Fourier and the +# subtracted (long range only) spherical expansion. First for hydrogen +# (``center_species=1``) + +plot_value_comparison( + fourier_space_expansion_long_range.keys[0], + fourier_space_expansion_long_range, + delta_expansion_long_range, +) + +# %% +# amd second for oxygen (``center_species=8``) + +plot_value_comparison( + fourier_space_expansion_long_range.keys[1], + fourier_space_expansion_long_range, + delta_expansion_long_range, +) + + +# %% +# We clearly see that the values of the subtracted spherical are much larger compared +# to the system with only a single water molecule, thus confirming the presence of +# long-range contributions in the descriptor for a system with two water molecules. +# +# .. end-body diff --git a/latest/_downloads/42f2842f9cfabd51c881bcbd574c2b08/splined-radial-integral.ipynb b/latest/_downloads/42f2842f9cfabd51c881bcbd574c2b08/splined-radial-integral.ipynb new file mode 100644 index 000000000..beb8c4b2e --- /dev/null +++ b/latest/_downloads/42f2842f9cfabd51c881bcbd574c2b08/splined-radial-integral.ipynb @@ -0,0 +1,230 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# Splined radial integrals\n\n.. start-body\n\nThis example illustrates how to generate splines and use custom basis function and\ndensity when computing density-based representations, such as SOAP or LODE.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import json\n\nimport ase.build\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport scipy\n\nimport featomic\nfrom featomic import SphericalExpansion\nfrom featomic.basis import RadialBasis\nfrom featomic.splines import SoapSpliner" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For this example, we will define a new custom radial basis for the SOAP spherical\nexpansion, based on Chebyshev polynomials of the first kind. This basis will then be\nused in combination with spherical harmonics to expand the density of neighboring\natoms around a central atom.\n\nIn featomic, defining custom radial basis is done by creating a class inheriting from\n:py:class:`featomic.basis.RadialBasis`, and implementing the required method. The\nmain one is ``compute_primitive``, which evaluates the radial basis on a set of\npoints. This function should also be able to evaluate the derivative of the radial\nbasis. If needed :py:meth:`featomic.basis.RadialBasis.finite_differences_derivative`\ncan be used to compute the derivative with finite differences.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "class Chebyshev(RadialBasis):\n def __init__(self, max_radial, radius):\n # initialize `RadialBasis`\n super().__init__(max_radial=max_radial, radius=radius)\n\n def compute_primitive(self, positions, n, *, derivative=False):\n # map argument from [0, cutoff] to [-1, 1]\n z = 2 * positions / self.radius - 1\n if derivative:\n return -2 * n / self.radius * scipy.special.chebyu(n)(z)\n else:\n return scipy.special.chebyt(n + 1)(z)\n\n @property\n def integration_radius(self):\n return self.radius" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can now look at the basis functions and their derivatives\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "radius = 4.5\nbasis = Chebyshev(max_radial=4, radius=radius)\n\nr = np.linspace(0, radius)\nfor n in range(basis.size):\n plt.plot(r, basis.compute_primitive(r, n, derivative=False))\n\nplt.title(\"Chebyshev radial basis functions\")\nplt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "for n in range(basis.size):\n plt.plot(r, basis.compute_primitive(r, n, derivative=True))\nplt.title(\"Chebyshev radial basis functions' derivatives\")\nplt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Before being used by featomic, the basis functions we implemented will be\northogonalized and normalized, to improve conditioning of the produced features. This\nis done automatically, and one can access the orthonormalized basis functions with the\n:py:meth:`featomic.basis.RadialBasis.compute` method.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "basis_orthonormal = basis.compute(r, derivative=False)\nfor n in range(basis.size):\n plt.plot(r, basis_orthonormal[:, n])\n\nplt.title(\"Orthonormalized Chebyshev radial basis functions\")\nplt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With this, our new radial basis definition is ready to be used with\n:py:class:`featomic.splines.SoapSpliner`. This class will take the whole set of hyper\nparameters, use them to compute a spline of the radial integral, and give us back new\nhypers that can be used with the native calculators to compute the expansion with our\ncustom basis.\n\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "spliner = SoapSpliner(\n cutoff=featomic.cutoff.Cutoff(\n radius=radius,\n smoothing=featomic.cutoff.ShiftedCosine(width=0.3),\n ),\n density=featomic.density.Gaussian(width=0.5),\n basis=featomic.basis.TensorProduct(\n max_angular=4,\n radial=Chebyshev(max_radial=4, radius=radius),\n spline_accuracy=1e-4,\n ),\n)\n\nhypers = spliner.get_hypers()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The hyper parameters have been transformed from what we gave to the\n:py:class:`featomic.splines.SoapSpliner`:\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(\"hypers['basis'] is\", type(hypers[\"basis\"]))\nprint(\"hypers['density'] is\", type(hypers[\"density\"]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And the new hypers can be used directly with the calculators:\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "calculator_splined = SphericalExpansion(**hypers)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As a comparison, let's look at the expansion coefficient for formic acid, using both\nour splined radial basis and the classic GTO radial basis:\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "atoms = ase.build.molecule(\"HCOOH\", vacuum=4, pbc=True)\n\ncalculator_gto = SphericalExpansion(\n # same parameters, only the radial basis changed\n cutoff=featomic.cutoff.Cutoff(\n radius=radius,\n smoothing=featomic.cutoff.ShiftedCosine(width=0.3),\n ),\n density=featomic.density.Gaussian(width=0.5),\n basis=featomic.basis.TensorProduct(\n max_angular=4,\n radial=featomic.basis.Gto(max_radial=4, radius=radius),\n spline_accuracy=1e-4,\n ),\n)\n\nexpansion_splined = calculator_splined.compute(atoms)\nexpansion_gto = calculator_gto.compute(atoms)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you can see, the coefficients ends up different, with values assigned to different\nbasis functions. In practice, which basis function will be the best will depend on the\nuse case and exact dataset, so you should try a couple and check how they performe for\nyou!\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "selection = dict(o3_lambda=0, center_type=8, neighbor_type=1)\n\nplt.matshow(expansion_splined.block(selection).values.reshape(2, 5))\nplt.matshow(expansion_gto.block(selection).values.reshape(2, 5))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Since the calculation of the splines requires computing some integral numerically, the\ncreation of the splines might take a while. After an initial calculation, you can save\nthe splines data in JSON files; and then reload them later to re-use:\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# convert the hypers from classes to a pure JSON-compatible dictionary\njson_hypers = featomic.utils.hypers_to_json(hypers)\n\n# save the data to a file\nwith open(\"splined-hypers.json\", \"w\") as fp:\n json.dump(json_hypers, fp)\n\n\n# load the data from the file\nwith open(\"splined-hypers.json\", \"r\") as fp:\n json_hypers = json.load(fp)\n\n# the hypers can be used directly with the calculators\ncalculator = featomic.SphericalExpansion(**json_hypers)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, you can use the same method to define custom\n:py:class:`featomic.basis.ExpansionBasis` and custom\n:py:class:`featomic.density.AtomicDensity`; by creating a new class inheriting from\nthe corresponding base class and implementing the corresponding methods. This allow\nyou to create a fully custom spherical expansion, and evaluate them efficiently\nthrough the splines.\n\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + ".. end-body\n\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/latest/_downloads/491be9e03568f919353d2c473a1b8769/compute-soap.zip b/latest/_downloads/491be9e03568f919353d2c473a1b8769/compute-soap.zip new file mode 100644 index 000000000..55bfc8484 Binary files /dev/null and b/latest/_downloads/491be9e03568f919353d2c473a1b8769/compute-soap.zip differ diff --git a/latest/_downloads/52d185a9d75bdcffe38b2bef27c7b982/long-range-descriptor.ipynb b/latest/_downloads/52d185a9d75bdcffe38b2bef27c7b982/long-range-descriptor.ipynb new file mode 100644 index 000000000..9b204efd9 --- /dev/null +++ b/latest/_downloads/52d185a9d75bdcffe38b2bef27c7b982/long-range-descriptor.ipynb @@ -0,0 +1,424 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n\n# Long-range only LODE descriptor\n\n.. start-body\n\nWe start the example by loading the required packages\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import ase\nimport ase.visualize.plot\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom ase.build import molecule\nfrom metatensor import LabelsEntry, TensorMap\n\nimport featomic\nfrom featomic import LodeSphericalExpansion, SphericalExpansion" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Single water molecule (short range) system**\n\nOur first test system is a single water molecule with a $15\\,\\mathrm{\u00c5}$\nvacuum layer around it.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "atoms = molecule(\"H2O\", vacuum=15, pbc=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We choose a ``cutoff`` for the projection of the spherical expansion and the\nneighbor search of the real space spherical expansion.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "cutoff = 3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can use ase's visualization tools to plot the system and draw a gray circle to\nindicate the ``cutoff`` radius.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "fig, ax = plt.subplots()\n\nase.visualize.plot.plot_atoms(atoms)\n\ncutoff_circle = plt.Circle(\n xy=atoms[0].position[:2],\n radius=cutoff,\n color=\"gray\",\n ls=\"dashed\",\n fill=False,\n)\nax.add_patch(cutoff_circle)\n\nax.set_xlabel(\"\u00c5\")\nax.set_ylabel(\"\u00c5\")\n\nfig.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you can see, for a single water molecule, the ``cutoff`` includes all atoms of\nthe system. The combination of the test system and the ``cutoff`` aims to\ndemonstrate that the full atomic fingerprint is contained within the ``cutoff``.\nBy later subtracting the short-range density from the LODE density, we will observe\nthat the difference between them is almost zero, indicating that a single water\nmolecule is a short-range system.\n\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the density, we choose a smeared power law as used in LODE, which does not decay\nexponentially like a :py:class:`Gaussian ` density and is\ntherefore suited to describe long-range interactions between atoms.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "density = featomic.density.SmearedPowerLaw(smearing=1.2, exponent=3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To visualize this we plot ``density`` together with a Gaussian density\n(``gaussian_density``) with the same ``width`` in a log-log plot.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "radial_positions = np.geomspace(1e-5, 10, num=1000)\ngaussian_density = featomic.density.Gaussian(width=density.smearing)\n\nplt.plot(\n radial_positions,\n density.compute(radial_positions, derivative=False),\n label=\"SmearedPowerLaw\",\n)\nplt.plot(\n radial_positions,\n gaussian_density.compute(radial_positions, derivative=False),\n label=\"Gaussian\",\n)\n\n\npositions_indicator = np.array([3.0, 8.0])\nplt.plot(\n positions_indicator,\n 2 * positions_indicator ** (-density.exponent),\n c=\"k\",\n label=f\"exponent={density.exponent}\",\n)\n\nplt.legend()\n\nplt.xlim(1e-1, 10)\nplt.ylim(1e-3, 5e-1)\n\nplt.xlabel(\"radial positions / \u00c5\")\nplt.ylabel(\"atomic density\")\n\nplt.xscale(\"log\")\nplt.yscale(\"log\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We see that the ``SmearedPowerLaw`` decays with a power law of 3, which is the\npotential exponent we picked above, wile the :py:class:`Gaussian\n` density decays exponentially and is therefore not suited\nfor long-range descriptors.\n\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As a projection basis, we don't use the usual :py:class:`Gto `\nwhich is commonly used for short range descriptors. Instead, we select the\n:py:class:`Monomials ` which is the optimal radial basis\nfor the LODE descriptor as discussed in [Huguenin-Dumittan et al.](https://doi.org/10.1021/acs.jpclett.3c02375)\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "by_angular = {}\nfor angular in range(2):\n by_angular[angular] = featomic.basis.Monomials(\n radius=cutoff, angular_channel=angular, max_radial=4\n )\n\n\nbasis = featomic.basis.Explicit(\n by_angular=by_angular,\n # We choose a relatively low spline accuracy (default is ``1e-8``) to achieve quick\n # computation of the spline points. You can increase the spline accuracy if\n # required, but be aware that the time to compute these points will increase\n # significantly!\n spline_accuracy=1e-2,\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now have all building blocks to construct the spline for the real and\nFourier space spherical expansions.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "real_space_spliner = featomic.splines.SoapSpliner(\n # We don't use a ``smoothing`` function in the cutoff or a ``radial_scaling`` in the\n # density to ensure the correct construction of the long-range only descriptor\n cutoff=featomic.cutoff.Cutoff(radius=cutoff, smoothing=None),\n basis=basis,\n density=density,\n)\nreal_space_hypers = real_space_spliner.get_hypers()\n\nfourier_space_spliner = featomic.splines.LodeSpliner(\n basis=basis,\n density=density,\n)\nfourier_space_hypers = fourier_space_spliner.get_hypers()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the splines ready, we now compute the two spherical expansions\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "real_space_calculator = SphericalExpansion(**real_space_hypers)\nreal_space_expansion = real_space_calculator.compute(atoms)\n\n\nfourier_space_calculator = LodeSphericalExpansion(**fourier_space_hypers)\nfourier_space_expansion = fourier_space_calculator.compute(atoms)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As described in the beginning, we now subtract the real space LODE contributions\nfrom Fourier space to obtain a descriptor that only contains the contributions from\natoms outside of the ``cutoff``.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "delta_expansion = fourier_space_expansion - real_space_expansion" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can now use the ``delta_expansion`` as a purely long-range descriptor in\ncombination with a short-range descriptor like\n:py:class:`featomic.SphericalExpansion` for your machine learning models.\n\nWe now verify that for our test ``atoms`` the LODE spherical expansion only contains\nshort-range contributions. To demonstrate this, we densify the\n:py:class:`metatensor.TensorMap` to have only one block per ``\"center_type\"`` and\nvisualize our result. Since we have to perform the densify operation several times in\nthis how-to, we define a helper function ``densify_tensormap``.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def densify_tensormap(tensor: TensorMap) -> TensorMap:\n dense_tensor = tensor.components_to_properties(\"o3_mu\")\n dense_tensor = dense_tensor.keys_to_samples(\"neighbor_type\")\n dense_tensor = dense_tensor.keys_to_properties([\"o3_lambda\", \"o3_sigma\"])\n\n return dense_tensor" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We apply the function to the Fourier space spherical expansion\n``fourier_space_expansion`` and ``subtracted_expansion``.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "fourier_space_expansion = densify_tensormap(fourier_space_expansion)\ndelta_expansion = densify_tensormap(delta_expansion)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, we plot the values of each block for the Fourier Space spherical expansion\nin the upper panel and the difference between the Fourier Space and the real space\nin the lower panel. And since we will do this plot several times we again define a\nsmall plot function to help us\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def plot_value_comparison(\n key: LabelsEntry,\n fourier_space_expansion: TensorMap,\n subtracted_expansion: TensorMap,\n):\n fig, ax = plt.subplots(2, layout=\"tight\")\n\n values_subtracted = subtracted_expansion[key].values\n values_fourier_space = fourier_space_expansion[key].values\n\n ax[0].set_title(f\"center_type={key.values[0]}\\n Fourier space sph. expansion\")\n im = ax[0].matshow(values_fourier_space, vmin=-0.25, vmax=0.5)\n ax[0].set_ylabel(\"sample index\")\n\n ax[1].set_title(\"Difference between Fourier and real space sph. expansion\")\n ax[1].matshow(values_subtracted, vmin=-0.25, vmax=0.5)\n ax[1].set_ylabel(\"sample index\")\n ax[1].set_xlabel(\"property index\")\n\n fig.colorbar(im, ax=ax[0], orientation=\"horizontal\", fraction=0.1, label=\"values\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We first plot the values of the TensorMaps for center_type=1 (hydrogen)\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plot_value_comparison(\n fourier_space_expansion.keys[0], fourier_space_expansion, delta_expansion\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "and for center_type=8 (oxygen)\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plot_value_comparison(\n fourier_space_expansion.keys[1], fourier_space_expansion, delta_expansion\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The plot shows that the spherical expansion for the Fourier space is non-zero while\nthe difference between the two expansions is very small.\n\n

Warning

Small residual values may stems from the contribution of the periodic images. You\n can verify and reduce those contributions by either increasing the cell and/or\n increase the ``potential_exponent``.

\n\n**Two water molecule (long range) system**\n\nWe now add a second water molecule shifted by $3\\,\\mathrm{\u00c5}$ in each\ndirection from our first water molecule to show that such a system has non\nnegligible long range effects.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "atoms_shifted = molecule(\"H2O\", vacuum=10, pbc=True)\natoms_shifted.positions = atoms.positions + 3\n\natoms_long_range = atoms + atoms_shifted\n\n\nfig, ax = plt.subplots()\n\nase.visualize.plot.plot_atoms(atoms_long_range, ax=ax)\n\ncutoff_circle = plt.Circle(\n xy=atoms[0].position[1:],\n radius=cutoff,\n color=\"gray\",\n ls=\"dashed\",\n fill=False,\n)\n\ncutoff_circle_shifted = plt.Circle(\n xy=atoms_shifted[0].position[1:],\n radius=cutoff,\n color=\"gray\",\n ls=\"dashed\",\n fill=False,\n)\n\nax.add_patch(cutoff_circle)\nax.add_patch(cutoff_circle_shifted)\n\nax.set_xlabel(\"\u00c5\")\nax.set_ylabel(\"\u00c5\")\n\nfig.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you can see, the ``cutoff`` radii of the two molecules are completely disjoint.\nTherefore, a short-range model will not able to describe the intermolecular\ninteractions between our two molecules. To verify we now again create a long-range\nonly descriptor for this system. We use the already defined\n``real_space_expansion_long_range`` and ``fourier_space_expansion_long_range``\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "real_space_expansion_long_range = real_space_calculator.compute(atoms_long_range)\nfourier_space_expansion_long_range = fourier_space_calculator.compute(atoms_long_range)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now first verify that the contribution from the short-range descriptors is the\nsame as for a single water molecule. Exemplarily, we compare only the first\n(Hydrogen) block of each tensor.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(\"Single water real space spherical expansion\")\nprint(np.round(real_space_expansion[1].values, 3))\n\nprint(\"\\nTwo water real space spherical expansion\")\nprint(np.round(real_space_expansion_long_range[1].values, 3))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Since the values of the block are the same, we can conclude that there is no\ninformation shared between the two molecules and that the short-range descriptor is\nnot able to distinguish the system with only one or two water molecules. Note that\nthe different number of `samples` in ``real_space_expansion_long_range`` reflects\nthe fact that the second system has more atoms then the first.\n\nAs above, we construct a long-range only descriptor and densify the result for\nplotting the values.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "delta_expansion_long_range = (\n fourier_space_expansion_long_range - real_space_expansion_long_range\n)\n\nfourier_space_expansion_long_range = densify_tensormap(\n fourier_space_expansion_long_range\n)\ndelta_expansion_long_range = densify_tensormap(delta_expansion_long_range)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As above, we plot the values of the spherical expansions for the Fourier and the\nsubtracted (long range only) spherical expansion. First for hydrogen\n(``center_species=1``)\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plot_value_comparison(\n fourier_space_expansion_long_range.keys[0],\n fourier_space_expansion_long_range,\n delta_expansion_long_range,\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "amd second for oxygen (``center_species=8``)\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plot_value_comparison(\n fourier_space_expansion_long_range.keys[1],\n fourier_space_expansion_long_range,\n delta_expansion_long_range,\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We clearly see that the values of the subtracted spherical are much larger compared\nto the system with only a single water molecule, thus confirming the presence of\nlong-range contributions in the descriptor for a system with two water molecules.\n\n.. end-body\n\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/latest/_downloads/536e92230d631426c3c8630f4db8a141/first-calculation.py b/latest/_downloads/536e92230d631426c3c8630f4db8a141/first-calculation.py new file mode 100644 index 000000000..759756fb2 --- /dev/null +++ b/latest/_downloads/536e92230d631426c3c8630f4db8a141/first-calculation.py @@ -0,0 +1,327 @@ +""" +.. _userdoc-tutorials-get-started: + +First descriptor computation +============================ + +This is an introduction to the featomic interface using a molecular crystals +dataset using the Python interface. If you are interested in another +programming language we recommend you first follow this tutorial and afterward +take a look at the how-to guide on :ref:`userdoc-how-to-computing-soap`. + +The dataset +----------- + +The atomic configurations used in our documentation are a small subset of the +`ShiftML2 dataset `_ +containing molecular crystals. There are four crystals - one with each of the +elements [hydrogen, carbon], [hydrogen, carbon, nitrogen, oxygen], [hydrogen, +carbon, nitrogen], or [hydrogen, carbon, oxygen]. Each crystal has 10 structures, +also denoted by frames, attributed to it. The first frame of each crystal structure +is the geometry-optimized frame. The following 9 frames contain atoms that are +slightly displaced from the geometry-optimized frame. You can obtain the dataset +from our :download:`website <../../static/dataset.xyz>`. +""" + +# %% +# +# We will start by importing all the required packages: the classic numpy; +# chemfiles to load data, and featomic to compute representations. Afterward +# we will load the dataset using chemfiles. + +import chemfiles +import numpy as np + +from featomic import SphericalExpansion + + +with chemfiles.Trajectory("dataset.xyz") as trajectory: + frames = [f for f in trajectory] + +print(f"The dataset contains {len(frames)} frames.") + +# %% +# +# We will not explain here how to use chemfiles in detail, as we only use a few +# functions. Briefly, :class:`chemfiles.Trajectory` loads structure data in a +# format featomic can use. If you want to learn more about the possibilities +# take a look at the `chemfiles documentation `_. +# +# Let us now take a look at the first frame of the dataset. + +frame0 = frames[0] + +print(frame0) + +# %% +# +# With ``frame0.atoms`` we get a list of the atoms that make up frame zero. +# The ``name`` attribute gives us the name of the specified atom. + +elements, counts = np.unique([atom.name for atom in frame0.atoms], return_counts=True) + +print( + f"The first frame contains " + f"{counts[0]} {elements[0]}-atoms, " + f"{counts[1]} {elements[1]}-atoms, " + f"{counts[2]} {elements[2]}-atoms and " + f"{counts[3]} {elements[3]}-atoms." +) + +# %% +# +# Calculate a descriptor +# ---------------------- +# +# We will now calculate an atomic descriptor for this structure using the SOAP +# spherical expansion as introduced by `Bartók, Kondor, and Csányi +# `_. +# +# To do so we define below a set of parameters telling featomic how the +# spherical expansion should be calculated. These parameters are also called +# hyper parameters since they are parameters of the representation, in +# opposition to parameters of machine learning models. Hyper parameters are a +# crucial part of calculating descriptors. Poorly selected hyper parameters will +# lead to a poor description of your dataset as discussed in the `literature +# `_. + +cutoff = { + "radius": 4.5, + "smoothing": {"type": "ShiftedCosine", "width": 0.5}, +} + +density = { + "type": "Gaussian", + "width": 0.3, + "radial_scaling": { + "type": "Willatt2018", + "scale": 2.0, + "rate": 1.0, + "exponent": 4, + }, +} + +basis = { + "type": "TensorProduct", + "max_angular": 5, + "radial": {"type": "Gto", "max_radial": 8}, +} + +# %% +# +# After we set the hyper parameters we initialize a +# :class:`featomic.calculators.SphericalExpansion` object with hyper parameters +# defined above and run the +# :py:func:`featomic.calculators.CalculatorBase.compute()` method. + +calculator = SphericalExpansion(cutoff=cutoff, density=density, basis=basis) +descriptor0 = calculator.compute(frame0) +print(type(descriptor0)) + +# %% +# +# The descriptor format is a :class:`metatensor.TensorMap` object. Metatensor is +# like numpy for storing representations of atomistic ML data. Extensive details +# on the metatensor are covered in the `corresponding documentation +# `_. +# +# We will now have a look at how the data is stored inside +# :class:`metatensor.TensorMap` objects. + + +print(descriptor0) + +# %% +# +# The :class:`metatensor.TensorMap` is structured in several instances of an +# :class:`metatensor.TensorBlock`. To distinguish the block each block is associated +# with a unique key. For the current example, we have one block for each angular channel +# labeled by ``o3_lambda``, the central atom type ``center_type`` and +# neighbor atom type labeled by ``neighbor_type``. Different atomic types are +# represented using their atomic number, e.g. 1 for hydrogen, 6 for carbon, etc. To +# summarize, this descriptor contains 112 blocks covering all combinations of the +# angular channels of the central and neighbor atom types in our dataset. +# +# Let us take a look at the second block (at index 1) in detail. This block contains the +# descriptor for the :math:`l=1` angular channel for hydrogen-hydrogen pairs. + +block = descriptor0.block(1) +print(descriptor0.keys[1]) + + +# %% +# +# The descriptor values +# --------------------- +# +# The values of the representation are stored as an array. Each entry in this +# array also has associated unique metadata as each block. For the spherical +# expansion calculator used in this tutorial the values have three dimensions +# which we can verify from the ``.shape`` attribute. + + +print(block.values.shape) + +# %% +# +# The descriptor values +# --------------------- +# +# The first dimension is denoted by the `samples`, the intermediate dimension by +# `components`, and the last dimension by `properties`. The "sample dimension" +# has a length of eight because we have eight hydrogen atoms in the first frame. +# We can reveal more detailed metadata information about the sample-dimension +# printing of the :py:attr:`metatensor.TensorBlock.samples` attribute of the +# block + +print(block.samples) + +# %% +# +# The result is an :class:`metatensor.TensorMap` instance. It contains in total +# eight tuples each with two values. The tuple values are named as follows + +print(block.samples.names) + +# %% +# +# Meaning that the first entry of each tuple indicates the _structure_, which is +# 0 for all because we only computed the representation of a single frame. The +# second entry of each tuple refers to the index of the _center_ atom. +# +# We can do a similar investigation for the second dimension: the +# :py:attr:`metatensor.TensorBlock.components`. + +print(block.components) + +# %% +# +# Here, the components are associated with the angular channels of the +# representation. The size of ``o3_mu`` is :math:`2l + 1`, where +# :math:`l` is the current ``o3_lambda`` of the block. Here, its +# dimension is three because we are looking at the ``o3_lambda=1`` +# block. You may have noticed that the return value of the last call is a +# :class:`list` of :class:`metatensor.Labels` and not a single ``Labels`` +# instance. The reason is that a block can have several component dimensions as +# we will see below for the gradients. +# +# The last value represents the number of radial channels. For the +# :py:attr:`metatensor.TensorBlock.properties` dimension we find an object + +print(block.properties) + +# %% +# +# containing a tuple of only one value ranging from 0 to 8. The name of this entry is + +print(block.properties.names) + +# %% +# +# and denoting the radial channels. The range results from our choice of +# ``max_radial = 9`` in the hyper parameters above. +# +# After looking at the metadata we can investigate the actual data of the +# representation in more details + +print(block.values[0, 0, :]) + +# %% +# +# By using ``[0, 0, :]`` we selected the first hydrogen and the first ``m`` +# channel. As you the output shows the values are floating point numbers between +# ``-1.0`` and ``1.0``. Values in this range are reasonable and can be directly +# used as input for a machine learning algorithm. +# +# Featomic is also able to process more than one structure within one function +# call. You can process a whole dataset with + +descriptor_full = calculator.compute(frames) + +block_full = descriptor_full.block(0) +print(block_full.values.shape) + +# %% +# +# Now, the 0th block of the :class:`metatensor.TensorMap` contains not eight but +# 420 entries in the first dimensions. This reflects the fact that in total we +# have 420 hydrogen atoms in the whole dataset. +# +# If you want to use another calculator instead of +# :class:`featomic.calculators.SphericalExpansion` shown here check out the +# :ref:`userdoc-references` section. +# +# Computing gradients +# ------------------- +# +# Additionally, featomic is also able to calculate gradients on top of the +# values. Gradients are useful for constructing an ML potential and running +# simulations. For example ``gradients`` of the representation with respect to +# atomic positions can be calculated by setting the ``gradients`` parameter of +# the :py:func:`featomic.calculators.CalculatorBase.compute()` method to +# ``["positions"]``. + +descriptor_gradients = calculator.compute(frame0, gradients=["positions"]) + +block_gradients = descriptor_gradients.block(0) +gradient_position = block_gradients.gradient("positions") + +print(gradient_position.values.shape) + +# %% +# +# The calculated descriptor contains the values and in each block the associated +# position gradients as an :class:`metatensor.block.Gradient` instance. The +# actual values are stored in the ``data`` attribute. Similar to the features +# the gradient data also has associated metadata. But, compared to the values +# were we found three dimensions, and gradients have four. Again the first is +# called `samples` and the `properties`. The dimensions between the sample and +# property dimensions are denoted by `components`. +# +# Looking at the shape in more detail we find that we have 52 samples, which is +# much more compared to features where we only have eight samples. This arises +# from the fact that we calculate the position gradient for each pair in the +# structure. For our selected block these are all hydrogen-hydrogen pairs. +# Naively one would come up with ``8 * 8 = 64`` samples, but featomic already +# ignores pairs that are outside of the cutoff radius. Their position gradient +# is always zero. The :attr:`metatensor.block.Gradient.samples` attribute shows +# this in detail. + +print(gradient_position.samples) + +# %% +# +# Note that we have a tuple of three with the names + +print(gradient_position.samples.names) + +# %% +# +# In the above output of the Labels instance for example the `(2, 0, 17)` entry +# is missing indicating that this pair is outside of the cutoff. +# +# Now looking at the :attr:`metatensor.block.Gradient.components` + +print(gradient_position.components) + +# %% +# +# we find two of them. Besides the `o3_mu` component that is also present in the +# features position gradients also have a component indicating the direction of the +# gradient vector. +# +# Finally, the :attr:`metatensor.block.Gradient.properties` dimension is the same as for +# the values + +print(gradient_position.properties) + +# %% +# +# Featomic can also calculate gradients with respect to the strain (i.e. the virial). +# For this, you have to add ``"strain"`` to the list parsed to the ``gradients`` +# parameter of the :py:func:`featomic.calculators.CalculatorBase.compute()` method. +# Strain gradients/virial are useful when computing the stress and the pressure. +# +# If you want to know about the effect of changing hypers take a look at the next +# tutorial. If you want to solve an explicit problem our :ref:`userdoc-how-to` might +# help you. diff --git a/latest/_downloads/5bc1ea0ad98caa228fc23e8e574adf83/long-range-descriptor.zip b/latest/_downloads/5bc1ea0ad98caa228fc23e8e574adf83/long-range-descriptor.zip new file mode 100644 index 000000000..9f4cc8f47 Binary files /dev/null and b/latest/_downloads/5bc1ea0ad98caa228fc23e8e574adf83/long-range-descriptor.zip differ diff --git a/latest/_downloads/5fc41c52f18084e21db68b260d315ac3/sample-selection.ipynb b/latest/_downloads/5fc41c52f18084e21db68b260d315ac3/sample-selection.ipynb new file mode 100644 index 000000000..b6e3b3cad --- /dev/null +++ b/latest/_downloads/5fc41c52f18084e21db68b260d315ac3/sample-selection.ipynb @@ -0,0 +1,230 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# Sample Selection\n\n.. start-body\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import chemfiles\nimport numpy as np\nfrom metatensor import Labels\n\nfrom featomic import SoapPowerSpectrum" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First we load the dataset with chemfiles\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "with chemfiles.Trajectory(\"dataset.xyz\") as trajectory:\n frames = [f for f in trajectory]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "and define the hyper parameters of the representation\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "HYPER_PARAMETERS = {\n \"cutoff\": {\n \"radius\": 5.0,\n \"smoothing\": {\"type\": \"ShiftedCosine\", \"width\": 0.5},\n },\n \"density\": {\n \"type\": \"Gaussian\",\n \"width\": 0.3,\n },\n \"basis\": {\n \"type\": \"TensorProduct\",\n \"max_angular\": 4,\n \"radial\": {\"type\": \"Gto\", \"max_radial\": 6},\n },\n}\n\ncalculator = SoapPowerSpectrum(**HYPER_PARAMETERS)\n\ndescriptor = calculator.compute(frames)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The selections for sample can be a set of ``Labels``, in which case the names\nof the labels must be a subset of the names of the samples produced by the\ncalculator. You can see the default set of names with:\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(\"sample names:\", descriptor.sample_names)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can use a subset of these names to define a selection. In this case, only\nsamples matching the labels in this selection will be used by featomic (here,\nonly atoms from system 0, 2, and 3)\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "selection = Labels(\n names=[\"system\"],\n values=np.array([[0], [2], [3]]),\n)\n\ndescriptor_selected = calculator.compute(frames, selected_samples=selection)\n\ndescriptor_selected = descriptor_selected.keys_to_samples(\"center_type\")\ndescriptor_selected = descriptor_selected.keys_to_properties(\n [\"neighbor_1_type\", \"neighbor_2_type\"]\n)\n\nsamples = descriptor_selected.block().samples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The first block should have ``[0, 2, 3]`` as ``samples[\"system\"]``\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(f\"we have the following systems: {np.unique(samples['system'])}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we want to select not only based on the system indexes but also atomic\nindexes, we can do the following (here we select atom 0 in the first system\nand atom 1 in the third system):\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "selection = Labels(\n names=[\"system\", \"atom\"],\n values=np.array([[0, 0], [2, 1]]),\n)\n\ndescriptor_selected = calculator.compute(frames, selected_samples=selection)\ndescriptor_selected = descriptor_selected.keys_to_samples(\"center_type\")\ndescriptor_selected = descriptor_selected.keys_to_properties(\n [\"neighbor_1_type\", \"neighbor_2_type\"]\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The values will have 2 rows, since we have two samples:\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(\n \"shape of first block of descriptor:\",\n descriptor_selected.block(0).values.shape,\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The previous selection method uses the same selection for all blocks. If you\ncan to use different selection for different blocks, you should use a\n`TensorMap` to create your selection\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "descriptor = calculator.compute(frames)\ndescriptor_selected = calculator.compute(frames, selected_samples=selection)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "notice how we are passing a TensorMap as the ``selected_samples`` argument:\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(type(descriptor_selected))\ndescriptor_for_comparison = calculator.compute(\n frames, selected_samples=descriptor_selected\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The descriptor had 420 samples stored in the first block,\nthe ``descriptor_selected`` had 0. So ``descriptor_for_comparison``\nwill also have 0 samples.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(\"shape of first block initially:\", descriptor.block(0).values.shape)\nprint(\n \"shape of first block of reference:\",\n descriptor_selected.block(0).values.shape,\n)\nprint(\n \"shape of first block after selection:\",\n descriptor_for_comparison.block(0).values.shape,\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + ".. end-body\n\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/latest/_downloads/683cb0f50a57b05d570812adf3a45786/sample-selection.zip b/latest/_downloads/683cb0f50a57b05d570812adf3a45786/sample-selection.zip new file mode 100644 index 000000000..4faf9be44 Binary files /dev/null and b/latest/_downloads/683cb0f50a57b05d570812adf3a45786/sample-selection.zip differ diff --git a/latest/_downloads/79a7c08af4248e467d582409b4cc073c/compute-soap.ipynb b/latest/_downloads/79a7c08af4248e467d582409b4cc073c/compute-soap.ipynb new file mode 100644 index 000000000..b15c6b2fb --- /dev/null +++ b/latest/_downloads/79a7c08af4248e467d582409b4cc073c/compute-soap.ipynb @@ -0,0 +1,140 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# Computing SOAP features\n\n.. start-body\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import chemfiles\n\nfrom featomic import SoapPowerSpectrum" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Read systems using chemfiles. You can obtain the dataset used in this\nexample from our :download:`website <../../static/dataset.xyz>`.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "with chemfiles.Trajectory(\"dataset.xyz\") as trajectory:\n systems = [s for s in trajectory]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Featomic can also handles systems read by [ASE](https://wiki.fysik.dtu.dk/ase/) using\n\n``systems = ase.io.read(\"dataset.xyz\", \":\")``.\n\nWe can now define hyper parameters for the calculation\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "HYPER_PARAMETERS = {\n \"cutoff\": {\n \"radius\": 5.0,\n \"smoothing\": {\"type\": \"ShiftedCosine\", \"width\": 0.5},\n },\n \"density\": {\n \"type\": \"Gaussian\",\n \"width\": 0.3,\n },\n \"basis\": {\n \"type\": \"TensorProduct\",\n \"max_angular\": 4,\n \"radial\": {\"type\": \"Gto\", \"max_radial\": 6},\n },\n}\n\ncalculator = SoapPowerSpectrum(**HYPER_PARAMETERS)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And then run the actual calculation, including gradients with respect to positions\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "descriptor = calculator.compute(systems, gradients=[\"positions\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The descriptor is a metatensor ``TensorMap``, containing multiple blocks. We\ncan transform it to a single block containing a dense representation, with one\nsample for each atom-centered environment by using ``keys_to_samples`` and\n``keys_to_properties``\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(\"before: \", len(descriptor.keys))\n\ndescriptor = descriptor.keys_to_samples(\"center_type\")\ndescriptor = descriptor.keys_to_properties([\"neighbor_1_type\", \"neighbor_2_type\"])\nprint(\"after: \", len(descriptor.keys))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "you can now use ``descriptor.block().values`` as the input of a machine\nlearning algorithm\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(descriptor.block().values.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + ".. end-body\n\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/latest/_downloads/94fe16a4bed8662f3e4bf7df34cf7786/first-calculation.zip b/latest/_downloads/94fe16a4bed8662f3e4bf7df34cf7786/first-calculation.zip new file mode 100644 index 000000000..8b8324678 Binary files /dev/null and b/latest/_downloads/94fe16a4bed8662f3e4bf7df34cf7786/first-calculation.zip differ diff --git a/latest/_downloads/a61b9667afd1dd08cd2729044cdfcc9a/profiling.ipynb b/latest/_downloads/a61b9667afd1dd08cd2729044cdfcc9a/profiling.ipynb new file mode 100644 index 000000000..29f74636d --- /dev/null +++ b/latest/_downloads/a61b9667afd1dd08cd2729044cdfcc9a/profiling.ipynb @@ -0,0 +1,104 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# Profiling calculation\n\n.. start-body\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import chemfiles\n\nimport featomic\nfrom featomic import SoapPowerSpectrum\n\n\ndef compute_soap(path):\n \"\"\"Compute SOAP power spectrum.\n\n This is the same code as the 'compute-soap' example\n \"\"\"\n with chemfiles.Trajectory(path) as trajectory:\n frames = [f for f in trajectory]\n\n HYPER_PARAMETERS = {\n \"cutoff\": {\n \"radius\": 5.0,\n \"smoothing\": {\"type\": \"ShiftedCosine\", \"width\": 0.5},\n },\n \"density\": {\n \"type\": \"Gaussian\",\n \"width\": 0.3,\n },\n \"basis\": {\n \"type\": \"TensorProduct\",\n \"max_angular\": 4,\n \"radial\": {\"type\": \"Gto\", \"max_radial\": 6},\n },\n }\n\n calculator = SoapPowerSpectrum(**HYPER_PARAMETERS)\n descriptor = calculator.compute(frames, gradients=[\"positions\"])\n descriptor = descriptor.keys_to_samples(\"center_type\")\n descriptor = descriptor.keys_to_properties([\"neighbor_1_type\", \"neighbor_2_type\"])\n\n return descriptor" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Run the calculation with profiling enabled.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "with featomic.Profiler() as profiler:\n descriptor = compute_soap(\"dataset.xyz\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display the recorded profiling data as table.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(profiler.as_short_table())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can also save this data as json for future usage\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(profiler.as_json())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + ".. end-body\n\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/latest/_downloads/b1679995c5f5a7c97fd29b7a3990fedc/compute-soap.py b/latest/_downloads/b1679995c5f5a7c97fd29b7a3990fedc/compute-soap.py new file mode 100644 index 000000000..b1d98520f --- /dev/null +++ b/latest/_downloads/b1679995c5f5a7c97fd29b7a3990fedc/compute-soap.py @@ -0,0 +1,77 @@ +""" +Computing SOAP features +======================= + +.. start-body +""" + +import chemfiles + +from featomic import SoapPowerSpectrum + + +# %% +# +# Read systems using chemfiles. You can obtain the dataset used in this +# example from our :download:`website <../../static/dataset.xyz>`. + +with chemfiles.Trajectory("dataset.xyz") as trajectory: + systems = [s for s in trajectory] + +# %% +# +# Featomic can also handles systems read by `ASE +# `_ using +# +# ``systems = ase.io.read("dataset.xyz", ":")``. +# +# We can now define hyper parameters for the calculation + +HYPER_PARAMETERS = { + "cutoff": { + "radius": 5.0, + "smoothing": {"type": "ShiftedCosine", "width": 0.5}, + }, + "density": { + "type": "Gaussian", + "width": 0.3, + }, + "basis": { + "type": "TensorProduct", + "max_angular": 4, + "radial": {"type": "Gto", "max_radial": 6}, + }, +} + +calculator = SoapPowerSpectrum(**HYPER_PARAMETERS) + +# %% +# +# And then run the actual calculation, including gradients with respect to positions + +descriptor = calculator.compute(systems, gradients=["positions"]) + +# %% +# +# The descriptor is a metatensor ``TensorMap``, containing multiple blocks. We +# can transform it to a single block containing a dense representation, with one +# sample for each atom-centered environment by using ``keys_to_samples`` and +# ``keys_to_properties`` + +print("before: ", len(descriptor.keys)) + +descriptor = descriptor.keys_to_samples("center_type") +descriptor = descriptor.keys_to_properties(["neighbor_1_type", "neighbor_2_type"]) +print("after: ", len(descriptor.keys)) + +# %% +# +# you can now use ``descriptor.block().values`` as the input of a machine +# learning algorithm + +print(descriptor.block().values.shape) + + +# %% +# +# .. end-body diff --git a/latest/_downloads/b957f733884c5245e2a56cba651d0969/splined-radial-integral.py b/latest/_downloads/b957f733884c5245e2a56cba651d0969/splined-radial-integral.py new file mode 100644 index 000000000..941d309d3 --- /dev/null +++ b/latest/_downloads/b957f733884c5245e2a56cba651d0969/splined-radial-integral.py @@ -0,0 +1,201 @@ +""" +Splined radial integrals +======================== + +.. start-body + +This example illustrates how to generate splines and use custom basis function and +density when computing density-based representations, such as SOAP or LODE. +""" + +# %% + +import json + +import ase.build +import matplotlib.pyplot as plt +import numpy as np +import scipy + +import featomic +from featomic import SphericalExpansion +from featomic.basis import RadialBasis +from featomic.splines import SoapSpliner + + +# %% +# +# For this example, we will define a new custom radial basis for the SOAP spherical +# expansion, based on Chebyshev polynomials of the first kind. This basis will then be +# used in combination with spherical harmonics to expand the density of neighboring +# atoms around a central atom. +# +# In featomic, defining custom radial basis is done by creating a class inheriting from +# :py:class:`featomic.basis.RadialBasis`, and implementing the required method. The +# main one is ``compute_primitive``, which evaluates the radial basis on a set of +# points. This function should also be able to evaluate the derivative of the radial +# basis. If needed :py:meth:`featomic.basis.RadialBasis.finite_differences_derivative` +# can be used to compute the derivative with finite differences. + + +class Chebyshev(RadialBasis): + def __init__(self, max_radial, radius): + # initialize `RadialBasis` + super().__init__(max_radial=max_radial, radius=radius) + + def compute_primitive(self, positions, n, *, derivative=False): + # map argument from [0, cutoff] to [-1, 1] + z = 2 * positions / self.radius - 1 + if derivative: + return -2 * n / self.radius * scipy.special.chebyu(n)(z) + else: + return scipy.special.chebyt(n + 1)(z) + + @property + def integration_radius(self): + return self.radius + + +# %% +# +# We can now look at the basis functions and their derivatives +radius = 4.5 +basis = Chebyshev(max_radial=4, radius=radius) + +r = np.linspace(0, radius) +for n in range(basis.size): + plt.plot(r, basis.compute_primitive(r, n, derivative=False)) + +plt.title("Chebyshev radial basis functions") +plt.show() + +# %% +for n in range(basis.size): + plt.plot(r, basis.compute_primitive(r, n, derivative=True)) +plt.title("Chebyshev radial basis functions' derivatives") +plt.show() + +# %% +# +# Before being used by featomic, the basis functions we implemented will be +# orthogonalized and normalized, to improve conditioning of the produced features. This +# is done automatically, and one can access the orthonormalized basis functions with the +# :py:meth:`featomic.basis.RadialBasis.compute` method. + +basis_orthonormal = basis.compute(r, derivative=False) +for n in range(basis.size): + plt.plot(r, basis_orthonormal[:, n]) + +plt.title("Orthonormalized Chebyshev radial basis functions") +plt.show() + + +# %% +# +# With this, our new radial basis definition is ready to be used with +# :py:class:`featomic.splines.SoapSpliner`. This class will take the whole set of hyper +# parameters, use them to compute a spline of the radial integral, and give us back new +# hypers that can be used with the native calculators to compute the expansion with our +# custom basis. +# + +spliner = SoapSpliner( + cutoff=featomic.cutoff.Cutoff( + radius=radius, + smoothing=featomic.cutoff.ShiftedCosine(width=0.3), + ), + density=featomic.density.Gaussian(width=0.5), + basis=featomic.basis.TensorProduct( + max_angular=4, + radial=Chebyshev(max_radial=4, radius=radius), + spline_accuracy=1e-4, + ), +) + +hypers = spliner.get_hypers() + +# %% +# +# The hyper parameters have been transformed from what we gave to the +# :py:class:`featomic.splines.SoapSpliner`: + +print("hypers['basis'] is", type(hypers["basis"])) +print("hypers['density'] is", type(hypers["density"])) + +# %% +# +# And the new hypers can be used directly with the calculators: + +calculator_splined = SphericalExpansion(**hypers) + +# %% +# +# As a comparison, let's look at the expansion coefficient for formic acid, using both +# our splined radial basis and the classic GTO radial basis: + +atoms = ase.build.molecule("HCOOH", vacuum=4, pbc=True) + +calculator_gto = SphericalExpansion( + # same parameters, only the radial basis changed + cutoff=featomic.cutoff.Cutoff( + radius=radius, + smoothing=featomic.cutoff.ShiftedCosine(width=0.3), + ), + density=featomic.density.Gaussian(width=0.5), + basis=featomic.basis.TensorProduct( + max_angular=4, + radial=featomic.basis.Gto(max_radial=4, radius=radius), + spline_accuracy=1e-4, + ), +) + +expansion_splined = calculator_splined.compute(atoms) +expansion_gto = calculator_gto.compute(atoms) + +# %% +# +# As you can see, the coefficients ends up different, with values assigned to different +# basis functions. In practice, which basis function will be the best will depend on the +# use case and exact dataset, so you should try a couple and check how they performe for +# you! + +selection = dict(o3_lambda=0, center_type=8, neighbor_type=1) + +plt.matshow(expansion_splined.block(selection).values.reshape(2, 5)) +plt.matshow(expansion_gto.block(selection).values.reshape(2, 5)) + + +# %% +# +# Since the calculation of the splines requires computing some integral numerically, the +# creation of the splines might take a while. After an initial calculation, you can save +# the splines data in JSON files; and then reload them later to re-use: + +# convert the hypers from classes to a pure JSON-compatible dictionary +json_hypers = featomic.utils.hypers_to_json(hypers) + +# save the data to a file +with open("splined-hypers.json", "w") as fp: + json.dump(json_hypers, fp) + + +# load the data from the file +with open("splined-hypers.json", "r") as fp: + json_hypers = json.load(fp) + +# the hypers can be used directly with the calculators +calculator = featomic.SphericalExpansion(**json_hypers) + + +# %% +# +# Finally, you can use the same method to define custom +# :py:class:`featomic.basis.ExpansionBasis` and custom +# :py:class:`featomic.density.AtomicDensity`; by creating a new class inheriting from +# the corresponding base class and implementing the corresponding methods. This allow +# you to create a fully custom spherical expansion, and evaluate them efficiently +# through the splines. + +# %% +# +# .. end-body diff --git a/latest/_downloads/baed817b984659f054f6dbda1066cc00/dataset.xyz b/latest/_downloads/baed817b984659f054f6dbda1066cc00/dataset.xyz new file mode 100644 index 000000000..c3442edc7 --- /dev/null +++ b/latest/_downloads/baed817b984659f054f6dbda1066cc00/dataset.xyz @@ -0,0 +1,1460 @@ +20 +Lattice="3.549 0.0 0.0 1.3633044072019755 5.103237985172127 0.0 0.35276448037117664 1.5448560525892414 9.295297809008963" Properties=species:S:1:pos:R:3:forces:R:3 energy=-4554.712769935985 energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="6 4 3" name crystal=WETGAE frame=0 pbc="T T T" +O 2.02312000 5.14665000 8.33983000 0.00103696 -0.01740519 -0.00528151 +O 3.24139000 1.50498000 0.95734500 0.00424216 -0.01735464 -0.00118144 +O 3.78983000 5.16709000 7.00368000 0.00266048 0.00637094 0.00200116 +O 1.47589000 1.48008000 2.29292000 -0.00487235 0.00590037 -0.00369057 +C 1.19211000 4.59081000 7.60062000 -0.01251664 -0.00378144 -0.00135354 +C 4.07440000 2.05806000 1.69639000 -0.00081186 -0.00519296 -0.00527930 +C 1.32438000 3.12357000 7.32355000 -0.01118533 -0.01352241 -0.00298926 +C 3.94244000 3.52474000 1.97145000 -0.00626146 0.00961788 0.00582144 +N 2.25042000 2.40973000 7.83079000 -0.00491906 0.00048798 -0.00455194 +N 3.01492000 4.23670000 1.46462000 0.00094263 0.01582550 -0.00162208 +N 0.41467800 2.55219000 6.57338000 -0.00283916 -0.00059027 0.00454750 +N 4.85187000 4.09716000 2.72072000 -0.01353110 -0.00918887 -0.00424976 +H 2.78121000 2.77377000 8.63105000 0.01394746 -0.00669947 -0.00138909 +H 2.48047000 3.87485000 0.66598600 0.00747682 -0.00794810 -0.00622834 +H 2.25505000 1.34633000 7.62757000 -0.00127826 0.02236824 -0.00203658 +H 3.01078000 5.29825000 1.66709000 0.00000215 0.00814022 0.00293038 +H -0.16194500 3.15012000 5.99969000 0.00684453 0.01323727 0.00146462 +H 5.42528000 3.49582000 3.29452000 0.00379395 0.01589929 0.00757051 +H 0.49478100 1.56012000 6.34200000 0.00823941 -0.00174164 0.00918537 +H 4.76962000 5.08990000 2.94978000 0.00902863 -0.01442260 0.00633232 +20 +Lattice="3.549 0.0 0.0 1.3633044072019755 5.103237985172127 0.0 0.35276448037117664 1.5448560525892414 9.295297809008963" Properties=species:S:1:pos:R:3:forces:R:3 energy=-4554.148814003207 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="6 4 3" crystal=WETGAE frame=10 pbc="T T T" +O 1.92656000 5.16795000 8.36906000 -0.36745744 -1.21622950 -1.36700927 +O 3.27764000 1.51044000 1.01515000 -0.92159650 -0.46687017 -0.99486266 +O 3.76698000 5.13299000 6.97579000 -1.30370357 0.36655292 -0.79114387 +O 1.50207000 1.49556000 2.37677000 -1.52027787 1.09879693 -1.67458006 +C 1.14604000 4.55900000 7.55326000 2.23006690 1.40948904 2.39111052 +C 4.08985000 2.10274000 1.71427000 2.39069400 -2.09158214 2.31800377 +C 1.36874000 3.12640000 7.27091000 -0.86687828 -1.33618689 -0.74383043 +C 3.93391000 3.52197000 2.00293000 0.21302464 1.18447123 0.12637692 +N 2.30584000 2.39665000 7.77803000 -1.42465340 1.74009177 -0.77371179 +N 2.98294000 4.20389000 1.47197000 0.66249101 0.87222104 -0.46929883 +N 0.46041300 2.56040000 6.48784000 1.58079650 -1.49634090 1.09518710 +N 4.83780000 4.11548000 2.75255000 -0.68905565 -1.02492400 -1.09080080 +H 2.76424000 2.82101000 8.56286000 0.84928165 0.10345553 0.87798545 +H 2.56107000 3.78141000 0.62587100 -0.39540327 0.12542407 0.35386761 +H 2.27450000 1.37301000 7.62974000 0.04181195 -1.12155120 -0.13834232 +H 3.03297000 5.29534000 1.51899000 -0.09632175 -0.79619866 0.64661188 +H -0.22770800 3.11119000 6.06124000 -0.64043609 0.94046840 -0.73512467 +H 5.46554000 3.51539000 3.25209000 0.08316593 -0.09030537 0.37348564 +H 0.53241600 1.55776000 6.22384000 0.00028407 0.62538999 0.27057416 +H 4.67216000 5.06885000 2.99095000 0.17416499 1.17382686 0.32550115 +20 +Lattice="3.549 0.0 0.0 1.3633044072019755 5.103237985172127 0.0 0.35276448037117664 1.5448560525892414 9.295297809008963" Properties=species:S:1:pos:R:3:forces:R:3 energy=-4553.967776665655 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="6 4 3" crystal=WETGAE frame=20 pbc="T T T" +O 2.06789000 5.17952000 8.30616000 0.23840348 0.22239940 0.71644818 +O 3.23007000 1.40283000 1.04010000 -0.06763235 0.02315453 -0.44059195 +O 3.81204000 5.19836000 6.99141000 0.92313402 -0.91092128 0.31702422 +O 1.48425000 1.44214000 2.38186000 -1.70758788 1.30116332 -1.11007893 +C 1.23747000 4.61060000 7.60972000 -1.22082663 -0.11864716 -1.05155034 +C 4.06911000 2.01020000 1.71613000 1.03941988 -0.06776348 1.49959078 +C 1.35438000 3.12995000 7.30768000 -0.98736532 0.46136184 -0.89278472 +C 3.88257000 3.50982000 1.95221000 2.23570276 0.45386861 1.89116465 +N 2.24173000 2.38397000 7.78908000 0.55689580 -1.65735367 -0.93838581 +N 2.93986000 4.24710000 1.49110000 0.48725027 -2.60866184 -0.41585228 +N 0.44838700 2.65431000 6.44118000 0.04663621 0.44261952 0.70955762 +N 4.84237000 4.11686000 2.74628000 -2.44765936 -2.32369105 -2.18124679 +H 2.81179000 2.54729000 8.61888000 0.01162956 0.75288585 0.04292806 +H 2.35794000 3.93865000 0.69615400 0.40003743 -0.12768150 0.11747885 +H 2.30860000 1.25728000 7.40625000 -0.21047719 0.78887101 0.46415765 +H 2.86528000 5.22819000 1.75738000 0.53186354 1.93267768 0.45206987 +H -0.15882300 3.38167000 6.03597000 0.50703440 -0.58116702 0.11901688 +H 5.40139000 3.59485000 3.41026000 -0.23945455 -0.36304234 -0.27803344 +H 0.47176100 1.70218000 6.02326000 0.11987614 0.62440269 0.58014886 +H 4.63041000 5.05044000 2.97853000 -0.21687975 1.75551839 0.39893957 +20 +Lattice="3.549 0.0 0.0 1.3633044072019755 5.103237985172127 0.0 0.35276448037117664 1.5448560525892414 9.295297809008963" Properties=species:S:1:pos:R:3:forces:R:3 energy=-4554.122663863212 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="6 4 3" crystal=WETGAE frame=30 pbc="T T T" +O 2.16133000 5.20068000 8.25427000 -0.80078036 -0.06588452 0.23027520 +O 3.20668000 1.43403000 1.01369000 -0.33738941 -0.52908161 -0.24162096 +O 3.85544000 5.29320000 7.01478000 -0.23462962 0.05616832 -1.12804066 +O 1.44338000 1.32894000 2.34493000 -0.14894298 0.71589282 0.19256997 +C 1.26752000 4.69557000 7.53938000 0.76420385 -1.12845718 0.89502158 +C 4.04136000 1.92992000 1.77669000 0.10442227 1.28746962 -0.23412363 +C 1.32594000 3.19550000 7.27099000 0.02984953 1.60516027 0.34374004 +C 3.89701000 3.45365000 2.00020000 0.87090977 -1.36755949 0.73980922 +N 2.24612000 2.48301000 7.76849000 0.74835557 0.91850604 1.25200383 +N 3.00617000 4.14572000 1.46970000 -2.22322262 -0.39358961 -1.41212699 +N 0.38593200 2.67319000 6.54895000 2.19999013 -4.10329553 1.03333150 +N 4.75362000 4.06625000 2.75946000 1.58321334 -3.02760767 0.06877958 +H 2.71423000 2.85802000 8.63251000 -0.09217970 -0.40721235 -0.87983664 +H 2.45950000 3.71235000 0.70339700 0.12292598 0.49596066 0.18109874 +H 2.32867000 1.43994000 7.53840000 -0.26832804 -0.37949431 0.19497035 +H 2.94334000 5.18374000 1.68831000 0.09873910 0.39651450 -0.05799895 +H -0.15364900 3.25961000 6.02224000 -1.66220791 1.45145458 -1.80328948 +H 5.34508000 3.40773000 3.25945000 0.09870157 0.53475860 0.26217899 +H 0.51927200 1.61404000 6.37441000 -0.69431098 1.94853624 -0.10719700 +H 4.63788000 4.99143000 3.05059000 -0.15931532 1.99176677 0.47045531 +20 +Lattice="3.549 0.0 0.0 1.3633044072019755 5.103237985172127 0.0 0.35276448037117664 1.5448560525892414 9.295297809008963" Properties=species:S:1:pos:R:3:forces:R:3 energy=-4553.878332846545 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="6 4 3" crystal=WETGAE frame=49 pbc="T T T" +O 1.95530000 5.22182000 8.21070000 -1.63334985 -1.05225482 -2.33849546 +O 3.29803000 1.50378000 1.01129000 0.36292510 0.61525984 0.64950180 +O 3.73313000 5.13207000 6.77995000 -0.78614050 1.33941105 -0.32467582 +O 1.49937000 1.46085000 2.36878000 1.29535777 0.30004003 1.06109942 +C 1.12896000 4.64239000 7.39802000 2.05847661 -1.09593787 2.82728788 +C 4.13943000 2.04965000 1.76877000 -1.79811128 0.47532396 -1.60758739 +C 1.25711000 3.11195000 7.26438000 0.00224330 0.62654699 -0.08035160 +C 4.04787000 3.54617000 2.03875000 -1.24168342 -0.42746441 0.14378946 +N 2.15938000 2.42732000 7.85262000 0.17133729 -0.23795920 -0.82308726 +N 3.11824000 4.30837000 1.62665000 -1.04224295 -2.97950747 -1.62659299 +N 0.37757000 2.46219000 6.54384000 -0.00639521 0.77194801 0.32180030 +N 4.89243000 4.04662000 2.86788000 0.37486376 2.56778644 0.67410725 +H 2.76062000 2.79273000 8.57612000 0.08311502 0.18232875 0.46966701 +H 2.49198000 3.85500000 0.94258900 0.41770708 0.83866814 0.00983077 +H 2.10449000 1.40409000 7.65520000 0.26079676 -0.39858630 0.31379029 +H 3.02087000 5.29781000 1.94968000 0.05456087 1.23157898 -0.32846203 +H -0.19171100 3.07456000 5.94730000 0.09347400 -0.83991255 0.24352358 +H 5.53147000 3.37799000 3.17420000 1.42214915 -0.73435334 1.23672633 +H 0.40388600 1.42362000 6.55898000 -0.15179639 0.68400600 -0.43559887 +H 4.88600000 5.08086000 3.15639000 0.06270766 -1.86692943 -0.38627431 +20 +Lattice="3.549 0.0 0.0 1.3633044072019755 5.103237985172127 0.0 0.35276448037117664 1.5448560525892414 9.295297809008963" Properties=species:S:1:pos:R:3:forces:R:3 energy=-4553.918660117589 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="6 4 3" crystal=WETGAE frame=50 pbc="T T T" +O 1.95734000 5.18497000 8.17907000 -0.12563336 -0.19892060 -0.83751629 +O 3.29538000 1.50293000 1.05122000 -0.01987231 0.35695037 -0.15486988 +O 3.73667000 5.12956000 6.76638000 0.84188202 0.19218019 0.70029651 +O 1.49691000 1.47436000 2.37821000 1.51639551 0.35868278 1.09882264 +C 1.15719000 4.61125000 7.40622000 -1.26484392 -0.53653781 0.33200861 +C 4.14150000 2.06717000 1.76753000 -1.66096350 0.46774537 -1.18810677 +C 1.23252000 3.08337000 7.28994000 0.63676969 0.87219018 -0.53783879 +C 4.04621000 3.55977000 1.99675000 0.66497470 0.26940533 2.29178366 +N 2.15464000 2.41336000 7.87549000 -0.05508640 -0.78558514 -0.71416504 +N 3.11598000 4.32609000 1.61421000 -0.71225214 -0.40956953 -0.79545818 +N 0.36513900 2.45908000 6.51799000 1.18599332 0.79830182 1.92618821 +N 4.89272000 4.08107000 2.88437000 1.61173716 -1.67609187 -0.07453011 +H 2.87324000 2.76684000 8.51594000 -0.85149280 0.09700567 0.15498507 +H 2.45967000 3.93860000 0.94520400 0.11175608 0.17423698 -0.29999837 +H 2.00875000 1.37812000 7.75982000 0.67062598 -0.15442766 0.10833395 +H 3.01273000 5.41422000 1.96652000 0.30067200 -0.38484169 -0.61492046 +H -0.17695100 3.07169000 5.95637000 -0.83310427 0.20759601 -0.54115037 +H 5.68878000 3.50958000 3.21562000 -1.24594117 0.34643095 -0.32371012 +H 0.37917600 1.45078000 6.48159000 -0.15625931 -0.48896623 -0.42065459 +H 4.97263000 5.05358000 3.15132000 -0.61535755 0.49421642 -0.10948734 +20 +Lattice="3.549 0.0 0.0 1.3633044072019755 5.103237985172127 0.0 0.35276448037117664 1.5448560525892414 9.295297809008963" Properties=species:S:1:pos:R:3:forces:R:3 energy=-4554.049247549261 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="6 4 3" crystal=WETGAE frame=70 pbc="T T T" +O 2.05539000 4.98245000 8.29100000 -1.06895157 -0.86277480 -1.34667699 +O 3.20028000 1.73013000 1.08101000 0.10267906 -0.08866089 -0.49197442 +O 3.84105000 4.87653000 6.87368000 0.07016386 1.08661505 0.69299972 +O 1.43242000 1.72841000 2.40406000 0.91681939 -0.80465759 0.07099536 +C 1.24786000 4.37396000 7.53049000 0.61151118 -0.19975518 0.71176877 +C 4.07432000 2.29992000 1.76150000 -0.98129752 -0.43627096 0.43796120 +C 1.35858000 2.88280000 7.24830000 -0.23388091 0.85661444 -0.06525614 +C 3.90793000 3.75078000 2.06340000 1.35422060 -1.36950838 0.10238030 +N 2.28716000 2.14815000 7.73285000 -0.08862593 -0.22452878 0.77294560 +N 2.97860000 4.39014000 1.53082000 -2.33735903 1.45433936 -2.01691730 +N 0.42096500 2.38687000 6.45583000 1.47525272 -0.78124512 0.98253165 +N 4.80560000 4.33786000 2.80249000 -1.32569164 2.41184389 -0.39850762 +H 2.72369000 2.49648000 8.64676000 -0.18828137 -0.42257160 -1.45192253 +H 2.49188000 4.01660000 0.64549600 0.60760310 0.30550311 1.57097489 +H 2.27884000 1.04060000 7.47685000 0.08198220 0.75507129 0.15867615 +H 2.88155000 5.42473000 1.76195000 0.31348741 0.37162519 -0.13754271 +H -0.07909820 3.07895000 5.87639000 0.21543839 -0.79905258 0.26745901 +H 5.37726000 3.77563000 3.36822000 0.76540713 -0.71195903 0.88338991 +H 0.58391200 1.36833000 6.27639000 -0.72496367 0.89921248 -0.49411101 +H 4.64826000 5.37241000 3.01294000 0.43448507 -1.43984348 -0.24917126 +20 +Lattice="3.549 0.0 0.0 1.3633044072019755 5.103237985172127 0.0 0.35276448037117664 1.5448560525892414 9.295297809008963" Properties=species:S:1:pos:R:3:forces:R:3 energy=-4553.997409862798 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="6 4 3" crystal=WETGAE frame=80 pbc="T T T" +O 2.00493000 4.90163000 8.29247000 0.72512823 0.92113885 0.53687205 +O 3.24267000 1.76257000 0.91952400 -0.23366083 -0.30588620 -0.06551891 +O 3.79259000 5.02393000 6.94426000 -0.31399340 -0.12479158 -0.06180161 +O 1.46709000 1.71027000 2.31358000 -0.76429641 0.21997433 -1.11877440 +C 1.18228000 4.42292000 7.51908000 -0.01050964 -1.52345576 -0.35298418 +C 4.06934000 2.28818000 1.66916000 1.15406537 -0.24131243 1.77467825 +C 1.37477000 2.90450000 7.24939000 -1.94044241 1.82976156 -1.18118022 +C 3.92306000 3.73836000 2.05554000 -0.82933504 -0.44951676 0.02687188 +N 2.28986000 2.27847000 7.80978000 2.39566137 -2.06573227 1.23602185 +N 2.91273000 4.41137000 1.59399000 1.25771168 -1.71795971 -1.80635424 +N 0.49951200 2.21713000 6.52059000 0.37811106 0.49140004 -0.40799859 +N 4.78976000 4.25529000 2.90047000 -0.05675813 -0.86258454 -0.97752314 +H 2.92263000 2.67944000 8.53974000 -0.96002935 -0.07114808 -0.48124675 +H 2.43621000 3.93958000 0.73158100 0.76836904 0.95382785 1.57063036 +H 2.33097000 1.18759000 7.62961000 -0.01411387 0.49512813 0.01364227 +H 3.00264000 5.44501000 1.63791000 -0.40952788 1.00936368 0.38502270 +H -0.04486260 2.74267000 5.81971000 0.35412832 -0.41517711 0.57170021 +H 5.54230000 3.65941000 3.26542000 -1.02927430 0.42162184 -0.18201662 +H 0.81296200 1.24794000 6.27607000 -0.56292761 0.70195744 0.24740903 +H 4.72412000 5.23451000 3.12939000 0.09169582 0.73339689 0.27254876 +20 +Lattice="3.549 0.0 0.0 1.3633044072019755 5.103237985172127 0.0 0.35276448037117664 1.5448560525892414 9.295297809008963" Properties=species:S:1:pos:R:3:forces:R:3 energy=-4553.773895554868 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="6 4 3" crystal=WETGAE frame=99 pbc="T T T" +O 2.00349000 4.94651000 8.36262000 -2.10015934 -0.57841594 -2.19078558 +O 3.29525000 1.65483000 1.00945000 0.51088128 0.48952622 0.60066626 +O 3.75125000 4.94654000 6.87115000 1.67329451 0.03698784 2.28414234 +O 1.56187000 1.69327000 2.34887000 -1.33045847 0.26916262 -0.25522416 +C 1.14570000 4.41213000 7.57423000 0.32878187 0.55436584 0.10769066 +C 4.10736000 2.23671000 1.76219000 0.69827562 0.18725447 -0.06071352 +C 1.23128000 2.92828000 7.30920000 1.32538311 0.11814939 0.77767129 +C 3.97761000 3.77422000 2.01574000 0.40610729 -2.50636279 -0.68432482 +N 2.14770000 2.16052000 7.82554000 -0.83811792 1.15385968 -0.46463074 +N 3.08774000 4.47143000 1.42284000 1.16669977 -0.00572487 1.68559981 +N 0.34756300 2.43801000 6.50091000 -0.63566926 0.70965018 0.44271260 +N 4.91710000 4.24873000 2.79010000 -1.01893333 2.35736736 -0.98405888 +H 2.61596000 2.43659000 8.69445000 0.23180141 0.57466213 -0.35397457 +H 2.50480000 4.11518000 0.67923600 -0.14269777 -0.30434200 -0.45643920 +H 2.16255000 1.12117000 7.63823000 -0.37379675 -0.29022870 -0.62410444 +H 3.24542000 5.50123000 1.62103000 -0.92494408 0.61737329 -0.17153423 +H -0.27505600 2.97891000 5.92325000 0.23059761 0.77238510 0.35168629 +H 5.39031000 3.53680000 3.32410000 0.55019037 0.05239548 0.05532551 +H 0.31719400 1.49734000 6.27291000 0.32707055 -2.75970901 -0.33277171 +H 5.03386000 5.30237000 2.89795000 -0.08430750 -1.44835383 0.27306967 +20 +Lattice="3.549 0.0 0.0 1.3633044072019755 5.103237985172127 0.0 0.35276448037117664 1.5448560525892414 9.295297809008963" Properties=species:S:1:pos:R:3:forces:R:3 energy=-4553.903503376718 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="6 4 3" crystal=WETGAE frame=100 pbc="T T T" +O 1.99527000 4.93170000 8.34732000 -0.78368767 0.35432835 -0.86289307 +O 3.34021000 1.69072000 1.01270000 -2.34640932 -1.57231186 -2.20191332 +O 3.73761000 4.95928000 6.89728000 1.79604926 -0.26233068 2.26685424 +O 1.56751000 1.70591000 2.33475000 -0.76180758 -0.17302856 -0.16182318 +C 1.16048000 4.41250000 7.58876000 -1.33664969 -0.00929228 -1.13156821 +C 4.11373000 2.23669000 1.73835000 2.93708941 2.20337370 2.27626962 +C 1.23963000 2.93055000 7.32532000 -1.04118879 -0.24656468 -1.23486485 +C 3.98155000 3.74697000 2.01121000 0.73210106 0.10850261 -0.06742512 +N 2.12846000 2.15251000 7.82481000 -0.88446977 0.03324226 -0.83933663 +N 3.08176000 4.45482000 1.43845000 0.05372526 -0.43499260 0.13030865 +N 0.31105700 2.42921000 6.50133000 1.32806734 -2.54503218 1.38763980 +N 4.93561000 4.27300000 2.77449000 -0.83093426 -2.77516134 -0.75975070 +H 2.65463000 2.52539000 8.61741000 0.20883477 -0.18313968 0.00845831 +H 2.55292000 4.01181000 0.65202400 0.29607127 0.46359047 0.70963476 +H 2.00871000 1.04209000 7.57407000 0.92478467 0.81209836 0.17821962 +H 3.11078000 5.53428000 1.59976000 -0.15148271 -0.24540974 0.23410511 +H -0.23810800 3.01654000 5.89468000 -0.03345005 0.26506428 0.18846392 +H 5.38198000 3.45210000 3.27173000 -0.02377396 1.48146964 -0.42777449 +H 0.31177200 1.36250000 6.33988000 -0.01905712 1.97418557 0.04293305 +H 4.95833000 5.22782000 3.07951000 -0.06380707 0.75141518 0.26445904 +44 +Lattice="6.6604 0.0 0.0 -1.9016531446419103 6.428112286470541 0.0 -1.2514063926874133 -2.2750363427377365 12.652321829591736" Properties=species:S:1:pos:R:3:forces:R:3 energy=-14302.429185648707 energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" name crystal=COVSEM frame=0 pbc="T T T" +N -2.10781000 4.14157000 8.23142000 -0.00528285 -0.00008150 0.00338993 +N 5.61516000 0.01149850 4.42090000 0.00510283 0.00011858 -0.00342169 +N 2.94458000 3.53473000 6.81278000 -0.00167876 -0.00476051 -0.00019830 +N 0.56276400 0.61833500 5.83954000 0.00181871 0.00488240 0.00020377 +N 4.14582000 3.60605000 6.10032000 -0.00031166 0.00207279 0.00239113 +N -0.63847600 0.54702200 6.55201000 0.00042463 -0.00208512 -0.00237107 +N -1.32727000 4.55736000 9.27272000 0.00122129 0.00114195 -0.00168966 +N 4.83461000 -0.40428400 3.37961000 -0.00134817 -0.00123926 0.00148556 +N -0.10794100 -1.49487000 10.26550000 0.00766261 -0.00053151 0.00245414 +N 3.61528000 5.64794000 2.38679000 -0.00769953 0.00049470 -0.00254534 +N 0.70221700 -1.11074000 11.30080000 0.00165949 0.00286007 -0.00155214 +N 2.80512000 5.26381000 1.35154000 -0.00166707 -0.00284339 0.00152013 +N 2.44068000 1.88191000 0.69653500 -0.00158319 -0.00194419 -0.00034735 +N 1.06665000 2.27116000 11.95580000 0.00161436 0.00196660 0.00040543 +N 2.38326000 -0.64630300 12.65710000 -0.00382120 -0.00024682 -0.00286528 +N 1.12407000 4.79938000 -0.00474388 0.00401081 0.00026068 0.00291123 +N -0.21034700 4.10380000 6.73503000 0.00215183 -0.00012099 0.00213230 +N 3.71769000 0.04928010 5.91730000 -0.00219621 0.00010134 -0.00215678 +N 0.15372800 3.88200000 5.56163000 0.00432243 0.00185584 0.00153216 +N 3.35361000 0.27107200 7.09070000 -0.00422848 -0.00185488 -0.00169331 +N 0.61380900 3.72061000 4.53098000 0.00142186 0.00172799 -0.00063261 +N 2.89353000 0.43247000 8.12135000 -0.00146498 -0.00172460 0.00072065 +N 2.31844000 3.72566000 9.15348000 0.00270527 -0.00247697 -0.00093396 +N 1.18890000 0.42740900 3.49883000 -0.00287218 0.00240244 0.00105762 +N 1.37156000 2.91150000 8.98770000 0.00395927 -0.00157178 -0.00281550 +N 2.13578000 1.24158000 3.66462000 -0.00322703 0.00214907 0.00272387 +N 0.47774100 2.20840000 9.03724000 0.00406855 0.00021633 0.00138437 +N 3.02960000 1.94468000 3.61508000 -0.00459440 -0.00064379 -0.00134110 +N 0.07374670 1.66892000 0.05168720 -0.00063073 0.00148833 0.00081753 +N 3.43360000 2.48416000 12.60060000 0.00036806 -0.00142823 -0.00069314 +N -0.29771000 2.12702000 1.15506000 0.00346891 0.00238938 0.00207561 +N 3.80504000 2.02606000 11.49730000 -0.00293358 -0.00273951 -0.00281498 +N -0.78275100 2.52123000 2.10840000 -0.00040548 0.00124346 0.00156724 +N 4.29009000 1.63184000 10.54390000 0.00006312 -0.00099095 -0.00101192 +C -1.57035000 3.93650000 6.96195000 -0.00083122 -0.00150032 0.00477367 +C 5.07769000 0.21657400 5.69037000 0.00083368 0.00149927 -0.00475394 +C 3.18943000 3.82709000 8.07560000 -0.00368889 0.00117381 -0.00098713 +C 0.31791300 0.32599200 4.57672000 0.00365211 -0.00131527 0.00109381 +C 0.19604800 -0.67586700 12.51810000 -0.00117277 -0.00103700 -0.00012319 +C 3.31129000 4.82894000 0.13422000 0.00111437 0.00107604 0.00023297 +C 2.08549000 -1.06791000 11.44780000 -0.00289611 0.00075695 -0.00287753 +C 1.42184000 5.22098000 1.20451000 0.00293070 -0.00074386 0.00294882 +H 2.78304000 -1.33714000 10.66360000 0.00178443 -0.00266285 0.00438313 +H 0.72430700 5.49021000 1.98872000 -0.00182488 0.00266529 -0.00437913 +44 +Lattice="6.6604 0.0 0.0 -1.9016531446419103 6.428112286470541 0.0 -1.2514063926874133 -2.2750363427377365 12.652321829591736" Properties=species:S:1:pos:R:3:forces:R:3 energy=-14300.964668963443 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" crystal=COVSEM frame=10 pbc="T T T" +N -2.08548000 4.14209000 8.18700000 -0.65055081 0.50559664 2.64323803 +N 5.70399000 -0.01543850 4.43366000 -1.22881248 -0.62278803 -1.42040080 +N 2.94259000 3.44419000 6.88590000 -0.49458666 0.35346549 -0.99530489 +N 0.64980200 0.75037600 5.76278000 -0.64616450 -0.66877993 0.85718523 +N 4.11606000 3.53996000 6.10994000 0.29462220 -0.52832570 0.44241743 +N -0.53916800 0.64831200 6.51196000 0.00753174 0.33836438 -0.20059798 +N -1.29690000 4.53335000 9.29525000 -1.87764064 0.07464478 0.13318212 +N 4.86275000 -0.44506600 3.37392000 -0.24007573 0.35136747 1.56653716 +N -0.14676800 -1.44615000 10.25640000 1.19701307 -0.87536293 -1.15176680 +N 3.56990000 5.71345000 2.32653000 1.20946750 -0.58333703 -0.37894101 +N 0.65466400 -1.21441000 11.35420000 0.77291989 0.23903289 -2.04906638 +N 2.75770000 5.20341000 1.35088000 -0.14598621 0.42507946 -0.44134786 +N 2.53794000 2.06285000 0.57862700 0.11536591 -0.84831492 -0.31909601 +N 0.94921200 2.25761000 11.96300000 -0.56121011 -0.00331780 -0.58958995 +N 2.42093000 -0.68689700 12.50430000 0.77294560 1.39753341 2.04948804 +N 0.99924800 4.83809000 0.00606972 1.14730336 0.17032170 0.90573280 +N -0.19702400 4.04936000 6.80174000 1.02902748 -0.73619940 -2.51148442 +N 3.82739000 -0.02579210 5.98865000 1.00818611 -0.15509100 -1.21219287 +N 0.21529500 3.82040000 5.58607000 -0.73012131 1.34984973 1.24356547 +N 3.45432000 0.29575900 7.12508000 1.36381082 -0.47723171 -3.07611925 +N 0.65736600 3.90484000 4.53316000 -0.15352828 -0.58366613 0.71430902 +N 2.87554000 0.60238800 8.01891000 -1.87025129 0.87232388 3.76174504 +N 2.32884000 3.79179000 9.24568000 0.89226536 0.33985870 -0.70762415 +N 1.21401000 0.41788300 3.52625000 2.33652599 0.86208575 -2.36826883 +N 1.40623000 2.96075000 9.11651000 -1.35285278 -1.27029980 -0.38527415 +N 2.07782000 1.34995000 3.67159000 0.72758620 -0.11586419 -0.76892440 +N 0.53013200 2.22142000 9.12696000 0.69667126 0.64392765 0.10595619 +N 2.92483000 2.11219000 3.52322000 -0.78366196 -0.71509578 0.32738834 +N 0.10790600 1.80758000 0.01629400 0.49983582 0.30537249 0.54755241 +N 3.32752000 2.22813000 12.63240000 -1.10641254 0.72182179 0.42997844 +N -0.27738300 2.16763000 1.15970000 -0.30064424 -0.17225671 0.17428223 +N 3.64590000 1.82373000 11.50320000 0.46729337 0.17783498 0.36495164 +N -0.83098000 2.41218000 2.13524000 0.51183825 0.04198884 -0.65710712 +N 4.18779000 1.44537000 10.58840000 0.40408126 -0.45080129 -1.34493378 +C -1.55528000 3.85006000 6.95542000 -0.68949788 0.39842483 0.00792707 +C 5.16762000 0.25429100 5.67864000 -0.21052810 -0.35664183 0.96252846 +C 3.16818000 3.84359000 8.10574000 1.55402103 0.02773408 0.43806713 +C 0.39275600 0.29651600 4.55240000 -1.31973697 0.63018253 1.81931774 +C 0.25037800 -0.53982900 12.46850000 -1.17502500 -0.29902855 0.95615213 +C 3.20819000 4.76696000 0.11144000 1.06882815 -0.04822880 0.71929696 +C 2.06106000 -1.19580000 11.39000000 -0.08643792 -0.98696937 -1.37430092 +C 1.39239000 5.22965000 1.21717000 -0.69359107 -0.34616613 -0.38663581 +H 2.76507000 -1.55783000 10.59840000 -0.92544287 0.32298147 0.77732676 +H 0.80979800 5.46967000 2.07306000 -0.83437954 0.29397068 0.39085088 +44 +Lattice="6.6604 0.0 0.0 -1.9016531446419103 6.428112286470541 0.0 -1.2514063926874133 -2.2750363427377365 12.652321829591736" Properties=species:S:1:pos:R:3:forces:R:3 energy=-14300.745018672038 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" crystal=COVSEM frame=20 pbc="T T T" +N -2.11057000 4.21143000 8.26244000 -1.13472039 -0.19279674 1.49542559 +N 5.63929000 -0.00618776 4.31012000 0.99778857 0.99383936 0.67976368 +N 2.97113000 3.43265000 6.92143000 -0.68143490 -0.29017162 -0.86266682 +N 0.66377200 0.81042300 5.65926000 -1.90604105 -0.59107091 -0.58658690 +N 4.15231000 3.37582000 6.19801000 0.80486328 1.07941596 1.32338279 +N -0.51449800 0.62727600 6.42148000 -1.15618395 0.04648925 -0.32198799 +N -1.34179000 4.54862000 9.35883000 -0.61117179 0.21523630 -0.76351480 +N 4.85546000 -0.54958200 3.33862000 0.37720500 0.46273326 0.42020516 +N -0.12970700 -1.48063000 10.35540000 0.90753257 -0.03118666 -1.23563104 +N 3.57588000 5.70712000 2.25382000 0.25406613 0.04439051 0.53336507 +N 0.75209000 -1.06736000 11.30350000 -0.99276464 0.40925997 1.70638975 +N 2.72563000 5.21603000 1.32209000 -0.36046095 0.29832253 -0.62392446 +N 2.53002000 1.79341000 0.74930000 1.19296616 0.21992342 -0.28480315 +N 0.84352300 2.24519000 11.91820000 1.32271945 0.45696679 1.61287873 +N 2.47334000 -0.70606400 12.62720000 -0.34611008 0.41376609 1.66025387 +N 0.99510200 4.88675000 0.04470880 -1.58242658 -0.98634202 -2.80617398 +N -0.20379400 4.12541000 6.83937000 -0.33646536 -0.28893852 -2.32030748 +N 3.74074000 0.11044600 5.87151000 0.95687204 -0.14028093 -0.29809113 +N 0.06450750 3.98734000 5.56934000 -0.93824182 0.17094288 4.71315606 +N 3.38275000 0.37977300 7.03568000 0.58913229 -0.17667284 -0.56227455 +N 0.50712400 3.81460000 4.56291000 1.07777559 -0.23719815 -2.82359578 +N 2.96115000 0.58504500 8.06630000 -0.43946272 0.13250283 0.69594620 +N 2.27867000 3.74434000 9.16313000 -0.76916608 -0.09237202 1.15148912 +N 1.33337000 0.46358300 3.41559000 0.10660565 -0.00809116 -1.41948549 +N 1.34807000 2.89239000 9.03702000 -2.06604080 -0.93875090 0.59336433 +N 2.23737000 1.32907000 3.47251000 0.40790655 0.72655262 0.57552087 +N 0.39743900 2.24041000 9.23342000 2.41078974 1.40215625 -0.83513030 +N 3.08396000 2.09856000 3.42024000 -0.47720652 -0.61101238 0.14538303 +N 0.18697300 1.80723000 0.10245600 0.83100111 -0.93604610 -1.97913751 +N 3.29532000 2.39052000 12.58820000 -1.18111851 -0.00584196 0.03977826 +N -0.20414600 2.05047000 1.22026000 -2.14194491 1.21611637 3.71043611 +N 3.68595000 1.74066000 11.59400000 -0.15875276 0.75172372 0.42627194 +N -0.76847300 2.32757000 2.19702000 1.02221405 -0.39835541 -1.48620047 +N 4.24790000 1.21827000 10.75980000 0.27799333 -0.34724599 -0.81101336 +C -1.56603000 3.85587000 7.04927000 0.17511732 -0.10840234 -0.63719135 +C 5.12262000 0.21814200 5.62620000 1.96948045 0.53642982 -0.44617330 +C 3.15339000 3.89068000 8.14000000 1.49845435 -0.57735150 -1.20535373 +C 0.37684700 0.53540900 4.38255000 -1.29720896 -1.36014443 2.16306395 +C 0.29077900 -0.66350400 12.57840000 -0.31042574 -0.41063911 -1.27618248 +C 3.13660000 4.78384000 0.10104400 1.63449142 -0.93331559 -1.61832946 +C 2.12377000 -1.03741000 11.43000000 -0.36173262 -0.05407801 -0.24427486 +C 1.35322000 5.29954000 1.18247000 0.31977221 0.25624900 2.31670793 +H 2.82277000 -1.13272000 10.65120000 0.63235768 -0.46825496 -1.12456967 +H 0.70775000 5.56266000 1.98131000 -0.51802587 0.35154334 0.60982967 +44 +Lattice="6.6604 0.0 0.0 -1.9016531446419103 6.428112286470541 0.0 -1.2514063926874133 -2.2750363427377365 12.652321829591736" Properties=species:S:1:pos:R:3:forces:R:3 energy=-14300.656772153823 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" crystal=COVSEM frame=30 pbc="T T T" +N -2.11528000 4.14829000 8.31336000 1.56354954 0.57879132 -0.68310097 +N 5.65440000 0.00579884 4.30404000 -0.37892661 0.94798116 1.42375866 +N 3.02241000 3.39366000 6.88266000 -0.06088218 -0.30244298 -0.47599193 +N 0.57713300 0.70172200 5.72959000 -1.43264954 0.27408165 1.83865758 +N 4.21854000 3.51310000 6.14393000 -0.47062758 0.29355879 1.29635021 +N -0.69719300 0.69384100 6.40156000 0.02386354 -0.06567163 0.29703801 +N -1.38029000 4.83787000 9.28558000 0.69480463 -0.87675132 -1.09180867 +N 4.85893000 -0.39871000 3.31933000 -1.02018288 -0.09914842 -0.47933590 +N -0.05193860 -1.49402000 10.38530000 -0.88223291 -0.19085504 0.73653878 +N 3.56841000 5.58708000 2.33449000 0.75035589 -0.46631635 -1.13728120 +N 0.78839700 -1.02869000 11.36270000 0.23222101 -0.13496646 -0.08815284 +N 2.72059000 5.17766000 1.32956000 -0.89130891 1.01888190 2.25830275 +N 2.67914000 1.80488000 0.72063200 -0.45530740 0.73612226 1.86683687 +N 0.91509200 2.15798000 12.04050000 -0.86167951 -0.94823827 -2.10373831 +N 2.54859000 -0.69258200 12.62590000 1.40100954 -0.09842131 0.58649434 +N 0.97837500 4.66314000 0.10129100 -0.16183912 -0.40806235 -1.93759877 +N -0.16831000 4.00709000 6.72357000 -1.58069366 0.83561881 4.09010577 +N 3.63378000 0.13175900 5.66779000 1.87146485 0.43204046 -0.06674892 +N 0.07863120 3.89649000 5.55983000 0.89288756 -0.18736657 -3.09401412 +N 3.39492000 0.34237400 6.87420000 -0.49065801 -0.71469469 -0.96629256 +N 0.41447400 3.82683000 4.47410000 0.30696812 -0.15640535 -0.54023505 +N 3.03535000 0.36196400 7.93401000 -0.73123202 0.47728416 2.30661892 +N 2.32609000 3.66231000 9.18010000 -0.38789668 -0.54568065 0.45091699 +N 1.19473000 0.67005200 3.44073000 -0.80642136 -1.23134758 -0.30411214 +N 1.28663000 2.93589000 9.08532000 1.85561657 1.36927184 -0.65867035 +N 2.20734000 1.36404000 3.63844000 -0.97395445 -0.33981139 0.36714376 +N 0.26485000 2.45314000 9.14647000 -0.61902908 -0.78218615 0.23733082 +N 3.13878000 2.00423000 3.61702000 0.85744234 0.77841177 -0.11298199 +N 0.24251000 1.57665000 0.21454400 0.34449131 0.15893120 -0.15061162 +N 3.31166000 2.51341000 12.56210000 -1.04258233 -0.55250436 0.08858839 +N -0.22811100 2.11831000 1.22985000 0.40435739 0.17945477 0.09241779 +N 3.68156000 1.83839000 11.56990000 -1.05129323 1.73204421 2.27492751 +N -0.77076800 2.58914000 2.11516000 -0.19849328 -0.07031607 -0.00007242 +N 4.23047000 1.33958000 10.73800000 1.37980308 -1.49050450 -2.54592692 +C -1.55110000 3.94205000 7.02133000 0.58975450 -0.21650437 -0.09409723 +C 5.03765000 0.34793700 5.51994000 0.74596445 -0.64274494 -0.55497262 +C 3.26102000 3.68512000 8.14818000 -1.85231528 0.12110102 0.00148637 +C 0.32860200 0.37197400 4.51171000 1.52152229 0.41453639 -2.42501822 +C 0.36477400 -0.64708800 12.62680000 -1.00245255 -0.91048934 -0.82910364 +C 3.16519000 4.71668000 0.15861900 2.38667793 0.43900044 -0.70131981 +C 2.20104000 -1.07138000 11.44700000 -2.55712665 0.31281378 -1.14450600 +C 1.31791000 5.15385000 1.22481000 -0.23251771 0.50777436 3.47340611 +H 2.63394000 -1.21021000 10.49930000 1.60698576 -0.34096839 -0.67948086 +H 0.63469000 5.31687000 2.09541000 0.71255553 0.16470075 -0.82174514 +44 +Lattice="6.6604 0.0 0.0 -1.9016531446419103 6.428112286470541 0.0 -1.2514063926874133 -2.2750363427377365 12.652321829591736" Properties=species:S:1:pos:R:3:forces:R:3 energy=-14300.890653999046 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" crystal=COVSEM frame=49 pbc="T T T" +N -2.21016000 4.30767000 8.20260000 -1.43441845 -0.56566326 2.23670034 +N 5.57979000 0.00332383 4.44463000 -0.27624344 0.33326022 -1.57674958 +N 2.87059000 3.31254000 6.92961000 0.42307091 -0.48704716 0.00909867 +N 0.51046600 0.72021900 5.78689000 1.01417164 0.37161800 0.85665044 +N 4.05927000 3.43112000 6.19349000 0.23377910 0.49515745 0.03429384 +N -0.63337500 0.56569100 6.50390000 -1.07591411 0.43297634 1.80006532 +N -1.41044000 4.75736000 9.24632000 0.46124151 -0.17114754 -0.35045267 +N 4.78545000 -0.32908500 3.36700000 0.82318496 -1.17267501 -1.66080409 +N -0.06143920 -1.59017000 10.37930000 -0.32126757 -0.37217952 -0.77659657 +N 3.61631000 5.62737000 2.40615000 -1.11443438 -0.34024437 0.06089864 +N 0.82902800 -1.27409000 11.37180000 -0.58111045 0.71070948 0.39379736 +N 2.85080000 5.13118000 1.31430000 -0.14608494 0.23886988 1.51669376 +N 2.58476000 1.78098000 0.78126500 -0.31649509 -0.68005164 -1.36175908 +N 1.15194000 2.11775000 11.90670000 -0.62565739 -0.02837243 0.29955974 +N 2.50995000 -0.75175500 12.69950000 0.12056006 0.28569173 -0.51687401 +N 1.18939000 4.67159000 -0.05508570 -0.29129108 -1.17125576 -1.89349921 +N -0.35264400 4.29768000 6.68206000 -0.47538052 -0.16756239 -0.08844132 +N 3.63407000 -0.10762700 5.95683000 2.37493828 0.91148178 -0.35936463 +N 0.07414610 4.09956000 5.51916000 -0.44170318 0.07294785 0.87256042 +N 3.25536000 0.22486500 7.10362000 0.89860056 -0.09608264 -1.34532459 +N 0.69877100 4.04693000 4.56785000 -0.10303336 -0.32546721 -0.44189550 +N 2.78801000 0.48825300 8.09625000 -0.58074021 0.23804199 1.32447294 +N 2.29377000 3.78482000 9.23676000 -0.58170181 -0.62363650 0.38742668 +N 1.09994000 0.55123700 3.44893000 0.33319954 0.16669902 0.02560865 +N 1.28656000 3.04070000 9.09208000 -1.90338253 -0.38420560 0.32213814 +N 2.07102000 1.36011000 3.57712000 -0.83016807 0.07827364 0.63373579 +N 0.27003400 2.50879000 9.12799000 1.22384511 0.21723405 -0.11267551 +N 2.90646000 2.13876000 3.53518000 -0.09534885 -0.56859432 0.03117936 +N 0.19584200 1.38234000 0.17227100 0.64149024 0.89482103 0.72553446 +N 3.49347000 2.29887000 12.53100000 -0.15671748 0.16076080 0.69966402 +N -0.09928740 2.16378000 1.14011000 0.39933552 -2.05241910 -2.65599071 +N 3.90000000 1.89727000 11.42710000 -0.38661781 0.27973551 0.09578748 +N -0.59458600 2.86908000 1.84637000 -1.08622938 1.51960939 2.38838000 +N 4.42644000 1.61558000 10.45720000 0.03542265 -0.29128645 -0.23551665 +C -1.69736000 4.01761000 6.97839000 0.81110591 -0.52452047 -1.53729858 +C 5.06290000 0.23829800 5.68428000 -2.73546865 -1.07605295 1.06187589 +C 3.11675000 3.67480000 8.16378000 2.26841233 2.16761994 -0.86432261 +C 0.24857100 0.41440600 4.56392000 1.13385649 -0.15309788 -2.24106608 +C 0.32957300 -0.83872900 12.61300000 0.42117807 -0.49063899 -0.24314666 +C 3.37235000 4.62740000 0.11218200 0.60568506 0.85770973 -0.00046487 +C 2.20593000 -1.13135000 11.45870000 0.06700449 -0.27421227 1.21141639 +C 1.44473000 5.00861000 1.14985000 1.73626597 1.10302383 0.45809499 +H 2.91975000 -1.44917000 10.70940000 -0.04463718 0.16427858 -0.06428169 +H 0.70889300 5.25742000 1.86951000 -0.42229752 0.31590270 0.88089594 +44 +Lattice="6.6604 0.0 0.0 -1.9016531446419103 6.428112286470541 0.0 -1.2514063926874133 -2.2750363427377365 12.652321829591736" Properties=species:S:1:pos:R:3:forces:R:3 energy=-14300.574076757937 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" crystal=COVSEM frame=50 pbc="T T T" +N -2.23124000 4.30636000 8.23264000 0.24394987 -0.04236340 0.41110603 +N 5.58664000 0.01906340 4.46425000 0.43752771 -0.32823577 -4.14269511 +N 2.89820000 3.28867000 6.95133000 0.02622633 -0.11041911 0.02203636 +N 0.48720900 0.67422400 5.79349000 2.29136714 1.51494541 2.52019532 +N 4.05215000 3.42553000 6.21739000 1.09544421 0.36854347 -0.44695955 +N -0.66151500 0.59195500 6.51826000 -1.04099853 -0.41350384 0.66875936 +N -1.42063000 4.78002000 9.24372000 0.88733912 -0.40723240 -0.94292637 +N 4.81124000 -0.33677600 3.35232000 -0.05886901 -0.70277505 -0.52655164 +N -0.06680650 -1.57911000 10.35100000 -0.34304173 -0.16179592 1.19644229 +N 3.62092000 5.63021000 2.40602000 -0.43085416 -0.58912201 -0.40252677 +N 0.83752100 -1.30380000 11.39000000 -1.54888397 0.88220206 -0.67494029 +N 2.85877000 5.12821000 1.31297000 0.24710307 0.05544841 0.81318851 +N 2.56694000 1.75967000 0.76281200 0.77588694 0.43301645 -0.19422987 +N 1.16833000 2.10032000 11.89860000 -0.34850018 0.22290899 0.49952112 +N 2.56712000 -0.74157800 12.69600000 -2.26694680 -0.01970375 -0.03256462 +N 1.17473000 4.68541000 -0.07836060 0.74242661 -1.31600887 -1.75068471 +N -0.36490300 4.28816000 6.70582000 0.25818915 -0.08579771 -0.85096316 +N 3.62491000 -0.13767500 5.96433000 2.49616065 1.22249271 0.10238493 +N 0.06958540 4.11448000 5.52777000 -0.23245755 0.02065542 0.77944535 +N 3.28010000 0.22029900 7.12905000 -0.38844381 0.33556650 0.15213989 +N 0.70981500 4.07822000 4.57570000 -0.63605493 -0.29297052 0.36488170 +N 2.75404000 0.50436100 8.11429000 0.77128981 -0.43163371 -0.96334093 +N 2.27274000 3.78528000 9.24536000 -0.48990108 -0.88356474 -0.31199668 +N 1.08693000 0.53805300 3.43603000 -0.03042782 -0.41133948 0.04154085 +N 1.24158000 3.03794000 9.11292000 2.13658673 1.55189730 -0.46786210 +N 2.05881000 1.31993000 3.53964000 -1.02366416 0.02033439 0.83983542 +N 0.25082300 2.50389000 9.09003000 -1.05982929 -0.90854558 0.10840182 +N 2.86625000 2.11161000 3.54343000 1.02655922 0.36239956 -0.08214315 +N 0.18096600 1.38933000 0.14971800 1.31738698 0.54750099 0.08855548 +N 3.50401000 2.31700000 12.54350000 1.23529166 -0.22901279 -0.64879217 +N -0.11325600 2.14027000 1.11332000 -1.66470702 1.43260326 0.86668802 +N 3.94441000 1.93467000 11.41810000 -1.23151214 0.45578049 1.21845093 +N -0.59574500 2.87533000 1.85924000 0.78350255 -1.33914880 -0.44472011 +N 4.44284000 1.63932000 10.43850000 0.10136060 -0.16433360 -0.07545159 +C -1.69252000 4.00886000 6.99479000 0.23618771 -0.42502135 -1.30973024 +C 5.06632000 0.20761000 5.65705000 -3.50597170 -0.27143650 3.38138633 +C 3.15849000 3.73299000 8.15096000 -1.51605612 0.64132055 1.56670685 +C 0.28016300 0.43009000 4.57486000 -0.70446684 -1.08082492 -2.84080160 +C 0.33863700 -0.79043800 12.58310000 -0.54251819 -1.38974297 0.11293931 +C 3.40380000 4.62972000 0.10758600 -0.96163886 0.70620491 -0.22999855 +C 2.17709000 -1.15795000 11.49730000 3.00430319 -0.62501461 0.09272221 +C 1.46715000 5.01172000 1.11979000 0.30453431 1.85095774 2.06864276 +H 2.97224000 -1.52727000 10.84010000 -0.67505856 0.23710868 -0.38758815 +H 0.75395300 5.34994000 1.88280000 0.28217292 -0.23234545 -0.18852048 +44 +Lattice="6.6604 0.0 0.0 -1.9016531446419103 6.428112286470541 0.0 -1.2514063926874133 -2.2750363427377365 12.652321829591736" Properties=species:S:1:pos:R:3:forces:R:3 energy=-14300.496197777016 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" crystal=COVSEM frame=70 pbc="T T T" +N -2.19882000 4.15344000 8.17730000 0.28141598 0.99956263 2.06519234 +N 5.56755000 -0.02387750 4.43378000 0.75354406 0.11481570 -0.08556888 +N 2.84287000 3.60406000 6.75666000 0.60161243 -0.25074169 0.35991433 +N 0.44158000 0.63886400 5.91927000 0.49613704 0.77467853 1.13909126 +N 4.04926000 3.75601000 6.04947000 -1.45350632 -0.31203936 -1.06162906 +N -0.79422800 0.55732200 6.59597000 0.89750012 -0.25892089 -0.73024986 +N -1.41154000 4.51181000 9.28506000 0.56314873 0.40843568 0.34489703 +N 4.86403000 -0.59859900 3.40442000 -0.42600403 0.39776560 0.17004196 +N -0.11723200 -1.28432000 10.21890000 -1.55422672 -0.84451483 -1.50875933 +N 3.63632000 5.73282000 2.35089000 0.63650744 0.17825715 -0.35952095 +N 0.63804400 -1.01838000 11.29020000 1.47112867 -0.10790097 1.12604034 +N 2.90614000 5.26744000 1.27291000 1.50106145 -0.50936742 1.30268541 +N 2.45504000 1.54945000 0.81307300 -3.10034418 0.10503419 -0.25300015 +N 1.40113000 2.11238000 11.88350000 0.99828737 0.47446881 0.39685903 +N 2.29490000 -1.01395000 12.76250000 2.20852620 0.28081794 -2.33406802 +N 1.46103000 4.50881000 -0.17112700 -2.32540340 0.30904969 2.12057904 +N -0.36340900 4.39968000 6.63212000 -0.69600791 -0.16533119 0.99788628 +N 3.66556000 0.12658500 5.90463000 -0.77777928 -1.09936772 -0.88551878 +N -0.05284860 4.11646000 5.47336000 0.52744639 -0.30935873 -0.30875452 +N 3.38343000 0.20320300 7.10450000 -0.17264546 0.72413578 -0.75909764 +N 0.37954200 3.87023000 4.45262000 0.30532930 0.01794496 -0.57087232 +N 2.98033000 0.46777300 8.12000000 -0.70754702 -0.02098257 1.98338498 +N 2.25029000 3.75898000 9.08963000 -1.75062301 -1.34142165 0.66031071 +N 1.18039000 0.43702800 3.61975000 0.48037617 0.42488560 -0.43798588 +N 1.24253000 2.94042000 8.93030000 3.63772531 2.34134424 -0.27276474 +N 2.11345000 1.27274000 3.72327000 1.20645416 0.26892042 0.66357087 +N 0.33142700 2.28735000 8.91654000 -1.42206688 -1.02205465 0.15175679 +N 3.06766000 1.91700000 3.76971000 -1.32644241 -0.52826400 -0.48405285 +N 0.02724340 1.76916000 0.05058130 0.16863300 -0.17065594 1.89967500 +N 3.64964000 2.39910000 12.68170000 1.42952822 0.53060884 -0.06860115 +N -0.25972200 2.07088000 1.26436000 0.10140122 0.05357356 -1.70430201 +N 4.10603000 2.12942000 11.52990000 -2.77920825 1.06344941 4.32039948 +N -0.61869200 2.47716000 2.25812000 -0.49584187 -0.07685233 0.51413733 +N 4.49305000 1.75999000 10.56150000 1.68840231 -1.18921235 -3.73989067 +C -1.71020000 4.08594000 6.90173000 2.23294139 0.33479568 0.33130875 +C 5.00477000 0.15828600 5.68102000 0.22769278 0.51544962 0.11272436 +C 3.14536000 3.80525000 8.04243000 -1.89512415 0.01466218 -0.79070678 +C 0.28185300 0.40265800 4.66132000 -1.24513384 -0.96153602 -0.87450932 +C 0.13589800 -0.75602100 12.60830000 1.38127375 0.01311597 -1.48850418 +C 3.53569000 4.82678000 0.13702800 0.93923427 -0.66031071 -1.67309396 +C 2.03916000 -1.13342000 11.44640000 -0.36867562 -0.44869144 0.39631704 +C 1.60974000 4.96556000 1.10855000 -1.85097830 -0.59947327 -1.84148579 +H 2.69730000 -1.34462000 10.55130000 -0.52047870 0.26164060 1.38720272 +H 0.83463900 5.03150000 1.87018000 0.13273012 0.26958839 -0.21103255 +44 +Lattice="6.6604 0.0 0.0 -1.9016531446419103 6.428112286470541 0.0 -1.2514063926874133 -2.2750363427377365 12.652321829591736" Properties=species:S:1:pos:R:3:forces:R:3 energy=-14300.947035986632 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" crystal=COVSEM frame=80 pbc="T T T" +N -2.17423000 4.27931000 8.16663000 0.70269278 -0.36341772 0.53870268 +N 5.62835000 -0.01034450 4.46394000 0.33877832 -0.76180244 -1.41205500 +N 2.92611000 3.70855000 6.72033000 -0.70038393 -0.92379222 -2.74393786 +N 0.50250300 0.65888600 5.95496000 0.26091503 0.33008131 -0.78217072 +N 4.15248000 3.75845000 6.06399000 -1.43640335 -0.57794800 -2.60572564 +N -0.72186300 0.58339700 6.61550000 -0.27568242 -1.24712902 -1.61429283 +N -1.40847000 4.54879000 9.27677000 -0.68167144 1.09613841 1.16148557 +N 4.95486000 -0.64145600 3.41795000 0.50520634 0.21454313 -0.73522238 +N -0.20139700 -1.35113000 10.23740000 0.42420425 -0.23316100 -1.03229278 +N 3.73600000 5.69366000 2.32727000 -0.18393415 -0.07966717 1.77554214 +N 0.58748100 -0.97699900 11.30670000 -0.43307816 -0.59374485 -0.33347414 +N 2.99369000 5.09206000 1.35201000 0.25455053 0.53100994 0.41912735 +N 2.28308000 1.68939000 0.81053200 1.36075121 0.29003689 -0.51464744 +N 1.30659000 2.17092000 11.92230000 -1.96722816 0.05318121 -0.15036531 +N 2.22311000 -0.84264700 12.74520000 0.91259764 0.18994282 0.29994952 +N 1.31671000 4.76062000 -0.02237460 0.59054126 -0.64351113 -0.63623490 +N -0.22433400 4.18498000 6.68135000 -1.08132372 0.01211668 1.15493440 +N 3.71568000 -0.03331620 6.00182000 0.27172035 -0.11497716 -1.99446129 +N 0.01871730 3.92745000 5.50207000 0.89348406 0.16122771 -1.26283846 +N 3.44700000 0.30458700 7.15177000 -0.68286957 -0.71033924 0.92410590 +N 0.37008200 3.79387000 4.42712000 0.11566210 -0.21126138 -0.12207135 +N 3.02419000 0.37715400 8.20558000 -0.17959978 0.59227932 0.57898158 +N 2.30406000 3.67689000 9.02647000 -0.56228484 -0.01034411 0.01434727 +N 1.14274000 0.55000200 3.56340000 0.67359818 0.03477993 0.07112186 +N 1.31585000 2.90746000 8.81420000 1.02700145 0.66232646 -0.11035843 +N 2.12916000 1.33037000 3.68558000 -1.53565307 -1.04755485 0.41388950 +N 0.39784200 2.23548000 8.80291000 0.00813749 -0.09947495 0.21207076 +N 3.01354000 2.02522000 3.58241000 0.99218357 0.70743904 0.00282347 +N -0.01937530 1.52890000 0.19541300 -0.98923708 0.86366955 0.32676973 +N 3.61422000 2.45762000 12.57860000 0.90866385 0.02909070 1.26849488 +N -0.38546700 2.03659000 1.29335000 -1.58147013 0.37355455 1.48022009 +N 4.08359000 2.04785000 11.51570000 -1.16129017 0.47243095 -0.04617938 +N -0.95494900 2.38865000 2.24727000 1.40988499 -0.67743426 -2.18486176 +N 4.47031000 1.81006000 10.48230000 0.92875960 -0.68139890 -1.15212675 +C -1.61019000 4.03277000 6.91361000 2.23175868 0.92672842 2.06341827 +C 5.05793000 0.09843850 5.69464000 0.33597942 1.71829910 2.14673230 +C 3.15140000 3.94349000 7.93892000 -0.81853640 0.04424946 3.84845293 +C 0.32209600 0.36963900 4.66324000 -0.25406510 0.34183845 0.64479154 +C 0.06845560 -0.63476700 12.58580000 0.22807331 -1.29637593 -1.14493795 +C 3.51129000 4.70625000 0.10692800 0.22514019 0.40121808 0.83071315 +C 1.96284000 -1.09537000 11.47860000 -0.50091774 0.02808082 0.53112306 +C 1.62900000 5.11189000 1.20239000 -1.01810543 0.43571097 -0.40695832 +H 2.63592000 -1.42871000 10.67280000 -0.18460624 0.34212127 0.50602910 +H 0.90671200 5.57578000 1.90395000 0.62804337 -0.57876561 -0.22859370 +44 +Lattice="6.6604 0.0 0.0 -1.9016531446419103 6.428112286470541 0.0 -1.2514063926874133 -2.2750363427377365 12.652321829591736" Properties=species:S:1:pos:R:3:forces:R:3 energy=-14300.603737166466 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" crystal=COVSEM frame=99 pbc="T T T" +N -2.08409000 4.15305000 8.18619000 -0.43269352 0.05793724 -0.17877652 +N 5.66499000 0.06588720 4.39111000 -1.97800109 -0.55422700 1.24556064 +N 2.96815000 3.49268000 6.79047000 -0.39052537 -0.55752829 -0.79133927 +N 0.51541400 0.88958900 5.75468000 -0.96450307 0.11819001 1.65665947 +N 4.18014000 3.52378000 6.06158000 -0.56603865 0.47035041 0.15540827 +N -0.73123700 0.77727500 6.54301000 0.60235291 -1.03170142 -2.07131670 +N -1.34196000 4.70617000 9.23184000 0.23354564 -0.57301148 -1.81332707 +N 4.91931000 -0.40984300 3.36823000 -0.70903826 -0.06219961 0.31608937 +N -0.12069000 -1.65119000 10.26330000 -0.85850677 0.48242534 0.90314112 +N 3.68687000 5.61463000 2.38534000 0.95072196 0.45289622 0.87710099 +N 0.57520700 -1.10532000 11.30100000 1.46716402 -0.40893961 -0.76435812 +N 2.90747000 5.21029000 1.39231000 -0.29539044 -0.70317100 -1.66593087 +N 2.14045000 1.73408000 0.73506800 0.66096377 0.65856751 1.01427449 +N 1.29417000 2.23935000 11.97270000 -1.20753403 -0.41706944 -1.33645942 +N 2.15416000 -0.62944900 12.79620000 -0.42254486 -0.72659890 -2.20321944 +N 1.31870000 4.68599000 -0.02492560 -0.52894791 -0.17887833 -0.61432396 +N -0.23227500 4.19988000 6.67414000 1.97215440 -0.32491493 -1.55827364 +N 3.69834000 -0.02140740 5.89521000 0.16618737 0.00625009 0.36856558 +N 0.21990100 3.91070000 5.50895000 -2.28754648 0.74039544 3.20533261 +N 3.42593000 0.26084500 7.09500000 -0.11062994 -0.59087550 -2.64436932 +N 0.61152600 3.72512000 4.47360000 0.79671802 -0.15779477 -1.60226007 +N 2.93371000 0.47847500 8.06957000 -1.03012791 0.57832852 2.89653797 +N 2.31617000 3.72277000 9.17775000 0.32323292 -0.30411317 -1.09499684 +N 1.18314000 0.64684000 3.46075000 -0.11683041 -0.57152024 0.41011461 +N 1.37270000 2.88786000 9.02484000 0.77463225 1.00386152 -0.44102338 +N 2.12002000 1.42180000 3.79167000 0.04840529 0.52750295 -0.96697647 +N 0.46619400 2.21194000 8.98496000 -0.50739795 -0.58260169 0.24884062 +N 2.91933000 2.22866000 3.78856000 0.62113739 -0.17579095 0.06238833 +N -0.17980600 1.31321000 -0.02472260 0.26296678 1.26212883 1.78916898 +N 3.59787000 2.57102000 12.64120000 -0.11707055 0.46222881 1.18945917 +N -0.50858100 1.84713000 1.11776000 1.37312850 -1.86988106 -4.54434257 +N 4.08379000 2.08466000 11.62890000 2.28436860 -3.12321157 -4.26315644 +N -1.00911000 2.30510000 1.99196000 -1.44857495 1.50914500 3.20043208 +N 4.66981000 1.53782000 10.74900000 -2.33517874 2.29134143 3.01467502 +C -1.55717000 3.95474000 6.88889000 -0.54777867 -0.11893769 1.16514168 +C 5.02575000 0.23750100 5.70134000 3.47486649 1.26025193 -1.63931481 +C 3.17888000 3.79909000 8.03189000 1.03129005 0.31289194 1.61275017 +C 0.30424100 0.49322900 4.52306000 -0.27991343 0.10354552 0.79879033 +C -0.03431180 -0.81715200 12.50170000 0.21985040 -0.69114853 -0.78121427 +C 3.47481000 4.81471000 0.15539300 0.56805953 0.62932892 1.54051760 +C 1.98939000 -0.97615700 11.48100000 -2.33673683 0.65657233 3.74594304 +C 1.52007000 5.09322000 1.18870000 0.18843667 0.17929074 1.05821978 +H 2.75025000 -1.29975000 10.83410000 0.78113199 -0.18760311 -1.07523020 +H 0.73723900 5.23214000 1.95766000 0.67019918 0.14828632 -0.42490874 +44 +Lattice="6.6604 0.0 0.0 -1.9016531446419103 6.428112286470541 0.0 -1.2514063926874133 -2.2750363427377365 12.652321829591736" Properties=species:S:1:pos:R:3:forces:R:3 energy=-14300.885429413325 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" crystal=COVSEM frame=100 pbc="T T T" +N -2.06816000 4.13229000 8.19665000 -0.59892820 0.08295870 -0.85336457 +N 5.66658000 0.08812950 4.43466000 -2.69950406 -1.77635461 -2.03336208 +N 2.94210000 3.48901000 6.78420000 0.83248721 -0.02510235 -0.09207069 +N 0.48913300 0.87356800 5.76157000 -0.15657453 0.32315630 1.59728756 +N 4.18894000 3.55058000 6.05478000 -1.61222567 0.11321544 -0.27254619 +N -0.73779700 0.77847800 6.53305000 1.08693386 -1.04367762 -1.77162892 +N -1.33131000 4.70283000 9.22050000 -0.63873916 -0.69014065 -0.93116615 +N 4.92037000 -0.37283200 3.36212000 -0.70374179 -0.05155010 0.61867427 +N -0.14876000 -1.65190000 10.24910000 0.61171172 0.70676026 0.49881047 +N 3.70127000 5.62885000 2.39683000 0.69553997 0.45462349 1.17801776 +N 0.57507600 -1.10921000 11.28070000 0.94310121 -0.08011095 0.26703632 +N 2.92245000 5.19989000 1.41013000 -0.77040535 -0.55756429 -2.52402626 +N 2.15078000 1.73191000 0.73085000 0.41234890 0.68678793 1.48805681 +N 1.28167000 2.23173000 11.95200000 0.20686325 0.14842002 0.10298142 +N 2.15480000 -0.63546300 12.78030000 -0.17317614 -0.03753096 0.09988941 +N 1.30881000 4.67423000 -0.04515400 -0.14010867 0.19238434 0.00402611 +N -0.21166000 4.15910000 6.66579000 0.35804977 0.05066446 0.22255880 +N 3.69264000 0.00757267 5.88872000 0.77306387 -0.10402221 0.06690987 +N 0.22676400 3.91507000 5.52836000 -0.62934949 -0.25936723 -0.86140183 +N 3.41188000 0.24572100 7.08834000 -0.94407823 0.19326057 -0.06039316 +N 0.62766100 3.70435000 4.47400000 -0.19531128 0.39947693 0.78719980 +N 2.92742000 0.46567200 8.09756000 0.27605215 -0.12039396 0.05860675 +N 2.32521000 3.70969000 9.17320000 0.25805597 -0.66939185 -1.33436140 +N 1.17706000 0.68272700 3.45812000 -2.21431118 -2.24400228 0.26092686 +N 1.37624000 2.86484000 8.98959000 1.64814912 1.88738513 0.02291275 +N 2.11070000 1.39421000 3.79151000 2.53822904 3.26918338 -0.29293298 +N 0.45122800 2.22715000 9.03674000 -1.09159784 -1.08612139 0.06808024 +N 2.90322000 2.23316000 3.82872000 -0.37299816 -1.52676734 -0.00065926 +N -0.15907200 1.33212000 -0.01717700 0.74289455 0.78367739 0.58834039 +N 3.61792000 2.54851000 12.64100000 -0.40990532 0.21484395 0.54004479 +N -0.48172200 1.87585000 1.07338000 -2.78066350 1.62453096 3.16113020 +N 4.06892000 2.03755000 11.59410000 -1.66213592 0.73952640 2.08031042 +N -1.02421000 2.33916000 2.01294000 2.09634896 -1.51046140 -3.04694237 +N 4.64488000 1.55185000 10.76820000 1.16326477 -1.03693619 -2.34323143 +C -1.57683000 3.96327000 6.88394000 1.39904008 0.11869652 1.26019536 +C 5.05818000 0.22955300 5.67080000 0.51612839 1.39435038 0.48379317 +C 3.20710000 3.79133000 8.03502000 -0.18749616 -0.08036189 1.24102007 +C 0.28150100 0.46833100 4.52320000 1.66729869 1.12674482 1.08318519 +C -0.00940967 -0.81595600 12.49660000 -0.48869215 -0.82907278 -1.11524685 +C 3.47841000 4.83438000 0.16741800 0.41465209 -0.34519888 -0.12130259 +C 1.97611000 -0.95847800 11.53420000 -0.36105179 -0.66031071 -0.92384879 +C 1.51751000 5.10552000 1.16503000 1.75789409 -0.29978909 -0.20112969 +H 2.78817000 -1.19530000 10.84180000 -0.44363562 0.10933513 -0.11197977 +H 0.81324600 5.22381000 1.92440000 -1.12347952 0.41424946 1.11160617 +40 +Lattice="5.3719 0.0 0.0 0.0 6.8819 0.0 0.0 0.0 10.8378" Properties=species:S:1:pos:R:3:forces:R:3 energy=-7267.569463858868 energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" name crystal=NIKVUZ frame=0 pbc="T T T" +O 0.31692900 0.99801900 3.05328000 -0.01925052 -0.02874365 -0.01923921 +O 3.00263000 2.44335000 7.78473000 -0.01429163 0.02099393 0.01552293 +O 5.05522000 4.43860000 2.36578000 0.01501169 -0.02246399 0.01679959 +O 2.36993000 5.88516000 8.47163000 -0.00110436 0.00174112 -0.00690254 +O 5.04152000 2.99531000 5.54604000 -0.02724341 -0.00174768 0.01504383 +O 2.35579000 0.44566700 5.29205000 -0.03139831 0.00131992 -0.02009389 +O 0.33051100 6.43622000 10.71060000 0.02392124 -0.00127244 -0.01372851 +O 3.01764000 3.88672000 0.12829400 0.00102084 0.00103716 -0.00617265 +C 0.90230000 1.95266000 3.53503000 0.01686587 -0.00415657 -0.00767073 +C 3.58810000 1.48863000 7.30299000 0.01896585 -0.00126277 0.00400509 +C 4.46970000 5.39324000 1.88406000 -0.01903948 0.00423183 0.00359221 +C 1.78399000 4.93047000 8.95323000 -0.02244455 -0.02038504 0.00527755 +C 0.57899900 2.92419000 4.73145000 -0.00760399 0.00253981 0.01129979 +C 3.26514000 0.51678100 6.10657000 -0.01033712 -0.00270164 -0.01403056 +C 4.79294000 6.36514000 0.68737200 0.00750541 0.00218454 -0.00940448 +C 2.10800000 3.95751000 10.15140000 -0.01334449 0.00102271 -0.01208233 +C 1.84728000 3.71527000 4.42247000 0.01775969 0.03001547 0.01960708 +C 4.53343000 6.60718000 6.41515000 0.01434748 -0.02289094 -0.01621476 +C 3.52447000 0.27466000 0.99625800 -0.01499838 0.02334500 -0.01581660 +C 0.83826900 3.16550000 9.84194000 -0.00901969 -0.00786475 0.00731067 +H 2.60353000 3.64135000 5.23063000 0.01009163 0.00076267 0.01079077 +H 5.28982000 6.68169000 5.60678000 0.00392720 -0.00379150 -0.00408354 +H 2.76804000 0.20024400 11.02570000 -0.00341464 0.00366960 -0.00320783 +H 0.08119390 3.24108000 -0.18683500 0.01689127 -0.01085797 -0.01817266 +H 1.67358000 4.77352000 4.20345000 -0.00208317 0.00896256 -0.00295851 +H 4.35936000 5.54877000 6.63457000 0.00104835 0.00079216 -0.00075635 +H 3.69843000 1.33311000 1.21567000 -0.00061135 -0.00118911 -0.00084740 +H 1.01281000 2.10638000 9.62162000 -0.00861356 0.02988229 0.01109143 +C 2.15391000 2.77824000 3.21726000 -0.00095611 -0.02045307 -0.00340469 +C 4.83964000 0.66269900 7.62030000 0.00264694 0.02055962 0.00728918 +C 3.21793000 6.21920000 2.20169000 0.00222579 -0.02023597 0.00227853 +C 0.53095500 4.10360000 8.63518000 0.02250697 0.02138016 0.01662774 +H 2.10899000 3.24201000 2.22615000 -0.00737058 0.01639459 -0.02369482 +H 4.79503000 7.08104000 8.61135000 -0.00857160 -0.01939291 0.02871002 +H 3.26294000 -0.19886600 3.19291000 0.00655585 0.01465097 0.02047169 +H 0.57735200 3.63880000 7.64322000 -0.00166863 0.00468748 0.01345340 +H 3.10062000 2.22111000 3.30657000 0.00689889 -0.01265008 0.00621081 +H 0.41441400 1.21965000 7.53135000 0.01122945 0.01569098 -0.00815508 +H 2.27114000 5.66197000 2.11229000 -0.00377589 -0.01006463 -0.00527894 +H 4.95553000 4.66213000 8.72594000 0.02772107 -0.01373987 -0.00346634 +40 +Lattice="5.3719 0.0 0.0 0.0 6.8819 0.0 0.0 0.0 10.8378" Properties=species:S:1:pos:R:3:forces:R:3 energy=-7266.1367300700795 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" crystal=NIKVUZ frame=10 pbc="T T T" +O 0.48602900 0.98961100 3.03245000 0.17050271 1.62337911 0.74280199 +O 2.97674000 2.43746000 7.87941000 0.41351515 -1.91100842 -1.22005530 +O 5.16566000 4.44612000 2.22285000 0.57083632 -0.93843209 0.47122562 +O 2.50196000 5.83856000 8.36820000 -0.11608377 -0.45210792 0.84774928 +O 4.89164000 3.08979000 5.52886000 -0.58134185 -0.27056284 0.29486851 +O 2.38387000 0.38941900 5.10080000 1.17969412 0.43046026 1.86826126 +O 0.33220700 6.52395000 10.68980000 -1.47998869 -0.40157546 1.52874709 +O 3.07871000 3.70708000 0.19654300 0.62795081 -0.02799458 0.86255369 +C 0.88712500 2.04897000 3.54281000 0.10286264 -1.44353044 -1.07965764 +C 3.45345000 1.42638000 7.33741000 1.04158989 0.71853592 0.69634215 +C 4.49848000 5.35912000 1.79032000 -0.33426912 -0.03536054 0.67906434 +C 1.88273000 5.00596000 9.01816000 -0.60439950 0.13790009 -0.22965196 +C 0.45152100 3.00522000 4.75505000 0.62998712 -0.42196071 -0.06715773 +C 3.21695000 0.47003000 6.03161000 -1.15311920 -0.40840637 -1.59287554 +C 4.78467000 6.36411000 0.69419700 0.52406282 1.36270525 -2.34040836 +C 2.15942000 3.92743000 10.29470000 -0.66453761 0.77462710 -2.21749935 +C 1.75426000 3.73988000 4.61253000 -0.43203429 0.84010796 -1.96209624 +C 4.50777000 6.57984000 6.32457000 0.03446240 0.81783706 0.20225069 +C 3.40616000 0.17319900 1.00874000 1.81020575 -0.20401858 0.47108523 +C 0.85154700 3.27096000 9.89542000 0.18599926 1.26714248 -0.33468564 +H 2.53043000 3.59590000 5.30372000 1.04683494 -0.22512734 1.91405261 +H 5.34111000 6.71927000 5.59763000 -0.37395050 -0.06616785 -0.23061458 +H 2.69794000 -0.03232140 11.06690000 -0.76296458 0.16711399 -0.87785175 +H 0.16209400 3.47972000 -0.14752800 -0.98978730 0.07553953 0.88800761 +H 1.62077000 4.81710000 4.44616000 0.01683527 -0.00642503 0.10725357 +H 4.37480000 5.51112000 6.52852000 -0.12522301 0.05425748 -0.20146547 +H 3.46486000 1.20708000 1.29349000 -0.03648272 0.73723298 -0.22845074 +H 0.88367200 2.23139000 9.75455000 0.09424122 -1.58776933 -0.32997692 +C 2.14229000 2.93848000 3.33564000 -2.45244675 1.75825404 -1.35980504 +C 4.76348000 0.56017600 7.59254000 0.25125643 0.67096022 -0.70189059 +C 3.23965000 6.09668000 2.18317000 -1.94509096 -0.94169224 0.27881094 +C 0.58446300 4.21134000 8.68579000 0.32749221 0.47096131 0.60916119 +H 1.98624000 3.62194000 2.41353000 0.15028509 -1.33078757 1.09846783 +H 4.63270000 6.77796000 8.43033000 0.18202331 0.28744728 0.92719122 +H 3.23388000 -0.33944400 3.17008000 0.48591279 0.27507873 0.44363357 +H 0.79608400 3.77995000 7.71948000 -0.08531743 -0.52618655 -0.53338564 +H 3.10350000 2.50730000 3.25281000 1.28873975 -0.77992358 0.19434352 +H 0.40102200 1.09349000 7.56475000 -1.13209786 -0.33755962 0.30867019 +H 2.22315000 5.55507000 2.20694000 1.21392065 0.27615705 -0.33065004 +H 4.95863000 4.74612000 8.61014000 0.91993043 -0.42910581 0.40363080 +40 +Lattice="5.3719 0.0 0.0 0.0 6.8819 0.0 0.0 0.0 10.8378" Properties=species:S:1:pos:R:3:forces:R:3 energy=-7266.244106191224 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" crystal=NIKVUZ frame=20 pbc="T T T" +O 0.33247500 1.23597000 3.01226000 0.07612162 0.09002923 0.81885522 +O 2.86408000 2.29061000 7.72974000 0.93309962 -0.10081655 -0.18690892 +O 5.07118000 4.37668000 2.26985000 1.29345001 -1.80150514 1.14867633 +O 2.58409000 5.79595000 8.56482000 -1.40314356 -1.24458877 0.15026864 +O 4.90254000 3.03697000 5.62321000 0.37484422 0.35425739 -0.56041821 +O 2.40022000 0.40077400 5.16578000 -0.93270881 -0.15278112 -0.59254158 +O 0.26587900 6.56870000 10.75290000 -0.58623209 -0.90810335 0.29352845 +O 3.10630000 3.80093000 0.15024700 -2.11993626 -0.40853595 -2.03366033 +C 0.88850500 2.09660000 3.68917000 0.45587613 -0.03548616 -1.86559760 +C 3.62248000 1.50134000 7.16671000 -1.32421583 -0.45426611 -0.33264676 +C 4.46389000 5.31762000 1.87041000 -1.72484513 1.05961332 -0.87430363 +C 1.89178000 4.81813000 8.93202000 2.79530336 1.48048234 0.18373977 +C 0.45107400 3.06881000 4.79961000 -0.26550343 -0.27953599 1.12449254 +C 3.29866000 0.50060600 5.96625000 0.47674063 0.55816079 0.46884426 +C 4.70662000 6.30133000 0.68793900 1.47008480 1.26550726 -0.28971293 +C 2.20276000 3.79689000 10.09700000 1.05455853 0.77996986 1.77932166 +C 1.72996000 3.90135000 4.61837000 0.04991529 -1.65698343 -0.06469153 +C 4.53391000 6.58705000 6.32517000 0.33074517 -2.21092761 -0.02418904 +C 3.50176000 0.20255400 1.09388000 0.07244957 1.89086640 -0.39192251 +C 0.84507600 3.12245000 9.80734000 0.87900361 -1.04411985 -1.16724484 +H 2.33766000 3.82546000 5.55055000 0.08079846 0.00158552 -0.29452192 +H 5.35862000 6.55754000 5.55888000 -0.59645994 -0.25842004 0.15485857 +H 2.81818000 0.25161200 11.05790000 -0.38737423 0.23648133 0.40912165 +H 0.09178990 3.08009000 -0.22877200 -0.03865499 0.04046382 0.11392610 +H 1.56016000 4.91488000 4.36760000 -0.07419432 1.26335268 -0.25898671 +H 4.27289000 5.54766000 6.75531000 0.43122337 1.23211892 -1.10757468 +H 3.83378000 1.24862000 1.42429000 -0.61650426 -1.13738919 -0.52267956 +H 0.99776100 2.10667000 9.32561000 -0.19650324 0.71974948 0.98163176 +C 2.16606000 2.94741000 3.42232000 0.11275933 -0.89123692 2.31816318 +C 4.86585000 0.64483500 7.43809000 -0.27229885 1.03681792 3.19511504 +C 3.15757000 6.12000000 2.22813000 -0.19055114 -0.75981241 0.64375795 +C 0.62547800 4.14230000 8.61699000 -2.42957936 -0.40940087 -0.10611406 +H 2.08967000 3.39649000 2.48027000 -0.15114847 0.79002801 -1.65772905 +H 4.72308000 7.12495000 8.51283000 0.54272902 0.39855339 -1.38163371 +H 3.16253000 -0.35773500 3.27621000 -0.10817917 -0.26624236 -0.86997904 +H 0.56075000 3.56886000 7.65670000 0.18481912 0.77568640 0.38735829 +H 3.15958000 2.42804000 3.48016000 -0.57053808 0.33692044 0.23669319 +H 0.42300600 1.21716000 7.36453000 0.40708019 -0.12985665 0.04353649 +H 2.20528000 5.52540000 2.03317000 0.86487797 0.46637086 0.30623793 +H 5.04151000 4.78582000 8.71936000 1.10209309 -0.62700979 -0.17507670 +40 +Lattice="5.3719 0.0 0.0 0.0 6.8819 0.0 0.0 0.0 10.8378" Properties=species:S:1:pos:R:3:forces:R:3 energy=-7266.021054476822 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" crystal=NIKVUZ frame=30 pbc="T T T" +O 0.34238600 1.21746000 3.05785000 0.57197789 1.45353204 0.78147138 +O 3.06443000 2.34778000 7.71419000 -1.08188936 1.02438921 0.31232064 +O 4.98750000 4.23578000 2.31385000 -0.90468893 1.70732563 -0.62695322 +O 2.54557000 5.75274000 8.44850000 -0.77976931 -1.29375854 0.49958848 +O 4.98087000 3.27672000 5.55075000 -0.18440620 -0.54026591 0.39028318 +O 2.31095000 0.40705700 5.29676000 -0.60403955 -0.02362715 -0.78397049 +O 0.25187200 6.58545000 10.81660000 1.12920794 0.03443437 -0.82711875 +O 2.95900000 3.74247000 0.03138510 2.84632947 -0.42638301 2.94934843 +C 0.87412400 2.20318000 3.59671000 0.40061284 -1.52341976 -0.33663248 +C 3.54707000 1.33863000 7.26809000 1.71108972 -0.65030912 0.10091786 +C 4.39861000 5.26868000 1.92779000 2.12465167 -2.19864287 0.33707060 +C 1.87347000 4.80041000 8.89093000 0.02794152 1.80073381 -0.81952885 +C 0.59800100 3.09649000 4.85968000 -0.63534016 0.87234445 -0.29745298 +C 3.22753000 0.38201200 6.08929000 1.23560019 0.13722183 -0.16414128 +C 4.78068000 6.42258000 0.82057900 -1.17612029 -1.53100966 1.08631166 +C 2.08649000 3.83526000 10.09030000 -2.69426929 0.06104313 -2.98344640 +C 1.84693000 3.94786000 4.57845000 -0.78212444 0.44723208 0.74938915 +C 4.65777000 6.62419000 6.13439000 -0.64533147 2.20266408 2.10665395 +C 3.53087000 0.21429000 1.22820000 -1.47474878 -0.54888425 0.30525062 +C 0.82708100 3.04400000 9.65602000 0.11381348 0.12930643 1.00813983 +H 2.58629000 3.95958000 5.42117000 -0.15113664 -0.07250562 -0.53698004 +H 5.35664000 6.93953000 5.31407000 -0.51401957 -0.38874154 0.31271145 +H 2.74411000 0.39111400 11.30710000 0.03051113 -0.24489295 -0.13134223 +H 0.05348530 3.03090000 -0.36073700 0.32347512 -0.31300404 -0.55923036 +H 1.51114000 5.01463000 4.38703000 0.43972600 -1.06212272 0.03606096 +H 4.65875000 5.58673000 6.37266000 0.14339865 -1.01503553 -0.14961609 +H 3.73999000 1.13829000 1.63802000 0.48113928 2.35085732 0.94795031 +H 1.16273000 2.03671000 9.32084000 -0.57362854 0.38207467 0.32223687 +C 2.14162000 3.03468000 3.37516000 1.11015607 0.50831995 -0.80015302 +C 4.90995000 0.68689400 7.52480000 -1.21794700 -1.94463845 -1.28575727 +C 3.15217000 5.98953000 2.31832000 0.19958497 1.41135566 -0.97139877 +C 0.56104000 4.06707000 8.50651000 0.33235211 -0.07728890 0.89033703 +H 2.24329000 3.58619000 2.43018000 -0.37755313 -0.35758749 -0.08691563 +H 4.83478000 6.97770000 8.47928000 0.45704444 0.42075435 -0.73686274 +H 2.98294000 -0.64900100 3.38246000 0.41715018 0.25790839 -0.31710907 +H 0.62389000 3.54480000 7.57215000 -0.08700716 0.15244019 -0.88350304 +H 3.12449000 2.51588000 3.47442000 -0.41257824 -0.25966599 0.08659115 +H 0.40187500 1.32740000 7.41535000 0.45268385 0.27180314 0.27824838 +H 2.23066000 5.59117000 1.93857000 -0.75547753 -0.94118831 -0.10014190 +H 4.97896000 4.64793000 8.59763000 0.50362255 -0.21277833 -0.10263587 +40 +Lattice="5.3719 0.0 0.0 0.0 6.8819 0.0 0.0 0.0 10.8378" Properties=species:S:1:pos:R:3:forces:R:3 energy=-7266.280542234361 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" crystal=NIKVUZ frame=49 pbc="T T T" +O 0.19857200 1.18663000 3.26377000 0.04360766 0.16516818 0.47482568 +O 3.25041000 2.38668000 7.78680000 -0.36565406 0.72378611 0.52300352 +O 5.07164000 4.37686000 2.23693000 0.38479541 -1.19081671 0.52963182 +O 2.47175000 5.67176000 8.40024000 -0.51705913 -1.11645013 0.60766995 +O 4.82379000 3.36598000 5.59790000 1.59582717 -0.57728979 -1.40270647 +O 2.29560000 0.49050000 5.31569000 0.34810166 0.25169454 0.38245828 +O 0.51145500 6.53107000 10.89440000 -0.92884701 -0.13622167 -0.00176638 +O 2.89028000 3.66323000 0.12274300 1.12437941 0.40661791 0.79328303 +C 0.80374600 2.15081000 3.73020000 -0.97563595 -0.82889795 -1.11149818 +C 3.78933000 1.47534000 7.21236000 0.33038419 -1.19769184 0.01805778 +C 4.48442000 5.34519000 1.82914000 0.03003743 0.98903140 -0.37427497 +C 1.88396000 4.67578000 8.85183000 0.32754209 1.85172907 -0.72457287 +C 0.41316200 3.19527000 4.82268000 0.64128455 1.33308614 0.56297903 +C 3.27924000 0.52939000 6.04991000 -0.10976348 -0.28599872 -0.04791554 +C 4.84834000 6.38159000 0.71777400 1.01931385 -0.39632115 -0.46751037 +C 2.06419000 3.78695000 10.08350000 -0.09704886 -0.67540309 0.76154019 +C 1.80000000 4.02450000 4.35981000 -1.33688109 -2.40214055 1.17907192 +C 4.40958000 6.43621000 6.35363000 -0.29617514 -0.46849973 0.93834467 +C 3.58605000 0.27488800 1.02233000 0.12854385 1.08194592 0.68914307 +C 0.77764700 3.06935000 9.82382000 -0.49496050 -0.53442950 -0.52648479 +H 2.57309000 3.92965000 5.20430000 -0.62558025 0.28635147 -1.03262702 +H 5.06827000 6.32165000 5.49611000 0.49660498 -0.09245070 -0.29679067 +H 2.79230000 0.16991900 11.05690000 0.52973981 0.64164965 0.59115318 +H -0.01967140 3.05305000 -0.21475100 0.46382187 0.31812362 -0.52731269 +H 1.57768000 5.00519000 4.04733000 -0.09926824 1.40857887 -0.03980453 +H 4.03609000 5.44560000 6.69532000 0.28142318 0.47813623 -0.40554833 +H 3.91320000 1.31580000 1.37771000 -0.98656314 -0.94965752 -0.89968556 +H 0.96664200 2.02377000 9.54683000 0.05678178 -0.07966100 0.17592002 +C 1.95311000 2.95055000 3.21596000 2.01783262 0.45324538 0.41314080 +C 4.96462000 0.45534100 7.51854000 0.45718894 1.16167069 -0.88952970 +C 3.30633000 6.21025000 2.23917000 -0.58856665 -0.91083901 -0.13492738 +C 0.58333800 3.96812000 8.55421000 -0.12445888 -0.44823224 0.51294485 +H 1.95587000 3.26309000 2.13976000 -0.54300670 -0.05224893 0.78523547 +H 4.97317000 6.94828000 8.56556000 -0.02812303 0.19558587 -0.70424058 +H 3.46697000 -0.25709100 3.23406000 -0.03004910 0.25952510 0.11282566 +H 0.56142300 3.43135000 7.61775000 -0.11125935 -0.09366940 -0.41243786 +H 2.96799000 2.47048000 3.30361000 -0.53797248 -0.18275967 0.13677857 +H 0.61253200 0.92635900 7.23703000 -1.12491934 -0.63332442 0.45778749 +H 2.36219000 5.60103000 2.26779000 0.29926458 0.66392054 -0.35416432 +H 5.09109000 4.60147000 8.67168000 -0.65469028 0.58316734 -0.29200687 +40 +Lattice="5.3719 0.0 0.0 0.0 6.8819 0.0 0.0 0.0 10.8378" Properties=species:S:1:pos:R:3:forces:R:3 energy=-7266.099396051272 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" crystal=NIKVUZ frame=50 pbc="T T T" +O 0.17797500 1.17201000 3.26680000 0.86030655 0.98752987 1.10108521 +O 3.23405000 2.36927000 7.78649000 0.69894411 -0.74871553 -0.66766921 +O 5.08235000 4.38603000 2.24777000 -0.39783656 -0.01171765 -0.16566286 +O 2.48532000 5.66584000 8.40323000 -0.70662142 -1.36409878 1.12412744 +O 4.84558000 3.35542000 5.58707000 0.72431576 -0.27609740 -1.03014334 +O 2.32085000 0.49349500 5.32618000 -0.84617576 0.18949185 -0.27552250 +O 0.49459900 6.52944000 10.87550000 2.12244566 -0.04130364 -1.58133643 +O 2.89346000 3.68646000 0.13884900 1.44963424 0.27727496 0.92724779 +C 0.81384600 2.12348000 3.77131000 -1.22594313 -0.99236355 -2.38835943 +C 3.81214000 1.45852000 7.16878000 -1.76683124 0.92607022 2.07624294 +C 4.48894000 5.35983000 1.79797000 0.92602394 -0.65538448 1.34968004 +C 1.88219000 4.69342000 8.90429000 -0.24916766 1.84560470 -2.28602953 +C 0.40026200 3.20589000 4.78505000 1.10055042 0.89667223 1.18403414 +C 3.27359000 0.52227900 6.07322000 1.23385698 -0.27404772 -0.56790527 +C 4.90745000 6.36220000 0.72256400 -3.17429939 0.67736227 0.47579190 +C 2.08311000 3.78868000 10.08800000 -1.06384536 -0.82258846 1.08931470 +C 1.76464000 4.01586000 4.36829000 -3.10032361 1.41752631 -1.61475563 +C 4.41474000 6.42154000 6.36624000 -0.22552020 -0.31552218 -0.24577381 +C 3.58267000 0.26884000 1.00260000 0.85006841 1.07233000 1.13462268 +C 0.78214800 3.05454000 9.84052000 -0.85219214 -0.51578901 -1.36885532 +H 2.49321000 4.01425000 5.14361000 0.99968091 -0.06782416 0.97019035 +H 5.11509000 6.27310000 5.50486000 -0.31366379 0.03212876 0.39743033 +H 2.75940000 0.18348300 11.13470000 -0.14436899 -0.01546020 -0.69643471 +H -0.08633850 3.03957000 -0.26452300 0.91892770 0.21618915 -0.31229596 +H 1.53045000 5.09972000 4.02494000 0.41688689 -1.62309629 0.69397674 +H 3.92657000 5.47962000 6.67602000 0.70826693 0.10011927 -0.04544569 +H 3.76801000 1.35896000 1.22715000 -0.23160806 -0.89411655 -0.17274162 +H 0.97203100 2.01267000 9.51388000 0.00903553 0.17676540 0.41723656 +C 1.96765000 2.98271000 3.24032000 1.39815562 -1.52502927 -0.15492182 +C 4.93479000 0.48184800 7.48938000 -0.68508072 -0.57300634 0.57298062 +C 3.30699000 6.21548000 2.22865000 1.37387412 0.55537371 -0.34897686 +C 0.55590600 3.96222000 8.55926000 -0.39642914 1.01635194 0.50928052 +H 1.82408000 3.23357000 2.15924000 -0.16994889 0.23107841 0.83985085 +H 5.08623000 6.97806000 8.52792000 -0.67796391 0.24951528 -0.52248416 +H 3.44940000 -0.21758800 3.22127000 0.02865613 -0.08540536 -0.10287395 +H 0.56372000 3.47770000 7.56661000 -0.04597194 0.11527130 0.40278645 +H 2.97004000 2.42797000 3.22684000 -0.75806406 0.55294145 0.36023675 +H 0.47664500 0.95647300 7.27440000 1.86563874 0.59051555 -0.76203898 +H 2.41563000 5.64895000 2.20291000 -1.54087241 -0.52732297 -0.14511975 +H 5.02047000 4.66272000 8.63766000 0.88746254 -0.79721682 -0.17075776 +40 +Lattice="5.3719 0.0 0.0 0.0 6.8819 0.0 0.0 0.0 10.8378" Properties=species:S:1:pos:R:3:forces:R:3 energy=-7266.16723403151 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" crystal=NIKVUZ frame=70 pbc="T T T" +O 0.25723900 1.11977000 3.22804000 1.19862773 1.35560386 0.34866010 +O 3.19525000 2.11522000 7.96753000 0.41160276 -0.84624261 -0.57079519 +O 4.91025000 4.40268000 2.33458000 -0.12044847 0.83380876 -0.70065647 +O 2.53981000 5.71275000 8.57209000 -1.13315715 -0.93018399 0.75416112 +O 4.65872000 3.26402000 5.46361000 0.40069974 -0.36966344 -0.58115159 +O 2.45240000 0.36590700 5.18063000 -0.28164327 0.42861267 -0.34037344 +O 0.28318100 6.57074000 10.61070000 0.92793684 -0.48975401 -0.05221602 +O 2.92719000 3.85075000 0.28596300 -0.16016430 -0.74223120 -0.21840082 +C 0.82121800 2.13117000 3.69224000 -1.03111521 -2.04343566 -0.86687314 +C 3.76402000 1.26358000 7.29235000 0.58975450 1.19409230 0.48306760 +C 4.41357000 5.39704000 1.80591000 -0.09531028 -0.69101483 0.62870671 +C 1.80681000 4.82923000 9.06876000 2.17525098 0.39830810 -0.74499771 +C 0.24195900 3.18072000 4.68978000 0.71699325 0.62990485 0.38134705 +C 3.40383000 0.44607200 5.92834000 1.00996018 -0.18751055 1.79766905 +C 4.85788000 6.45378000 0.68012000 -1.38753182 0.53404898 0.16475578 +C 2.09354000 3.79361000 10.22870000 0.31409419 1.11806992 0.34296665 +C 1.52372000 4.00655000 4.45276000 -0.11873766 0.20887642 1.25150503 +C 4.70860000 6.57403000 6.12777000 1.08061409 -0.57074376 -1.46884553 +C 3.61425000 0.42035300 0.99623900 -0.62166189 -1.38289869 0.49198573 +C 0.90069100 2.95596000 9.81367000 -0.93182949 0.07555187 -1.14874318 +H 2.07384000 3.98841000 5.41236000 0.16212759 0.18568147 0.14608957 +H 5.44387000 6.77011000 5.24887000 -0.90030263 -0.51592785 0.94390854 +H 2.88884000 0.35265200 10.96180000 0.54296042 0.47230548 0.57751091 +H 0.09271130 2.85409000 -0.27430800 0.00664774 0.41809377 0.20343597 +H 1.38436000 5.04980000 4.16470000 0.12073283 0.01055752 -0.20326113 +H 4.48944000 5.48416000 6.18434000 0.41298087 0.43751588 0.09005186 +H 3.86497000 1.41672000 1.35902000 -0.28131057 0.27681217 -0.24416738 +H 1.01108000 1.91800000 9.42217000 0.46558667 0.60542795 0.26964496 +C 2.11944000 2.97517000 3.46670000 -1.60556137 0.49929641 0.55660784 +C 5.18850000 0.47136100 7.38785000 -2.69183188 -0.98184259 0.39464274 +C 3.16110000 6.26299000 2.13706000 2.53624415 0.90338795 -0.77837577 +C 0.63990200 4.02923000 8.62971000 -2.12392662 0.38372738 1.03294070 +H 2.14592000 3.45807000 2.51176000 0.09486188 -0.22612030 -1.15752607 +H 5.29489000 6.77528000 8.34895000 -0.34645615 0.45728510 -0.82690277 +H 3.31525000 -0.27334800 3.16150000 -0.22182090 0.26603307 0.12563798 +H 0.72190600 3.58978000 7.67385000 0.48581251 -0.57210131 -1.42481796 +H 3.09582000 2.58821000 3.74350000 0.14802818 -0.40471581 0.06281051 +H 0.73036100 1.01630000 7.24355000 0.56035651 0.71435016 -0.24064960 +H 2.20355000 5.82935000 2.01340000 -1.20063319 -0.64454985 -0.22297635 +H 5.01972000 4.61795000 8.52329000 0.89158144 -0.80842168 0.74363503 +40 +Lattice="5.3719 0.0 0.0 0.0 6.8819 0.0 0.0 0.0 10.8378" Properties=species:S:1:pos:R:3:forces:R:3 energy=-7266.0648920163985 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" crystal=NIKVUZ frame=80 pbc="T T T" +O 0.47722400 1.06500000 3.12016000 0.00827623 0.61817548 0.13000732 +O 2.97096000 2.01792000 7.84454000 -0.71614993 1.49984275 0.72950424 +O 5.09937000 4.57137000 2.23170000 -1.62484978 1.59643395 -0.18916943 +O 2.70068000 5.59338000 8.60794000 -0.77162405 -0.77961504 -0.00100576 +O 4.69017000 3.25738000 5.30681000 -1.24954585 0.01871290 1.18654868 +O 2.42811000 0.27863500 5.24022000 1.07135812 -0.09741344 0.97191299 +O 0.34062300 6.43637000 10.68510000 -0.91185202 0.66803431 0.32069267 +O 3.04827000 3.69188000 0.19081700 -0.52820743 0.14563808 0.51829326 +C 0.87630900 2.13157000 3.57207000 0.31887798 -0.24818293 0.41622098 +C 3.68754000 1.26344000 7.24200000 -0.12056725 -0.91728219 0.56370923 +C 4.42311000 5.55959000 1.85014000 2.35989218 -1.57444073 -0.43417242 +C 1.94077000 4.72703000 9.06074000 0.10566463 1.77925995 -0.30479657 +C 0.31208100 3.21399000 4.63194000 0.80152598 -0.65440746 -1.35684827 +C 3.35972000 0.31440300 6.06247000 0.29011505 0.14811971 -1.34050634 +C 4.75906000 6.50118000 0.63212200 0.41224760 -1.02409096 0.29984771 +C 2.06176000 3.86416000 10.31800000 0.27482316 -0.06063793 -0.16002855 +C 1.51476000 4.08776000 4.39449000 0.90440096 -0.37976891 0.23764501 +C 4.74819000 6.53713000 6.35261000 0.07062975 -1.01107603 -1.94920473 +C 3.44823000 0.37924700 0.92581400 -0.19768647 -0.06032374 -1.70221428 +C 0.69468800 3.25971000 10.04240000 1.35116099 -3.02601359 0.45730155 +H 2.18683000 4.08219000 5.29369000 -0.20502902 -0.01970493 -0.25811613 +H 5.54319000 6.79512000 5.59325000 -0.62165675 -0.27124264 -0.15459889 +H 2.72803000 0.31878500 10.85080000 0.62681438 -0.03112619 1.24874881 +H -0.10531500 3.44411000 -0.08101020 -0.31801512 0.34850275 0.29273398 +H 1.31605000 5.14146000 4.17779000 0.02927468 -0.09738876 -0.33990601 +H 4.80130000 5.47222000 6.53059000 -0.22552020 -0.49793372 -0.25455567 +H 3.63766000 1.42844000 1.11154000 -0.16343217 0.49127816 0.26156347 +H 0.82225700 2.09897000 10.10480000 -0.31986837 1.65482370 -0.70848290 +C 2.10711000 3.04262000 3.33330000 -1.26056560 1.31652823 -0.78900471 +C 4.97038000 0.48781900 7.55395000 0.81266915 1.46131734 0.80242073 +C 3.15280000 6.33108000 2.13257000 0.00400251 -0.86524821 -0.13438025 +C 0.58712500 4.06908000 8.72593000 0.80362400 -1.26845375 -0.74401555 +H 2.08291000 3.37506000 2.23055000 0.44502556 -0.38997413 1.49146609 +H 4.87327000 6.74506000 8.44626000 0.11405568 0.62360050 0.43621799 +H 3.16173000 -0.12409700 3.13537000 -0.31749730 0.19164334 0.10891707 +H 0.67709300 3.53545000 7.74496000 -0.15515991 0.07699117 0.68992468 +H 3.07176000 2.71257000 3.73069000 0.21144701 -0.40274428 -0.49617097 +H 0.55243700 1.10495000 7.52423000 -0.69544227 -0.60951086 0.33421359 +H 2.31535000 5.60637000 1.99073000 -0.12094726 0.63766444 0.17980753 +H 5.01031000 4.57647000 8.76191000 -0.49227318 1.01000646 -0.36051751 +40 +Lattice="5.3719 0.0 0.0 0.0 6.8819 0.0 0.0 0.0 10.8378" Properties=species:S:1:pos:R:3:forces:R:3 energy=-7266.022986485084 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" crystal=NIKVUZ frame=99 pbc="T T T" +O 0.60788800 1.22760000 2.74854000 -0.02092775 -0.02960893 0.28803503 +O 3.05214000 2.20420000 7.67507000 -0.56682540 0.58971336 0.26839335 +O 5.00377000 4.64272000 2.16615000 1.92644018 -3.16662722 1.63530389 +O 2.60688000 5.50655000 8.43690000 -0.11007613 -0.81376958 0.72699999 +O 4.60321000 2.98353000 5.32681000 -1.02290311 -0.28620903 0.44443935 +O 2.66717000 0.04831410 5.24068000 -0.59433621 -0.29733163 -0.68030875 +O 0.12611800 6.88108000 10.56750000 0.78535375 -0.00434837 -0.66113861 +O 2.88100000 3.95220000 0.50655100 -0.37917858 -0.53046486 -0.51595870 +C 0.95304600 2.14010000 3.48040000 -1.05129837 0.01284251 -0.37944392 +C 3.67974000 1.26251000 7.25977000 1.17456734 -2.07309591 -0.15523087 +C 4.42759000 5.59423000 1.81613000 -2.54453853 4.01537409 -2.28780359 +C 2.03394000 4.57945000 9.01177000 -0.49366723 0.47042446 -0.73735639 +C 0.24421600 2.99828000 4.67627000 1.87872565 -0.15042496 -0.37590865 +C 3.53042000 0.15884900 6.08188000 -0.95124646 1.45523925 -0.02817353 +C 4.67377000 6.73394000 0.59720900 0.65158439 -1.49330700 1.48611305 +C 2.13996000 3.78604000 10.38260000 0.64162908 0.54892024 -0.06039573 +C 1.45814000 3.95326000 4.63030000 -1.19123838 0.85214072 -0.48897394 +C 4.81542000 6.39570000 6.43889000 0.37853323 1.07199575 0.19008731 +C 3.45091000 0.54606700 1.01806000 -0.90629330 1.25671409 -0.15943976 +C 0.82399600 3.07344000 10.08270000 0.44340988 0.42476218 -0.02424946 +H 2.03368000 4.00093000 5.58228000 -0.05968867 -0.01811296 -0.45908795 +H 5.57330000 6.58658000 5.65466000 0.25579443 0.47162825 0.00953591 +H 2.77985000 0.60414600 10.97330000 -0.32196845 0.14955490 0.24844930 +H 0.12720000 3.13688000 0.11107300 -0.13617385 0.02484570 -0.58541448 +H 1.03190000 4.96795000 4.33676000 0.84463824 -0.83440011 0.44413647 +H 4.84808000 5.34130000 6.50906000 -0.32908218 -1.35938338 0.50406169 +H 3.71569000 1.59032000 1.33941000 -0.49581359 -0.69172445 -0.05399111 +H 0.95401000 2.06892000 9.72206000 0.17647538 -0.96946016 0.64300719 +C 2.05077000 3.15849000 3.41570000 0.65255113 1.06065205 1.12365436 +C 4.90493000 0.42021100 7.70195000 1.92117971 0.54096011 0.76842560 +C 3.05682000 6.40186000 2.09734000 1.01008873 -0.55531715 0.91247937 +C 0.68441300 3.87441000 8.75736000 -0.02732826 1.15408079 0.55744088 +H 2.03387000 3.79332000 2.51286000 0.16439274 -0.67805647 0.02523882 +H 4.73824000 6.75595000 8.64794000 -0.34839065 0.21763154 -0.34403571 +H 3.01663000 -0.13285200 3.15039000 0.04370130 0.04889971 -0.48456090 +H 0.69723100 3.25848000 7.87019000 -0.16869368 -0.23816334 -0.41045554 +H 3.06508000 2.78863000 3.66976000 -0.11615987 -0.07859862 -0.41672389 +H 0.54780900 0.92805300 7.92329000 -1.15990177 -0.36525503 -0.64922412 +H 2.15989000 5.77150000 1.93745000 0.18900282 0.41968528 -0.23844359 +H 5.25229000 4.62983000 8.71810000 -0.14236250 -0.15240625 -0.07948000 +40 +Lattice="5.3719 0.0 0.0 0.0 6.8819 0.0 0.0 0.0 10.8378" Properties=species:S:1:pos:R:3:forces:R:3 energy=-7266.054606113258 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 3 2" crystal=NIKVUZ frame=100 pbc="T T T" +O 0.61462600 1.21486000 2.72392000 0.24036215 1.09604585 1.41113969 +O 3.04739000 2.22191000 7.66376000 0.30455745 -0.57831823 -0.18602548 +O 4.98666000 4.66634000 2.17215000 0.99144309 -0.90336224 0.50542952 +O 2.60388000 5.50305000 8.45883000 -0.49507774 -0.90706977 0.55483378 +O 4.58456000 2.95362000 5.32999000 0.75083411 0.03130231 -0.43507385 +O 2.66954000 0.04562640 5.23235000 -0.34724805 0.23098328 0.18881770 +O 0.14843500 6.85676000 10.55350000 -1.06836536 -0.61760983 1.59837770 +O 2.91282000 3.95159000 0.51991300 -0.13817006 -0.37500362 -0.92634790 +C 0.94139600 2.13543000 3.49149000 -0.99005984 -0.63557670 -1.50924784 +C 3.68313000 1.25080000 7.26949000 0.34604169 -0.89458449 0.79013086 +C 4.41214000 5.63456000 1.75537000 -1.65204177 1.04421755 -0.13411851 +C 1.99114000 4.58157000 9.00812000 0.71539403 0.90897239 -0.53968998 +C 0.26123000 3.00852000 4.68617000 -0.78806883 -1.19354723 0.17333863 +C 3.51189000 0.20032600 6.10786000 -0.34488881 0.27480773 -1.35689455 +C 4.67081000 6.70705000 0.62428300 1.94899904 0.32120689 -1.05702679 +C 2.19933000 3.79598000 10.37650000 -1.32236978 -0.35303972 0.05581042 +C 1.43094000 3.94559000 4.62924000 0.21512523 -0.93982562 0.16136861 +C 4.81743000 6.41821000 6.39004000 1.28985561 -0.67024546 1.83614818 +C 3.45935000 0.59771000 1.01910000 -1.01838311 0.10921789 -0.06291901 +C 0.82202400 3.06322000 10.09950000 0.77844776 -0.52225276 -1.37754051 +H 2.00526000 3.86622000 5.56413000 0.26728366 0.10656194 0.04174366 +H 5.69011000 6.57946000 5.71224000 -0.40703751 0.46240416 -0.22512014 +H 2.81065000 0.65670000 10.93660000 -0.14513775 -0.03215653 0.61591290 +H 0.04364080 3.10338000 0.03422180 -0.01980361 0.33589509 0.10987764 +H 1.09029000 4.93529000 4.47693000 -0.01708591 1.35163922 -0.28708527 +H 4.88750000 5.30510000 6.55308000 -0.67216864 0.84140894 -0.08666520 +H 3.64742000 1.65092000 1.34901000 -0.14781735 -0.77302788 -0.00471712 +H 0.83067100 2.03728000 9.68247000 0.58134699 -0.09940810 1.12909995 +C 2.03718000 3.17121000 3.42517000 -0.10985450 0.39750746 0.94936956 +C 4.95475000 0.41116500 7.72641000 -1.40377091 0.04049153 -0.99207558 +C 3.04787000 6.37001000 2.10848000 1.29678730 0.58256570 0.05577186 +C 0.67863300 3.85873000 8.76070000 -0.83270318 1.02953656 -0.16085438 +H 2.14001000 3.74373000 2.51948000 -0.28773575 0.02111508 -0.62910781 +H 4.73516000 6.69551000 8.62370000 0.07562231 0.41096204 -0.14187861 +H 2.97182000 -0.17190200 3.17988000 0.10756364 -0.24618004 -0.96292956 +H 0.68392900 3.24076000 7.82809000 -0.02111647 0.35920471 0.62146135 +H 3.01046000 2.76166000 3.63878000 0.82536525 -0.39122009 0.27850755 +H 0.45288100 1.03324000 7.85120000 0.86370554 0.11131334 0.04821857 +H 2.18848000 5.71447000 1.86227000 0.07876986 0.54419455 -0.02961340 +H 5.17853000 4.58032000 8.71401000 0.55138850 -0.47911736 -0.02042865 +34 +Lattice="5.3875 0.0 0.0 -1.9748077529732335 5.548968944659611 0.0 -0.9950502671437214 -2.62412198615541 9.385386234334366" Properties=species:S:1:pos:R:3:forces:R:3 energy=-3041.9416748830567 energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 4 3" name crystal=KIKYIM frame=0 pbc="T T T" +C -0.15926200 -1.07218000 8.45139000 0.00187018 0.00222766 -0.00064316 +C 2.57690000 3.99703000 0.93400300 -0.00187997 -0.00235371 0.00062395 +C -0.39542200 -0.78463800 6.91682000 -0.00211550 -0.00099016 0.00085730 +C 2.81307000 3.70949000 2.46856000 0.00210570 0.00095465 -0.00085518 +C 2.86758000 3.32356000 6.29956000 -0.00027596 -0.00264524 -0.00032559 +C -0.44993900 -0.39872100 3.08582000 0.00027973 0.00267746 0.00035907 +C -0.95162400 3.28853000 5.99477000 0.00140726 -0.00118243 0.00005098 +C 3.36927000 -0.36368800 3.39061000 -0.00143275 0.00120128 -0.00001605 +C 1.16808000 -0.82810200 6.61873000 0.00045791 0.00202148 -0.00043285 +C 1.24957000 3.75295000 2.76666000 -0.00049502 -0.00202118 0.00043587 +C 1.32337000 -1.46144000 8.04303000 0.00287642 0.00303433 0.00153091 +C 1.09427000 4.38629000 1.34236000 -0.00288713 -0.00305356 -0.00156324 +C -0.79822700 2.64585000 7.42052000 0.00157422 -0.00232527 0.00134029 +C 3.21587000 0.27899200 1.96486000 -0.00158246 0.00236467 -0.00133436 +C -2.36753000 2.36564000 7.54617000 0.00046489 -0.00383037 -0.00284336 +C 4.78517000 0.55920000 1.83921000 -0.00045925 0.00390166 0.00290657 +C -2.74670000 3.14257000 8.79562000 -0.00055919 0.00020391 -0.00022644 +C 5.16434000 -0.21771600 0.58976300 0.00056082 -0.00022968 0.00025888 +H -0.28785300 -0.25689500 9.16181000 -0.00100910 0.00118130 -0.00097569 +H 2.70549000 3.18175000 0.22358500 0.00103525 -0.00132652 0.00084052 +H 4.34875000 0.02258880 6.56860000 0.00052965 -0.00212969 0.00192411 +H -1.93111000 2.90226000 2.81679000 -0.00048440 0.00212171 -0.00194707 +H 2.10943000 3.15299000 5.52804000 0.00445114 0.00276623 0.00161850 +H 0.30821400 -0.22814900 3.85735000 -0.00440929 -0.00274195 -0.00161592 +H -0.52963100 2.91628000 5.05883000 -0.00133669 0.00065601 -0.00028461 +H 2.94728000 0.00857171 4.32655000 0.00132211 -0.00063698 0.00034787 +H 1.74342000 0.02208240 6.24193000 -0.00341169 0.00048563 -0.00145272 +H 0.67422100 2.90277000 3.14346000 0.00340296 -0.00052738 0.00145234 +H 2.16496000 -1.28286000 8.72285000 0.00082354 -0.00017913 -0.00117425 +H 0.25268600 4.20771000 0.66254500 -0.00084290 0.00018265 0.00113887 +H -0.08172950 1.87031000 7.70139000 -0.00108365 -0.00114814 0.00096313 +H 2.49938000 1.05454000 1.68400000 0.00105961 0.00118655 -0.00096807 +H 2.68596000 1.33329000 7.43679000 -0.00440060 0.00124890 -0.00253350 +H -0.26831600 1.59154000 1.94859000 0.00444415 -0.00109469 0.00254293 +34 +Lattice="5.3875 0.0 0.0 -1.9748077529732335 5.548968944659611 0.0 -0.9950502671437214 -2.62412198615541 9.385386234334366" Properties=species:S:1:pos:R:3:forces:R:3 energy=-3040.9201595288228 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 4 3" crystal=KIKYIM frame=10 pbc="T T T" +C -0.22726400 -1.13054000 8.39429000 0.30868767 2.58144928 0.94926157 +C 2.55256000 3.96083000 0.96583800 -0.11830160 1.10879338 0.29062105 +C -0.53331200 -0.80080300 6.87072000 2.07188235 -1.58944055 0.14904068 +C 2.74723000 3.71869000 2.49827000 2.20426845 -0.53144702 0.57851878 +C 2.89332000 3.29491000 6.27087000 -0.30873190 -1.10569777 0.05735206 +C -0.44458800 -0.36859000 3.13182000 0.40281216 -1.00152696 -0.95923745 +C -0.93772600 3.34735000 5.95200000 -0.50079228 -0.98230025 -0.28028521 +C 3.38543000 -0.33245300 3.46886000 0.47139120 -0.52355374 -0.26835324 +C 1.11096000 -0.83534200 6.56271000 -0.12629002 2.68144463 0.68208796 +C 1.24219000 3.79516000 2.79409000 -0.20323645 0.98129752 0.89700133 +C 1.27958000 -1.43193000 8.01098000 -0.15458861 0.03669777 -1.36110602 +C 1.06487000 4.41607000 1.40620000 1.98982302 1.15926414 0.93682258 +C -0.70340700 2.67624000 7.35484000 -0.13911828 -1.14923169 0.41832208 +C 3.27014000 0.36326000 2.07983000 -1.08478956 -0.57235328 -2.06107857 +C -2.26657000 2.27026000 7.50985000 0.04268088 1.10300326 0.54116065 +C 4.80506000 0.53842900 1.85082000 0.61327495 1.07547188 0.25627008 +C -2.66321000 3.07892000 8.76736000 -1.62712778 -1.23598585 0.93230772 +C 5.16927000 -0.24557100 0.56797600 0.01433117 -0.41496731 0.07408839 +H -0.44719900 -0.22657400 9.07250000 0.53145731 -1.49565185 -0.58884433 +H 2.68685000 3.08338000 0.34270800 -0.17703896 0.04626803 -0.34303144 +H 4.15996000 -0.04937300 6.53337000 -0.11638716 0.23038216 -0.13232697 +H -1.96288000 2.90232000 2.83019000 -0.55023150 0.39571232 -0.05386255 +H 2.15173000 3.00891000 5.53121000 -0.09173130 0.07697523 -0.38548036 +H 0.35823000 -0.15303500 3.84233000 -0.00061444 -0.24882828 0.19411675 +H -0.58441700 3.06217000 4.96655000 0.24389896 -0.18916223 -0.09896073 +H 3.06442000 -0.09679710 4.47293000 -0.39344100 0.49863306 0.17723797 +H 1.70301000 0.04654000 6.21831000 -0.42443925 -0.49211274 0.09889645 +H 0.63361400 3.01278000 3.19074000 -0.39632938 -0.83268261 0.20991977 +H 2.14363000 -1.22352000 8.61479000 0.33595577 0.25085996 0.66948441 +H 0.23365700 4.23804000 0.81323000 -1.76623474 -0.18819807 -1.39974970 +H 0.10379300 1.93018000 7.63087000 -0.74404640 0.77186060 -0.20580447 +H 2.63332000 1.18299000 1.70623000 -0.09065144 -0.32059651 0.48235129 +H 2.81761000 1.21501000 7.47259000 0.01834580 0.40753271 -0.27450691 +H -0.18416800 1.56953000 1.97754000 -0.23468464 -0.53190468 -0.18223054 +34 +Lattice="5.3875 0.0 0.0 -1.9748077529732335 5.548968944659611 0.0 -0.9950502671437214 -2.62412198615541 9.385386234334366" Properties=species:S:1:pos:R:3:forces:R:3 energy=-3040.775258909183 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 4 3" crystal=KIKYIM frame=20 pbc="T T T" +C -0.18285900 -1.04999000 8.44511000 1.03248304 -1.18347879 -0.05511211 +C 2.54766000 3.96157000 0.94639200 -0.47098445 0.70708422 -0.08370175 +C -0.47412900 -0.82238400 6.86989000 1.33863972 -0.42511648 -0.05475678 +C 2.80197000 3.78144000 2.50631000 -0.52873708 -0.52934386 0.01066077 +C 2.84963000 3.22269000 6.24290000 0.58402094 0.54533098 1.39642783 +C -0.42922200 -0.35738800 3.12953000 -0.12388758 0.15756543 -1.53082968 +C -0.96648000 3.20669000 5.97956000 -0.30431217 1.38561892 1.90859673 +C 3.42423000 -0.28942500 3.42383000 -0.71220072 1.42244226 -0.32942619 +C 1.12439000 -0.81649700 6.54320000 0.07378860 -1.86806586 0.45983512 +C 1.26397000 3.86474000 2.84582000 0.33849653 -0.11754004 -0.93419491 +C 1.38514000 -1.44334000 7.99872000 -1.97038034 -0.32747935 -0.69377105 +C 1.04094000 4.40011000 1.40722000 -0.39415731 0.13161169 -0.95776678 +C -0.73618900 2.58247000 7.44391000 -0.55917894 1.80576803 -0.57385480 +C 3.24426000 0.36479800 1.96006000 0.42783105 -1.37736568 0.39623322 +C -2.39473000 2.30650000 7.56511000 1.77196316 2.30900491 -0.11406596 +C 4.83437000 0.52975000 1.81116000 0.02346733 0.90287373 -0.03918968 +C -2.70400000 3.12737000 8.80259000 -0.74253974 -0.04385490 -0.79474856 +C 5.09760000 -0.24106800 0.54008300 0.83612275 -0.68523499 1.22376283 +H -0.23975200 -0.30377300 9.26171000 -0.32440740 -0.00517836 -0.83160789 +H 2.67341000 3.13489000 0.23841600 -0.04851013 0.08009861 0.31305186 +H 4.28947000 -0.01750780 6.48111000 -0.15351954 -0.10851444 0.10368642 +H -2.09891000 2.94109000 2.94340000 0.89040388 -0.61476619 0.03208773 +H 2.14741000 3.01000000 5.42659000 -0.09315930 0.06577962 0.27821187 +H 0.26038700 -0.22105900 3.93646000 0.86009057 0.25454795 0.32110970 +H -0.51801800 2.84207000 5.10516000 0.54693021 -0.57583969 -1.46208352 +H 3.00451000 0.14241600 4.32533000 -0.08824746 -0.01384354 0.31544350 +H 1.71305000 0.00677065 6.11331000 -0.27264646 -0.12757814 0.06646713 +H 0.82758800 2.99484000 3.25373000 -0.97370248 -0.90432383 0.57904843 +H 2.23305000 -1.24707000 8.65733000 0.07117996 0.20193033 0.06499080 +H 0.11739800 4.16878000 0.76342200 1.12399889 0.36833110 0.71567171 +H 0.08896340 1.90208000 7.75402000 -0.72500481 0.00888476 -0.23810164 +H 2.60952000 1.16666000 1.60738000 -0.34389688 0.20337323 0.16424516 +H 2.69995000 1.31388000 7.51695000 -0.67530025 -1.92348856 -0.09023595 +H -0.08265340 1.51219000 1.78317000 -0.41465158 0.28076961 0.43391994 +34 +Lattice="5.3875 0.0 0.0 -1.9748077529732335 5.548968944659611 0.0 -0.9950502671437214 -2.62412198615541 9.385386234334366" Properties=species:S:1:pos:R:3:forces:R:3 energy=-3040.675229861709 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 4 3" crystal=KIKYIM frame=30 pbc="T T T" +C -0.13019800 -1.10185000 8.41699000 -0.28744316 1.88160529 -0.39126328 +C 2.61712000 4.07537000 0.93859800 -0.89185398 0.13917073 0.24307004 +C -0.41303400 -0.85687100 6.80570000 -0.82720102 -0.05819743 0.76610133 +C 2.88294000 3.75522000 2.44656000 -0.91696337 0.87248843 -0.05579551 +C 2.82109000 3.20863000 6.26114000 -0.04553552 0.45739822 -1.93161324 +C -0.41237200 -0.31894100 3.11043000 -0.32274698 -1.25042517 -0.17284755 +C -0.95001900 3.12756000 6.05525000 -0.54173658 -0.06000029 -3.36224703 +C 3.40956000 -0.29486000 3.43403000 -0.47315806 -1.24311809 -0.11240760 +C 1.14866000 -0.97877900 6.58483000 1.08853309 1.47040361 -1.62638216 +C 1.31797000 3.79780000 2.77504000 -0.09971921 0.27689033 0.33760641 +C 1.28357000 -1.55005000 7.97368000 1.17633626 0.74838128 1.65557446 +C 1.15318000 4.46296000 1.39940000 -1.19286331 -0.17741846 -0.93639063 +C -0.86491100 2.59410000 7.43143000 -0.13230280 -2.09892007 1.33426884 +C 3.21091000 0.37156000 2.02941000 0.13072723 -0.14854189 -0.56349840 +C -2.49344000 2.36116000 7.50615000 0.72117901 -2.05090214 3.27631048 +C 4.79516000 0.65671200 1.88287000 0.27186485 0.49412643 0.09733631 +C -2.75511000 3.18889000 8.82924000 -0.31829692 0.31246051 -1.88581675 +C 5.13636000 -0.11098300 0.61250100 0.39700147 -0.95811645 0.45838244 +H -0.12392000 -0.16360300 9.04075000 -0.42658201 -1.02797847 -0.43818797 +H 2.64893000 3.19690000 0.26680200 0.33096423 0.68943103 -0.02386616 +H 4.21319000 -0.11855100 6.47995000 0.89694991 -0.03957787 0.01830872 +H -1.87868000 2.89970000 2.60815000 0.42167686 -0.14069694 0.81515283 +H 2.16038000 2.96847000 5.35911000 0.50390948 0.50004923 1.29176851 +H 0.32343800 -0.30184300 3.90066000 0.40755739 0.61293557 0.27654426 +H -0.51333100 2.65941000 5.12953000 -0.32432718 0.50169576 0.73816886 +H 2.87497000 -0.03807320 4.35776000 0.54906422 0.27763800 0.00149289 +H 1.87764000 -0.22389900 6.21849000 -0.68968814 -0.01040052 0.06021061 +H 0.65382600 2.95200000 3.03199000 0.38172037 0.18288000 0.29413832 +H 2.19975000 -1.32722000 8.57684000 -0.62688637 -0.20010742 -0.05807968 +H 0.29307600 4.16156000 0.74764300 0.44386342 0.57966549 0.24619907 +H -0.14780900 1.82907000 7.71950000 -0.13619956 -0.28261977 0.22743104 +H 2.45888000 1.14091000 1.74303000 0.49747812 -0.43575159 0.18826851 +H 2.54518000 1.29476000 7.59950000 0.28485149 0.93181921 -0.61271959 +H -0.22800300 1.70658000 2.00811000 -0.25017142 -0.74627298 -0.15522161 +34 +Lattice="5.3875 0.0 0.0 -1.9748077529732335 5.548968944659611 0.0 -0.9950502671437214 -2.62412198615541 9.385386234334366" Properties=species:S:1:pos:R:3:forces:R:3 energy=-3040.587473148406 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 4 3" crystal=KIKYIM frame=49 pbc="T T T" +C -0.12912200 -1.13583000 8.37409000 0.32524712 1.32155217 0.91138922 +C 2.56083000 4.00706000 0.98104800 0.33779205 0.06796300 1.77595351 +C -0.36432000 -0.75606200 6.90598000 -0.34523128 -2.06820053 -0.19940499 +C 2.79286000 3.74455000 2.60356000 0.96973270 -0.34561540 -0.66623454 +C 2.82481000 3.32886000 6.28368000 -0.98194544 0.47258522 -0.71229842 +C -0.43999000 -0.37291000 3.10413000 -0.48905005 0.52283383 1.59308637 +C -1.07083000 3.22526000 5.82138000 0.54363920 0.32291307 2.79825499 +C 3.38654000 -0.28113200 3.48069000 -0.90914722 -0.16057002 -0.54793808 +C 1.14350000 -0.88803300 6.53545000 -0.30146339 -0.18125763 -0.80813372 +C 1.25415000 3.79445000 2.86533000 -0.60294940 -0.38431719 0.09089158 +C 1.34833000 -1.53055000 7.92973000 -1.00520363 0.53737599 -0.49512608 +C 1.08562000 4.42460000 1.45692000 0.57220929 -0.13496852 -0.79563816 +C -0.79645500 2.63173000 7.31869000 -1.62392418 -0.28786482 -0.64414362 +C 3.25919000 0.31730000 1.97267000 -0.85679956 0.94448446 1.23318849 +C -2.39161000 2.35448000 7.48552000 -0.57043523 -0.38229682 0.61644769 +C 4.86582000 0.54473600 1.88521000 -1.13454041 0.00978978 -0.29539507 +C -2.74756000 3.13771000 8.78173000 -0.05160924 -1.24178626 0.79744821 +C 5.23411000 -0.23703100 0.64245500 -0.22194842 0.41304258 -1.89924820 +H -0.32367600 -0.24353500 8.95946000 0.48308817 -0.02958034 0.83693008 +H 2.66789000 3.13749000 0.37745300 0.09042158 -0.56564270 -0.78795056 +H 4.41574000 0.11601000 6.79997000 -0.41997993 0.33011576 -0.85449071 +H -1.90220000 3.04002000 3.12217000 -0.56279906 0.01036710 -0.85374509 +H 2.01406000 3.20814000 5.55388000 -0.07393361 -0.09659172 0.00649877 +H 0.22518600 -0.17288400 3.92807000 0.78712781 -0.02732599 0.17931593 +H -0.79009100 2.66761000 4.94281000 0.42271559 0.34235627 -0.60057885 +H 2.86600000 0.08497650 4.40955000 0.84980102 -0.09646316 -0.78264895 +H 1.65444000 -0.05536350 6.12641000 0.90354736 0.94796574 -0.35017757 +H 0.71038100 2.85649000 3.16240000 0.22199625 0.96458535 0.06808178 +H 2.16816000 -1.35322000 8.58018000 1.00827353 0.14899337 0.68628914 +H 0.22073000 4.29235000 0.80723600 -0.16317403 -0.33416371 -0.22156276 +H -0.09602480 1.92959000 7.68311000 0.83569595 -1.24659423 -0.04596428 +H 2.53837000 1.15799000 1.71099000 0.87298723 -1.04060258 0.05546281 +H 2.57430000 1.33472000 7.34118000 0.50169268 0.48995045 0.09340766 +H -0.28201600 1.57033000 2.05753000 0.58816556 0.77697195 -0.18196931 +34 +Lattice="5.3875 0.0 0.0 -1.9748077529732335 5.548968944659611 0.0 -0.9950502671437214 -2.62412198615541 9.385386234334366" Properties=species:S:1:pos:R:3:forces:R:3 energy=-3040.4179734376567 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 4 3" crystal=KIKYIM frame=50 pbc="T T T" +C -0.15698300 -1.14746000 8.36951000 1.16723456 2.79737567 1.75062815 +C 2.55147000 4.02948000 1.01096000 1.17731328 -2.64149483 0.11509698 +C -0.38303500 -0.73672800 6.90817000 -0.70958334 -1.00156810 -0.68980641 +C 2.76591000 3.71969000 2.63382000 0.88029430 1.16008689 -2.35667316 +C 2.83235000 3.35870000 6.27257000 -1.36022670 0.13375239 0.04371996 +C -0.45973100 -0.37929200 3.12382000 1.61319754 0.44523022 1.93564473 +C -1.08584000 3.24024000 5.80242000 1.28508364 0.44186002 2.15868279 +C 3.42934000 -0.28049700 3.49693000 -1.62994057 -1.16382013 -3.30380586 +C 1.14992000 -0.84168500 6.57770000 0.63330385 0.31115593 -2.62055576 +C 1.25480000 3.77753000 2.88241000 -0.43821162 1.10657709 -0.88490172 +C 1.36741000 -1.50703000 7.93003000 -0.32721402 -0.80545977 0.44363100 +C 1.11826000 4.39455000 1.40811000 -1.48242609 0.25900830 0.10869853 +C -0.82822700 2.61795000 7.32012000 1.20378022 -1.73161227 -0.49338493 +C 3.25166000 0.29632700 1.95115000 1.29014357 -1.21177121 2.02454834 +C -2.37759000 2.36454000 7.51637000 -0.76477978 -0.50737070 -0.68257133 +C 4.86373000 0.52721600 1.86415000 -0.40024671 1.73673905 0.66227504 +C -2.74697000 3.12410000 8.77627000 0.01998596 -0.67272400 0.80076494 +C 5.23809000 -0.22411400 0.62937000 -0.47520311 -0.56003769 -1.13693153 +H -0.24771900 -0.24824900 9.01444000 0.12807796 -0.68415513 0.22768198 +H 2.62862000 3.07106000 0.42289200 0.16965836 1.15303178 0.09893451 +H 4.34001000 0.12764000 6.68441000 0.55705521 -0.75543125 -0.12653221 +H -1.99606000 2.90973000 2.92040000 0.59885621 -0.58022085 0.40537709 +H 1.98700000 3.25352000 5.58632000 -0.10587649 -0.19288416 -0.16785756 +H 0.25480700 -0.14610300 3.94360000 0.07213384 -0.26701575 -0.54731073 +H -0.77271900 2.76291000 4.83859000 -0.07905577 0.68967785 0.72928313 +H 2.83842000 0.07846910 4.29199000 -0.04652848 0.72143098 1.35113014 +H 1.77916000 -0.02735510 6.12454000 -0.51717226 -0.44576038 0.59675819 +H 0.75513200 2.88076000 3.21841000 -0.54741357 -0.09731163 0.35522104 +H 2.25647000 -1.35585000 8.57953000 -0.49302806 0.02959890 -0.13560872 +H 0.26057100 4.22727000 0.69159200 0.63983445 -0.02353742 0.60510913 +H -0.12164400 1.73437000 7.58864000 -0.95631154 1.58844810 -0.43369420 +H 2.62872000 1.09786000 1.69616000 -1.09485286 1.08659448 -0.51189893 +H 2.65375000 1.32490000 7.37750000 0.13942990 0.50459494 0.00609357 +H -0.21047100 1.59001000 2.03969000 -0.14730827 -0.82300498 -0.32774469 +34 +Lattice="5.3875 0.0 0.0 -1.9748077529732335 5.548968944659611 0.0 -0.9950502671437214 -2.62412198615541 9.385386234334366" Properties=species:S:1:pos:R:3:forces:R:3 energy=-3040.4344635363423 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 4 3" crystal=KIKYIM frame=70 pbc="T T T" +C -0.05470280 -1.01795000 8.62276000 -0.43824711 0.33221584 -1.55465867 +C 2.57429000 3.94391000 0.85250400 0.44866059 3.02368931 0.78476753 +C -0.42829900 -0.69388700 7.07021000 1.59332291 -1.05008481 0.06357207 +C 2.83277000 3.54310000 2.32715000 -1.59611513 1.01389911 -0.18881050 +C 2.80288000 3.44183000 6.31752000 -0.07963118 0.88967369 1.49943137 +C -0.44912300 -0.59417800 3.05491000 -1.33226853 -0.32363864 0.41721548 +C -1.03806000 3.48019000 5.98529000 0.06155632 -1.31833829 -1.65919972 +C 3.30141000 -0.57984400 3.33263000 0.27906754 -1.02508340 0.97667982 +C 1.14134000 -0.65959900 6.65506000 -0.49437429 -0.20738107 0.05994373 +C 1.23623000 3.56765000 2.60113000 0.03587758 0.66985465 -0.38866184 +C 1.40338000 -1.38321000 8.07543000 -0.83282659 -0.05001428 -1.20190331 +C 1.15124000 4.39591000 1.24246000 -0.37329333 -0.83752657 1.45465818 +C -0.78987600 2.75786000 7.31934000 -0.25809968 0.72554989 1.10768781 +C 3.23509000 0.20397700 2.04338000 -1.53583305 1.32773310 -2.56818239 +C -2.35231000 2.46890000 7.63390000 0.22791647 -0.23689270 -2.33348695 +C 4.75842000 0.49637600 1.89252000 0.38741434 -0.78321973 0.63049620 +C -2.68487000 3.16604000 8.85754000 0.11059189 1.80464188 2.59416082 +C 5.18026000 -0.21604000 0.64485200 0.20840591 -0.59185766 -1.79394609 +H -0.16745700 -0.08645440 9.24717000 -0.05251530 -1.46913863 -0.20986475 +H 2.66950000 3.29215000 0.05116310 0.40546863 -1.36308063 -1.26190257 +H 4.33416000 0.11445100 6.85890000 -1.04472663 1.27068546 -0.44676671 +H -1.94035000 2.70819000 2.52233000 0.69420814 -0.73703243 0.63013111 +H 2.01244000 3.30224000 5.53451000 0.46737925 0.08245168 0.72358556 +H 0.17875000 -0.54462200 3.92444000 0.66956154 0.30786338 0.28427916 +H -0.71311200 2.98500000 4.99874000 -0.07558015 1.13245781 1.17138432 +H 2.73261000 -0.37942200 4.25569000 0.68324495 0.25284280 0.01605083 +H 1.61566000 0.24055200 6.19760000 -0.10283693 -0.60164328 0.50949752 +H 0.59063000 2.67938000 2.78676000 0.41752864 0.47471100 0.12397037 +H 2.30246000 -1.29008000 8.66967000 0.35558871 0.15960431 0.38043225 +H 0.27077200 4.32572000 0.65369300 -0.73939785 -0.15633490 -1.09035343 +H -0.00712238 2.01894000 7.40453000 0.07439641 -0.43369574 0.40658088 +H 2.47632000 1.03080000 1.70006000 1.24196110 -1.46095738 0.81338391 +H 2.59525000 1.50113000 7.57405000 0.10876898 -1.11974628 -0.33220247 +H -0.33954400 1.53159000 1.98750000 0.48482264 0.29778054 0.38202993 +34 +Lattice="5.3875 0.0 0.0 -1.9748077529732335 5.548968944659611 0.0 -0.9950502671437214 -2.62412198615541 9.385386234334366" Properties=species:S:1:pos:R:3:forces:R:3 energy=-3040.8326749293597 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 4 3" crystal=KIKYIM frame=80 pbc="T T T" +C -0.12759900 -0.95974900 8.43775000 0.05806991 0.57371082 1.77730591 +C 2.71061000 4.01467000 0.89251100 -0.22586216 -1.21149867 -1.35700254 +C -0.34692300 -0.62088000 6.94480000 -0.28568916 0.15680233 -0.32732046 +C 2.83251000 3.61528000 2.40555000 0.73300094 -0.44096270 -0.12558656 +C 2.87476000 3.49462000 6.28087000 -0.32428244 -0.16569629 0.64991317 +C -0.55390100 -0.55209700 3.17401000 0.10755644 0.18425194 -0.59315350 +C -0.91223700 3.42272000 5.98787000 -0.50106224 0.55932292 -1.04503517 +C 3.19547000 -0.72258000 3.36729000 1.88633097 0.70742361 -1.35363439 +C 1.22803000 -0.66971000 6.68869000 0.80208134 -0.30231545 -0.85852220 +C 1.27766000 3.46961000 2.58397000 -0.27326353 1.01632108 -0.42150254 +C 1.35396000 -1.41645000 8.09792000 -1.07400121 -0.13109746 -1.11015092 +C 1.17384000 4.25380000 1.19450000 -0.30773482 -0.02369847 -0.09013876 +C -0.82150300 2.75371000 7.36842000 -0.18898071 -0.31107931 0.89447136 +C 3.20908000 0.07299890 1.97254000 -2.17074641 -0.58735823 0.73332490 +C -2.39932000 2.51329000 7.59238000 -0.08972944 -0.24137722 -0.41500228 +C 4.66511000 0.49922900 1.95266000 0.74795448 0.44825127 0.74888522 +C -2.75889000 3.31110000 8.89198000 0.46983671 -0.52118318 -1.50098432 +C 5.16404000 -0.11992900 0.67159900 0.66761265 -0.34116431 -0.63401347 +H -0.20078000 -0.13093100 9.14829000 0.11715951 -0.09230003 -0.21799921 +H 2.95370000 3.20572000 0.11286900 -0.27400041 1.21904228 1.07128613 +H 4.42616000 0.25815200 6.65833000 0.30004774 -0.64600510 0.05187098 +H -1.89821000 2.76325000 2.62980000 -0.18128951 0.53755596 0.38085186 +H 2.07909000 3.27564000 5.53281000 0.48459330 0.35312456 0.26687999 +H 0.19610100 -0.29471400 3.93665000 -0.26088881 -0.42119555 0.15903507 +H -0.50688900 3.08166000 4.97005000 -0.44386394 0.37483033 1.44991192 +H 2.70329000 -0.45718500 4.28014000 -0.41944977 0.12642526 0.52404739 +H 1.84556000 0.19927900 6.28527000 -0.68790379 -0.93637006 0.63663085 +H 0.80639300 2.53394000 2.85386000 -0.24957030 -0.31101504 -0.01472944 +H 2.12755000 -1.50243000 8.84376000 0.53636297 0.74186096 0.33252797 +H 0.39692500 4.22878000 0.38058500 0.50810912 -0.23902518 0.76264576 +H -0.11301000 1.97206000 7.61161000 0.17781287 -0.27900326 0.12230275 +H 2.40367000 0.76672200 1.76834000 -0.18961166 0.40031511 -0.37148378 +H 2.55523000 1.49357000 7.55008000 0.43347205 0.40791066 -0.35031692 +H -0.50382400 1.57597000 2.08187000 0.11793342 -0.60480060 0.22468151 +34 +Lattice="5.3875 0.0 0.0 -1.9748077529732335 5.548968944659611 0.0 -0.9950502671437214 -2.62412198615541 9.385386234334366" Properties=species:S:1:pos:R:3:forces:R:3 energy=-3040.7046453677804 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 4 3" crystal=KIKYIM frame=99 pbc="T T T" +C -0.12115700 -1.15130000 8.55793000 0.17028416 0.53235205 -0.02797982 +C 2.50014000 3.96166000 0.88406700 0.17166690 -0.13384649 -0.04595430 +C -0.37995500 -0.74279100 7.08698000 0.55059146 -1.22204533 -1.46609445 +C 2.68918000 3.69907000 2.41133000 1.58166039 -2.13741977 0.75109122 +C 2.99529000 3.38650000 6.33372000 0.10701394 -0.50324408 -0.31993882 +C -0.50181000 -0.47424700 3.04516000 -1.35461655 1.31773665 0.04255171 +C -0.81901400 3.39369000 6.05441000 0.15595540 1.61156232 -0.40395630 +C 3.20931000 -0.35732000 3.30236000 1.14633663 -0.65596041 1.83787082 +C 1.16464000 -0.65807800 6.75382000 1.04584763 -0.05400139 -1.58967195 +C 1.12638000 3.72285000 2.71360000 -0.58184065 -0.52715842 0.22519264 +C 1.39696000 -1.39534000 8.07537000 0.01162591 -0.42367564 2.70189004 +C 1.02621000 4.31398000 1.26149000 0.75827489 1.44484685 0.79579242 +C -0.64958900 2.75115000 7.45354000 -0.25317036 -0.43728397 -0.52927187 +C 3.14531000 0.21621400 1.87695000 -0.17878423 2.42602610 -0.03851770 +C -2.21668000 2.36627000 7.49539000 -0.41400880 -0.57125284 1.46104994 +C 4.71571000 0.48647400 1.80558000 0.67969169 0.26040904 -0.41774976 +C -2.70291000 3.05063000 8.75980000 0.22413952 0.53929403 1.84444256 +C 5.15296000 -0.26396600 0.57558000 -0.28946508 -1.08600827 -1.62530230 +H -0.29934400 -0.44881700 9.36289000 0.00916922 0.31799044 0.01083561 +H 2.62132000 3.14002000 0.17632500 0.15037045 0.08398097 0.15744356 +H 4.27508000 -0.05233570 6.72684000 -0.33424855 0.73327862 -0.01873661 +H -1.96639000 2.89979000 2.72097000 -0.95393584 0.45436021 -0.09589341 +H 2.30955000 3.19518000 5.50435000 -0.20415948 0.24398946 0.10341543 +H 0.26875500 -0.28116300 3.80917000 -0.23525183 -0.20623898 -0.07787049 +H -0.26117700 3.05775000 5.15286000 -0.69095826 0.27154346 0.28933652 +H 2.83511000 0.02511320 4.31325000 0.20169430 -0.39093624 -1.46568821 +H 1.66604000 0.26780800 6.34026000 -0.34751339 -0.89177171 0.65644378 +H 0.47998100 2.89186000 3.12745000 0.82697991 0.64792828 -0.49361890 +H 2.22026000 -1.35183000 8.83789000 -0.45682795 0.58616010 -0.70395776 +H 0.26853300 4.21157000 0.55010200 -1.51255428 -0.50890102 -1.08801887 +H 0.15880500 2.05722000 7.70069000 -0.20476728 -0.17529524 0.13009525 +H 2.55796000 1.17170000 1.64429000 0.25923919 -1.68606261 -0.11190264 +H 2.82361000 1.32992000 7.51784000 0.23282522 -0.08901725 -0.85401763 +H -0.28542000 1.50174000 1.85300000 -0.27126167 0.22866517 0.36669433 +34 +Lattice="5.3875 0.0 0.0 -1.9748077529732335 5.548968944659611 0.0 -0.9950502671437214 -2.62412198615541 9.385386234334366" Properties=species:S:1:pos:R:3:forces:R:3 energy=-3040.6249976469003 name energy_unit=eV force_unit=eVperAnstrom length_unit=Angstrom kpts="4 4 3" crystal=KIKYIM frame=100 pbc="T T T" +C -0.13087400 -1.15234000 8.54777000 -0.10922303 1.06605650 1.00337301 +C 2.48216000 3.92872000 0.90896700 0.62526658 0.78238155 -0.23632963 +C -0.37971800 -0.72030600 7.07001000 0.38974222 -1.88953971 -0.96992810 +C 2.66225000 3.67881000 2.43092000 0.76910437 0.16294418 0.26590195 +C 3.03866000 3.38315000 6.32011000 -1.43931898 0.45737714 0.06382404 +C -0.50143100 -0.47293100 3.07921000 -2.18624502 1.10639197 -1.84818094 +C -0.82467200 3.39567000 6.07636000 0.36965470 2.30915917 -0.62186244 +C 3.26148000 -0.34759200 3.28633000 1.03936845 -1.28990189 -1.06531088 +C 1.15300000 -0.66191700 6.74850000 0.52347660 -1.91092615 0.03152512 +C 1.09282000 3.72748000 2.69712000 0.69990056 0.42839875 0.82569435 +C 1.40258000 -1.38986000 8.13018000 -0.70033765 -0.65025770 -0.04899134 +C 1.01359000 4.30672000 1.24589000 -1.64447758 1.63763845 -1.23455632 +C -0.67575000 2.73061000 7.42217000 1.30714885 0.33169699 0.77823693 +C 3.13561000 0.24794400 1.84978000 2.20857247 -1.68560495 1.15650277 +C -2.19230000 2.36562000 7.49832000 -1.64066207 -1.28640519 0.51622609 +C 4.75152000 0.51802900 1.78955000 -0.47709236 -0.75571921 0.65479827 +C -2.71060000 3.03488000 8.77499000 0.61994954 0.43909300 0.84054505 +C 5.16836000 -0.28707200 0.59218200 -0.44422698 -0.53035173 -1.55177903 +H -0.36288100 -0.45525800 9.37306000 0.24271471 -0.03581084 -0.46395505 +H 2.63121000 3.14113000 0.18049300 0.12337181 -0.21674400 0.08225216 +H 4.24516000 -0.04756990 6.68497000 0.17565828 0.32877108 0.24423629 +H -2.00441000 2.97840000 2.77831000 0.18181042 -1.27722635 0.31962206 +H 2.32301000 3.31689000 5.49661000 -0.09853959 -0.30223729 0.05283103 +H 0.25619600 -0.30203700 3.82646000 0.26978740 -0.06240170 0.46021718 +H -0.26464000 3.06290000 5.20776000 -0.31864196 0.03204356 -0.42516996 +H 2.87467000 0.05343320 4.17055000 -0.90391245 0.62203213 1.44284653 +H 1.58836000 0.21548000 6.35662000 0.92940751 1.11661982 -0.28718194 +H 0.58672000 2.90824000 3.22212000 -0.21279581 0.02249777 -0.48103746 +H 2.30148000 -1.34517000 8.77577000 -0.54817976 0.47733713 -0.03704677 +H 0.17081000 4.26630000 0.45970000 1.09060026 -0.49923213 1.19406659 +H 0.20728700 2.10045000 7.58492000 -0.49822991 -0.42670645 0.43975429 +H 2.51140000 1.05963000 1.64625000 -1.19466308 1.09851925 -0.70367494 +H 2.79427000 1.34362000 7.36086000 0.52252015 0.23226163 -0.17542174 +H -0.37328800 1.55513000 1.96008000 0.32849700 0.16784521 -0.22202556 diff --git a/latest/_downloads/bbdfa9e1459a8f3df5a34d118d90df12/keys-selection.py b/latest/_downloads/bbdfa9e1459a8f3df5a34d118d90df12/keys-selection.py new file mode 100644 index 000000000..f323d5f97 --- /dev/null +++ b/latest/_downloads/bbdfa9e1459a8f3df5a34d118d90df12/keys-selection.py @@ -0,0 +1,138 @@ +""" +Keys Selection +============== + +.. start-body +""" + +import chemfiles +import numpy as np +from metatensor import Labels, TensorBlock, TensorMap + +from featomic import SoapPowerSpectrum + + +# %% +# +# First we load the dataset with chemfiles + +with chemfiles.Trajectory("dataset.xyz") as trajectory: + frames = [f for f in trajectory] + +# %% +# +# and define the hyper parameters of the representation + +HYPER_PARAMETERS = { + "cutoff": { + "radius": 5.0, + "smoothing": {"type": "ShiftedCosine", "width": 0.5}, + }, + "density": { + "type": "Gaussian", + "width": 0.3, + }, + "basis": { + "type": "TensorProduct", + "max_angular": 4, + "radial": {"type": "Gto", "max_radial": 6}, + }, +} + +calculator = SoapPowerSpectrum(**HYPER_PARAMETERS) + +# %% +# +# The selections for keys should be a set of ``Labels``, with the names of the +# keys being a subset of the names of the keys produced by the calculator. + +descriptor = calculator.compute(frames) +print("keys names:", descriptor.keys.names) + +# %% +# +# We can use these names to define a selection, and only blocks matching the +# labels in this selection will be used by featomic. Here, only blocks with +# keys ``[1,1,1]`` and ``[4,4,4]`` will be calculated. + +selection = Labels( + names=["center_type", "neighbor_1_type", "neighbor_2_type"], + values=np.array([[1, 1, 1], [4, 4, 4]], dtype=np.int32), +) +selected_descriptor = calculator.compute(frames, selected_keys=selection) + +# %% +# +# We get a TensorMap with 2 blocks, corresponding to the requested keys + +print(selected_descriptor.keys) + +# %% +# +# The block for ``[1, 1, 1]`` will be exactly the same as the one in the full +# ``TensorMap`` +answer = np.array_equal(descriptor.block(0).values, selected_descriptor.block(0).values) +print(f"Are the blocks 0 in the descriptor and selected_descriptor equal? {answer}") + +# %% +# +# Since there is no block for ``[4, 4, 4]`` in the full ``TensorMap``, an empty +# block with no samples and the default set of properties is generated + +print(selected_descriptor.block(1).values.shape) + +# %% +# +# ``selected_keys`` can be used simultaneously with samples and properties +# selection. Here we define a selection for properties as a ``TensorMap`` to +# select different properties for each block: + +selection = [ + Labels(names=["l", "n_1", "n_2"], values=np.array([[0, 0, 0]])), + Labels(names=["l", "n_1", "n_2"], values=np.array([[1, 1, 1]])), +] +blocks = [] +for entries in selection: + blocks.append( + TensorBlock( + values=np.empty((len(entries), 1)), + samples=Labels.single(), + components=[], + properties=entries, + ) + ) + +keys = Labels( + names=["center_type", "neighbor_1_type", "neighbor_2_type"], + values=np.array([[1, 1, 1], [8, 8, 8]], dtype=np.int32), +) + +selected_properties = TensorMap(keys, blocks) + +# %% +# +# Only one of the key from our ``selected_properties`` will be used in the +# ``selected_keys``, meaning the output will only contain this one key/block. + +selected_keys = Labels( + names=["center_type", "neighbor_1_type", "neighbor_2_type"], + values=np.array([[1, 1, 1]], dtype=np.int32), +) + +descriptor = calculator.compute( + frames, + selected_properties=selected_properties, + selected_keys=selected_keys, +) + +# %% +# +# As expected, we get 1 block with values of the form (420, 1), i.e. with only 1 +# property. + +print(f"list of keys: {descriptor.keys}") +print(descriptor.block(0).values.shape) + +# %% +# +# .. end-body diff --git a/latest/_downloads/bc82bea3a5dd7bdba60b65220891d9e5/examples_python.zip b/latest/_downloads/bc82bea3a5dd7bdba60b65220891d9e5/examples_python.zip new file mode 100644 index 000000000..9ae26ad35 Binary files /dev/null and b/latest/_downloads/bc82bea3a5dd7bdba60b65220891d9e5/examples_python.zip differ diff --git a/latest/_downloads/c7b538745d9e014f991073659387d6c0/splined-radial-integral.zip b/latest/_downloads/c7b538745d9e014f991073659387d6c0/splined-radial-integral.zip new file mode 100644 index 000000000..224beb42c Binary files /dev/null and b/latest/_downloads/c7b538745d9e014f991073659387d6c0/splined-radial-integral.zip differ diff --git a/latest/_downloads/cd406b7304ffdc24d0054d9b0c7d63d0/keys-selection.zip b/latest/_downloads/cd406b7304ffdc24d0054d9b0c7d63d0/keys-selection.zip new file mode 100644 index 000000000..6ceb56f15 Binary files /dev/null and b/latest/_downloads/cd406b7304ffdc24d0054d9b0c7d63d0/keys-selection.zip differ diff --git a/latest/_downloads/da3a0f5fe9cb072a4fc31c517eab269a/property-selection.zip b/latest/_downloads/da3a0f5fe9cb072a4fc31c517eab269a/property-selection.zip new file mode 100644 index 000000000..ac2162e76 Binary files /dev/null and b/latest/_downloads/da3a0f5fe9cb072a4fc31c517eab269a/property-selection.zip differ diff --git a/latest/_downloads/fb625db3c50d423b1b7881136ffdeec8/examples_jupyter.zip b/latest/_downloads/fb625db3c50d423b1b7881136ffdeec8/examples_jupyter.zip new file mode 100644 index 000000000..f38927265 Binary files /dev/null and b/latest/_downloads/fb625db3c50d423b1b7881136ffdeec8/examples_jupyter.zip differ diff --git a/latest/_downloads/fc1ab03aab487600310e5f3e33ce7513/keys-selection.ipynb b/latest/_downloads/fc1ab03aab487600310e5f3e33ce7513/keys-selection.ipynb new file mode 100644 index 000000000..8f22ad70d --- /dev/null +++ b/latest/_downloads/fc1ab03aab487600310e5f3e33ce7513/keys-selection.ipynb @@ -0,0 +1,230 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# Keys Selection\n\n.. start-body\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import chemfiles\nimport numpy as np\nfrom metatensor import Labels, TensorBlock, TensorMap\n\nfrom featomic import SoapPowerSpectrum" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First we load the dataset with chemfiles\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "with chemfiles.Trajectory(\"dataset.xyz\") as trajectory:\n frames = [f for f in trajectory]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "and define the hyper parameters of the representation\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "HYPER_PARAMETERS = {\n \"cutoff\": {\n \"radius\": 5.0,\n \"smoothing\": {\"type\": \"ShiftedCosine\", \"width\": 0.5},\n },\n \"density\": {\n \"type\": \"Gaussian\",\n \"width\": 0.3,\n },\n \"basis\": {\n \"type\": \"TensorProduct\",\n \"max_angular\": 4,\n \"radial\": {\"type\": \"Gto\", \"max_radial\": 6},\n },\n}\n\ncalculator = SoapPowerSpectrum(**HYPER_PARAMETERS)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The selections for keys should be a set of ``Labels``, with the names of the\nkeys being a subset of the names of the keys produced by the calculator.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "descriptor = calculator.compute(frames)\nprint(\"keys names:\", descriptor.keys.names)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can use these names to define a selection, and only blocks matching the\nlabels in this selection will be used by featomic. Here, only blocks with\nkeys ``[1,1,1]`` and ``[4,4,4]`` will be calculated.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "selection = Labels(\n names=[\"center_type\", \"neighbor_1_type\", \"neighbor_2_type\"],\n values=np.array([[1, 1, 1], [4, 4, 4]], dtype=np.int32),\n)\nselected_descriptor = calculator.compute(frames, selected_keys=selection)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We get a TensorMap with 2 blocks, corresponding to the requested keys\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(selected_descriptor.keys)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The block for ``[1, 1, 1]`` will be exactly the same as the one in the full\n``TensorMap``\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "answer = np.array_equal(descriptor.block(0).values, selected_descriptor.block(0).values)\nprint(f\"Are the blocks 0 in the descriptor and selected_descriptor equal? {answer}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Since there is no block for ``[4, 4, 4]`` in the full ``TensorMap``, an empty\nblock with no samples and the default set of properties is generated\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(selected_descriptor.block(1).values.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "``selected_keys`` can be used simultaneously with samples and properties\nselection. Here we define a selection for properties as a ``TensorMap`` to\nselect different properties for each block:\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "selection = [\n Labels(names=[\"l\", \"n_1\", \"n_2\"], values=np.array([[0, 0, 0]])),\n Labels(names=[\"l\", \"n_1\", \"n_2\"], values=np.array([[1, 1, 1]])),\n]\nblocks = []\nfor entries in selection:\n blocks.append(\n TensorBlock(\n values=np.empty((len(entries), 1)),\n samples=Labels.single(),\n components=[],\n properties=entries,\n )\n )\n\nkeys = Labels(\n names=[\"center_type\", \"neighbor_1_type\", \"neighbor_2_type\"],\n values=np.array([[1, 1, 1], [8, 8, 8]], dtype=np.int32),\n)\n\nselected_properties = TensorMap(keys, blocks)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Only one of the key from our ``selected_properties`` will be used in the\n``selected_keys``, meaning the output will only contain this one key/block.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "selected_keys = Labels(\n names=[\"center_type\", \"neighbor_1_type\", \"neighbor_2_type\"],\n values=np.array([[1, 1, 1]], dtype=np.int32),\n)\n\ndescriptor = calculator.compute(\n frames,\n selected_properties=selected_properties,\n selected_keys=selected_keys,\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As expected, we get 1 block with values of the form (420, 1), i.e. with only 1\nproperty.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(f\"list of keys: {descriptor.keys}\")\nprint(descriptor.block(0).values.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + ".. end-body\n\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/latest/_images/core-concepts.svg b/latest/_images/core-concepts.svg new file mode 100644 index 000000000..e936c4360 --- /dev/null +++ b/latest/_images/core-concepts.svg @@ -0,0 +1,381 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Systems + + + positions + cell and periodicity + neighbors list + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Calculators + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TensorMap + + + key:   0, 3 + + + key:   1, -2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/latest/_images/featomic-python.svg b/latest/_images/featomic-python.svg new file mode 100644 index 000000000..df0ea2b22 --- /dev/null +++ b/latest/_images/featomic-python.svg @@ -0,0 +1,69 @@ + + + + + + + libfeatomic.so + + + + featomic-c-api + + + + + + cbindgen + + + + + + featomic.h + + + + + + pycparser + + + + + + + featomic + + + Python module + + + + + + + + + _c_api.py + + + + + + + + + + + calls + + + generates + + + + + + + diff --git a/latest/_images/long-range-descriptor.svg b/latest/_images/long-range-descriptor.svg new file mode 100644 index 000000000..dd491ebb7 --- /dev/null +++ b/latest/_images/long-range-descriptor.svg @@ -0,0 +1 @@ +All atom contributionsFourier space LODE descriptorInterior partreal space LODE descriptorExterior partresult of this how-to guide \ No newline at end of file diff --git a/latest/_images/moments-descriptor.svg b/latest/_images/moments-descriptor.svg new file mode 100644 index 000000000..99be80f8c --- /dev/null +++ b/latest/_images/moments-descriptor.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/latest/_images/sphx_glr_compute-soap_thumb.png b/latest/_images/sphx_glr_compute-soap_thumb.png new file mode 100644 index 000000000..8a5fed589 Binary files /dev/null and b/latest/_images/sphx_glr_compute-soap_thumb.png differ diff --git a/latest/_images/sphx_glr_first-calculation_thumb.png b/latest/_images/sphx_glr_first-calculation_thumb.png new file mode 100644 index 000000000..8a5fed589 Binary files /dev/null and b/latest/_images/sphx_glr_first-calculation_thumb.png differ diff --git a/latest/_images/sphx_glr_keys-selection_thumb.png b/latest/_images/sphx_glr_keys-selection_thumb.png new file mode 100644 index 000000000..8a5fed589 Binary files /dev/null and b/latest/_images/sphx_glr_keys-selection_thumb.png differ diff --git a/latest/_images/sphx_glr_long-range-descriptor_001.png b/latest/_images/sphx_glr_long-range-descriptor_001.png new file mode 100644 index 000000000..1837ea7d2 Binary files /dev/null and b/latest/_images/sphx_glr_long-range-descriptor_001.png differ diff --git a/latest/_images/sphx_glr_long-range-descriptor_002.png b/latest/_images/sphx_glr_long-range-descriptor_002.png new file mode 100644 index 000000000..41c65aff2 Binary files /dev/null and b/latest/_images/sphx_glr_long-range-descriptor_002.png differ diff --git a/latest/_images/sphx_glr_long-range-descriptor_003.png b/latest/_images/sphx_glr_long-range-descriptor_003.png new file mode 100644 index 000000000..8139afe44 Binary files /dev/null and b/latest/_images/sphx_glr_long-range-descriptor_003.png differ diff --git a/latest/_images/sphx_glr_long-range-descriptor_004.png b/latest/_images/sphx_glr_long-range-descriptor_004.png new file mode 100644 index 000000000..d8a3a51fb Binary files /dev/null and b/latest/_images/sphx_glr_long-range-descriptor_004.png differ diff --git a/latest/_images/sphx_glr_long-range-descriptor_005.png b/latest/_images/sphx_glr_long-range-descriptor_005.png new file mode 100644 index 000000000..33e4d72bb Binary files /dev/null and b/latest/_images/sphx_glr_long-range-descriptor_005.png differ diff --git a/latest/_images/sphx_glr_long-range-descriptor_006.png b/latest/_images/sphx_glr_long-range-descriptor_006.png new file mode 100644 index 000000000..39cb3ba03 Binary files /dev/null and b/latest/_images/sphx_glr_long-range-descriptor_006.png differ diff --git a/latest/_images/sphx_glr_long-range-descriptor_007.png b/latest/_images/sphx_glr_long-range-descriptor_007.png new file mode 100644 index 000000000..91267f207 Binary files /dev/null and b/latest/_images/sphx_glr_long-range-descriptor_007.png differ diff --git a/latest/_images/sphx_glr_long-range-descriptor_thumb.png b/latest/_images/sphx_glr_long-range-descriptor_thumb.png new file mode 100644 index 000000000..e0fcb1a58 Binary files /dev/null and b/latest/_images/sphx_glr_long-range-descriptor_thumb.png differ diff --git a/latest/_images/sphx_glr_profiling_thumb.png b/latest/_images/sphx_glr_profiling_thumb.png new file mode 100644 index 000000000..8a5fed589 Binary files /dev/null and b/latest/_images/sphx_glr_profiling_thumb.png differ diff --git a/latest/_images/sphx_glr_property-selection_thumb.png b/latest/_images/sphx_glr_property-selection_thumb.png new file mode 100644 index 000000000..8a5fed589 Binary files /dev/null and b/latest/_images/sphx_glr_property-selection_thumb.png differ diff --git a/latest/_images/sphx_glr_sample-selection_thumb.png b/latest/_images/sphx_glr_sample-selection_thumb.png new file mode 100644 index 000000000..8a5fed589 Binary files /dev/null and b/latest/_images/sphx_glr_sample-selection_thumb.png differ diff --git a/latest/_images/sphx_glr_splined-radial-integral_001.png b/latest/_images/sphx_glr_splined-radial-integral_001.png new file mode 100644 index 000000000..7f297e7e5 Binary files /dev/null and b/latest/_images/sphx_glr_splined-radial-integral_001.png differ diff --git a/latest/_images/sphx_glr_splined-radial-integral_002.png b/latest/_images/sphx_glr_splined-radial-integral_002.png new file mode 100644 index 000000000..45f63c2e9 Binary files /dev/null and b/latest/_images/sphx_glr_splined-radial-integral_002.png differ diff --git a/latest/_images/sphx_glr_splined-radial-integral_003.png b/latest/_images/sphx_glr_splined-radial-integral_003.png new file mode 100644 index 000000000..d3e60ff91 Binary files /dev/null and b/latest/_images/sphx_glr_splined-radial-integral_003.png differ diff --git a/latest/_images/sphx_glr_splined-radial-integral_004.png b/latest/_images/sphx_glr_splined-radial-integral_004.png new file mode 100644 index 000000000..d1db3ed8e Binary files /dev/null and b/latest/_images/sphx_glr_splined-radial-integral_004.png differ diff --git a/latest/_images/sphx_glr_splined-radial-integral_005.png b/latest/_images/sphx_glr_splined-radial-integral_005.png new file mode 100644 index 000000000..e5f3b75cb Binary files /dev/null and b/latest/_images/sphx_glr_splined-radial-integral_005.png differ diff --git a/latest/_images/sphx_glr_splined-radial-integral_thumb.png b/latest/_images/sphx_glr_splined-radial-integral_thumb.png new file mode 100644 index 000000000..bf79c3955 Binary files /dev/null and b/latest/_images/sphx_glr_splined-radial-integral_thumb.png differ diff --git a/latest/_sources/devdoc/explanations/architecture.rst.txt b/latest/_sources/devdoc/explanations/architecture.rst.txt new file mode 100644 index 000000000..1fe63cc3f --- /dev/null +++ b/latest/_sources/devdoc/explanations/architecture.rst.txt @@ -0,0 +1,28 @@ +Code organization +----------------- + +The code is organized in three main products, each in a separate directory: + +- ``featomic/`` contains the main Rust implementation of all calculators, and + the corresponding unit and regression tests; +- ``featomic-torch/`` contains the TorchScript bindings to featomic, written in + C++; +- ``python/`` contains the Python interface to featomic and featomic-torch, and + the corresponding tests + +Finally, ``docs/`` contains the documentation for everything related to +featomic. + +The main featomic crate +^^^^^^^^^^^^^^^^^^^^^^^^ + +Inside the main featomic crate, the following code organization is used: + +- ``featomic/benches``: benchmarks of the code on some simple systems; +- ``featomic/tests``: regression tests for all calculators; +- ``featomic/src/system/``: definition of everything related to systems: + ``UnitCell``, the ``System`` trait and ``SimpleSystem`` implementation; +- ``featomic/src/calculator.rs``: convenience wrapper around implementations of + ``CalculatorBase`` that setup everything before a calculation; +- ``featomic/src/calculators/``: definition of the ``CalculatorBase`` trait and + various implementations of this trait; diff --git a/latest/_sources/devdoc/explanations/index.rst.txt b/latest/_sources/devdoc/explanations/index.rst.txt new file mode 100644 index 000000000..32c99881c --- /dev/null +++ b/latest/_sources/devdoc/explanations/index.rst.txt @@ -0,0 +1,15 @@ +.. _devdoc-explanations: + +Explanations +============ + +The explanation section discusses topics that broaden your knowledge of +featomic. Technical facts and some tidbits of useful information are found here +to give you more clarity and understanding of what featomic is all about. + +.. toctree:: + :maxdepth: 2 + + architecture + interfaces + radial-integral diff --git a/latest/_sources/devdoc/explanations/interfaces.rst.txt b/latest/_sources/devdoc/explanations/interfaces.rst.txt new file mode 100644 index 000000000..f26d968f7 --- /dev/null +++ b/latest/_sources/devdoc/explanations/interfaces.rst.txt @@ -0,0 +1,69 @@ +Python and C interface +====================== + +How is the C interface exported +------------------------------- + +Featomic exports a C interface, created directly in Rust without involving any C +code. + +This is done by marking functions as ``#[no_mangle] extern pub fn `` in +``featomic/src/c-api/*.rs``, and only using types safe to send to C (mostly +pointers and basic values such as floats or integers). Of these markers, ``pub`` +ensures that the function is exported from the library (it should appear as a +``T`` symbol in ``nm`` output); ``extern`` forces the function to use the C +calling convention (a calling convention describes where in memory/CPU registers +the caller should put data that the function expects); and ``#[no_mangle]`` +tells the compiler to export the function under this exact name, instead of +using a mangled named containing the module path and functions parameters. + +Additionally, the C interfaces expose C-compatible structs declared with +``#[repr(C)] pub struct {}``; where ``#[repr(C)]`` ensures that the +compiler lays out the fields in the exact order they are declared, without +re-organizing them. + +``featomic`` is then compiled to a shared library (``libfeatomic.so`` / +``libfeatomic.dylib`` / ``libfeatomic.dll``), which can be used by any language +able to call C code to call the exported functions without ever realizing it is +speaking with Rust code. + +The list of exported functions, together with the types of the function's +parameters, and struct definitions are extracted from the rust source code using +`cbindgen`_, which creates the ``featomic/include/featomic.h`` header file +containing all of this information in a C compatible syntax. All of the +documentation is also reproduced using `doxygen`_ syntax. + + +How does the Python interface works +----------------------------------- + +The Python interface used the `ctypes`_ module to call exported symbols from the +shared library. For the Python code to be able to call exported function safely, +it needs to know a few things. In particular, it needs to know the name of the +function, the number and types of parameters and the return type of the +function. All this information is available in ``featomic/include/featomic.h``, +but not in a way that is easily accessible from `ctypes`_. There is a script in +``python/scripts/generate-declaration.py`` which reads the header file using +`pycparser`_, and creates the `python/featomic/_c_api.py` file which +declares all functions in the way expected by the `ctypes`_ module. You will +need to manually re-run this script if you modify any of the exported functions +in `featomic/src/c-api`. + +The schematic below describes all the relationships between the components +involved in creating the Python interface. + +.. figure:: ../../../static/images/featomic-python.* + :width: 400px + :align: center + + Schematic representation of all components in the Python interface. The rust + crate ``featomic`` is compiled to a shared library (``libfeatomic.so`` on + Linux), and `cbindgen`_ is used to generate the corresponding header. This + header is then read with `pycparser`_ to create ctypes' compatible + declarations, used to ensure that Python and rust agree fully on the + parameters types, allowing Python to directly call Rust code. + +.. _ctypes: https://docs.python.org/3/library/ctypes.html +.. _pycparser: https://github.com/eliben/pycparser +.. _cbindgen: https://github.com/eqrion/cbindgen/blob/master/docs.md +.. _doxygen: https://doxygen.org diff --git a/latest/_sources/devdoc/explanations/radial-integral.rst.txt b/latest/_sources/devdoc/explanations/radial-integral.rst.txt new file mode 100644 index 000000000..899eca3cf --- /dev/null +++ b/latest/_sources/devdoc/explanations/radial-integral.rst.txt @@ -0,0 +1,275 @@ +.. _radial-integral: + +SOAP and LODE radial integrals +============================== + +On this page, we describe the exact mathematical expression that are implemented +in the radial integral and the splined radial integral classes i.e. +:ref:`python-utils-splines`. Note that this page assumes knowledge of spherical +expansion & friends and currently serves as a reference page for the developers +to support the implementation. + +Preliminaries +------------- + +In this subsection, we briefly provide all the preliminary knowledge that is needed to +understand what the radial integral class is doing. The actual explanation for what is +computed in the radial integral class can be found in the next subsection (1.2). The +spherical expansion coefficients :math:`\langle anlm | \rho_i \rangle` are completely +determined by specifying two ingredients: + +- the atomic density function :math:`g(r)` as implemented in + :ref:`python-atomic-density`, often chosen to be a Gaussian or Delta function, that + defined the type of density under consideration. For a given central atom :math:`i` in + the system, the total density function :math:`\rho_i(\boldsymbol{r})` around is + then defined as :math:`\rho_i(\boldsymbol{r}) = \sum_{j} g(\boldsymbol{r} - + \boldsymbol{r}_{ij})`. + +- the radial basis functions :math:`R_{nl}(r)` as implementated + :ref:`python-radial-basis`, on which the density :math:`\rho_i` is projected. To be + more precise, the actual basis functions are of the form + + .. math:: + + B_{nlm}(\boldsymbol{r}) = R_{nl}(r)Y_{lm}(\hat{r}), + + where :math:`Y_{lm}(\hat{r})` are the real spherical harmonics evaluated at the point + :math:`\hat{r}`, i.e. at the spherical angles :math:`(\theta, \phi)` that determine + the orientation of the unit vector :math:`\hat{r} = \boldsymbol{r}/r`. + +The spherical expansion coefficient :math:`\langle nlm | \rho_i \rangle` (we omit the +atom type index :math:`a` for simplicity) is then defined as + +.. math:: + + \begin{aligned} + \langle nlm | \rho_i \rangle & = \int \mathrm{d}^3\boldsymbol{r} + B_{nlm}(\boldsymbol{r}) \rho_i(\boldsymbol{r}) \\ \label{expansion_coeff_def} & = + \int \mathrm{d}^3\boldsymbol{r} R_{nl}(r)Y_{lm}(\hat{r})\rho_i(\boldsymbol{r}). + \end{aligned} + +In practice, the atom centered density :math:`\rho_i` is a superposition of the neighbor +contributions, namely :math:`\rho_i(\boldsymbol{r}) = \sum_{j} g(\boldsymbol{r} - +\boldsymbol{r}_{ij})`. Due to linearity of integration, evaluating the integral can then +be simplified to + +.. math:: + + \begin{aligned} + \langle nlm | \rho_i \rangle & = \int \mathrm{d}^3\boldsymbol{r} + R_{nl}(r)Y_{lm}(\hat{r})\rho_i(\boldsymbol{r}) \\ & = \int + \mathrm{d}^3\boldsymbol{r} R_{nl}(r)Y_{lm}(\hat{r})\left( \sum_{j} + g(\boldsymbol{r} - \boldsymbol{r}_{ij})\right) \\ & = \sum_{j} \int + \mathrm{d}^3\boldsymbol{r} R_{nl}(r)Y_{lm}(\hat{r}) g(\boldsymbol{r} - + \boldsymbol{r}_{ij}) \\ & = \sum_j \langle nlm | g;\boldsymbol{r}_{ij} \rangle. + \end{aligned} + +Thus, instead of having to compute integrals for arbitrary densities :math:`\rho_i`, we +have reduced our problem to the evaluation of integrals of the form + +.. math:: + + \begin{aligned} + \langle nlm | g;\boldsymbol{r}_{ij} \rangle & = \int \mathrm{d}^3\boldsymbol{r} + R_{nl}(r)Y_{lm}(\hat{r})g(\boldsymbol{r} - \boldsymbol{r}_{ij}), + \end{aligned} + +which are completely specified by + +- the density function :math:`g(\boldsymbol{r})` + +- the radial basis :math:`R_{nl}(r)` + +- the position of the neighbor atom :math:`\boldsymbol{r}_{ij}` relative to the center + atom + +The radial integral class +------------------------- + +In the previous subsection, we have explained how the computation of the spherical +expansion coefficients can be reduced to integrals of the form + +.. math:: + + \begin{aligned} + \langle nlm | g;\boldsymbol{r}_{ij} \rangle & = \int \mathrm{d}^3\boldsymbol{r} + R_{nl}(r)Y_{lm}(\hat{r})g(\boldsymbol{r} - \boldsymbol{r}_{ij}). + \end{aligned} + +If the atomic density is spherically symmetric, i.e. if :math:`g(\boldsymbol{r}) = g(r)` +this integral can always be written in the following form: + +.. math:: + + \begin{aligned} \label{expansion_coeff_spherical_symmetric} + \langle nlm | g;\boldsymbol{r}_{ij} \rangle & = + Y_{lm}(\hat{r}_{ij})I_{nl}(r_{ij}). + \end{aligned} + +The key point is that the dependence on the vectorial position +:math:`\boldsymbol{r}_{ij}` is split into a factor that contains information about the +orientation of this vector, namely :math:`Y_{lm}(\hat{r}_{ij})`, which is just the +spherical harmonic evaluated at :math:`\hat{r}_{ij}`, and a remaining part that captures +the dependence on the distance of atom :math:`j` from the central atom :math:`i`, namely +:math:`I_{nl}(r_{ij})`, which we shall call the radial integral. The radial integral +class computes and outputs this radial part :math:`I_{nl}(r_{ij})`. Since the angular +part is just the usual spherical harmonic, this is the part that also depends on the +choice of atomic density :math:`g(r)`, as well as the radial basis :math:`R_{nl}(r)`. In +the following, for users only interested in a specific type of density, we provide the +explicit expressions of :math:`I_{nl}(r)` for the Delta and Gaussian densities, followed +by the general expression. + +Delta Densities +~~~~~~~~~~~~~~~ + +Here, we consider the especially simple special case where the atomic density function +:math:`g(\boldsymbol{r}) = \delta(\boldsymbol{r})`. Then: + +.. math:: + + \begin{aligned} + \langle nlm | g;\boldsymbol{r}_{ij} \rangle & = \int \mathrm{d}^3\boldsymbol{r} + R_{nl}(r)Y_{lm}(\hat{r})g(\boldsymbol{r} - \boldsymbol{r}_{ij}) \\ & = \int + \mathrm{d}^3\boldsymbol{r} R_{nl}(r)Y_{lm}(\hat{r})\delta(\boldsymbol{r} - + \boldsymbol{r}_{ij}) \\ & = R_{nl}(r) Y_{lm}(\hat{r}_{ij}) = + B_{nlm}(\boldsymbol{r}_{ij}). + \end{aligned} + +Thus, in this particularly simple case, the radial integral is simply the radial basis +function evaluated at the pair distance :math:`r_{ij}`, and we see that the integrals +have indeed the form presented above. + +Gaussian Densities +~~~~~~~~~~~~~~~~~~ + +Here, we consider another popular use case, where the atomic density function is a +Gaussian. In featomic, we use the convention + +.. math:: + + g(r) = \frac{1}{(\pi \sigma^2)^{3/4}}e^{-\frac{r^2}{2\sigma^2}}. + +The prefactor was chosen such that the “L2-norm” of the Gaussian + +.. math:: + + \begin{aligned} + \|g\|^2 = \int \mathrm{d}^3\boldsymbol{r} |g(r)|^2 = 1, + \end{aligned} + +but does not affect the following calculations in any way. With these conventions, it +can be shown that the integral has the desired form + +.. math:: + + \begin{aligned} + \langle nlm | g;\boldsymbol{r}_{ij} \rangle & = \int \mathrm{d}^3\boldsymbol{r} + R_{nl}(r)Y_{lm}(\hat{r})g(\boldsymbol{r} - \boldsymbol{r}_{ij}) \\ & = + Y_{lm}(\hat{r}_{ij}) \cdot I_{nl}(r_{ij}) + \end{aligned} + +with + +.. math:: + + I_{nl}(r_{ij}) = \frac{1}{(\pi \sigma^2)^{3/4}}4\pi e^{-\frac{r_{ij}^2}{2\sigma^2}} + \int_0^\infty \mathrm{d}r r^2 R_{nl}(r) e^{-\frac{r^2}{2\sigma^2}} + i_l\left(\frac{rr_{ij}}{\sigma^2}\right), + +where :math:`i_l` is a modified spherical Bessel function. The first factor, of course, +is just the normalization factor of the Gaussian density. See the next two subsections +for a derivation of this formula. + +Derivation of the General Case +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We now derive an explicit formula for radial integral that works for any density. Let +:math:`g(r)` be a generic spherically symmetric density function. Our goal will be to +show that + +.. math:: + + \langle nlm | g;\boldsymbol{r}_{ij} \rangle = Y_{lm}(\hat{r}_{ij}) \left[2\pi + \int_0^\infty \mathrm{d}r r^2 R_{nl}(r) \int_{-1}^1 \mathrm{d}(\cos\theta) + P_l(\cos\theta) g(\sqrt{r^2+r_{ij}^2-2rr_{ij}\cos\theta}) \right] + +and thus we have the desired form :math:`\langle nlm | g;\boldsymbol{r}_{ij} \rangle = +Y_{lm}(\hat{r}_{ij}) I_{nl}(r_{ij})` with + +.. math:: + + \begin{aligned} + I_{nl}(r_{ij}) = 2\pi \int_0^\infty \mathrm{d}r r^2 R_{nl}(r) \int_{-1}^1 + \mathrm{d}u P_l(u) g(\sqrt{r^2+r_{ij}^2-2rr_{ij}u}), + \end{aligned} + +where :math:`P_l(x)` is the :math:`l`-th Legendre polynomial. + +Derivation of the explicit radial integral for Gaussian densities +----------------------------------------------------------------- + +Denoting by :math:`\theta(\boldsymbol{r},\boldsymbol{r}_{ij})` the angle between a +generic position vector :math:`\boldsymbol{r}` and the vector +:math:`\boldsymbol{r}_{ij}`, we can write + +.. math:: + + \begin{aligned} + g(\boldsymbol{r}- \boldsymbol{r}_{ij}) & = \frac{1}{(\pi + \sigma^2)^{3/4}}e^{-\frac{(\boldsymbol{r}- \boldsymbol{r}_{ij})^2}{2\sigma^2}} \\ + & = \frac{1}{(\pi + \sigma^2)^{3/4}}e^{-\frac{(r_{ij})^2}{2\sigma^2}}e^{-\frac{(\boldsymbol{r}^2- + 2\boldsymbol{r}\boldsymbol{r}_{ij})}{2\sigma^2}}, + \end{aligned} + +where the first factor no longer depends on the integration variable :math:`r`. + +Analytical Expressions for the GTO Basis +---------------------------------------- + +While the above integrals are hard to compute in general, the GTO basis is one of the +few sets of basis functions for which many of the integrals can be evaluated +analytically. This is also useful to test the correctness of more numerical +implementations. + +The primitive basis functions are defined as + +.. math:: + + \begin{aligned} + R_{nl}(r) = R_n(r) = r^n e^{-\frac{r^2}{2\sigma_n^2}} + \end{aligned} + +In this form, the basis functions are not yet orthonormal, which requires an extra +linear transformation. Since this transformation can also be applied after computing the +integrals, we simply evaluate the radial integral with respect to these primitive basis +functions. + +Real Space Integral for Gaussian Densities +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We now evaluate + +.. math:: + + \begin{aligned} + I_{nl}(r_{ij}) & = \frac{1}{(\pi \sigma^2)^{3/4}}4\pi + e^{-\frac{r_{ij}^2}{2\sigma^2}} \int_0^\infty \mathrm{d}r r^2 R_{nl}(r) + e^{-\frac{r^2}{2\sigma^2}} i_l\left(\frac{rr_{ij}}{\sigma^2}\right) \\ & = + \frac{1}{(\pi \sigma^2)^{3/4}}4\pi e^{-\frac{r_{ij}^2}{2\sigma^2}} \int_0^\infty + \mathrm{d}r r^2 r^n e^{-\frac{r^2}{2\sigma_n^2}} e^{-\frac{r^2}{2\sigma^2}} + i_l\left(\frac{rr_{ij}}{\sigma^2}\right), + \end{aligned} + +the result of which can be conveniently expressed using :math:`a=\frac{1}{2\sigma^2}`, +:math:`b_n = \frac{1}{2\sigma_n^2}`, :math:`n_\mathrm{eff}=\frac{n+l+3}{2}` and +:math:`l_\mathrm{eff}=l+\frac{3}{2}` as + +.. math:: + + \begin{aligned} + I_{nl}(r_{ij}) = \frac{1}{(\pi \sigma^2)^{3/4}} \cdot + \pi^{\frac{3}{2}}\frac{\Gamma\left(n_\mathrm{eff}\right)}{\Gamma\left(l_\mathrm{eff}\right)}\frac{(ar_{ij})^l}{(a+b)^{n_\mathrm{eff}}}M\left(n_\mathrm{eff},l_\mathrm{eff},\frac{a^2r_{ij}^2}{a^2+b^2}\right), + \end{aligned} + +where :math:`M(a,b,z)` is the confluent hypergeometric function (hyp1f1). diff --git a/latest/_sources/devdoc/get-started.rst.txt b/latest/_sources/devdoc/get-started.rst.txt new file mode 100644 index 000000000..4c19e4ef6 --- /dev/null +++ b/latest/_sources/devdoc/get-started.rst.txt @@ -0,0 +1,6 @@ +.. _devdoc-get-started: + +Getting started +=============== + +.. include:: ../../../CONTRIBUTING.rst diff --git a/latest/_sources/devdoc/how-to/index.rst.txt b/latest/_sources/devdoc/how-to/index.rst.txt new file mode 100644 index 000000000..d98198406 --- /dev/null +++ b/latest/_sources/devdoc/how-to/index.rst.txt @@ -0,0 +1,10 @@ +.. _devdoc-how-to: + +How-to guides +============= + +.. toctree:: + :maxdepth: 2 + + new-calculator + profiling diff --git a/latest/_sources/devdoc/how-to/new-calculator.rst.txt b/latest/_sources/devdoc/how-to/new-calculator.rst.txt new file mode 100644 index 000000000..49d0f6f44 --- /dev/null +++ b/latest/_sources/devdoc/how-to/new-calculator.rst.txt @@ -0,0 +1,574 @@ +Adding a new calculator +======================= + +Introduction +------------ + +Before adding a new calculator it be might worth taking a look if your desired already +exists in our :ref:`list ` supported ones. + +In this tutorial, we will go over all the steps required to create a new +calculator. For simplicity sake, the calculator we will implement will be very +basic, keeping the focus on how different bits of the code interact with one +another instead of complex math or performance tricks. + +The calculator that we will create computes an atom-centered representation, +where each atomic environment is represented with the moments of the positions +of the neighbors up to a maximal order. Each atomic type in the neighborhood +will be considered separately. The resulting descriptor will represent an +atom-centered environment :math:`\ket{\mathcal{A}_i}` on a basis of atomic types +:math:`\alpha` and moment order :math:`k`: + +.. math:: + + \braket{\alpha k | \mathcal{A}_i} = \frac{1}{N_\text{neighbors}} \sum_{j \in \mathcal{A}_i} r_{ij}^k \ \delta_{\alpha, \alpha_j} + +.. figure:: ../../../static/images/moments-descriptor.* + :width: 40% + :align: center + +Throughout this tutorial, very basic knowledge of the Rust and Python +programming languages is assumed. If you are just starting up, you may find the +official `Rust book `_ useful; as well +as the documentation for the `standard library +`_; and the `API documentation`_ for +featomic itself. + +We will also assume that you have a local copy of the featomic git repository, +and can build the code and run the tests. If not, please look at the +:ref:`devdoc-get-started` sections. + +.. _API documentation: ../reference/rust/featomic/index.html + +The traits we'll use +-------------------- + +Two of the three :ref:`core concepts ` in featomic are +represented in the code as Rust traits: systems implements the `System`_ trait, +and calculators implement the `CalculatorBase`_ trait. Traits (also called +interfaces in other languages) define contracts that the implementing code must +follow, in the form of a set of function and documented behavior for these +functions. Fulfilling this contract allow to add new systems which work with all +calculators, already implement or not; and new calculators which can use any +system, already implemented or not. + +In this tutorial, our goal is to write a new struct implementing +`CalculatorBase`_. This implementation will take as input a slice of boxed +`System`_ trait objects, and using data from those fill up a `TensorMap`_ +(defined in the metatensor crate). + +.. _System: ../reference/rust/featomic/systems/trait.System.html +.. _CalculatorBase: ../reference/rust/featomic/calculators/trait.CalculatorBase.html +.. _Calculator: ../reference/rust/featomic/struct.Calculator.html +.. _TensorMap: ../reference/rust/metatensor/tensor/struct.TensorMap.html + +Implementation +-------------- + +Let's start by creating a new file in ``featomic/src/calculators/moments.rs``, +and importing everything we'll need. Everything in here will be explained when +we get to using it. + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/s1_scaffold.rs + :language: rust + :start-after: [imports] + :end-before: [imports] + +Then, we can define a struct for our new calculator ``GeometricMoments``. It +will contain two fields: ``cutoff`` to store the cutoff radius, and +``max_moment`` to store the maximal moment to compute. + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/s1_scaffold.rs + :language: rust + :start-after: [struct] + :end-before: [struct] + +We can then write a skeleton implementation for the `CalculatorBase`_ trait, +leaving all function unimplemented with the ``todo!()`` macro. +``CalculatorBase`` is the trait defining all the functions required for a +calculator. Users might be more familiar with the concrete struct `Calculator`_, +which uses a ``Box`` (i.e. a pointer to a +``CalculatorBase``) to provide its functionalities. + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/s1_scaffold.rs + :language: rust + :start-after: [impl] + :end-before: [impl] + +We'll go over these functions one by one, explaining what they do as we go. Most +of the functions here are used to communicate metadata about the calculator and +the representation, and the ``compute`` function does the main part of the work. + +Calculator metadata +^^^^^^^^^^^^^^^^^^^ + +The first function returning metadata about the calculator itself is ``name``, +which should return a user-facing name for the current instance of the +descriptor. As a quick refresher on Rust, all functions return the last (and in +this case only) expression. Here the expression creates a reference to a str +(``&str``) and then convert it to an heap-allocated ``String`` using the `Into`_ +trait. + +.. _Into: https://doc.rust-lang.org/std/convert/trait.Into.html + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/s2_metadata.rs + :language: rust + :start-after: [CalculatorBase::name] + :end-before: [CalculatorBase::name] + :dedent: 4 + +Then, the ``parameters`` function should return the parameters used to +create the current instance of the calculator in JSON format. To this end, we +use `serde`_ and ``serde_json`` everywhere in featomic, so it is a good idea to +do the same here. Let's start by adding the corresponding ``#[derive]`` to the +definition of ``GeometricMoments``, and use it to implement the function. + +.. _serde: https://serde.rs/ + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/s2_metadata.rs + :language: rust + :start-after: [struct] + :end-before: [struct] + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/s2_metadata.rs + :language: rust + :start-after: [CalculatorBase::parameters] + :end-before: [CalculatorBase::parameters] + :dedent: 4 + +One interesting thing here is that ``serde_json::to_string`` returns a +``Result``, and we use ``expect`` to extract the string +value. This `Result`_ would only contain an error if ``GeometricMoments`` +contained maps with non-string keys, which is not the case here. ``expect`` +allow us to indicate we don't ever expect this function to fail, but if it were +to return an error, then the code would immediately stop and show the given +message (using a `panic`_). + +Finally, the ``cutoffs`` function should return all the radial cutoffs used +in neighbors lists. Here, we only have one --- ``self.cutoffs`` --- and we use +``std::slice::from_ref`` to construct a list with a single element from a +scalar. + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/s2_metadata.rs + :language: rust + :start-after: [CalculatorBase::cutoffs] + :end-before: [CalculatorBase::cutoffs] + :dedent: 4 + +.. _Result: https://doc.rust-lang.org/std/result/index.html +.. _panic: https://doc.rust-lang.org/std/macro.panic.html + +Representation metadata +^^^^^^^^^^^^^^^^^^^^^^^ + +The next set of functions in the `CalculatorBase`_ trait is used to communicate +metadata about the representation, and called by the concrete `Calculator`_ +struct when initializing and allocating the corresponding memory. + +Keys +++++ + +First, we have one function defining the set of keys that will be in the final +``TensorMap``. In our case, we will want to have the central atom type and the +neighbor atom type as keys. This allow to only store data if a given neighbor +is actually present around a given atom. + +We could manually create a set of `Labels`_ with a `LabelsBuilder`_ and return +them. But since multiple calculators will create the same kind of keys, there +are already implementation of typical atomic types keys. Here we use +``CenterSingleNeighborsTypesKeys`` to create a set of keys containing the +central atom type and one neighbor type. This key builder requires a ``cutoff`` +(to determine which neighbors it should use) and ``self_pairs`` indicated +whether atoms should be considered to be their own neighbor or not. + +.. _Labels: ../reference/rust/metatensor/labels/struct.Labels.html +.. _LabelsBuilder: ../reference/rust/metatensor/labels/struct.LabelsBuilder.html + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/s2_metadata.rs + :language: rust + :start-after: [CalculatorBase::keys] + :end-before: [CalculatorBase::keys] + :dedent: 4 + +Samples ++++++++ + +Having defined the keys, we need to define the metadata associated with each +block. For each block, the first set of metadata — called the **samples** -- +describes the rows of the data. Three functions are used to define the samples: +first, ``features_names`` defines the name associated with the different columns +in the sample labels. Then, ``samples`` determines the set of samples associated +with each key/block. The return type of the ``samples`` function takes some +unpacking: we are returning a `Result`_ since any call to a `System`_ function +can fail. The non-error case of the result is a ``Vec``: we need +one set of `Labels`_ for each key/block. + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/s2_metadata.rs + :language: rust + :start-after: [CalculatorBase::samples] + :end-before: [CalculatorBase::samples] + :dedent: 4 + +Like for ``CalculatorBase::keys``, we could manually write code to detect the +right set of samples for each key. But since a lot of representation are built +on atom-centered neighborhoods, there is already a tool to create the right set +of samples in the form of ``AtomCenteredSamples``. + +Components +++++++++++ + +The next set of metadata associated with a block are the **components**. Each +block can have 0 or more components, that should be used to store metadata and +information about symmetry operations or any kind of tensorial components. + +Here, we dont' have any components (the ``GeometricMoments`` representation is +invariant), so we just return a list (one for each key) of empty vectors. + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/s2_metadata.rs + :language: rust + :start-after: [CalculatorBase::components] + :end-before: [CalculatorBase::components] + :dedent: 4 + + +Properties +++++++++++ + +The **properties** define metadata associated with the columns of the data +arrays. Like for the samples, we have one function to define the set of names +associated with each variable in the properties `Labels`_, and one function to +compute the set of properties defined for each key. + +In our case, there is only one variable in the properties labels, the power +:math:`k` used to compute the moment. When building the full list of Labels for +each key in ``CalculatorBase::properties``, we use the fact that the properties +are the same for each key/block and make copies of the ``Labels`` (since +``Labels`` are reference-counted, the copies are actually quite cheap). + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/s2_metadata.rs + :language: rust + :start-after: [CalculatorBase::properties] + :end-before: [CalculatorBase::properties] + :dedent: 4 + + +Gradients ++++++++++ + +Finally, we have metadata related to the gradients. First, the +``supports_gradient`` function should return which if any of the gradients can +be computed by the current calculator. Typically ``parameter`` is either +``"positions"``, ``"cell"```, or ``"strain"``. Here we only support computing +the gradients with respect to positions. + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/s2_metadata.rs + :language: rust + :start-after: [CalculatorBase::supports_gradient] + :end-before: [CalculatorBase::supports_gradient] + :dedent: 4 + +If the user request the calculation of some gradients, and the calculator +supports it, the next step is to define the same set of metadata as for the +values above: samples, components and properties. Properties are easy, because +they are the same between the values and the gradients. The components are also +similar, with some additional components added at the beginning depending on the +kind of gradient. For example, if a calculator uses ``[first, second]`` as it's +set of components, the ``"positions"`` gradient would use ``[xyz, first, +second]``, where ``xyz`` contains 3 entries. Similarly, the ``"strain"`` +gradients would use ``[xyz_1, xyz_2, first, second]`` and the ``"cell"`` +gradients would use ``[abc, xyz, first, second]``. + +Finally, the samples needs to be defined. For the ``"cell"`` or ``"strain"`` +gradients, there is always exactly one gradient sample per value sample. For the +``"positions"`` gradient samples, we could have one gradient sample for each +atom in the same system for each value sample. However, this would create a very +large number of gradient samples (number of atoms squared), and a lot of entries +would be filled with zeros. Instead, each calculator which supports positions +gradients must implement the ``positions_gradient_samples`` function, and use it +to return only the sample associated with non-zero gradients. This function get +as input the set of keys, the list of samples associated with each key, and the +list of systems on which we want to run the calculation. + +We are again using the ``AtomCenteredSamples`` here to share code between +multiple calculators all using atom-centered samples. + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/s2_metadata.rs + :language: rust + :start-after: [CalculatorBase::positions_gradient_samples] + :end-before: [CalculatorBase::positions_gradient_samples] + :dedent: 4 + + +We are now done defining the metadata associated with our ``GeometricMoments`` +calculator! In the next section, we'll go over the actual calculation of the +representation, and how to use the functions provided by `System`_. + +The compute function +^^^^^^^^^^^^^^^^^^^^ + +We are finally approaching the most important function in `CalculatorBase`_, +``compute``. This function takes as input a list of systems and a `TensorMap`_ +in which to write the results of the calculation. The function also returns a +`Result`_, to be able to indicate that an error was reached during the +calculation. + +The `TensorMap`_ is initialized by the concrete `Calculator`_ struct, according +to parameters provided by the user. In particular, the tensor map will only +contain samples and properties requested by the user, meaning that the code in +``compute`` should check for each block whether a particular sample +(respectively property) is present in ``block.samples`` (resp. +``block.property``) before computing it. + +This being said, let's start writing our ``compute`` function. We'll defensively +check that the tensor map keys match what we expect from them, and return a unit +value ``()`` wrapped in ``Ok`` at the end of the function. + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/s3_compute_1.rs + :language: rust + :start-after: [compute] + :end-before: [compute] + :dedent: 4 + +From here, the easiest way to implement our geometric moments descriptor is to +iterate over the systems, and then iterate over the pairs in the system. Before +we can get the pairs with ``system.pairs()``, we need to compute the neighbors +list for our current cutoff, using ``system.compute_neighbors()``, which +requires a mutable reference to the system to be able to store the list of +computed pairs (hence the iteration using ``systems.iter_mut()``). + +All the functions on the `System`_ trait return `Result`_, but in contrary to +the ``CalculatorBase::parameters`` function above, we want to send the possible +errors back to the user so that they can deal with them as they want. The +question mark ``?`` operator does exactly that: if the value returned by the +called function is ``Err(e)``, ``?`` immediately returns ``Err(e)``; and if the +result is ``Ok(v)``, ``?`` extract the ``v`` and the execution continues. + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/s3_compute_2.rs + :language: rust + :start-after: [compute] + :end-before: [compute] + :dedent: 4 + +For each pair, we now have to find the corresponding block (using the center and +neighbor atomic types), and check wether the corresponding sample was +requested by the user. + +To find blocks and check for samples, we can use the `Labels::position`_ +function on the keys and the samples `Labels`_. This function returns an +``Option``, which will be ``None`` is the label (key or sample) was not +found, and ``Some(position)`` where ``position`` is an unsigned integer if the +label was found. For the keys, we know the blocks must exists, so we again use +``expect`` to immediately extract the value of the block index and access the +block. For the samples, we keep them as ``Option`` and will deal with +missing samples later. + +One thing to keep in mind is that a given pair can participate to two different +samples. If two atoms ``i`` and ``j`` are closer than the cutoff, the list of +pairs will only contain the ``i-j`` pair, and not the ``j-i`` pair (it is a +so-called half neighbors list). That being said, we can get the list of atomic types +with ``system.types()`` before the loop over pairs, and then construct the two +candidate samples and check for their presence. If neither of the samples was +requested, then we can skip the calculation for this pair. We also use +``system.pairs_containing()`` to get the number of neighbors a given center has. + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/s3_compute_3.rs + :language: rust + :start-after: [compute] + :end-before: [compute] + :dedent: 4 + + +.. _Labels::position: ../reference/rust/metatensor/labels/struct.Labels.html#method.position + +Now, we can check if the samples are present, and if they are, iterate over the +requested features, compute the moments for the current pair distance, and +accumulate it in the descriptor values array: + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/s3_compute_4.rs + :language: rust + :start-after: [compute] + :end-before: [compute] + :dedent: 4 + + +Finally, we can deal with the gradients. We first check if gradient data is +defined in the descriptor we need to fill, by checking if it is defined on the +first block (we know it is either defined on all blocks or none). + +If we need to compute the gradients with respect to atomic positions, we will us +the following expression: + +.. math:: + + \frac{\partial}{\partial \vec{r_{j}}} \braket{\alpha k | \chi_i} + = \frac{\vec{r_{ij}}}{r_{ij}} \cdot \frac{k \ r_{ij}^{k - 1} \ \delta_{\alpha, \alpha_j}}{N_\text{neighbors}} + = \vec{r_{ij}} \frac{k \ r_{ij}^{k - 2} \ \delta_{\alpha, \alpha_j}}{N_\text{neighbors}} + +The code to compute gradients is very similar to the code computing the +representation, checking the existence of a given gradient sample before writing +to it. There are now four possible contributions for a given pair: +:math:`\partial \ket{\chi_i} / \partial r_j`, :math:`\partial \ket{\chi_j} / +\partial r_i`, :math:`\partial \ket{\chi_i} / \partial r_i` and :math:`\partial +\ket{\chi_j} / \partial r_j`, where :math:`\ket{\chi_i}` is the representation +around atom :math:`i`. Another way to say it is that in addition to the +gradients of the descriptor centered on :math:`i` with respect to atom +:math:`j`, we also need to account for the gradient of the descriptor centered +on atom :math:`i` with respect to its own position. + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/s3_compute_5.rs + :language: rust + :start-after: [compute] + :end-before: [compute] + :dedent: 4 + +-------------------------------------------------------------------------------- + +.. html_hidden:: + :toggle: Here is the final implementation for the compute function + :before-not-html: Here is the final implementation for the compute function + + .. literalinclude:: ../../../../featomic/src/tutorials/moments/moments.rs + :language: rust + :start-after: [compute] + :end-before: [compute] + :dedent: 4 + +Registering the new calculator +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Now that we are done with the code for this calculator, we need to make it +available to users. The entry point for users is the `Calculator`_ struct, which +needs to be constructed from a calculator name and hyper-parameters in JSON +format. + +When the user calls ``Calculator::new("calculator_name", "{\"hyper_parameters\": +1}")``, featomic looks for ``"calculator_name"`` in the global calculator +registry, and tries to create an instance using the hyper-parameters. In order +to make our calculator available to all users, we need to add it to this +registry, in ``featomic/src/calculator.rs``. The registry looks like this: + +.. literalinclude:: ../../../../featomic/src/calculator.rs + :language: rust + :start-after: [calculator-registration] + :end-before: [calculator-registration] + +``add_calculator!`` is a local macro that takes three or four arguments: the +registry itself (a ``BTreeMap``), the calculator name, the struct implementing +`CalculatorBase`_ and optionally a struct to use as parameters to create the +previous one. In our case, we want to use the three arguments version in +something like ``add_calculator!(map, "geometric_moments", GeometricMoments);``. +You'll need to make sure to bring your new calculator in scope with a `use` item. + +Additionally, you may want to add a convenience class in Python for our new +calculator. For this, you can add a class like this to +``python/featomic/calculators.py``: + +.. code-block:: python + + class GeometricMoments(CalculatorBase): + """ TODO: documentation """ + + def __init__(self, cutoff, max_moment, gradients): + parameters = { + "cutoff": cutoff, + "max_moment": max_moment, + "gradients": gradients, + } + super().__init__("geometric_moments", parameters) + + + ############################################################################# + + # this allows using the calculator like this + from featomic import GeometricMoments + calculator = GeometricMoments(cutoff=3.5, max_moment=6, gradients=False) + + # instead of + from featomic.calculators import CalculatorBase + calculator = CalculatorBase( + "geometric_moments", + {"cutoff": 3.5, "max_moment": 6, "gradients": False}, + ) + +We have now finished our implementation of the geometric moments calculator! In +the next steps, we'll see how to write tests to ensure the calculator works and +how to write some documentation for it. + +Testing the new calculator +-------------------------- + +Before we can release our new calculator in the world, we need to make sure it +currently behaves as intended, and that we have a way to ensure it continues to +behave as intended as the code changes. To achieve both goals, featomic uses +unit tests and regression tests. Unit tests are written in the same file as the +main part of the code, in a ``tests`` module, and are expected to test high +level properties of the code. For example, unit tests allow to check that the +computed gradient match the derivatives of the computed values; or that the +right values are computed when the users requests a subset of samples & +features. On the other hand, regression tests check the exact values produced by +a given calculator on a specific system; and that these values stay the same as +we modify the code, for example when trying to optimize it. These regression +tests live in the ``featomic/tests`` folder, with one file per test. + +This tutorial will focus on unit tests and introduce some utilities for tests +that should apply to all calculators. To write regression tests, you should take +inspiration from existing tests such as ``spherical-expansion`` test. Each Rust +file in ``featomic/tests`` is associated with a Python file in +``featomic/tests/data`` used to generate the values the regression test is +checking, so you'll need one of these as well. + +Testing properties +^^^^^^^^^^^^^^^^^^ + +If this is the first time you are writing tests in Rust, you should read the +`corresponding chapter +`_ in the official +Rust book for a great introduction to this subject. + +Depending on the representation you are working with, you should write tests +that check the fundamental properties of this representation. For example, for +our geometric moments representation, the first moment (with order 0) should +always be the number of neighbor of the current atomic type over the total +number of neighbors. A test checking this property would look like this: + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/moments.rs + :language: rust + :start-after: [property-test] + :end-before: [property-test] + +The ``featomic::systems::test_utils::test_systems`` function provides a couple +of very simple systems to be used for testing. + +Testing partial calculations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +One properties that all calculators must respect is that computing only a subset +of samples or feature should give the same values as computing everything. +Featomic provides a function (``calculators::tests_utils::compute_partial``) to +check this for you, simplifying the tests a bit. Here is how one can use it with +the ``GeometricMoments`` calculator: + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/moments.rs + :language: rust + :start-after: [partial-test] + :end-before: [partial-test] + + +Testing gradients +^^^^^^^^^^^^^^^^^ + +If a calculator can compute gradients, it is a good idea to check if the +gradient does match the finite differences definition of derivatives. Featomic +provides ``calculators::tests_utils::finite_difference`` to help check this. + +.. literalinclude:: ../../../../featomic/src/tutorials/moments/moments.rs + :language: rust + :start-after: [finite-differences-test] + :end-before: [finite-differences-test] + +Documenting the new calculator +------------------------------ + +.. warning:: Work in progress + + This section of the documentation is not yet written diff --git a/latest/_sources/devdoc/how-to/profiling.rst.txt b/latest/_sources/devdoc/how-to/profiling.rst.txt new file mode 100644 index 000000000..3405da7fd --- /dev/null +++ b/latest/_sources/devdoc/how-to/profiling.rst.txt @@ -0,0 +1,78 @@ +Profiling calculation +===================== + +It can be interesting to know where a calculation is spending its time. To this +end, featomic includes self-profiling code that can record and display which +part of the calculation takes time, and which function called long-running +functions. All the example should output something similar to the table below. + +.. code-block:: text + + ╔════╦══════════════════════════════╦════════════╦═══════════╦══════════╦═════════════╗ + ║ id ║ span name ║ call count ║ called by ║ total ║ mean ║ + ╠════╬══════════════════════════════╬════════════╬═══════════╬══════════╬═════════════╣ + ║ 2 ║ Full calculation ║ 1 ║ — ║ 660.58ms ║ 660.58ms ║ + ╠════╬══════════════════════════════╬════════════╬═══════════╬══════════╬═════════════╣ + ║ 3 ║ SoapPowerSpectrum::compute ║ 1 ║ 2 ║ 584.02ms ║ 584.02ms ║ + ╠════╬══════════════════════════════╬════════════╬═══════════╬══════════╬═════════════╣ + ║ 1 ║ Calculator::prepare ║ 2 ║ 3, 2 ║ 148.15ms ║ 74.08ms ║ + ╠════╬══════════════════════════════╬════════════╬═══════════╬══════════╬═════════════╣ + ║ 0 ║ NeighborsList ║ 20 ║ 1 ║ 20.82ms ║ 1.04ms ║ + ╠════╬══════════════════════════════╬════════════╬═══════════╬══════════╬═════════════╣ + ║ 5 ║ SphericalExpansion::compute ║ 1 ║ 3 ║ 196.38ms ║ 196.38ms ║ + ╠════╬══════════════════════════════╬════════════╬═══════════╬══════════╬═════════════╣ + ║ 4 ║ GtoRadialIntegral::compute ║ 74448 ║ 5 ║ 117.04ms ║ 1.57µs ║ + ╠════╬══════════════════════════════╬════════════╬═══════════╬══════════╬═════════════╣ + ║ 6 ║ SphericalHarmonics::compute ║ 74448 ║ 5 ║ 9.95ms ║ 133.00ns ⚠️ ║ + ╚════╩══════════════════════════════╩════════════╩═══════════╩══════════╩═════════════╝ + +In this table, the first columns assign a unique numeric identifier to each +section of the code. The second one displays the name of the section. Then come +the number of time this section of the code have been executed, which other +function/section called the current one, and finally the total and mean time +spent in this function. + +The ⚠️ symbol is added when the mean cost of the function is close to the +profiling overhead (30 to 80ns per function call), and thus the measurement +might not be very reliable. + +Some of the most important sections are: + +- ``Calculator::prepare``: building the list of samples/properties that will be in the descriptor +- ``XXX::compute``: building blocks for the overall calculation +- ``NeighborsList``: construction of the list of neighbors + +You can obtain a dataset for profiling from our :download:`website <../../../static/dataset.xyz>`. + +.. tabs:: + + .. group-tab:: Python + + .. container:: sphx-glr-footer sphx-glr-footer-example + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code for this example: profiling.py <../../examples/profiling.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook for this example: profiling.ipynb <../../examples/profiling.ipynb>` + + .. include:: ../../examples/profiling.rst + :start-after: start-body + :end-before: end-body + + .. group-tab:: Rust + + .. literalinclude:: ../../../../featomic/examples/profiling.rs + :language: rust + + .. group-tab:: C++ + + .. literalinclude:: ../../../../featomic/examples/profiling.cpp + :language: c++ + + .. group-tab:: C + + .. literalinclude:: ../../../../featomic/examples/profiling.c + :language: c diff --git a/latest/_sources/devdoc/index.rst.txt b/latest/_sources/devdoc/index.rst.txt new file mode 100644 index 000000000..a2d5adabd --- /dev/null +++ b/latest/_sources/devdoc/index.rst.txt @@ -0,0 +1,22 @@ +.. _devdoc: + +Developer documentation +####################### + +This developer documentation is divided into three parts: + +1. :ref:`devdoc-get-started` explains how you can start developing code and + documentation; +2. The :ref:`devdoc-how-to`, take you through a series of steps on key problems + for developing featomic; +3. In the :ref:`devdoc-explanations` section discusses key topics and concepts + at a fairly high level and provides useful explanations to expand your + knowledge about the architecture of featomic; + +.. toctree:: + :maxdepth: 2 + :hidden: + + get-started + how-to/index + explanations/index diff --git a/latest/_sources/examples/compute-soap.rst.txt b/latest/_sources/examples/compute-soap.rst.txt new file mode 100644 index 000000000..b6091ba18 --- /dev/null +++ b/latest/_sources/examples/compute-soap.rst.txt @@ -0,0 +1,206 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples/compute-soap.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + :ref:`Go to the end ` + to download the full example code. + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_compute-soap.py: + + +Computing SOAP features +======================= + +.. start-body + +.. GENERATED FROM PYTHON SOURCE LINES 7-13 + +.. code-block:: Python + + + import chemfiles + + from featomic import SoapPowerSpectrum + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 14-16 + +Read systems using chemfiles. You can obtain the dataset used in this +example from our :download:`website <../../static/dataset.xyz>`. + +.. GENERATED FROM PYTHON SOURCE LINES 17-21 + +.. code-block:: Python + + + with chemfiles.Trajectory("dataset.xyz") as trajectory: + systems = [s for s in trajectory] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 22-28 + +Featomic can also handles systems read by `ASE +`_ using + +``systems = ase.io.read("dataset.xyz", ":")``. + +We can now define hyper parameters for the calculation + +.. GENERATED FROM PYTHON SOURCE LINES 29-48 + +.. code-block:: Python + + + HYPER_PARAMETERS = { + "cutoff": { + "radius": 5.0, + "smoothing": {"type": "ShiftedCosine", "width": 0.5}, + }, + "density": { + "type": "Gaussian", + "width": 0.3, + }, + "basis": { + "type": "TensorProduct", + "max_angular": 4, + "radial": {"type": "Gto", "max_radial": 6}, + }, + } + + calculator = SoapPowerSpectrum(**HYPER_PARAMETERS) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 49-50 + +And then run the actual calculation, including gradients with respect to positions + +.. GENERATED FROM PYTHON SOURCE LINES 51-54 + +.. code-block:: Python + + + descriptor = calculator.compute(systems, gradients=["positions"]) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 55-59 + +The descriptor is a metatensor ``TensorMap``, containing multiple blocks. We +can transform it to a single block containing a dense representation, with one +sample for each atom-centered environment by using ``keys_to_samples`` and +``keys_to_properties`` + +.. GENERATED FROM PYTHON SOURCE LINES 60-67 + +.. code-block:: Python + + + print("before: ", len(descriptor.keys)) + + descriptor = descriptor.keys_to_samples("center_type") + descriptor = descriptor.keys_to_properties(["neighbor_1_type", "neighbor_2_type"]) + print("after: ", len(descriptor.keys)) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + before: 40 + after: 1 + + + + +.. GENERATED FROM PYTHON SOURCE LINES 68-70 + +you can now use ``descriptor.block().values`` as the input of a machine +learning algorithm + +.. GENERATED FROM PYTHON SOURCE LINES 71-75 + +.. code-block:: Python + + + print(descriptor.block().values.shape) + + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + (1380, 2450) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 76-77 + +.. end-body + + +.. _sphx_glr_download_examples_compute-soap.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: compute-soap.ipynb ` + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: compute-soap.py ` + + .. container:: sphx-glr-download sphx-glr-download-zip + + :download:`Download zipped: compute-soap.zip ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/latest/_sources/examples/first-calculation.rst.txt b/latest/_sources/examples/first-calculation.rst.txt new file mode 100644 index 000000000..df0c33ae4 --- /dev/null +++ b/latest/_sources/examples/first-calculation.rst.txt @@ -0,0 +1,864 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples/first-calculation.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + :ref:`Go to the end ` + to download the full example code. + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_first-calculation.py: + + +.. _userdoc-tutorials-get-started: + +First descriptor computation +============================ + +This is an introduction to the featomic interface using a molecular crystals +dataset using the Python interface. If you are interested in another +programming language we recommend you first follow this tutorial and afterward +take a look at the how-to guide on :ref:`userdoc-how-to-computing-soap`. + +The dataset +----------- + +The atomic configurations used in our documentation are a small subset of the +`ShiftML2 dataset `_ +containing molecular crystals. There are four crystals - one with each of the +elements [hydrogen, carbon], [hydrogen, carbon, nitrogen, oxygen], [hydrogen, +carbon, nitrogen], or [hydrogen, carbon, oxygen]. Each crystal has 10 structures, +also denoted by frames, attributed to it. The first frame of each crystal structure +is the geometry-optimized frame. The following 9 frames contain atoms that are +slightly displaced from the geometry-optimized frame. You can obtain the dataset +from our :download:`website <../../static/dataset.xyz>`. + +.. GENERATED FROM PYTHON SOURCE LINES 27-30 + +We will start by importing all the required packages: the classic numpy; +chemfiles to load data, and featomic to compute representations. Afterward +we will load the dataset using chemfiles. + +.. GENERATED FROM PYTHON SOURCE LINES 31-43 + +.. code-block:: Python + + + import chemfiles + import numpy as np + + from featomic import SphericalExpansion + + + with chemfiles.Trajectory("dataset.xyz") as trajectory: + frames = [f for f in trajectory] + + print(f"The dataset contains {len(frames)} frames.") + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + The dataset contains 40 frames. + + + + +.. GENERATED FROM PYTHON SOURCE LINES 44-50 + +We will not explain here how to use chemfiles in detail, as we only use a few +functions. Briefly, :class:`chemfiles.Trajectory` loads structure data in a +format featomic can use. If you want to learn more about the possibilities +take a look at the `chemfiles documentation `_. + +Let us now take a look at the first frame of the dataset. + +.. GENERATED FROM PYTHON SOURCE LINES 51-56 + +.. code-block:: Python + + + frame0 = frames[0] + + print(frame0) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Frame with 20 atoms + + + + +.. GENERATED FROM PYTHON SOURCE LINES 57-59 + +With ``frame0.atoms`` we get a list of the atoms that make up frame zero. +The ``name`` attribute gives us the name of the specified atom. + +.. GENERATED FROM PYTHON SOURCE LINES 60-71 + +.. code-block:: Python + + + elements, counts = np.unique([atom.name for atom in frame0.atoms], return_counts=True) + + print( + f"The first frame contains " + f"{counts[0]} {elements[0]}-atoms, " + f"{counts[1]} {elements[1]}-atoms, " + f"{counts[2]} {elements[2]}-atoms and " + f"{counts[3]} {elements[3]}-atoms." + ) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + The first frame contains 4 C-atoms, 8 H-atoms, 4 N-atoms and 4 O-atoms. + + + + +.. GENERATED FROM PYTHON SOURCE LINES 72-86 + +Calculate a descriptor +---------------------- + +We will now calculate an atomic descriptor for this structure using the SOAP +spherical expansion as introduced by `Bartók, Kondor, and Csányi +`_. + +To do so we define below a set of parameters telling featomic how the +spherical expansion should be calculated. These parameters are also called +hyper parameters since they are parameters of the representation, in +opposition to parameters of machine learning models. Hyper parameters are a +crucial part of calculating descriptors. Poorly selected hyper parameters will +lead to a poor description of your dataset as discussed in the `literature +`_. + +.. GENERATED FROM PYTHON SOURCE LINES 87-110 + +.. code-block:: Python + + + cutoff = { + "radius": 4.5, + "smoothing": {"type": "ShiftedCosine", "width": 0.5}, + } + + density = { + "type": "Gaussian", + "width": 0.3, + "radial_scaling": { + "type": "Willatt2018", + "scale": 2.0, + "rate": 1.0, + "exponent": 4, + }, + } + + basis = { + "type": "TensorProduct", + "max_angular": 5, + "radial": {"type": "Gto", "max_radial": 8}, + } + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 111-115 + +After we set the hyper parameters we initialize a +:class:`featomic.calculators.SphericalExpansion` object with hyper parameters +defined above and run the +:py:func:`featomic.calculators.CalculatorBase.compute()` method. + +.. GENERATED FROM PYTHON SOURCE LINES 116-121 + +.. code-block:: Python + + + calculator = SphericalExpansion(cutoff=cutoff, density=density, basis=basis) + descriptor0 = calculator.compute(frame0) + print(type(descriptor0)) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 122-129 + +The descriptor format is a :class:`metatensor.TensorMap` object. Metatensor is +like numpy for storing representations of atomistic ML data. Extensive details +on the metatensor are covered in the `corresponding documentation +`_. + +We will now have a look at how the data is stored inside +:class:`metatensor.TensorMap` objects. + +.. GENERATED FROM PYTHON SOURCE LINES 130-134 + +.. code-block:: Python + + + + print(descriptor0) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + TensorMap with 96 blocks + keys: o3_lambda o3_sigma center_type neighbor_type + 0 1 1 1 + 1 1 1 1 + 2 1 1 1 + 3 1 1 1 + 4 1 1 1 + 5 1 1 1 + 0 1 1 6 + 1 1 1 6 + 2 1 1 6 + 3 1 1 6 + 4 1 1 6 + 5 1 1 6 + 0 1 1 7 + 1 1 1 7 + 2 1 1 7 + 3 1 1 7 + 4 1 1 7 + 5 1 1 7 + 0 1 1 8 + 1 1 1 8 + 2 1 1 8 + 3 1 1 8 + 4 1 1 8 + 5 1 1 8 + 0 1 6 1 + 1 1 6 1 + 2 1 6 1 + 3 1 6 1 + 4 1 6 1 + 5 1 6 1 + 0 1 6 6 + 1 1 6 6 + 2 1 6 6 + 3 1 6 6 + 4 1 6 6 + 5 1 6 6 + 0 1 6 7 + 1 1 6 7 + 2 1 6 7 + 3 1 6 7 + 4 1 6 7 + 5 1 6 7 + 0 1 6 8 + 1 1 6 8 + 2 1 6 8 + 3 1 6 8 + 4 1 6 8 + 5 1 6 8 + 0 1 7 1 + 1 1 7 1 + 2 1 7 1 + 3 1 7 1 + 4 1 7 1 + 5 1 7 1 + 0 1 7 6 + 1 1 7 6 + 2 1 7 6 + 3 1 7 6 + 4 1 7 6 + 5 1 7 6 + 0 1 7 7 + 1 1 7 7 + 2 1 7 7 + 3 1 7 7 + 4 1 7 7 + 5 1 7 7 + 0 1 7 8 + 1 1 7 8 + 2 1 7 8 + 3 1 7 8 + 4 1 7 8 + 5 1 7 8 + 0 1 8 1 + 1 1 8 1 + 2 1 8 1 + 3 1 8 1 + 4 1 8 1 + 5 1 8 1 + 0 1 8 6 + 1 1 8 6 + 2 1 8 6 + 3 1 8 6 + 4 1 8 6 + 5 1 8 6 + 0 1 8 7 + 1 1 8 7 + 2 1 8 7 + 3 1 8 7 + 4 1 8 7 + 5 1 8 7 + 0 1 8 8 + 1 1 8 8 + 2 1 8 8 + 3 1 8 8 + 4 1 8 8 + 5 1 8 8 + + + + +.. GENERATED FROM PYTHON SOURCE LINES 135-146 + +The :class:`metatensor.TensorMap` is structured in several instances of an +:class:`metatensor.TensorBlock`. To distinguish the block each block is associated +with a unique key. For the current example, we have one block for each angular channel +labeled by ``o3_lambda``, the central atom type ``center_type`` and +neighbor atom type labeled by ``neighbor_type``. Different atomic types are +represented using their atomic number, e.g. 1 for hydrogen, 6 for carbon, etc. To +summarize, this descriptor contains 112 blocks covering all combinations of the +angular channels of the central and neighbor atom types in our dataset. + +Let us take a look at the second block (at index 1) in detail. This block contains the +descriptor for the :math:`l=1` angular channel for hydrogen-hydrogen pairs. + +.. GENERATED FROM PYTHON SOURCE LINES 147-152 + +.. code-block:: Python + + + block = descriptor0.block(1) + print(descriptor0.keys[1]) + + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + LabelsEntry(o3_lambda=1, o3_sigma=1, center_type=1, neighbor_type=1) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 153-160 + +The descriptor values +--------------------- + +The values of the representation are stored as an array. Each entry in this +array also has associated unique metadata as each block. For the spherical +expansion calculator used in this tutorial the values have three dimensions +which we can verify from the ``.shape`` attribute. + +.. GENERATED FROM PYTHON SOURCE LINES 161-165 + +.. code-block:: Python + + + + print(block.values.shape) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + (8, 3, 9) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 166-175 + +The descriptor values +--------------------- + +The first dimension is denoted by the `samples`, the intermediate dimension by +`components`, and the last dimension by `properties`. The "sample dimension" +has a length of eight because we have eight hydrogen atoms in the first frame. +We can reveal more detailed metadata information about the sample-dimension +printing of the :py:attr:`metatensor.TensorBlock.samples` attribute of the +block + +.. GENERATED FROM PYTHON SOURCE LINES 176-179 + +.. code-block:: Python + + + print(block.samples) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Labels( + system atom + 0 12 + 0 13 + ... + 0 18 + 0 19 + ) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 180-182 + +The result is an :class:`metatensor.TensorMap` instance. It contains in total +eight tuples each with two values. The tuple values are named as follows + +.. GENERATED FROM PYTHON SOURCE LINES 183-186 + +.. code-block:: Python + + + print(block.samples.names) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + ['system', 'atom'] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 187-193 + +Meaning that the first entry of each tuple indicates the _structure_, which is +0 for all because we only computed the representation of a single frame. The +second entry of each tuple refers to the index of the _center_ atom. + +We can do a similar investigation for the second dimension: the +:py:attr:`metatensor.TensorBlock.components`. + +.. GENERATED FROM PYTHON SOURCE LINES 194-197 + +.. code-block:: Python + + + print(block.components) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [Labels( + o3_mu + -1 + 0 + 1 + )] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 198-209 + +Here, the components are associated with the angular channels of the +representation. The size of ``o3_mu`` is :math:`2l + 1`, where +:math:`l` is the current ``o3_lambda`` of the block. Here, its +dimension is three because we are looking at the ``o3_lambda=1`` +block. You may have noticed that the return value of the last call is a +:class:`list` of :class:`metatensor.Labels` and not a single ``Labels`` +instance. The reason is that a block can have several component dimensions as +we will see below for the gradients. + +The last value represents the number of radial channels. For the +:py:attr:`metatensor.TensorBlock.properties` dimension we find an object + +.. GENERATED FROM PYTHON SOURCE LINES 210-213 + +.. code-block:: Python + + + print(block.properties) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Labels( + n + 0 + 1 + ... + 7 + 8 + ) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 214-215 + +containing a tuple of only one value ranging from 0 to 8. The name of this entry is + +.. GENERATED FROM PYTHON SOURCE LINES 216-219 + +.. code-block:: Python + + + print(block.properties.names) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + ['n'] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 220-225 + +and denoting the radial channels. The range results from our choice of +``max_radial = 9`` in the hyper parameters above. + +After looking at the metadata we can investigate the actual data of the +representation in more details + +.. GENERATED FROM PYTHON SOURCE LINES 226-229 + +.. code-block:: Python + + + print(block.values[0, 0, :]) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [-0.00237693 0.01533393 -0.03954346 -0.20278318 -0.05190685 -0.14738365 + -0.17762571 -0.05567855 -0.01701108] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 230-237 + +By using ``[0, 0, :]`` we selected the first hydrogen and the first ``m`` +channel. As you the output shows the values are floating point numbers between +``-1.0`` and ``1.0``. Values in this range are reasonable and can be directly +used as input for a machine learning algorithm. + +Featomic is also able to process more than one structure within one function +call. You can process a whole dataset with + +.. GENERATED FROM PYTHON SOURCE LINES 238-244 + +.. code-block:: Python + + + descriptor_full = calculator.compute(frames) + + block_full = descriptor_full.block(0) + print(block_full.values.shape) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + (420, 1, 9) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 245-262 + +Now, the 0th block of the :class:`metatensor.TensorMap` contains not eight but +420 entries in the first dimensions. This reflects the fact that in total we +have 420 hydrogen atoms in the whole dataset. + +If you want to use another calculator instead of +:class:`featomic.calculators.SphericalExpansion` shown here check out the +:ref:`userdoc-references` section. + +Computing gradients +------------------- + +Additionally, featomic is also able to calculate gradients on top of the +values. Gradients are useful for constructing an ML potential and running +simulations. For example ``gradients`` of the representation with respect to +atomic positions can be calculated by setting the ``gradients`` parameter of +the :py:func:`featomic.calculators.CalculatorBase.compute()` method to +``["positions"]``. + +.. GENERATED FROM PYTHON SOURCE LINES 263-271 + +.. code-block:: Python + + + descriptor_gradients = calculator.compute(frame0, gradients=["positions"]) + + block_gradients = descriptor_gradients.block(0) + gradient_position = block_gradients.gradient("positions") + + print(gradient_position.values.shape) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + (52, 3, 1, 9) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 272-288 + +The calculated descriptor contains the values and in each block the associated +position gradients as an :class:`metatensor.block.Gradient` instance. The +actual values are stored in the ``data`` attribute. Similar to the features +the gradient data also has associated metadata. But, compared to the values +were we found three dimensions, and gradients have four. Again the first is +called `samples` and the `properties`. The dimensions between the sample and +property dimensions are denoted by `components`. + +Looking at the shape in more detail we find that we have 52 samples, which is +much more compared to features where we only have eight samples. This arises +from the fact that we calculate the position gradient for each pair in the +structure. For our selected block these are all hydrogen-hydrogen pairs. +Naively one would come up with ``8 * 8 = 64`` samples, but featomic already +ignores pairs that are outside of the cutoff radius. Their position gradient +is always zero. The :attr:`metatensor.block.Gradient.samples` attribute shows +this in detail. + +.. GENERATED FROM PYTHON SOURCE LINES 289-292 + +.. code-block:: Python + + + print(gradient_position.samples) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Labels( + sample system atom + 0 0 12 + 0 0 13 + ... + 7 0 18 + 7 0 19 + ) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 293-294 + +Note that we have a tuple of three with the names + +.. GENERATED FROM PYTHON SOURCE LINES 295-298 + +.. code-block:: Python + + + print(gradient_position.samples.names) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + ['sample', 'system', 'atom'] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 299-303 + +In the above output of the Labels instance for example the `(2, 0, 17)` entry +is missing indicating that this pair is outside of the cutoff. + +Now looking at the :attr:`metatensor.block.Gradient.components` + +.. GENERATED FROM PYTHON SOURCE LINES 304-307 + +.. code-block:: Python + + + print(gradient_position.components) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [Labels( + xyz + 0 + 1 + 2 + ), Labels( + o3_mu + 0 + )] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 308-314 + +we find two of them. Besides the `o3_mu` component that is also present in the +features position gradients also have a component indicating the direction of the +gradient vector. + +Finally, the :attr:`metatensor.block.Gradient.properties` dimension is the same as for +the values + +.. GENERATED FROM PYTHON SOURCE LINES 315-318 + +.. code-block:: Python + + + print(gradient_position.properties) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Labels( + n + 0 + 1 + ... + 7 + 8 + ) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 319-327 + +Featomic can also calculate gradients with respect to the strain (i.e. the virial). +For this, you have to add ``"strain"`` to the list parsed to the ``gradients`` +parameter of the :py:func:`featomic.calculators.CalculatorBase.compute()` method. +Strain gradients/virial are useful when computing the stress and the pressure. + +If you want to know about the effect of changing hypers take a look at the next +tutorial. If you want to solve an explicit problem our :ref:`userdoc-how-to` might +help you. + + +.. _sphx_glr_download_examples_first-calculation.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: first-calculation.ipynb ` + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: first-calculation.py ` + + .. container:: sphx-glr-download sphx-glr-download-zip + + :download:`Download zipped: first-calculation.zip ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/latest/_sources/examples/index.rst.txt b/latest/_sources/examples/index.rst.txt new file mode 100644 index 000000000..4c3bc306c --- /dev/null +++ b/latest/_sources/examples/index.rst.txt @@ -0,0 +1,190 @@ +:orphan: + +Featomic Python Examples +========================= + +This folder consists of introductory examples and examples demonstrating +specific features of featomic using its Python API. + + + +.. raw:: html + +
+ +.. thumbnail-parent-div-open + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/images/thumb/sphx_glr_compute-soap_thumb.png + :alt: + + :ref:`sphx_glr_examples_compute-soap.py` + +.. raw:: html + +
Computing SOAP features
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/images/thumb/sphx_glr_profiling_thumb.png + :alt: + + :ref:`sphx_glr_examples_profiling.py` + +.. raw:: html + +
Profiling calculation
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/images/thumb/sphx_glr_first-calculation_thumb.png + :alt: + + :ref:`sphx_glr_examples_first-calculation.py` + +.. raw:: html + +
First descriptor computation
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/images/thumb/sphx_glr_keys-selection_thumb.png + :alt: + + :ref:`sphx_glr_examples_keys-selection.py` + +.. raw:: html + +
Keys Selection
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/images/thumb/sphx_glr_sample-selection_thumb.png + :alt: + + :ref:`sphx_glr_examples_sample-selection.py` + +.. raw:: html + +
Sample Selection
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/images/thumb/sphx_glr_property-selection_thumb.png + :alt: + + :ref:`sphx_glr_examples_property-selection.py` + +.. raw:: html + +
Property Selection
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/images/thumb/sphx_glr_splined-radial-integral_thumb.png + :alt: + + :ref:`sphx_glr_examples_splined-radial-integral.py` + +.. raw:: html + +
Splined radial integrals
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/images/thumb/sphx_glr_long-range-descriptor_thumb.png + :alt: + + :ref:`sphx_glr_examples_long-range-descriptor.py` + +.. raw:: html + +
Long-range only LODE descriptor
+
+ + +.. thumbnail-parent-div-close + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /examples/compute-soap + /examples/profiling + /examples/first-calculation + /examples/keys-selection + /examples/sample-selection + /examples/property-selection + /examples/splined-radial-integral + /examples/long-range-descriptor + + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-gallery + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download all examples in Python source code: examples_python.zip ` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download all examples in Jupyter notebooks: examples_jupyter.zip ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/latest/_sources/examples/keys-selection.rst.txt b/latest/_sources/examples/keys-selection.rst.txt new file mode 100644 index 000000000..3809bd587 --- /dev/null +++ b/latest/_sources/examples/keys-selection.rst.txt @@ -0,0 +1,352 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples/keys-selection.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + :ref:`Go to the end ` + to download the full example code. + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_keys-selection.py: + + +Keys Selection +============== + +.. start-body + +.. GENERATED FROM PYTHON SOURCE LINES 7-15 + +.. code-block:: Python + + + import chemfiles + import numpy as np + from metatensor import Labels, TensorBlock, TensorMap + + from featomic import SoapPowerSpectrum + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 16-17 + +First we load the dataset with chemfiles + +.. GENERATED FROM PYTHON SOURCE LINES 18-22 + +.. code-block:: Python + + + with chemfiles.Trajectory("dataset.xyz") as trajectory: + frames = [f for f in trajectory] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 23-24 + +and define the hyper parameters of the representation + +.. GENERATED FROM PYTHON SOURCE LINES 25-44 + +.. code-block:: Python + + + HYPER_PARAMETERS = { + "cutoff": { + "radius": 5.0, + "smoothing": {"type": "ShiftedCosine", "width": 0.5}, + }, + "density": { + "type": "Gaussian", + "width": 0.3, + }, + "basis": { + "type": "TensorProduct", + "max_angular": 4, + "radial": {"type": "Gto", "max_radial": 6}, + }, + } + + calculator = SoapPowerSpectrum(**HYPER_PARAMETERS) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 45-47 + +The selections for keys should be a set of ``Labels``, with the names of the +keys being a subset of the names of the keys produced by the calculator. + +.. GENERATED FROM PYTHON SOURCE LINES 48-52 + +.. code-block:: Python + + + descriptor = calculator.compute(frames) + print("keys names:", descriptor.keys.names) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + keys names: ['center_type', 'neighbor_1_type', 'neighbor_2_type'] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 53-56 + +We can use these names to define a selection, and only blocks matching the +labels in this selection will be used by featomic. Here, only blocks with +keys ``[1,1,1]`` and ``[4,4,4]`` will be calculated. + +.. GENERATED FROM PYTHON SOURCE LINES 57-64 + +.. code-block:: Python + + + selection = Labels( + names=["center_type", "neighbor_1_type", "neighbor_2_type"], + values=np.array([[1, 1, 1], [4, 4, 4]], dtype=np.int32), + ) + selected_descriptor = calculator.compute(frames, selected_keys=selection) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 65-66 + +We get a TensorMap with 2 blocks, corresponding to the requested keys + +.. GENERATED FROM PYTHON SOURCE LINES 67-70 + +.. code-block:: Python + + + print(selected_descriptor.keys) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Labels( + center_type neighbor_1_type neighbor_2_type + 1 1 1 + 4 4 4 + ) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 71-73 + +The block for ``[1, 1, 1]`` will be exactly the same as the one in the full +``TensorMap`` + +.. GENERATED FROM PYTHON SOURCE LINES 74-77 + +.. code-block:: Python + + answer = np.array_equal(descriptor.block(0).values, selected_descriptor.block(0).values) + print(f"Are the blocks 0 in the descriptor and selected_descriptor equal? {answer}") + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Are the blocks 0 in the descriptor and selected_descriptor equal? True + + + + +.. GENERATED FROM PYTHON SOURCE LINES 78-80 + +Since there is no block for ``[4, 4, 4]`` in the full ``TensorMap``, an empty +block with no samples and the default set of properties is generated + +.. GENERATED FROM PYTHON SOURCE LINES 81-84 + +.. code-block:: Python + + + print(selected_descriptor.block(1).values.shape) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + (0, 245) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 85-88 + +``selected_keys`` can be used simultaneously with samples and properties +selection. Here we define a selection for properties as a ``TensorMap`` to +select different properties for each block: + +.. GENERATED FROM PYTHON SOURCE LINES 89-112 + +.. code-block:: Python + + + selection = [ + Labels(names=["l", "n_1", "n_2"], values=np.array([[0, 0, 0]])), + Labels(names=["l", "n_1", "n_2"], values=np.array([[1, 1, 1]])), + ] + blocks = [] + for entries in selection: + blocks.append( + TensorBlock( + values=np.empty((len(entries), 1)), + samples=Labels.single(), + components=[], + properties=entries, + ) + ) + + keys = Labels( + names=["center_type", "neighbor_1_type", "neighbor_2_type"], + values=np.array([[1, 1, 1], [8, 8, 8]], dtype=np.int32), + ) + + selected_properties = TensorMap(keys, blocks) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 113-115 + +Only one of the key from our ``selected_properties`` will be used in the +``selected_keys``, meaning the output will only contain this one key/block. + +.. GENERATED FROM PYTHON SOURCE LINES 116-128 + +.. code-block:: Python + + + selected_keys = Labels( + names=["center_type", "neighbor_1_type", "neighbor_2_type"], + values=np.array([[1, 1, 1]], dtype=np.int32), + ) + + descriptor = calculator.compute( + frames, + selected_properties=selected_properties, + selected_keys=selected_keys, + ) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 129-131 + +As expected, we get 1 block with values of the form (420, 1), i.e. with only 1 +property. + +.. GENERATED FROM PYTHON SOURCE LINES 132-136 + +.. code-block:: Python + + + print(f"list of keys: {descriptor.keys}") + print(descriptor.block(0).values.shape) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + list of keys: Labels( + center_type neighbor_1_type neighbor_2_type + 1 1 1 + ) + (420, 1) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 137-138 + +.. end-body + + +.. _sphx_glr_download_examples_keys-selection.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: keys-selection.ipynb ` + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: keys-selection.py ` + + .. container:: sphx-glr-download sphx-glr-download-zip + + :download:`Download zipped: keys-selection.zip ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/latest/_sources/examples/long-range-descriptor.rst.txt b/latest/_sources/examples/long-range-descriptor.rst.txt new file mode 100644 index 000000000..ac4d6c493 --- /dev/null +++ b/latest/_sources/examples/long-range-descriptor.rst.txt @@ -0,0 +1,768 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples/long-range-descriptor.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + :ref:`Go to the end ` + to download the full example code. + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_long-range-descriptor.py: + + +.. _userdoc-tutorials-long-range-descriptor: + +Long-range only LODE descriptor +=============================== + +.. start-body + +We start the example by loading the required packages + +.. GENERATED FROM PYTHON SOURCE LINES 13-25 + +.. code-block:: Python + + + import ase + import ase.visualize.plot + import matplotlib.pyplot as plt + import numpy as np + from ase.build import molecule + from metatensor import LabelsEntry, TensorMap + + import featomic + from featomic import LodeSphericalExpansion, SphericalExpansion + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 26-30 + +**Single water molecule (short range) system** + +Our first test system is a single water molecule with a :math:`15\,\mathrm{Å}` +vacuum layer around it. + +.. GENERATED FROM PYTHON SOURCE LINES 31-35 + +.. code-block:: Python + + + + atoms = molecule("H2O", vacuum=15, pbc=True) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 36-38 + +We choose a ``cutoff`` for the projection of the spherical expansion and the +neighbor search of the real space spherical expansion. + +.. GENERATED FROM PYTHON SOURCE LINES 38-41 + +.. code-block:: Python + + + cutoff = 3 + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 42-44 + +We can use ase's visualization tools to plot the system and draw a gray circle to +indicate the ``cutoff`` radius. + +.. GENERATED FROM PYTHON SOURCE LINES 44-64 + +.. code-block:: Python + + + fig, ax = plt.subplots() + + ase.visualize.plot.plot_atoms(atoms) + + cutoff_circle = plt.Circle( + xy=atoms[0].position[:2], + radius=cutoff, + color="gray", + ls="dashed", + fill=False, + ) + ax.add_patch(cutoff_circle) + + ax.set_xlabel("Å") + ax.set_ylabel("Å") + + fig.show() + + + + + +.. image-sg:: /examples/images/sphx_glr_long-range-descriptor_001.png + :alt: long range descriptor + :srcset: /examples/images/sphx_glr_long-range-descriptor_001.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 65-71 + +As you can see, for a single water molecule, the ``cutoff`` includes all atoms of +the system. The combination of the test system and the ``cutoff`` aims to +demonstrate that the full atomic fingerprint is contained within the ``cutoff``. +By later subtracting the short-range density from the LODE density, we will observe +that the difference between them is almost zero, indicating that a single water +molecule is a short-range system. + +.. GENERATED FROM PYTHON SOURCE LINES 75-78 + +For the density, we choose a smeared power law as used in LODE, which does not decay +exponentially like a :py:class:`Gaussian ` density and is +therefore suited to describe long-range interactions between atoms. + +.. GENERATED FROM PYTHON SOURCE LINES 79-84 + +.. code-block:: Python + + + + density = featomic.density.SmearedPowerLaw(smearing=1.2, exponent=3) + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 85-87 + +To visualize this we plot ``density`` together with a Gaussian density +(``gaussian_density``) with the same ``width`` in a log-log plot. + +.. GENERATED FROM PYTHON SOURCE LINES 88-123 + +.. code-block:: Python + + + radial_positions = np.geomspace(1e-5, 10, num=1000) + gaussian_density = featomic.density.Gaussian(width=density.smearing) + + plt.plot( + radial_positions, + density.compute(radial_positions, derivative=False), + label="SmearedPowerLaw", + ) + plt.plot( + radial_positions, + gaussian_density.compute(radial_positions, derivative=False), + label="Gaussian", + ) + + + positions_indicator = np.array([3.0, 8.0]) + plt.plot( + positions_indicator, + 2 * positions_indicator ** (-density.exponent), + c="k", + label=f"exponent={density.exponent}", + ) + + plt.legend() + + plt.xlim(1e-1, 10) + plt.ylim(1e-3, 5e-1) + + plt.xlabel("radial positions / Å") + plt.ylabel("atomic density") + + plt.xscale("log") + plt.yscale("log") + + + + +.. image-sg:: /examples/images/sphx_glr_long-range-descriptor_002.png + :alt: long range descriptor + :srcset: /examples/images/sphx_glr_long-range-descriptor_002.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 124-128 + +We see that the ``SmearedPowerLaw`` decays with a power law of 3, which is the +potential exponent we picked above, wile the :py:class:`Gaussian +` density decays exponentially and is therefore not suited +for long-range descriptors. + +.. GENERATED FROM PYTHON SOURCE LINES 131-136 + +As a projection basis, we don't use the usual :py:class:`Gto ` +which is commonly used for short range descriptors. Instead, we select the +:py:class:`Monomials ` which is the optimal radial basis +for the LODE descriptor as discussed in `Huguenin-Dumittan et al. +`_ + +.. GENERATED FROM PYTHON SOURCE LINES 137-154 + +.. code-block:: Python + + + by_angular = {} + for angular in range(2): + by_angular[angular] = featomic.basis.Monomials( + radius=cutoff, angular_channel=angular, max_radial=4 + ) + + + basis = featomic.basis.Explicit( + by_angular=by_angular, + # We choose a relatively low spline accuracy (default is ``1e-8``) to achieve quick + # computation of the spline points. You can increase the spline accuracy if + # required, but be aware that the time to compute these points will increase + # significantly! + spline_accuracy=1e-2, + ) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 155-157 + +We now have all building blocks to construct the spline for the real and +Fourier space spherical expansions. + +.. GENERATED FROM PYTHON SOURCE LINES 158-175 + +.. code-block:: Python + + + + real_space_spliner = featomic.splines.SoapSpliner( + # We don't use a ``smoothing`` function in the cutoff or a ``radial_scaling`` in the + # density to ensure the correct construction of the long-range only descriptor + cutoff=featomic.cutoff.Cutoff(radius=cutoff, smoothing=None), + basis=basis, + density=density, + ) + real_space_hypers = real_space_spliner.get_hypers() + + fourier_space_spliner = featomic.splines.LodeSpliner( + basis=basis, + density=density, + ) + fourier_space_hypers = fourier_space_spliner.get_hypers() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 176-177 + +With the splines ready, we now compute the two spherical expansions + +.. GENERATED FROM PYTHON SOURCE LINES 178-187 + +.. code-block:: Python + + + + real_space_calculator = SphericalExpansion(**real_space_hypers) + real_space_expansion = real_space_calculator.compute(atoms) + + + fourier_space_calculator = LodeSphericalExpansion(**fourier_space_hypers) + fourier_space_expansion = fourier_space_calculator.compute(atoms) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 188-191 + +As described in the beginning, we now subtract the real space LODE contributions +from Fourier space to obtain a descriptor that only contains the contributions from +atoms outside of the ``cutoff``. + +.. GENERATED FROM PYTHON SOURCE LINES 191-196 + +.. code-block:: Python + + + + delta_expansion = fourier_space_expansion - real_space_expansion + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 197-206 + +You can now use the ``delta_expansion`` as a purely long-range descriptor in +combination with a short-range descriptor like +:py:class:`featomic.SphericalExpansion` for your machine learning models. + +We now verify that for our test ``atoms`` the LODE spherical expansion only contains +short-range contributions. To demonstrate this, we densify the +:py:class:`metatensor.TensorMap` to have only one block per ``"center_type"`` and +visualize our result. Since we have to perform the densify operation several times in +this how-to, we define a helper function ``densify_tensormap``. + +.. GENERATED FROM PYTHON SOURCE LINES 207-217 + +.. code-block:: Python + + + + def densify_tensormap(tensor: TensorMap) -> TensorMap: + dense_tensor = tensor.components_to_properties("o3_mu") + dense_tensor = dense_tensor.keys_to_samples("neighbor_type") + dense_tensor = dense_tensor.keys_to_properties(["o3_lambda", "o3_sigma"]) + + return dense_tensor + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 218-220 + +We apply the function to the Fourier space spherical expansion +``fourier_space_expansion`` and ``subtracted_expansion``. + +.. GENERATED FROM PYTHON SOURCE LINES 220-226 + +.. code-block:: Python + + + + fourier_space_expansion = densify_tensormap(fourier_space_expansion) + delta_expansion = densify_tensormap(delta_expansion) + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 227-231 + +Finally, we plot the values of each block for the Fourier Space spherical expansion +in the upper panel and the difference between the Fourier Space and the real space +in the lower panel. And since we will do this plot several times we again define a +small plot function to help us + +.. GENERATED FROM PYTHON SOURCE LINES 231-255 + +.. code-block:: Python + + + + def plot_value_comparison( + key: LabelsEntry, + fourier_space_expansion: TensorMap, + subtracted_expansion: TensorMap, + ): + fig, ax = plt.subplots(2, layout="tight") + + values_subtracted = subtracted_expansion[key].values + values_fourier_space = fourier_space_expansion[key].values + + ax[0].set_title(f"center_type={key.values[0]}\n Fourier space sph. expansion") + im = ax[0].matshow(values_fourier_space, vmin=-0.25, vmax=0.5) + ax[0].set_ylabel("sample index") + + ax[1].set_title("Difference between Fourier and real space sph. expansion") + ax[1].matshow(values_subtracted, vmin=-0.25, vmax=0.5) + ax[1].set_ylabel("sample index") + ax[1].set_xlabel("property index") + + fig.colorbar(im, ax=ax[0], orientation="horizontal", fraction=0.1, label="values") + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 256-257 + +We first plot the values of the TensorMaps for center_type=1 (hydrogen) + +.. GENERATED FROM PYTHON SOURCE LINES 257-262 + +.. code-block:: Python + + + plot_value_comparison( + fourier_space_expansion.keys[0], fourier_space_expansion, delta_expansion + ) + + + + +.. image-sg:: /examples/images/sphx_glr_long-range-descriptor_003.png + :alt: center_type=1 Fourier space sph. expansion, Difference between Fourier and real space sph. expansion + :srcset: /examples/images/sphx_glr_long-range-descriptor_003.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 263-264 + +and for center_type=8 (oxygen) + +.. GENERATED FROM PYTHON SOURCE LINES 264-270 + +.. code-block:: Python + + + plot_value_comparison( + fourier_space_expansion.keys[1], fourier_space_expansion, delta_expansion + ) + + + + + +.. image-sg:: /examples/images/sphx_glr_long-range-descriptor_004.png + :alt: center_type=8 Fourier space sph. expansion, Difference between Fourier and real space sph. expansion + :srcset: /examples/images/sphx_glr_long-range-descriptor_004.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 271-284 + +The plot shows that the spherical expansion for the Fourier space is non-zero while +the difference between the two expansions is very small. + +.. warning:: + Small residual values may stems from the contribution of the periodic images. You + can verify and reduce those contributions by either increasing the cell and/or + increase the ``potential_exponent``. + +**Two water molecule (long range) system** + +We now add a second water molecule shifted by :math:`3\,\mathrm{Å}` in each +direction from our first water molecule to show that such a system has non +negligible long range effects. + +.. GENERATED FROM PYTHON SOURCE LINES 284-321 + +.. code-block:: Python + + + + atoms_shifted = molecule("H2O", vacuum=10, pbc=True) + atoms_shifted.positions = atoms.positions + 3 + + atoms_long_range = atoms + atoms_shifted + + + fig, ax = plt.subplots() + + ase.visualize.plot.plot_atoms(atoms_long_range, ax=ax) + + cutoff_circle = plt.Circle( + xy=atoms[0].position[1:], + radius=cutoff, + color="gray", + ls="dashed", + fill=False, + ) + + cutoff_circle_shifted = plt.Circle( + xy=atoms_shifted[0].position[1:], + radius=cutoff, + color="gray", + ls="dashed", + fill=False, + ) + + ax.add_patch(cutoff_circle) + ax.add_patch(cutoff_circle_shifted) + + ax.set_xlabel("Å") + ax.set_ylabel("Å") + + fig.show() + + + + + +.. image-sg:: /examples/images/sphx_glr_long-range-descriptor_005.png + :alt: long range descriptor + :srcset: /examples/images/sphx_glr_long-range-descriptor_005.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 322-327 + +As you can see, the ``cutoff`` radii of the two molecules are completely disjoint. +Therefore, a short-range model will not able to describe the intermolecular +interactions between our two molecules. To verify we now again create a long-range +only descriptor for this system. We use the already defined +``real_space_expansion_long_range`` and ``fourier_space_expansion_long_range`` + +.. GENERATED FROM PYTHON SOURCE LINES 327-332 + +.. code-block:: Python + + + + real_space_expansion_long_range = real_space_calculator.compute(atoms_long_range) + fourier_space_expansion_long_range = fourier_space_calculator.compute(atoms_long_range) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 333-336 + +We now first verify that the contribution from the short-range descriptors is the +same as for a single water molecule. Exemplarily, we compare only the first +(Hydrogen) block of each tensor. + +.. GENERATED FROM PYTHON SOURCE LINES 336-344 + +.. code-block:: Python + + + + print("Single water real space spherical expansion") + print(np.round(real_space_expansion[1].values, 3)) + + print("\nTwo water real space spherical expansion") + print(np.round(real_space_expansion_long_range[1].values, 3)) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Single water real space spherical expansion + [[[-0.267 -0.101 -0.06 -0.044 -0.035] + [ 0. 0. 0. 0. 0. ] + [ 0. 0. 0. 0. 0. ]] + + [[ 0.267 0.101 0.06 0.044 0.035] + [ 0. 0. 0. 0. 0. ] + [ 0. 0. 0. 0. 0. ]]] + + Two water real space spherical expansion + [[[-0.267 -0.101 -0.06 -0.044 -0.035] + [ 0. 0. 0. 0. 0. ] + [ 0. 0. 0. 0. 0. ]] + + [[ 0.267 0.101 0.06 0.044 0.035] + [ 0. 0. 0. 0. 0. ] + [ 0. 0. 0. 0. 0. ]] + + [[-0.267 -0.101 -0.06 -0.044 -0.035] + [ 0. 0. 0. 0. 0. ] + [ 0. 0. 0. 0. 0. ]] + + [[ 0.267 0.101 0.06 0.044 0.035] + [ 0. 0. 0. 0. 0. ] + [ 0. 0. 0. 0. 0. ]]] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 345-353 + +Since the values of the block are the same, we can conclude that there is no +information shared between the two molecules and that the short-range descriptor is +not able to distinguish the system with only one or two water molecules. Note that +the different number of `samples` in ``real_space_expansion_long_range`` reflects +the fact that the second system has more atoms then the first. + +As above, we construct a long-range only descriptor and densify the result for +plotting the values. + +.. GENERATED FROM PYTHON SOURCE LINES 353-365 + +.. code-block:: Python + + + + delta_expansion_long_range = ( + fourier_space_expansion_long_range - real_space_expansion_long_range + ) + + fourier_space_expansion_long_range = densify_tensormap( + fourier_space_expansion_long_range + ) + delta_expansion_long_range = densify_tensormap(delta_expansion_long_range) + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 366-369 + +As above, we plot the values of the spherical expansions for the Fourier and the +subtracted (long range only) spherical expansion. First for hydrogen +(``center_species=1``) + +.. GENERATED FROM PYTHON SOURCE LINES 369-376 + +.. code-block:: Python + + + plot_value_comparison( + fourier_space_expansion_long_range.keys[0], + fourier_space_expansion_long_range, + delta_expansion_long_range, + ) + + + + +.. image-sg:: /examples/images/sphx_glr_long-range-descriptor_006.png + :alt: center_type=1 Fourier space sph. expansion, Difference between Fourier and real space sph. expansion + :srcset: /examples/images/sphx_glr_long-range-descriptor_006.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 377-378 + +amd second for oxygen (``center_species=8``) + +.. GENERATED FROM PYTHON SOURCE LINES 378-386 + +.. code-block:: Python + + + plot_value_comparison( + fourier_space_expansion_long_range.keys[1], + fourier_space_expansion_long_range, + delta_expansion_long_range, + ) + + + + + +.. image-sg:: /examples/images/sphx_glr_long-range-descriptor_007.png + :alt: center_type=8 Fourier space sph. expansion, Difference between Fourier and real space sph. expansion + :srcset: /examples/images/sphx_glr_long-range-descriptor_007.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 387-392 + +We clearly see that the values of the subtracted spherical are much larger compared +to the system with only a single water molecule, thus confirming the presence of +long-range contributions in the descriptor for a system with two water molecules. + +.. end-body + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** (0 minutes 5.106 seconds) + + +.. _sphx_glr_download_examples_long-range-descriptor.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: long-range-descriptor.ipynb ` + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: long-range-descriptor.py ` + + .. container:: sphx-glr-download sphx-glr-download-zip + + :download:`Download zipped: long-range-descriptor.zip ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/latest/_sources/examples/profiling.rst.txt b/latest/_sources/examples/profiling.rst.txt new file mode 100644 index 000000000..1c9999fe1 --- /dev/null +++ b/latest/_sources/examples/profiling.rst.txt @@ -0,0 +1,188 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples/profiling.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + :ref:`Go to the end ` + to download the full example code. + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_profiling.py: + + +Profiling calculation +===================== + +.. start-body + +.. GENERATED FROM PYTHON SOURCE LINES 7-46 + +.. code-block:: Python + + + import chemfiles + + import featomic + from featomic import SoapPowerSpectrum + + + def compute_soap(path): + """Compute SOAP power spectrum. + + This is the same code as the 'compute-soap' example + """ + with chemfiles.Trajectory(path) as trajectory: + frames = [f for f in trajectory] + + HYPER_PARAMETERS = { + "cutoff": { + "radius": 5.0, + "smoothing": {"type": "ShiftedCosine", "width": 0.5}, + }, + "density": { + "type": "Gaussian", + "width": 0.3, + }, + "basis": { + "type": "TensorProduct", + "max_angular": 4, + "radial": {"type": "Gto", "max_radial": 6}, + }, + } + + calculator = SoapPowerSpectrum(**HYPER_PARAMETERS) + descriptor = calculator.compute(frames, gradients=["positions"]) + descriptor = descriptor.keys_to_samples("center_type") + descriptor = descriptor.keys_to_properties(["neighbor_1_type", "neighbor_2_type"]) + + return descriptor + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 47-48 + +Run the calculation with profiling enabled. + +.. GENERATED FROM PYTHON SOURCE LINES 49-52 + +.. code-block:: Python + + + with featomic.Profiler() as profiler: + descriptor = compute_soap("dataset.xyz") + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 53-54 + +Display the recorded profiling data as table. + +.. GENERATED FROM PYTHON SOURCE LINES 55-58 + +.. code-block:: Python + + + print(profiler.as_short_table()) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + ╔════╦══════════════════════════════════════════════╦════════════╦═══════════╦══════════╦══════════════╗ + ║ id ║ span name ║ call count ║ called by ║ total ║ mean ║ + ╠════╬══════════════════════════════════════════════╬════════════╬═══════════╬══════════╬══════════════╣ + ║ 4 ║ SoapPowerSpectrum::compute ║ 1 ║ — ║ 764.15ms ║ 764.15ms ║ + ╠════╬══════════════════════════════════════════════╬════════════╬═══════════╬══════════╬══════════════╣ + ║ 5 ║ SphericalExpansion::compute ║ 1 ║ 4 ║ 313.33ms ║ 313.33ms ║ + ╠════╬══════════════════════════════════════════════╬════════════╬═══════════╬══════════╬══════════════╣ + ║ 1 ║ SoapRadialIntegralSpline::with_accuracy ║ 30 ║ 5 ║ 134.14ms ║ 4.47ms ║ + ╠════╬══════════════════════════════════════════════╬════════════╬═══════════╬══════════╬══════════════╣ + ║ 0 ║ GtoRadialIntegral::compute ║ 19230 ║ 1 ║ 126.28ms ║ 6.57µs ║ + ╠════╬══════════════════════════════════════════════╬════════════╬═══════════╬══════════╬══════════════╣ + ║ 3 ║ Calculator::prepare ║ 2 ║ 4 ║ 57.23ms ║ 28.62ms ║ + ╠════╬══════════════════════════════════════════════╬════════════╬═══════════╬══════════╬══════════════╣ + ║ 2 ║ NeighborsList ║ 40 ║ 3 ║ 12.18ms ║ 304.44µs ║ + ╠════╬══════════════════════════════════════════════╬════════════╬═══════════╬══════════╬══════════════╣ + ║ 6 ║ SplinedRadialIntegral::compute ║ 176531 ║ 5 ║ 43.89ms ║ 248.00ns ⚠️ ║ + ╠════╬══════════════════════════════════════════════╬════════════╬═══════════╬══════════╬══════════════╣ + ║ 7 ║ SphericalHarmonics::compute ║ 35307 ║ 5 ║ 21.26ms ║ 602.00ns ⚠️ ║ + ╚════╩══════════════════════════════════════════════╩════════════╩═══════════╩══════════╩══════════════╝ + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 59-60 + +You can also save this data as json for future usage + +.. GENERATED FROM PYTHON SOURCE LINES 61-63 + +.. code-block:: Python + + print(profiler.as_json()) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + {"timings":{"featomic::calculators::soap::radial_integral::gto::GtoRadialIntegral::compute":{"id":0,"elapsed":"126.277379ms","called":19230},"featomic::calculators::soap::radial_integral::spline::SoapRadialIntegralSpline::with_accuracy":{"id":1,"elapsed":"134.13893ms","called":30},"featomic::systems::neighbors::NeighborsList":{"id":2,"elapsed":"12.1774ms","called":40},"featomic::calculator::Calculator::prepare":{"id":3,"elapsed":"57.234561ms","called":2},"featomic::calculators::soap::power_spectrum::SoapPowerSpectrum::compute":{"id":4,"elapsed":"764.147734ms","called":1},"featomic::calculators::soap::spherical_expansion::SphericalExpansion::compute":{"id":5,"elapsed":"313.326795ms","called":1},"featomic::calculators::soap::radial_integral::spline::SplinedRadialIntegral::compute":{"id":6,"elapsed":"43.892819ms","called":176531},"featomic::math::spherical_harmonics::SphericalHarmonics::compute":{"id":7,"elapsed":"21.261398ms","called":35307}},"calls":[{"caller":0,"callee":1,"count":19230},{"caller":2,"callee":3,"count":40},{"caller":3,"callee":4,"count":1},{"caller":1,"callee":5,"count":5},{"caller":6,"callee":5,"count":1},{"caller":7,"callee":5,"count":1},{"caller":5,"callee":4,"count":1}]} + + + + +.. GENERATED FROM PYTHON SOURCE LINES 64-65 + +.. end-body + + +.. _sphx_glr_download_examples_profiling.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: profiling.ipynb ` + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: profiling.py ` + + .. container:: sphx-glr-download sphx-glr-download-zip + + :download:`Download zipped: profiling.zip ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/latest/_sources/examples/property-selection.rst.txt b/latest/_sources/examples/property-selection.rst.txt new file mode 100644 index 000000000..9b3859279 --- /dev/null +++ b/latest/_sources/examples/property-selection.rst.txt @@ -0,0 +1,382 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples/property-selection.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + :ref:`Go to the end ` + to download the full example code. + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_property-selection.py: + + +Property Selection +================== + +.. start-body + +.. GENERATED FROM PYTHON SOURCE LINES 7-16 + +.. code-block:: Python + + + import chemfiles + import numpy as np + from metatensor import Labels, MetatensorError, TensorBlock, TensorMap + from skmatter.feature_selection import FPS + + from featomic import SoapPowerSpectrum + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 17-18 + +First we load the dataset with chemfiles + +.. GENERATED FROM PYTHON SOURCE LINES 19-23 + +.. code-block:: Python + + + with chemfiles.Trajectory("dataset.xyz") as trajectory: + frames = [f for f in trajectory] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 24-25 + +and define the hyper parameters of the representation + +.. GENERATED FROM PYTHON SOURCE LINES 26-47 + +.. code-block:: Python + + + HYPER_PARAMETERS = { + "cutoff": { + "radius": 5.0, + "smoothing": {"type": "ShiftedCosine", "width": 0.5}, + }, + "density": { + "type": "Gaussian", + "width": 0.3, + }, + "basis": { + "type": "TensorProduct", + "max_angular": 4, + "radial": {"type": "Gto", "max_radial": 6}, + }, + } + + calculator = SoapPowerSpectrum(**HYPER_PARAMETERS) + + descriptor = calculator.compute(frames) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 48-51 + +The selections for feature can be a set of ``Labels``, in which case the names +of the labels must be a subset of the names of the properties produced by the +calculator. You can see the default set of names with: + +.. GENERATED FROM PYTHON SOURCE LINES 52-55 + +.. code-block:: Python + + + print("property names:", descriptor.property_names) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + property names: ['l', 'n_1', 'n_2'] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 56-59 + +We can use a subset of these names to define a selection. In this case, only +properties matching the labels in this selection will be used by featomic +(here, only properties with ``l = 0`` will be used) + +.. GENERATED FROM PYTHON SOURCE LINES 60-74 + +.. code-block:: Python + + + selection = Labels( + names=["l"], + values=np.array([[0]]), + ) + selected_descriptor = calculator.compute(frames, selected_properties=selection) + + selected_descriptor = selected_descriptor.keys_to_samples("center_type") + selected_descriptor = selected_descriptor.keys_to_properties( + ["neighbor_1_type", "neighbor_2_type"] + ) + + properties = selected_descriptor.block().properties + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 75-76 + +We expect to get `[0]` as the list of `l` properties + +.. GENERATED FROM PYTHON SOURCE LINES 77-80 + +.. code-block:: Python + + + print(f"we have the following angular components: {np.unique(properties['l'])}") + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + we have the following angular components: [0] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 81-84 + +The previous selection method uses the same selection for all blocks. If you +can to use different selection for different blocks, you should use a +``TensorMap`` to create your selection + +.. GENERATED FROM PYTHON SOURCE LINES 85-91 + +.. code-block:: Python + + + selected_descriptor = calculator.compute(frames, selected_properties=selection) + descriptor_for_comparison = calculator.compute( + frames, selected_properties=selected_descriptor + ) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 92-95 + +The descriptor had 180 properties stored in the first block, the +selected_descriptor had 36. So ``descriptor_for_comparison`` will also have 36 +properties. + +.. GENERATED FROM PYTHON SOURCE LINES 96-103 + +.. code-block:: Python + + print("shape of first block initially:", descriptor.block(0).values.shape) + print("shape of first block of reference:", selected_descriptor.block(0).values.shape) + print( + "shape of first block after selection:", + descriptor_for_comparison.block(0).values.shape, + ) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + shape of first block initially: (420, 245) + shape of first block of reference: (420, 49) + shape of first block after selection: (420, 49) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 104-110 + +The ``TensorMap`` format allows us to select different features within each +block, and then construct a general matrix of features. We can select the most +significant features using FPS, which selects features based on the distance +between them. The following code snippet selects the 10 most important +features in each block, then constructs a TensorMap containing this selection, +and calculates the final matrix of features for it. + +.. GENERATED FROM PYTHON SOURCE LINES 111-142 + +.. code-block:: Python + + + + def fps_feature_selection(descriptor, n_to_select): + """ + Select ``n_to_select`` features block by block in the ``descriptor``, using + Farthest Point Sampling to do the selection; and return a ``TensorMap`` with + the right structure to be used as properties selection with featomic calculators + """ + blocks = [] + for block in descriptor: + # create a separate FPS selector for each block + fps = FPS(n_to_select=n_to_select) + mask = fps.fit(block.values).get_support() + selected_properties = Labels( + names=block.properties.names, + values=block.properties.values[mask], + ) + # The only important data here is the properties, so we create empty + # sets of samples and components. + blocks.append( + TensorBlock( + values=np.empty((1, len(selected_properties))), + samples=Labels.single(), + components=[], + properties=selected_properties, + ) + ) + + return TensorMap(descriptor.keys, blocks) + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 143-145 + +We can then apply this function to subselect according to the data contained +in a descriptor + +.. GENERATED FROM PYTHON SOURCE LINES 146-149 + +.. code-block:: Python + + + selection = fps_feature_selection(descriptor, n_to_select=10) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 150-152 + +and use the selection with featomic, potentially running the calculation on a +different set of systems + +.. GENERATED FROM PYTHON SOURCE LINES 153-156 + +.. code-block:: Python + + + selected_descriptor = calculator.compute(frames, selected_properties=selection) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 157-159 + +Note that in this case it is no longer possible to have a single feature +matrix, because each block will have its own properties. + +.. GENERATED FROM PYTHON SOURCE LINES 160-166 + +.. code-block:: Python + + + try: + selected_descriptor.keys_to_samples("center_type") + except MetatensorError as err: + print(err) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + invalid parameter: can not move keys to samples if the blocks have different property labels + + + + +.. GENERATED FROM PYTHON SOURCE LINES 167-168 + +.. end-body + + +.. _sphx_glr_download_examples_property-selection.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: property-selection.ipynb ` + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: property-selection.py ` + + .. container:: sphx-glr-download sphx-glr-download-zip + + :download:`Download zipped: property-selection.zip ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/latest/_sources/examples/sample-selection.rst.txt b/latest/_sources/examples/sample-selection.rst.txt new file mode 100644 index 000000000..779be7c36 --- /dev/null +++ b/latest/_sources/examples/sample-selection.rst.txt @@ -0,0 +1,350 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples/sample-selection.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + :ref:`Go to the end ` + to download the full example code. + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_sample-selection.py: + + +Sample Selection +================ + +.. start-body + +.. GENERATED FROM PYTHON SOURCE LINES 7-15 + +.. code-block:: Python + + + import chemfiles + import numpy as np + from metatensor import Labels + + from featomic import SoapPowerSpectrum + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 16-17 + +First we load the dataset with chemfiles + +.. GENERATED FROM PYTHON SOURCE LINES 18-22 + +.. code-block:: Python + + + with chemfiles.Trajectory("dataset.xyz") as trajectory: + frames = [f for f in trajectory] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 23-24 + +and define the hyper parameters of the representation + +.. GENERATED FROM PYTHON SOURCE LINES 25-46 + +.. code-block:: Python + + + HYPER_PARAMETERS = { + "cutoff": { + "radius": 5.0, + "smoothing": {"type": "ShiftedCosine", "width": 0.5}, + }, + "density": { + "type": "Gaussian", + "width": 0.3, + }, + "basis": { + "type": "TensorProduct", + "max_angular": 4, + "radial": {"type": "Gto", "max_radial": 6}, + }, + } + + calculator = SoapPowerSpectrum(**HYPER_PARAMETERS) + + descriptor = calculator.compute(frames) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 47-50 + +The selections for sample can be a set of ``Labels``, in which case the names +of the labels must be a subset of the names of the samples produced by the +calculator. You can see the default set of names with: + +.. GENERATED FROM PYTHON SOURCE LINES 51-54 + +.. code-block:: Python + + + print("sample names:", descriptor.sample_names) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + sample names: ['system', 'atom'] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 55-58 + +We can use a subset of these names to define a selection. In this case, only +samples matching the labels in this selection will be used by featomic (here, +only atoms from system 0, 2, and 3) + +.. GENERATED FROM PYTHON SOURCE LINES 59-74 + +.. code-block:: Python + + + selection = Labels( + names=["system"], + values=np.array([[0], [2], [3]]), + ) + + descriptor_selected = calculator.compute(frames, selected_samples=selection) + + descriptor_selected = descriptor_selected.keys_to_samples("center_type") + descriptor_selected = descriptor_selected.keys_to_properties( + ["neighbor_1_type", "neighbor_2_type"] + ) + + samples = descriptor_selected.block().samples + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 75-76 + +The first block should have ``[0, 2, 3]`` as ``samples["system"]`` + +.. GENERATED FROM PYTHON SOURCE LINES 77-80 + +.. code-block:: Python + + + print(f"we have the following systems: {np.unique(samples['system'])}") + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + we have the following systems: [0 2 3] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 81-84 + +If we want to select not only based on the system indexes but also atomic +indexes, we can do the following (here we select atom 0 in the first system +and atom 1 in the third system): + +.. GENERATED FROM PYTHON SOURCE LINES 85-97 + +.. code-block:: Python + + + selection = Labels( + names=["system", "atom"], + values=np.array([[0, 0], [2, 1]]), + ) + + descriptor_selected = calculator.compute(frames, selected_samples=selection) + descriptor_selected = descriptor_selected.keys_to_samples("center_type") + descriptor_selected = descriptor_selected.keys_to_properties( + ["neighbor_1_type", "neighbor_2_type"] + ) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 98-99 + +The values will have 2 rows, since we have two samples: + +.. GENERATED FROM PYTHON SOURCE LINES 100-106 + +.. code-block:: Python + + + print( + "shape of first block of descriptor:", + descriptor_selected.block(0).values.shape, + ) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + shape of first block of descriptor: (2, 2450) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 107-110 + +The previous selection method uses the same selection for all blocks. If you +can to use different selection for different blocks, you should use a +`TensorMap` to create your selection + +.. GENERATED FROM PYTHON SOURCE LINES 111-115 + +.. code-block:: Python + + + descriptor = calculator.compute(frames) + descriptor_selected = calculator.compute(frames, selected_samples=selection) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 116-117 + +notice how we are passing a TensorMap as the ``selected_samples`` argument: + +.. GENERATED FROM PYTHON SOURCE LINES 118-124 + +.. code-block:: Python + + + print(type(descriptor_selected)) + descriptor_for_comparison = calculator.compute( + frames, selected_samples=descriptor_selected + ) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 125-128 + +The descriptor had 420 samples stored in the first block, +the ``descriptor_selected`` had 0. So ``descriptor_for_comparison`` +will also have 0 samples. + +.. GENERATED FROM PYTHON SOURCE LINES 129-140 + +.. code-block:: Python + + + print("shape of first block initially:", descriptor.block(0).values.shape) + print( + "shape of first block of reference:", + descriptor_selected.block(0).values.shape, + ) + print( + "shape of first block after selection:", + descriptor_for_comparison.block(0).values.shape, + ) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + shape of first block initially: (420, 245) + shape of first block of reference: (0, 245) + shape of first block after selection: (0, 245) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 141-142 + +.. end-body + + +.. _sphx_glr_download_examples_sample-selection.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: sample-selection.ipynb ` + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: sample-selection.py ` + + .. container:: sphx-glr-download sphx-glr-download-zip + + :download:`Download zipped: sample-selection.zip ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/latest/_sources/examples/sg_execution_times.rst.txt b/latest/_sources/examples/sg_execution_times.rst.txt new file mode 100644 index 000000000..b164aa4ae --- /dev/null +++ b/latest/_sources/examples/sg_execution_times.rst.txt @@ -0,0 +1,58 @@ + +:orphan: + +.. _sphx_glr_examples_sg_execution_times: + + +Computation times +================= +**00:13.510** total execution time for 8 files **from examples**: + +.. container:: + + .. raw:: html + + + + + + + + .. list-table:: + :header-rows: 1 + :class: table table-striped sg-datatable + + * - Example + - Time + - Mem (MB) + * - :ref:`sphx_glr_examples_long-range-descriptor.py` (``long-range-descriptor.py``) + - 00:05.106 + - 0.0 + * - :ref:`sphx_glr_examples_compute-soap.py` (``compute-soap.py``) + - 00:02.923 + - 0.0 + * - :ref:`sphx_glr_examples_splined-radial-integral.py` (``splined-radial-integral.py``) + - 00:02.252 + - 0.0 + * - :ref:`sphx_glr_examples_profiling.py` (``profiling.py``) + - 00:01.338 + - 0.0 + * - :ref:`sphx_glr_examples_property-selection.py` (``property-selection.py``) + - 00:01.054 + - 0.0 + * - :ref:`sphx_glr_examples_sample-selection.py` (``sample-selection.py``) + - 00:00.410 + - 0.0 + * - :ref:`sphx_glr_examples_keys-selection.py` (``keys-selection.py``) + - 00:00.243 + - 0.0 + * - :ref:`sphx_glr_examples_first-calculation.py` (``first-calculation.py``) + - 00:00.183 + - 0.0 diff --git a/latest/_sources/examples/splined-radial-integral.rst.txt b/latest/_sources/examples/splined-radial-integral.rst.txt new file mode 100644 index 000000000..506479781 --- /dev/null +++ b/latest/_sources/examples/splined-radial-integral.rst.txt @@ -0,0 +1,418 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples/splined-radial-integral.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + :ref:`Go to the end ` + to download the full example code. + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_splined-radial-integral.py: + + +Splined radial integrals +======================== + +.. start-body + +This example illustrates how to generate splines and use custom basis function and +density when computing density-based representations, such as SOAP or LODE. + +.. GENERATED FROM PYTHON SOURCE LINES 12-26 + +.. code-block:: Python + + + import json + + import ase.build + import matplotlib.pyplot as plt + import numpy as np + import scipy + + import featomic + from featomic import SphericalExpansion + from featomic.basis import RadialBasis + from featomic.splines import SoapSpliner + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 27-38 + +For this example, we will define a new custom radial basis for the SOAP spherical +expansion, based on Chebyshev polynomials of the first kind. This basis will then be +used in combination with spherical harmonics to expand the density of neighboring +atoms around a central atom. + +In featomic, defining custom radial basis is done by creating a class inheriting from +:py:class:`featomic.basis.RadialBasis`, and implementing the required method. The +main one is ``compute_primitive``, which evaluates the radial basis on a set of +points. This function should also be able to evaluate the derivative of the radial +basis. If needed :py:meth:`featomic.basis.RadialBasis.finite_differences_derivative` +can be used to compute the derivative with finite differences. + +.. GENERATED FROM PYTHON SOURCE LINES 39-59 + +.. code-block:: Python + + + + class Chebyshev(RadialBasis): + def __init__(self, max_radial, radius): + # initialize `RadialBasis` + super().__init__(max_radial=max_radial, radius=radius) + + def compute_primitive(self, positions, n, *, derivative=False): + # map argument from [0, cutoff] to [-1, 1] + z = 2 * positions / self.radius - 1 + if derivative: + return -2 * n / self.radius * scipy.special.chebyu(n)(z) + else: + return scipy.special.chebyt(n + 1)(z) + + @property + def integration_radius(self): + return self.radius + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 60-61 + +We can now look at the basis functions and their derivatives + +.. GENERATED FROM PYTHON SOURCE LINES 62-72 + +.. code-block:: Python + + radius = 4.5 + basis = Chebyshev(max_radial=4, radius=radius) + + r = np.linspace(0, radius) + for n in range(basis.size): + plt.plot(r, basis.compute_primitive(r, n, derivative=False)) + + plt.title("Chebyshev radial basis functions") + plt.show() + + + + +.. image-sg:: /examples/images/sphx_glr_splined-radial-integral_001.png + :alt: Chebyshev radial basis functions + :srcset: /examples/images/sphx_glr_splined-radial-integral_001.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 73-78 + +.. code-block:: Python + + for n in range(basis.size): + plt.plot(r, basis.compute_primitive(r, n, derivative=True)) + plt.title("Chebyshev radial basis functions' derivatives") + plt.show() + + + + +.. image-sg:: /examples/images/sphx_glr_splined-radial-integral_002.png + :alt: Chebyshev radial basis functions' derivatives + :srcset: /examples/images/sphx_glr_splined-radial-integral_002.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 79-83 + +Before being used by featomic, the basis functions we implemented will be +orthogonalized and normalized, to improve conditioning of the produced features. This +is done automatically, and one can access the orthonormalized basis functions with the +:py:meth:`featomic.basis.RadialBasis.compute` method. + +.. GENERATED FROM PYTHON SOURCE LINES 84-93 + +.. code-block:: Python + + + basis_orthonormal = basis.compute(r, derivative=False) + for n in range(basis.size): + plt.plot(r, basis_orthonormal[:, n]) + + plt.title("Orthonormalized Chebyshev radial basis functions") + plt.show() + + + + + +.. image-sg:: /examples/images/sphx_glr_splined-radial-integral_003.png + :alt: Orthonormalized Chebyshev radial basis functions + :srcset: /examples/images/sphx_glr_splined-radial-integral_003.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 94-100 + +With this, our new radial basis definition is ready to be used with +:py:class:`featomic.splines.SoapSpliner`. This class will take the whole set of hyper +parameters, use them to compute a spline of the radial integral, and give us back new +hypers that can be used with the native calculators to compute the expansion with our +custom basis. + + +.. GENERATED FROM PYTHON SOURCE LINES 101-117 + +.. code-block:: Python + + + spliner = SoapSpliner( + cutoff=featomic.cutoff.Cutoff( + radius=radius, + smoothing=featomic.cutoff.ShiftedCosine(width=0.3), + ), + density=featomic.density.Gaussian(width=0.5), + basis=featomic.basis.TensorProduct( + max_angular=4, + radial=Chebyshev(max_radial=4, radius=radius), + spline_accuracy=1e-4, + ), + ) + + hypers = spliner.get_hypers() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 118-120 + +The hyper parameters have been transformed from what we gave to the +:py:class:`featomic.splines.SoapSpliner`: + +.. GENERATED FROM PYTHON SOURCE LINES 121-125 + +.. code-block:: Python + + + print("hypers['basis'] is", type(hypers["basis"])) + print("hypers['density'] is", type(hypers["density"])) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + hypers['basis'] is + hypers['density'] is + + + + +.. GENERATED FROM PYTHON SOURCE LINES 126-127 + +And the new hypers can be used directly with the calculators: + +.. GENERATED FROM PYTHON SOURCE LINES 128-131 + +.. code-block:: Python + + + calculator_splined = SphericalExpansion(**hypers) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 132-134 + +As a comparison, let's look at the expansion coefficient for formic acid, using both +our splined radial basis and the classic GTO radial basis: + +.. GENERATED FROM PYTHON SOURCE LINES 135-155 + +.. code-block:: Python + + + atoms = ase.build.molecule("HCOOH", vacuum=4, pbc=True) + + calculator_gto = SphericalExpansion( + # same parameters, only the radial basis changed + cutoff=featomic.cutoff.Cutoff( + radius=radius, + smoothing=featomic.cutoff.ShiftedCosine(width=0.3), + ), + density=featomic.density.Gaussian(width=0.5), + basis=featomic.basis.TensorProduct( + max_angular=4, + radial=featomic.basis.Gto(max_radial=4, radius=radius), + spline_accuracy=1e-4, + ), + ) + + expansion_splined = calculator_splined.compute(atoms) + expansion_gto = calculator_gto.compute(atoms) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 156-160 + +As you can see, the coefficients ends up different, with values assigned to different +basis functions. In practice, which basis function will be the best will depend on the +use case and exact dataset, so you should try a couple and check how they performe for +you! + +.. GENERATED FROM PYTHON SOURCE LINES 161-168 + +.. code-block:: Python + + + selection = dict(o3_lambda=0, center_type=8, neighbor_type=1) + + plt.matshow(expansion_splined.block(selection).values.reshape(2, 5)) + plt.matshow(expansion_gto.block(selection).values.reshape(2, 5)) + + + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/images/sphx_glr_splined-radial-integral_004.png + :alt: splined radial integral + :srcset: /examples/images/sphx_glr_splined-radial-integral_004.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/images/sphx_glr_splined-radial-integral_005.png + :alt: splined radial integral + :srcset: /examples/images/sphx_glr_splined-radial-integral_005.png + :class: sphx-glr-multi-img + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 169-172 + +Since the calculation of the splines requires computing some integral numerically, the +creation of the splines might take a while. After an initial calculation, you can save +the splines data in JSON files; and then reload them later to re-use: + +.. GENERATED FROM PYTHON SOURCE LINES 173-190 + +.. code-block:: Python + + + # convert the hypers from classes to a pure JSON-compatible dictionary + json_hypers = featomic.utils.hypers_to_json(hypers) + + # save the data to a file + with open("splined-hypers.json", "w") as fp: + json.dump(json_hypers, fp) + + + # load the data from the file + with open("splined-hypers.json", "r") as fp: + json_hypers = json.load(fp) + + # the hypers can be used directly with the calculators + calculator = featomic.SphericalExpansion(**json_hypers) + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 191-197 + +Finally, you can use the same method to define custom +:py:class:`featomic.basis.ExpansionBasis` and custom +:py:class:`featomic.density.AtomicDensity`; by creating a new class inheriting from +the corresponding base class and implementing the corresponding methods. This allow +you to create a fully custom spherical expansion, and evaluate them efficiently +through the splines. + +.. GENERATED FROM PYTHON SOURCE LINES 200-201 + +.. end-body + + +.. _sphx_glr_download_examples_splined-radial-integral.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: splined-radial-integral.ipynb ` + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: splined-radial-integral.py ` + + .. container:: sphx-glr-download sphx-glr-download-zip + + :download:`Download zipped: splined-radial-integral.zip ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/latest/_sources/explanations/concepts.rst.txt b/latest/_sources/explanations/concepts.rst.txt new file mode 100644 index 000000000..c253bfd26 --- /dev/null +++ b/latest/_sources/explanations/concepts.rst.txt @@ -0,0 +1,83 @@ +.. _core-concepts: + +Core concepts of featomic +========================== + +Featomic is a library computing representations of atomic systems for machine +learning applications. These representations encode fundamental symmetries of +the systems to ensure that the machine learning algorithm is as efficient as +possible. Examples of representations include the `Smooth Overlap of Atomic +Positions `_ (SOAP), `Behler-Parrinello symmetry functions `_, +`Coulomb matrices`_, and many others. This documentation does not describe each +method in details, delegating instead to many other good resources on the +subject. This section in particular explains the three core objects featomic is +built upon: systems, calculators and descriptors. + +.. figure:: ../../static/images/core-concepts.* + + Schematic representations of the three core concepts in featomic: systems, + calculators and descriptors. The core operation provided by this library to + compute the representation (associated with a given calculator) of one or + multiple systems, getting the corresponding data in a descriptor. + +.. _SOAP: https://doi.org/10.1103/PhysRevB.87.184115 +.. _BPSF: https://doi.org/10.1063/1.3553717 +.. _Coulomb matrices: https://doi.org/10.1103/PhysRevLett.108.058301 + +Systems: atoms and molecules +---------------------------- + +Systems describe the input data featomic uses to compute various +representations. They contains information about the atomic positions, different +atomic types, unit cell and periodicity, and are responsible for computing the +neighbors of each atomic center. + +Featomic uses systems in a generic manner, and while it provides a default +implementation called ``SimpleSystem`` it is able to use data from any source by +going through a few lines of adaptor code. This enables using it directly inside +molecular simulation engines, re-using the neighbors list calculation done by +the engine, when using machine learning force-fields in simulations. + +Both implementation and data related to systems are thus provided by users of +the featomic library. + +Calculators: computing representations +-------------------------------------- + +Calculators are provided by featomic, and compute a single representations. +There is a calculator +for the :ref:`sorted distances vector ` representation, +one for the :ref:`spherical expansion ` representation, +one for the :ref:`LODE spherical expansion ` representation, +and hopefully soon many others. + +All calculators are registered globally in featomic, and can be constructed +with a name and a set of parameters (often called hyper-parameters). These +parameters control the features of the final representation: how many are they, +and what do they represent. All :ref:`available calculators ` +and the corresponding parameters are documented. + +From a user perspective, calculators are black boxes that take systems as input +and returns a descriptor object, described below. + +Descriptors: data storage for atomistic machine learning +-------------------------------------------------------- + +After using a calculator on one or multiple systems, users will get the +numerical representation of their atomic systems in a ``descriptor`` object. +Featomic uses `metatensor`_ ``TensorMap`` type when returning descriptors. + +.. _metatensor: https://lab-cosmo.github.io/metatensor/ + +A ``TensorMap`` can be seen as a dictionary mapping some keys to a set of data +blocks. Each block contains both data (and gradients) arrays — i.e. +multidimensional arrays containing the descriptor values — and metadata +describing the different dimensions of these arrays. Which keys are present in a +``TensorMap`` will depend on ``Calculator`` being used. Typically, +representation using one-hot encoding of atomic types will have the +corresponding keys (for example ``center_type``, ``neighbor_type``, *etc.*), and +equivariant representations will have keys for the different equivariance +classes (``o3_lambda`` for SO(3) equivariants, *etc.*). + +For more information on ``TensorMap`` and what can be done with one, please see +the `metatensor`_ documentation. diff --git a/latest/_sources/explanations/index.rst.txt b/latest/_sources/explanations/index.rst.txt new file mode 100644 index 000000000..4015f7d86 --- /dev/null +++ b/latest/_sources/explanations/index.rst.txt @@ -0,0 +1,16 @@ +.. _userdoc-explanations: + +Explanations +============ + +The explanation section discusses topics that broaden your knowledge of +featomic. The theory behind the calculators and additional useful information +are found here to give you more clarity and understanding of what featomic is +all about. + +.. toctree:: + :maxdepth: 1 + + concepts + soap + rotation_adapted diff --git a/latest/_sources/explanations/rotation_adapted.rst.txt b/latest/_sources/explanations/rotation_adapted.rst.txt new file mode 100644 index 000000000..d1b1301af --- /dev/null +++ b/latest/_sources/explanations/rotation_adapted.rst.txt @@ -0,0 +1,114 @@ +Rotation-Adapted Features +========================= + +Equivariance +------------ + +Descriptors like SOAP are translation, rotation, and permutation invariant. +Indeed, such invariances are extremely useful if one wants to learn an invariant +target (e.g., the energy). Being already encoded in the descriptor, the learning +algorithm does not have to learn such a physical requirement. + +The situation is different if the target is not invariant. For example, one may +want to learn a dipole. The dipole rotates with a rotation of the molecule, and +as such, invariant descriptors do not have the required symmetries for this +task. + +Instead, one would need a rotation equivariant descriptor. Rotation equivariance +means that, if we first rotate the system and compute the descriptor, we obtain +the same result as first computing the descriptor and then applying the +rotation, i.e., the descriptor behaves correctly upon rotation operations. +Denoting a system as :math:`A`, the function computing the descriptor as +:math:`f(\cdot)`, and the rotation operator as :math:`\hat{R}`, rotation +equivariance can be expressed as: + +.. math:: + :name: eq:equivariance + + f(\hat{R} A) = \hat{R} f(A) + +Of course, invariance is a special case of equivariance. + + +Rotation Equivariance of the Spherical Expansion +------------------------------------------------ + +The spherical expansion is a rotation equivariant descriptor. +Let's consider the expansion coefficients of :math:`\rho_i(\mathbf{r})`. +We have: + +.. math:: + + \hat{R} \rho_i(\mathbf{r}) &= \sum_{nlm} c_{nlm}^{i} R_n(r) \hat{R} Y_l^m(\hat{\mathbf{r}}) \nonumber \\ + &= \sum_{nlmm'} c_{nlm}^{i} R_n(r) D_{m,m'}^{l}(\hat{R}) Y_l^{m'}(\hat{\mathbf{r}}) \nonumber \\ + &= \sum_{nlm} \left( \sum_{m'} D_{m',m}^l(\hat{R}) c_{nlm'}^{i}\right) B_{nlm}(\mathbf{r}) \nonumber + +and noting that :math:`Y_l^m(\hat{R} \hat{\mathbf{r}}) = \hat{R} +Y_l^m(\hat{\mathbf{r}})` and :math:`\hat{R}r = r`, equation :ref:`(1) +` is satisfied and we conclude that the expansion coefficients +:math:`c_{nlm}^{i}` are rotation equivariant. Indeed, each :math:`c_{nlm}^{i}` +transforms under rotation as the spherical harmonics +:math:`Y_l^m(\hat{\mathbf{r}})`. + +Using the Dirac notation, the coefficient :math:`c_{nlm}^{i}` can be expressed +as :math:`\braket{nlm\vert\rho_i}`. Equivalently, and to stress the fact that +this coefficient describes something that transforms under rotation as a +spherical harmonics :math:`Y_l^m(\hat{\mathbf{r}})`, it is sometimes written as +:math:`\braket{n\vert\rho_i;lm}`, i.e., the atomic density is "tagged" with a +label that tells how it transforms under rotations. + + +Completeness Relations of Spherical Harmonics +--------------------------------------------- + +Spherical harmonics can be combined together using rules coming from standard +theory of angular momentum: + +.. math:: + :name: eq:cg_coupling + + \ket{lm} \propto \ket{l_1 l_2 l m} = \sum_{m_1 m_2} C_{m_1 m_2 m}^{l_1 l_2 l} \ket{l_1 m_1} \ket{l_2 m_2} + +where :math:`C_{m_1 m_2 m}^{l_1 l_2 l}` is a Clebsch-Gordan (CG) coefficient. + +Thanks to the one-to-one correspondence (under rotation) between +:math:`c_{nlm}^{i}` and :math:`Y_l^m`, :ref:`(2) ` means that +one can take products of two spherical expansion coefficients (which amounts to +considering density correlations), and combine them with CG coefficients to get +new coefficients that transform as a single spherical harmonics. This process is +known as coupling, from the uncoupled basis of angular momentum (formed by the +product of rotation eigenstates) to a coupled basis (a single rotation +eigenstate). + +One can also write the inverse of :ref:`(2) `: + +.. math:: + :name: eq:cg_decoupling + + \ket{l_1 m_1} \ket{l_2 m_2} = \sum_{l m} C_{m_1 m_2 m}^{l_1 l_2 l} \ket{l_1 l_2 l m} + +that express the product of two rotation eigenstates in terms of one. This +process is known as decoupling. + +Example: :math:`\lambda`-SOAP +----------------------------- + +A straightforward application of :ref:`(2) ` is the construction +of :math:`\lambda`-SOAP features. Indeed, :math:`\lambda`-SOAP was created in +order to have a rotation and inversion equivariant version of the 3-body density +correlations. The :math:`\lambda` represents the degree of a spherical +harmonics, :math:`Y_{\lambda}^{\mu}(\hat{\mathbf{r}})`, and it indicates that +this descriptor can transform under rotations as a spherical harmonics, i.e., it +is rotation equivariant. + +It is then obtained by considering two expansion coefficients of the atomic +density, and combining them with a CG iteration to a coupled basis, as in +:ref:`(2) `. The :math:`\lambda`-SOAP descriptor is then: + +.. math:: + + \braket{n_1 l_1 n_2 l_2\vert\overline{\rho_i^{\otimes 2}, \sigma, \lambda \mu}} = + \frac{\delta_{\sigma, (-1)^{l_1 + l_2 + \lambda}}}{\sqrt{2 \lambda + 1}} + \sum_{m} C_{m (\mu-m) \mu}^{l_1 l_2 \lambda} c_{n_1 l_1 m}^{i} c_{n_2 l_2 (\mu - m)}^{i} + +where we have assumed complex spherical harmonics coefficients. diff --git a/latest/_sources/explanations/soap.rst.txt b/latest/_sources/explanations/soap.rst.txt new file mode 100644 index 000000000..8a6c94a56 --- /dev/null +++ b/latest/_sources/explanations/soap.rst.txt @@ -0,0 +1,8 @@ +.. _theory: + +What is SOAP +============ + +TBD + +.. We can take inspiration from https://lab-cosmo.github.io/librascal/SOAP.html diff --git a/latest/_sources/get-started/featomic.rst.txt b/latest/_sources/get-started/featomic.rst.txt new file mode 100644 index 000000000..284b06c5f --- /dev/null +++ b/latest/_sources/get-started/featomic.rst.txt @@ -0,0 +1,24 @@ +What is featomic +================= + +Featomic is a library for the efficient computing of representations for +atomistic machine learning also called "descriptors" or "fingerprints". These +representation can be used for atomistic machine learning (ML) models including +ML potentials, visualization or similarity analysis. + +There exist several libraries able to compute such structural representations, +such as `DScribe`_, `QUIP`_, and many more. Featomic tries to distinguish +itself by focussing on speed and memory efficiency of the calculations, with the +explicit goal of running molecular simulations with ML potentials. In +particular, memory efficiency is achieved by using the `metatensor`_ to store the +structural representation. Additionally, featomic is not limited to a single +representation but supports several: + +.. include:: ../../../README.rst + :start-after: inclusion-marker-representations-start + :end-before: inclusion-marker-representations-end + + +.. _DScribe: https://singroup.github.io/dscribe/ +.. _QUIP: https://www.libatoms.org +.. _metatensor: https://lab-cosmo.github.io/metatensor/ diff --git a/latest/_sources/get-started/index.rst.txt b/latest/_sources/get-started/index.rst.txt new file mode 100644 index 000000000..9f3db5ec5 --- /dev/null +++ b/latest/_sources/get-started/index.rst.txt @@ -0,0 +1,13 @@ +.. _userdoc-get-started: + +Getting started +=============== + +The following sections describes how to install and start with using featomic. + +.. toctree:: + :maxdepth: 2 + + featomic + installation + tutorials diff --git a/latest/_sources/get-started/installation.rst.txt b/latest/_sources/get-started/installation.rst.txt new file mode 100644 index 000000000..f4c905fe8 --- /dev/null +++ b/latest/_sources/get-started/installation.rst.txt @@ -0,0 +1,168 @@ +Installation +============ + +You can install featomic in different ways depending on which language you plan +to use it from. In all cases you will need a Rust compiler, which you can +install using `rustup `_ or your OS package manager. + +.. _install-python-lib: + +Installing the Python module +---------------------------- + +For building and using the Python package, clone the repository using `git +`_ and install featomic using `pip +`_. + +From source: + +.. code-block:: bash + + # Make sure you are using the latest version of pip + pip install --upgrade pip + + git clone https://github.com/metatensor/featomic + cd featomic + pip install . + + # alternatively, the same thing in a single command + pip install git+https://github.com/metatensor/featomic + + +Featomic is also provided as prebuilt wheel which avoids the intermediate step +of building the package with a Rust compiler from the source code. + +.. code-block:: bash + + pip install --upgrade pip + pip install --extra-index-url https://luthaf.fr/nightly-wheels/ featomic + + +.. _install-c-lib: + +Installing the C/C++ library +---------------------------- + +This installs a C-compatible shared library that can also be called from C++, as +well as CMake files that can be used with ``find_package(featomic)``. + +.. code-block:: bash + + git clone https://github.com/metatensor/featomic + cd featomic/featomic + mkdir build + cd build + cmake .. + make install + +The build and installation can be configures with a few cmake options, using +``-D