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..0ad96477c --- /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: b1e09eb4e4ce65f5c8a7ee094b28f8f8 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/latest/.doctrees/devdoc/explanations/architecture.doctree b/latest/.doctrees/devdoc/explanations/architecture.doctree new file mode 100644 index 000000000..2f3abb85d 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..63b2bde61 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..88ec3b98a 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..ee944e19b 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..451ab4d79 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..f891491f3 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..5e5226d1b 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..40463a51a 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..066696c48 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..1ba7ca861 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..c205d27bd 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..7cb855b88 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..f8205e504 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..bacbb6943 Binary files /dev/null and b/latest/.doctrees/examples/keys-selection.doctree differ diff --git a/latest/.doctrees/examples/profiling.doctree b/latest/.doctrees/examples/profiling.doctree new file mode 100644 index 000000000..d03b558f4 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..9f4ed19a9 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..b5b104eb2 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..9f2d0e3c6 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..4b388cb60 Binary files /dev/null and b/latest/.doctrees/examples/splined-radial-integral.doctree differ diff --git a/latest/.doctrees/examples/understanding-hypers.doctree b/latest/.doctrees/examples/understanding-hypers.doctree new file mode 100644 index 000000000..212740fd1 Binary files /dev/null and b/latest/.doctrees/examples/understanding-hypers.doctree differ diff --git a/latest/.doctrees/explanations/concepts.doctree b/latest/.doctrees/explanations/concepts.doctree new file mode 100644 index 000000000..8d8a9179b 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..6df25970d 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..131a45117 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..0b0a5b563 Binary files /dev/null and b/latest/.doctrees/explanations/soap.doctree differ diff --git a/latest/.doctrees/get-started/index.doctree b/latest/.doctrees/get-started/index.doctree new file mode 100644 index 000000000..04aacf08e 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..d947e6080 Binary files /dev/null and b/latest/.doctrees/get-started/installation.doctree differ diff --git a/latest/.doctrees/get-started/rascaline.doctree b/latest/.doctrees/get-started/rascaline.doctree new file mode 100644 index 000000000..2827e604d Binary files /dev/null and b/latest/.doctrees/get-started/rascaline.doctree differ diff --git a/latest/.doctrees/get-started/tutorials.doctree b/latest/.doctrees/get-started/tutorials.doctree new file mode 100644 index 000000000..db377a4f5 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..3ee1f9ec5 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..c4537937a 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..93d65fc2f Binary files /dev/null and b/latest/.doctrees/how-to/keys-selection.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..218ca0757 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..049a00174 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..8b32c848c 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..2c8075b23 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..de74d0bff 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..7ad2af467 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..9b6f112a2 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..3eada0ad5 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..79b2ee14f 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..b5c68d4da 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..512fdb49b 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..6950cd735 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..1df67a664 Binary files /dev/null and b/latest/.doctrees/references/api/index.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..ea2fe7aee Binary files /dev/null and b/latest/.doctrees/references/api/python/calculators.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..36ce2432e 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..5e48a7e36 Binary files /dev/null and b/latest/.doctrees/references/api/python/misc.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..6c3859c4c Binary files /dev/null and b/latest/.doctrees/references/api/python/systems.doctree differ diff --git a/latest/.doctrees/references/api/python/utils/atomic-density.doctree b/latest/.doctrees/references/api/python/utils/atomic-density.doctree new file mode 100644 index 000000000..df492cb23 Binary files /dev/null and b/latest/.doctrees/references/api/python/utils/atomic-density.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..ae5750bb5 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..15f62a463 Binary files /dev/null and b/latest/.doctrees/references/api/python/utils/power-spectrum.doctree differ diff --git a/latest/.doctrees/references/api/python/utils/radial-basis.doctree b/latest/.doctrees/references/api/python/utils/radial-basis.doctree new file mode 100644 index 000000000..5d3902ee6 Binary files /dev/null and b/latest/.doctrees/references/api/python/utils/radial-basis.doctree differ diff --git a/latest/.doctrees/references/api/python/utils/splines.doctree b/latest/.doctrees/references/api/python/utils/splines.doctree new file mode 100644 index 000000000..41cbef84b Binary files /dev/null and b/latest/.doctrees/references/api/python/utils/splines.doctree differ diff --git a/latest/.doctrees/references/api/rust.doctree b/latest/.doctrees/references/api/rust.doctree new file mode 100644 index 000000000..46e3097a8 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..46d278d91 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..3395b3bd3 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..5025dfc1e 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..38d651026 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..1aafe5c3f Binary files /dev/null and b/latest/.doctrees/references/api/torch/systems.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..460e9e8de 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..08c04a355 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..c2e21f3cc 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..b722c1f7d 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..c8b625a2a 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..265d9c14e 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..0a250f878 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..102a0f426 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..90d92df7d 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..50882ee7e 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..b573b12d8 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..fa1351892 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..1d78328aa --- /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 rascaline 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\": 5.0,\n \"max_radial\": 6,\n \"max_angular\": 4,\n \"atomic_gaussian_width\": 0.3,\n \"center_atom_weight\": 1.0,\n \"radial_basis\": {\n \"Gto\": {},\n },\n \"cutoff_function\": {\n \"ShiftedCosine\": {\"width\": 0.5},\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 rascaline\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(\"species_center\")\nselected_descriptor = selected_descriptor.keys_to_properties(\n [\"species_neighbor_1\", \"species_neighbor_2\"]\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 rascaline 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 rascaline, 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(\"species_center\")\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.11.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/latest/_downloads/08b985c96711d158571cd9dd7ef9d241/understanding-hypers.ipynb b/latest/_downloads/08b985c96711d158571cd9dd7ef9d241/understanding-hypers.ipynb new file mode 100644 index 000000000..98d681f9a --- /dev/null +++ b/latest/_downloads/08b985c96711d158571cd9dd7ef9d241/understanding-hypers.ipynb @@ -0,0 +1,273 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n\n# Changing SOAP hyper parameters\n\nIn the first `tutorial ` we show how to\ncalculate a descriptor using default hyper parameters. Here we will look at how the\nchange of some hyper parameters affects the values of the descriptor. The\ndefinition of every hyper parameter is given in the `userdoc-calculators` and\nbackground on the mathematical foundation of the spherical expansion is given in\nthe `userdoc-explanations` section.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We use the same molecular crystals dataset as in the first\n`tutorial ` which can downloaded from our\n:download:`website <../../static/dataset.xyz>`.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# We first import the crucial packages, load the dataset using chemfiles and\n# save the first frame in a variable.\n\nimport time\n\nimport chemfiles\nimport matplotlib.pyplot as plt\nimport numpy as np\n\nfrom rascaline import SphericalExpansion\n\n\nwith chemfiles.Trajectory(\"dataset.xyz\") as trajectory:\n frames = [frame for frame in trajectory]\n\nframe0 = frames[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Increasing ``max_radial`` and ``max_angular``\n\nAs mentioned above changing ``max_radial`` has an effect on the accuracy of\nthe descriptor and on the computation time. We now will increase the number of\nradial channels and angular channels. Note, that here we directly pass the\nparameters into the ``SphericalExpansion`` class without defining a\n``HYPERPARAMETERS`` dictionary like we did in the previous tutorial.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "calculator_ext = SphericalExpansion(\n cutoff=4.5,\n max_radial=12,\n max_angular=8,\n atomic_gaussian_width=0.3,\n center_atom_weight=1.0,\n radial_basis={\"Gto\": {\"spline_accuracy\": 1e-6}},\n cutoff_function={\"ShiftedCosine\": {\"width\": 0.5}},\n radial_scaling={\"Willatt2018\": {\"scale\": 2.0, \"rate\": 1.0, \"exponent\": 4}},\n)\n\ndescriptor_ext = calculator_ext.compute(frame0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compared to our previous set of hypers we now have 144 blocks instead of 112\nbecause we increased the number of angular channels.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(len(descriptor_ext.blocks()))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The increase of the radial channels to 12 is reflected in the shape of the 0th\nblock values.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(descriptor_ext.block(0).values.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that the increased number of radial and angular channels can increase the\naccuracy of your representation but will increase the computational time\ntransforming the coordinates into a descriptor. A very simple time measurement\nof the computation shows that the extended calculator takes more time for\nthe computation compared to a calculation using the default hyper parameters\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "start_time = time.time()\ncalculator_ext.compute(frames)\nprint(f\"Extended hypers took {time.time() - start_time:.2f} s.\")\n\n# using smaller max_radial and max_angular, everything else stays the same\ncalculator_small = SphericalExpansion(\n cutoff=4.5,\n max_radial=9,\n max_angular=6,\n atomic_gaussian_width=0.3,\n center_atom_weight=1.0,\n radial_basis={\"Gto\": {\"spline_accuracy\": 1e-6}},\n cutoff_function={\"ShiftedCosine\": {\"width\": 0.5}},\n radial_scaling={\"Willatt2018\": {\"scale\": 2.0, \"rate\": 1.0, \"exponent\": 4}},\n)\n\nstart_time = time.time()\ncalculator_small.compute(frames)\nprint(f\"Smaller hypers took {time.time() - start_time:.2f} s.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Reducing the ``cutoff`` and the ``center_atom_weight``\n\nThe cutoff controls how many neighboring atoms are taken into account for a\ndescriptor. By decreasing the cutoff from 6 \u00c5 to 0.1 \u00c5 fewer and fewer atoms\ncontribute to the descriptor which can be seen by the reduced range of the\nfeatures.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "for cutoff in [6.0, 4.5, 3.0, 1.0, 0.1]:\n calculator_cutoff = SphericalExpansion(\n cutoff=cutoff,\n max_radial=6,\n max_angular=6,\n atomic_gaussian_width=0.3,\n center_atom_weight=1.0,\n radial_basis={\"Gto\": {\"spline_accuracy\": 1e-6}},\n cutoff_function={\"ShiftedCosine\": {\"width\": 0.5}},\n radial_scaling={\"Willatt2018\": {\"scale\": 2.0, \"rate\": 1.0, \"exponent\": 4}},\n )\n\n descriptor = calculator_cutoff.compute(frame0)\n\n print(f\"Descriptor for cutoff={cutoff} \u00c5: {descriptor.block(0).values[0]}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For a ``cutoff`` of 0.1 \u00c5 there is no neighboring atom within the cutoff and\none could expect all features to be 0. This is not the case because the\ncentral atom also contributes to the descriptor. We can vary this contribution\nusing the ``center_atom_weight`` parameter so that the descriptor finally is 0\neverywhere.\n\n..Add a sophisticated and referenced note on how the ``center_atom_weight``\ncould affect ML models.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "for center_weight in [1.0, 0.5, 0.0]:\n calculator_cutoff = SphericalExpansion(\n cutoff=0.1,\n max_radial=6,\n max_angular=6,\n atomic_gaussian_width=0.3,\n center_atom_weight=center_weight,\n radial_basis={\"Gto\": {\"spline_accuracy\": 1e-6}},\n cutoff_function={\"ShiftedCosine\": {\"width\": 0.5}},\n radial_scaling={\"Willatt2018\": {\"scale\": 2.0, \"rate\": 1.0, \"exponent\": 4}},\n )\n\n descriptor = calculator_cutoff.compute(frame0)\n\n print(\n f\"Descriptor for center_weight={center_weight}: \"\n f\"{descriptor.block(0).values[0]}\"\n )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Choosing the ``cutoff_function``\n\nIn a naive descriptor approach all atoms within the cutoff are taken in into\naccount equally and atoms without the cutoff are ignored. This behavior is\nimplemented using the ``cutoff_function={\"Step\": {}}`` parameter in each\ncalculator. However, doing so means that small movements of an atom near the\ncutoff result in large changes in the descriptor: there is a discontinuity in\nthe representation as atoms enter or leave the cutoff. A solution is to use\nsome smoothing function to get rid of this discontinuity, such as a shifted\ncosine function:\n\n\\begin{align}f(r) = \\begin{cases}\n 1 &r < r_c - w,\\\\\n 0.5 + 0.5 \\cos[\\pi (r - r_c + w) / w] &r_c - w < r <= r_c, \\\\\n 0 &r_c < r,\n \\end{cases}\\end{align}\n\nwhere $r_\\mathrm{c}$ is the cutoff distance and $w$ the width.\nSuch smoothing function is used as a multiplicative weight for the\ncontribution to the representation coming from each neighbor one by one\n\nThe following functions compute such a shifted cosine weighting.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def shifted_cosine(r, cutoff, width):\n \"\"\"A shifted cosine switching function.\n\n Parameters\n ----------\n r : float\n distance between neighboring atoms in \u00c5\n cutoff : float\n cutoff distance in \u00c5\n width : float\n width of the switching in \u00c5\n\n Returns\n -------\n float\n weighting of the features\n \"\"\"\n if r <= (cutoff - width):\n return 1.0\n elif r >= cutoff:\n return 0.0\n else:\n s = np.pi * (r - cutoff + width) / width\n return 0.5 * (1.0 + np.cos(s))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us plot the weighting for different widths.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "r = np.linspace(1e-3, 4.5, num=100)\n\nplt.plot([0, 4.5, 4.5, 5.0], [1, 1, 0, 0], c=\"k\", label=r\"Step function\")\n\nfor width in [4.5, 2.5, 1.0, 0.5, 0.1]:\n weighting_values = [shifted_cosine(r=r_i, cutoff=4.5, width=width) for r_i in r]\n plt.plot(r, weighting_values, label=f\"Shifted cosine: $width={width}\\\\,\u00c5$\")\n\nplt.legend()\nplt.xlabel(r\"distance $r$ from the central atom in $\u00c5$\")\nplt.ylabel(\"feature weighting\")\nplt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From the plot we conclude that a larger ``width`` of the shifted cosine\nfunction will decrease the feature values already for smaller distances ``r``\nfrom the central atom.\n\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Choosing the ``radial_scaling``\n\nAs mentioned above all atoms within the cutoff are taken equally for a\ndescriptor. This might limit the accuracy of a model, so it is sometimes\nuseful to weigh neighbors that further away from the central atom less than\nneighbors closer to the central atom. This can be achieved by a\n``radial_scaling`` function with a long-range algebraic decay and smooth\nbehavior at $r \\rightarrow 0$. The ``'Willatt2018'`` radial scaling\navailable in rascaline corresponds to the function introduced in this\n[publication](https://doi.org/10.1039/C8CP05921G):\n\n\\begin{align}u(r) = \\begin{cases}\n 1 / (r/r_0)^m & \\text{if c=0,} \\\\\n 1 & \\text{if m=0,} \\\\\n c / (c+(r/r_0)^m) & \\text{else},\n \\end{cases}\\end{align}\n\nwhere $c$ is the ``rate``, $r_0$ is the ``scale`` parameter and\n$m$ the ``exponent`` of the RadialScaling function.\n\nThe following functions compute such a radial scaling.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def radial_scaling(r, rate, scale, exponent):\n \"\"\"Radial scaling function.\n\n Parameters\n ----------\n r : float\n distance between neighboring atoms in \u00c5\n rate : float\n decay rate of the scaling\n scale : float\n scaling of the distance between atoms in \u00c5\n exponent : float\n exponent of the decay\n\n Returns\n -------\n float\n weighting of the features\n \"\"\"\n if rate == 0:\n return 1 / (r / scale) ** exponent\n if exponent == 0:\n return 1\n else:\n return rate / (rate + (r / scale) ** exponent)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the following we show three different radial scaling functions, where the\nfirst one uses the parameters we use for the calculation of features in the\n`first tutorial `.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "r = np.linspace(1e-3, 4.5, num=100)\n\nplt.axvline(4.5, c=\"k\", ls=\"--\", label=\"cutoff\")\n\nradial_scaling_params = {\"scale\": 2.0, \"rate\": 1.0, \"exponent\": 4}\nplt.plot(r, radial_scaling(r, **radial_scaling_params), label=radial_scaling_params)\n\nradial_scaling_params = {\"scale\": 2.0, \"rate\": 3.0, \"exponent\": 6}\nplt.plot(r, radial_scaling(r, **radial_scaling_params), label=radial_scaling_params)\n\nradial_scaling_params = {\"scale\": 2.0, \"rate\": 0.8, \"exponent\": 2}\nplt.plot(r, radial_scaling(r, **radial_scaling_params), label=radial_scaling_params)\n\nplt.legend()\nplt.xlabel(r\"distance $r$ from the central atom in $\u00c5$\")\nplt.ylabel(\"feature weighting\")\nplt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the end the total weight is the product of ``cutoff_function`` and the\n``radial_scaling``\n\n.. math:\n\n rs(r) = sc(r) \\cdot u(r)\n\nThe shape of this function should be a \"S\" like but the optimal shape depends\non each dataset.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def feature_scaling(r, cutoff, width, rate, scale, exponent):\n \"\"\"Features Scaling factor using cosine shifting and radial scaling.\n\n Parameters\n ----------\n r : float\n distance between neighboring atoms\n cutoff : float\n cutoff distance in \u00c5\n width : float\n width of the decay in \u00c5\n rate : float\n decay rate of the scaling\n scale : float\n scaling of the distance between atoms in \u00c5\n exponent : float\n exponent of the decay\n\n Returns\n -------\n float\n weighting of the features\n \"\"\"\n s = radial_scaling(r, rate, scale, exponent)\n s *= np.array([shifted_cosine(ri, cutoff, width) for ri in r])\n return s\n\n\nr = np.linspace(1e-3, 4.5, num=100)\n\nplt.axvline(4.5, c=\"k\", ls=\"--\", label=r\"$r_\\mathrm{cut}$\")\n\nradial_scaling_params = {}\nplt.plot(\n r,\n feature_scaling(r, scale=2.0, rate=4.0, exponent=6, cutoff=4.5, width=0.5),\n label=\"feature weighting function\",\n)\n\nplt.legend()\nplt.xlabel(r\"distance $r$ from the central atom $[\u00c5]$\")\nplt.ylabel(\"feature weighting\")\nplt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally we see how the magnitude of the features further away from the central\natom reduces when we apply both a ``shifted_cosine`` and a ``radial_scaling``.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "calculator_step = SphericalExpansion(\n cutoff=4.5,\n max_radial=6,\n max_angular=6,\n atomic_gaussian_width=0.3,\n center_atom_weight=1.0,\n radial_basis={\"Gto\": {\"spline_accuracy\": 1e-6}},\n cutoff_function={\"Step\": {}},\n)\n\ndescriptor_step = calculator_step.compute(frame0)\nprint(f\"Step cutoff: {str(descriptor_step.block(0).values[0]):>97}\")\n\ncalculator_cosine = SphericalExpansion(\n cutoff=4.5,\n max_radial=6,\n max_angular=6,\n atomic_gaussian_width=0.3,\n center_atom_weight=1.0,\n radial_basis={\"Gto\": {\"spline_accuracy\": 1e-6}},\n cutoff_function={\"ShiftedCosine\": {\"width\": 0.5}},\n)\n\ndescriptor_cosine = calculator_cosine.compute(frame0)\nprint(f\"Cosine smoothing: {str(descriptor_cosine.block(0).values[0]):>92}\")\n\ncalculator_rs = SphericalExpansion(\n cutoff=4.5,\n max_radial=6,\n max_angular=6,\n atomic_gaussian_width=0.3,\n center_atom_weight=1.0,\n radial_basis={\"Gto\": {\"spline_accuracy\": 1e-6}},\n cutoff_function={\"ShiftedCosine\": {\"width\": 0.5}},\n radial_scaling={\"Willatt2018\": {\"scale\": 2.0, \"rate\": 1.0, \"exponent\": 4}},\n)\n\ndescriptor_rs = calculator_rs.compute(frame0)\n\nprint(f\"cosine smoothing + radial scaling: {str(descriptor_rs.block(0).values[0]):>50}\")" + ] + } + ], + "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.11.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..711c8c93d --- /dev/null +++ b/latest/_downloads/157269325187c1e5cc5b17bff969fe70/profiling.py @@ -0,0 +1,65 @@ +""" +Profiling calculation +===================== + +.. start-body +""" + +import chemfiles + +import rascaline +from rascaline 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": 5.0, + "max_radial": 6, + "max_angular": 4, + "atomic_gaussian_width": 0.3, + "center_atom_weight": 1.0, + "radial_basis": { + "Gto": {}, + }, + "cutoff_function": { + "ShiftedCosine": {"width": 0.5}, + }, + } + + calculator = SoapPowerSpectrum(**HYPER_PARAMETERS) + descriptor = calculator.compute(frames, gradients=["positions"]) + descriptor = descriptor.keys_to_samples("species_center") + descriptor = descriptor.keys_to_properties( + ["species_neighbor_1", "species_neighbor_2"] + ) + + return descriptor + + +# %% +# +# Run the calculation with profiling enabled. + +with rascaline.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..ef935ff57 --- /dev/null +++ b/latest/_downloads/1dcd7388f9219fe5f08cc17fa4fa2d0d/property-selection.py @@ -0,0 +1,166 @@ +""" +Property Selection +================== + +.. start-body +""" + +import chemfiles +import numpy as np +from metatensor import Labels, MetatensorError, TensorBlock, TensorMap +from skmatter.feature_selection import FPS + +from rascaline 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": 5.0, + "max_radial": 6, + "max_angular": 4, + "atomic_gaussian_width": 0.3, + "center_atom_weight": 1.0, + "radial_basis": { + "Gto": {}, + }, + "cutoff_function": { + "ShiftedCosine": {"width": 0.5}, + }, +} + +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 rascaline +# (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("species_center") +selected_descriptor = selected_descriptor.keys_to_properties( + ["species_neighbor_1", "species_neighbor_2"] +) + +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 rascaline 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 rascaline, 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("species_center") +except MetatensorError as err: + print(err) + +# %% +# +# .. end-body diff --git a/latest/_downloads/1ea175a310000e5e69ad132e5fc4c813/understanding-hypers.py b/latest/_downloads/1ea175a310000e5e69ad132e5fc4c813/understanding-hypers.py new file mode 100644 index 000000000..24f0a0ccf --- /dev/null +++ b/latest/_downloads/1ea175a310000e5e69ad132e5fc4c813/understanding-hypers.py @@ -0,0 +1,418 @@ +""" +.. _userdoc-tutorials-understanding-hypers: + +Changing SOAP hyper parameters +============================== + +In the first :ref:`tutorial ` we show how to +calculate a descriptor using default hyper parameters. Here we will look at how the +change of some hyper parameters affects the values of the descriptor. The +definition of every hyper parameter is given in the :ref:`userdoc-calculators` and +background on the mathematical foundation of the spherical expansion is given in +the :ref:`userdoc-explanations` section. +""" + +# %% +# +# We use the same molecular crystals dataset as in the first +# :ref:`tutorial ` which can downloaded from our +# :download:`website <../../static/dataset.xyz>`. + +# We first import the crucial packages, load the dataset using chemfiles and +# save the first frame in a variable. + +import time + +import chemfiles +import matplotlib.pyplot as plt +import numpy as np + +from rascaline import SphericalExpansion + + +with chemfiles.Trajectory("dataset.xyz") as trajectory: + frames = [frame for frame in trajectory] + +frame0 = frames[0] + +# %% +# +# Increasing ``max_radial`` and ``max_angular`` +# --------------------------------------------- +# +# As mentioned above changing ``max_radial`` has an effect on the accuracy of +# the descriptor and on the computation time. We now will increase the number of +# radial channels and angular channels. Note, that here we directly pass the +# parameters into the ``SphericalExpansion`` class without defining a +# ``HYPERPARAMETERS`` dictionary like we did in the previous tutorial. + +calculator_ext = SphericalExpansion( + cutoff=4.5, + max_radial=12, + max_angular=8, + atomic_gaussian_width=0.3, + center_atom_weight=1.0, + radial_basis={"Gto": {"spline_accuracy": 1e-6}}, + cutoff_function={"ShiftedCosine": {"width": 0.5}}, + radial_scaling={"Willatt2018": {"scale": 2.0, "rate": 1.0, "exponent": 4}}, +) + +descriptor_ext = calculator_ext.compute(frame0) + +# %% +# +# Compared to our previous set of hypers we now have 144 blocks instead of 112 +# because we increased the number of angular channels. + +print(len(descriptor_ext.blocks())) + +# %% +# +# The increase of the radial channels to 12 is reflected in the shape of the 0th +# block values. + +print(descriptor_ext.block(0).values.shape) + +# %% +# +# Note that the increased number of radial and angular channels can increase the +# accuracy of your representation but will increase the computational time +# transforming the coordinates into a descriptor. A very simple time measurement +# of the computation shows that the extended calculator takes more time for +# the computation compared to a calculation using the default hyper parameters + +start_time = time.time() +calculator_ext.compute(frames) +print(f"Extended hypers took {time.time() - start_time:.2f} s.") + +# using smaller max_radial and max_angular, everything else stays the same +calculator_small = SphericalExpansion( + cutoff=4.5, + max_radial=9, + max_angular=6, + atomic_gaussian_width=0.3, + center_atom_weight=1.0, + radial_basis={"Gto": {"spline_accuracy": 1e-6}}, + cutoff_function={"ShiftedCosine": {"width": 0.5}}, + radial_scaling={"Willatt2018": {"scale": 2.0, "rate": 1.0, "exponent": 4}}, +) + +start_time = time.time() +calculator_small.compute(frames) +print(f"Smaller hypers took {time.time() - start_time:.2f} s.") + +# %% +# +# Reducing the ``cutoff`` and the ``center_atom_weight`` +# ------------------------------------------------------ +# +# The cutoff controls how many neighboring atoms are taken into account for a +# descriptor. By decreasing the cutoff from 6 Å to 0.1 Å fewer and fewer atoms +# contribute to the descriptor which can be seen by the reduced range of the +# features. + +for cutoff in [6.0, 4.5, 3.0, 1.0, 0.1]: + calculator_cutoff = SphericalExpansion( + cutoff=cutoff, + max_radial=6, + max_angular=6, + atomic_gaussian_width=0.3, + center_atom_weight=1.0, + radial_basis={"Gto": {"spline_accuracy": 1e-6}}, + cutoff_function={"ShiftedCosine": {"width": 0.5}}, + radial_scaling={"Willatt2018": {"scale": 2.0, "rate": 1.0, "exponent": 4}}, + ) + + descriptor = calculator_cutoff.compute(frame0) + + print(f"Descriptor for cutoff={cutoff} Å: {descriptor.block(0).values[0]}") + +# %% +# +# For a ``cutoff`` of 0.1 Å there is no neighboring atom within the cutoff and +# one could expect all features to be 0. This is not the case because the +# central atom also contributes to the descriptor. We can vary this contribution +# using the ``center_atom_weight`` parameter so that the descriptor finally is 0 +# everywhere. +# +# ..Add a sophisticated and referenced note on how the ``center_atom_weight`` +# could affect ML models. + +for center_weight in [1.0, 0.5, 0.0]: + calculator_cutoff = SphericalExpansion( + cutoff=0.1, + max_radial=6, + max_angular=6, + atomic_gaussian_width=0.3, + center_atom_weight=center_weight, + radial_basis={"Gto": {"spline_accuracy": 1e-6}}, + cutoff_function={"ShiftedCosine": {"width": 0.5}}, + radial_scaling={"Willatt2018": {"scale": 2.0, "rate": 1.0, "exponent": 4}}, + ) + + descriptor = calculator_cutoff.compute(frame0) + + print( + f"Descriptor for center_weight={center_weight}: " + f"{descriptor.block(0).values[0]}" + ) + +# %% +# +# Choosing the ``cutoff_function`` +# -------------------------------- +# +# In a naive descriptor approach all atoms within the cutoff are taken in into +# account equally and atoms without the cutoff are ignored. This behavior is +# implemented using the ``cutoff_function={"Step": {}}`` parameter in each +# calculator. However, doing so means that small movements of an atom near the +# cutoff result in large changes in the descriptor: there is a discontinuity in +# the representation as atoms enter or leave the cutoff. A solution is to use +# some smoothing function to get rid of this discontinuity, such as a shifted +# cosine function: +# +# .. math:: +# +# f(r) = \begin{cases} +# 1 &r < r_c - w,\\ +# 0.5 + 0.5 \cos[\pi (r - r_c + w) / w] &r_c - w < r <= r_c, \\ +# 0 &r_c < r, +# \end{cases} +# +# where :math:`r_\mathrm{c}` is the cutoff distance and :math:`w` the width. +# Such smoothing function is used as a multiplicative weight for the +# contribution to the representation coming from each neighbor one by one +# +# The following functions compute such a shifted cosine weighting. + + +def shifted_cosine(r, cutoff, width): + """A shifted cosine switching function. + + Parameters + ---------- + r : float + distance between neighboring atoms in Å + cutoff : float + cutoff distance in Å + width : float + width of the switching in Å + + Returns + ------- + float + weighting of the features + """ + if r <= (cutoff - width): + return 1.0 + elif r >= cutoff: + return 0.0 + else: + s = np.pi * (r - cutoff + width) / width + return 0.5 * (1.0 + np.cos(s)) + + +# %% +# +# Let us plot the weighting for different widths. + +r = np.linspace(1e-3, 4.5, num=100) + +plt.plot([0, 4.5, 4.5, 5.0], [1, 1, 0, 0], c="k", label=r"Step function") + +for width in [4.5, 2.5, 1.0, 0.5, 0.1]: + weighting_values = [shifted_cosine(r=r_i, cutoff=4.5, width=width) for r_i in r] + plt.plot(r, weighting_values, label=f"Shifted cosine: $width={width}\\,Å$") + +plt.legend() +plt.xlabel(r"distance $r$ from the central atom in $Å$") +plt.ylabel("feature weighting") +plt.show() + +# %% +# +# From the plot we conclude that a larger ``width`` of the shifted cosine +# function will decrease the feature values already for smaller distances ``r`` +# from the central atom. + +# %% +# +# Choosing the ``radial_scaling`` +# ------------------------------- +# +# As mentioned above all atoms within the cutoff are taken equally for a +# descriptor. This might limit the accuracy of a model, so it is sometimes +# useful to weigh neighbors that further away from the central atom less than +# neighbors closer to the central atom. This can be achieved by a +# ``radial_scaling`` function with a long-range algebraic decay and smooth +# behavior at :math:`r \rightarrow 0`. The ``'Willatt2018'`` radial scaling +# available in rascaline corresponds to the function introduced in this +# `publication `_: +# +# .. math:: +# +# u(r) = \begin{cases} +# 1 / (r/r_0)^m & \text{if c=0,} \\ +# 1 & \text{if m=0,} \\ +# c / (c+(r/r_0)^m) & \text{else}, +# \end{cases} +# +# where :math:`c` is the ``rate``, :math:`r_0` is the ``scale`` parameter and +# :math:`m` the ``exponent`` of the RadialScaling function. +# +# The following functions compute such a radial scaling. + + +def radial_scaling(r, rate, scale, exponent): + """Radial scaling function. + + Parameters + ---------- + r : float + distance between neighboring atoms in Å + rate : float + decay rate of the scaling + scale : float + scaling of the distance between atoms in Å + exponent : float + exponent of the decay + + Returns + ------- + float + weighting of the features + """ + if rate == 0: + return 1 / (r / scale) ** exponent + if exponent == 0: + return 1 + else: + return rate / (rate + (r / scale) ** exponent) + + +# %% +# +# In the following we show three different radial scaling functions, where the +# first one uses the parameters we use for the calculation of features in the +# :ref:`first tutorial `. + +r = np.linspace(1e-3, 4.5, num=100) + +plt.axvline(4.5, c="k", ls="--", label="cutoff") + +radial_scaling_params = {"scale": 2.0, "rate": 1.0, "exponent": 4} +plt.plot(r, radial_scaling(r, **radial_scaling_params), label=radial_scaling_params) + +radial_scaling_params = {"scale": 2.0, "rate": 3.0, "exponent": 6} +plt.plot(r, radial_scaling(r, **radial_scaling_params), label=radial_scaling_params) + +radial_scaling_params = {"scale": 2.0, "rate": 0.8, "exponent": 2} +plt.plot(r, radial_scaling(r, **radial_scaling_params), label=radial_scaling_params) + +plt.legend() +plt.xlabel(r"distance $r$ from the central atom in $Å$") +plt.ylabel("feature weighting") +plt.show() + +# %% +# +# In the end the total weight is the product of ``cutoff_function`` and the +# ``radial_scaling`` +# +# .. math: +# +# rs(r) = sc(r) \cdot u(r) +# +# The shape of this function should be a "S" like but the optimal shape depends +# on each dataset. + + +def feature_scaling(r, cutoff, width, rate, scale, exponent): + """Features Scaling factor using cosine shifting and radial scaling. + + Parameters + ---------- + r : float + distance between neighboring atoms + cutoff : float + cutoff distance in Å + width : float + width of the decay in Å + rate : float + decay rate of the scaling + scale : float + scaling of the distance between atoms in Å + exponent : float + exponent of the decay + + Returns + ------- + float + weighting of the features + """ + s = radial_scaling(r, rate, scale, exponent) + s *= np.array([shifted_cosine(ri, cutoff, width) for ri in r]) + return s + + +r = np.linspace(1e-3, 4.5, num=100) + +plt.axvline(4.5, c="k", ls="--", label=r"$r_\mathrm{cut}$") + +radial_scaling_params = {} +plt.plot( + r, + feature_scaling(r, scale=2.0, rate=4.0, exponent=6, cutoff=4.5, width=0.5), + label="feature weighting function", +) + +plt.legend() +plt.xlabel(r"distance $r$ from the central atom $[Å]$") +plt.ylabel("feature weighting") +plt.show() + +# %% +# +# Finally we see how the magnitude of the features further away from the central +# atom reduces when we apply both a ``shifted_cosine`` and a ``radial_scaling``. + +calculator_step = SphericalExpansion( + cutoff=4.5, + max_radial=6, + max_angular=6, + atomic_gaussian_width=0.3, + center_atom_weight=1.0, + radial_basis={"Gto": {"spline_accuracy": 1e-6}}, + cutoff_function={"Step": {}}, +) + +descriptor_step = calculator_step.compute(frame0) +print(f"Step cutoff: {str(descriptor_step.block(0).values[0]):>97}") + +calculator_cosine = SphericalExpansion( + cutoff=4.5, + max_radial=6, + max_angular=6, + atomic_gaussian_width=0.3, + center_atom_weight=1.0, + radial_basis={"Gto": {"spline_accuracy": 1e-6}}, + cutoff_function={"ShiftedCosine": {"width": 0.5}}, +) + +descriptor_cosine = calculator_cosine.compute(frame0) +print(f"Cosine smoothing: {str(descriptor_cosine.block(0).values[0]):>92}") + +calculator_rs = SphericalExpansion( + cutoff=4.5, + max_radial=6, + max_angular=6, + atomic_gaussian_width=0.3, + center_atom_weight=1.0, + radial_basis={"Gto": {"spline_accuracy": 1e-6}}, + cutoff_function={"ShiftedCosine": {"width": 0.5}}, + radial_scaling={"Willatt2018": {"scale": 2.0, "rate": 1.0, "exponent": 4}}, +) + +descriptor_rs = calculator_rs.compute(frame0) + +print(f"cosine smoothing + radial scaling: {str(descriptor_rs.block(0).values[0]):>50}") diff --git a/latest/_downloads/1fca5afa28681412baa1843c260225ba/sample-selection.py b/latest/_downloads/1fca5afa28681412baa1843c260225ba/sample-selection.py new file mode 100644 index 000000000..d9f9576d9 --- /dev/null +++ b/latest/_downloads/1fca5afa28681412baa1843c260225ba/sample-selection.py @@ -0,0 +1,140 @@ +""" +Sample Selection +================ + +.. start-body +""" + +import chemfiles +import numpy as np +from metatensor import Labels + +from rascaline 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": 5.0, + "max_radial": 6, + "max_angular": 4, + "atomic_gaussian_width": 0.3, + "center_atom_weight": 1.0, + "radial_basis": { + "Gto": {}, + }, + "cutoff_function": { + "ShiftedCosine": {"width": 0.5}, + }, +} + +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 rascaline (here, +# only atoms from structures 0, 2, and 3) + +selection = Labels( + names=["structure"], + values=np.array([[0], [2], [3]]), +) + +descriptor_selected = calculator.compute(frames, selected_samples=selection) + +descriptor_selected = descriptor_selected.keys_to_samples("species_center") +descriptor_selected = descriptor_selected.keys_to_properties( + ["species_neighbor_1", "species_neighbor_2"] +) + +samples = descriptor_selected.block().samples + +# %% +# +# The first block should have ``[0, 2, 3]`` as ``samples["structure"]`` + +print(f"we have the following structures: {np.unique(samples['structure'])}") + +# %% +# +# If we want to select not only based on the structure indexes but also atomic +# indexes, we can do the following (here we select atom 0 in the first structure +# and atom 1 in the third structure): + +selection = Labels( + names=["structure", "center"], + values=np.array([[0, 0], [2, 1]]), +) + +descriptor_selected = calculator.compute(frames, selected_samples=selection) +descriptor_selected = descriptor_selected.keys_to_samples("species_center") +descriptor_selected = descriptor_selected.keys_to_properties( + ["species_neighbor_1", "species_neighbor_2"] +) + +# %% +# +# 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/33cbf89244c381c85dfb98b83889ff69/first-calculation.ipynb b/latest/_downloads/33cbf89244c381c85dfb98b83889ff69/first-calculation.ipynb new file mode 100644 index 000000000..f39c8ea7c --- /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 rascaline 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 rascaline 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 rascaline 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 rascaline 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 rascaline 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). The effect of changing some hyper\nparameters is discussed in a `second tutorial\n`.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "HYPER_PARAMETERS = {\n \"cutoff\": 4.5,\n \"max_radial\": 9,\n \"max_angular\": 6,\n \"atomic_gaussian_width\": 0.3,\n \"center_atom_weight\": 1.0,\n \"radial_basis\": {\"Gto\": {\"spline_accuracy\": 1e-6}},\n \"cutoff_function\": {\"ShiftedCosine\": {\"width\": 0.5}},\n \"radial_scaling\": {\"Willatt2018\": {\"scale\": 2.0, \"rate\": 1.0, \"exponent\": 4}},\n}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "After we set the hyper parameters we initialize a\n:class:`rascaline.calculators.SphericalExpansion` object with hyper parameters\ndefined above and run the\n:py:func:`rascaline.calculators.CalculatorBase.compute()` method.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "calculator = SphericalExpansion(**HYPER_PARAMETERS)\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\nassociated with a unique key. For the current example, we have one block for\neach angular channel labeled by ``spherical_harmonics_l``, the central atom\nspecies ``species_center`` and neighbor atom species labeled by\n``species_neighbor``. Different atomic species are represented using their\natomic number, e.g. 1 for hydrogen, 6 for carbon, etc. To summarize, this\ndescriptor contains 112 blocks covering all combinations of the angular\nchannels of the central and neighbor atom species in our dataset.\n\nLet us take a look at the second block (at index 1) in detail. This block\ncontains the descriptor for the $l=1$ angular channel for\nhydrogen-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 ``spherical_harmonics_m`` is $2l + 1$, where\n$l$ is the current ``spherical_harmonics_l`` of the block. Here, its\ndimension is three because we are looking at the ``spherical_harmonics_l=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\nRascaline 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:`rascaline.calculators.SphericalExpansion` shown here check out the\n`userdoc-references` section.\n\n## Computing gradients\n\nAdditionally, rascaline 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:`rascaline.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 rascaline 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 `spherical_harmonics_m` component that is\nalso present in the features position gradients also have a component\nindicating the direction of the gradient vector.\n\nFinally, the :attr:`metatensor.block.Gradient.properties` dimension is the same\nas for the values\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(gradient_position.properties)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Rascaline can also calculate gradients with respect to the cell. For this, you\nhave to add ``\"cell\"`` to the list parsed to the ``gradients`` parameter of\nthe :py:func:`rascaline.calculators.CalculatorBase.compute()` method. Cell\ngradients 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\nnext tutorial. If you want to solve an explicit problem our\n`userdoc-how-to` might help 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.11.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/latest/_downloads/42f2842f9cfabd51c881bcbd574c2b08/splined-radial-integral.ipynb b/latest/_downloads/42f2842f9cfabd51c881bcbd574c2b08/splined-radial-integral.ipynb new file mode 100644 index 000000000..c996d729f --- /dev/null +++ b/latest/_downloads/42f2842f9cfabd51c881bcbd574c2b08/splined-radial-integral.ipynb @@ -0,0 +1,201 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n\n# Splined radial integrals\n\n.. start-body\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This script illustrates how to generate splined radial basis\nfunctions/integrals, using a \"rectangular\" Laplacian eigenstate (LE,\nhttps://doi.org/10.1063/5.0124363) basis as the example, i.e, a LE basis\ntruncated with l_max, n_max hyper-parameters.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import ase\nimport numpy as np\nimport scipy as sp\nimport scipy.optimize\nfrom scipy.special import jv\nfrom scipy.special import spherical_jn as j_l\n\nfrom rascaline import SphericalExpansion\nfrom rascaline.utils import RadialIntegralFromFunction" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Set some hyper-parameters:\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "max_angular = 6\nmax_radial = 8\ncutoff = 5.0 # This is also the radius of the LE sphere" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Spherical Bessel zeros (from the scipy cookbook)\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def Jn(r, n):\n return np.sqrt(np.pi / (2 * r)) * jv(n + 0.5, r)\n\n\ndef Jn_zeros(n, nt):\n zeros_j = np.zeros((n + 1, nt), dtype=np.float64)\n zeros_j[0] = np.arange(1, nt + 1) * np.pi\n points = np.arange(1, nt + n + 1) * np.pi\n roots = np.zeros(nt + n, dtype=np.float64)\n for i in range(1, n + 1):\n for j in range(nt + n - i):\n roots[j] = scipy.optimize.brentq(Jn, points[j], points[j + 1], (i,))\n points = roots\n zeros_j[i][:nt] = roots[:nt]\n return zeros_j\n\n\nz_ln = Jn_zeros(max_angular, max_radial)\nz_nl = z_ln.T" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Define the radial basis functions:\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def R_nl(n, el, r):\n # Un-normalized LE radial basis functions\n return j_l(el, z_nl[n, el] * r / cutoff)\n\n\ndef N_nl(n, el):\n # Normalization factor for LE basis functions, excluding the a**(-1.5) factor\n def function_to_integrate_to_get_normalization_factor(x):\n return j_l(el, x) ** 2 * x**2\n\n integral, _ = sp.integrate.quadrature(\n function_to_integrate_to_get_normalization_factor, 0.0, z_nl[n, el]\n )\n return (1.0 / z_nl[n, el] ** 3 * integral) ** (-0.5)\n\n\ndef laplacian_eigenstate_basis(n, el, r):\n R = np.zeros_like(r)\n for i in range(r.shape[0]):\n R[i] = R_nl(n, el, r[i])\n return N_nl(n, el) * R * cutoff ** (-1.5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Quick normalization check:\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "normalization_check_integral, _ = sp.integrate.quadrature(\n lambda x: laplacian_eigenstate_basis(1, 1, x) ** 2 * x**2,\n 0.0,\n cutoff,\n)\nprint(f\"Normalization check (needs to be close to 1): {normalization_check_integral}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now the derivatives (by finite differences):\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def laplacian_eigenstate_basis_derivative(n, el, r):\n delta = 1e-6\n all_derivatives_except_at_zero = (\n laplacian_eigenstate_basis(n, el, r[1:] + delta)\n - laplacian_eigenstate_basis(n, el, r[1:] - delta)\n ) / (2.0 * delta)\n derivative_at_zero = (\n laplacian_eigenstate_basis(n, el, np.array([delta / 10.0]))\n - laplacian_eigenstate_basis(n, el, np.array([0.0]))\n ) / (delta / 10.0)\n return np.concatenate([derivative_at_zero, all_derivatives_except_at_zero])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The radial basis functions and their derivatives can be input into a spline\ngenerator class. This will output the positions of the spline points, the\nvalues of the basis functions evaluated at the spline points, and the\ncorresponding derivatives.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "spliner = RadialIntegralFromFunction(\n radial_integral=laplacian_eigenstate_basis,\n radial_integral_derivative=laplacian_eigenstate_basis_derivative,\n spline_cutoff=cutoff,\n max_radial=max_radial,\n max_angular=max_angular,\n accuracy=1e-5,\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The, we feed the splines to the Rust calculator:\n(IMPORTANT: \"atomic_gaussian_width\" will be ignored)\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "hypers_spherical_expansion = {\n \"cutoff\": cutoff,\n \"max_radial\": max_radial,\n \"max_angular\": max_angular,\n \"center_atom_weight\": 0.0,\n \"radial_basis\": spliner.compute(),\n \"atomic_gaussian_width\": 1.0, # ignored\n \"cutoff_function\": {\"Step\": {}},\n}\ncalculator = SphericalExpansion(**hypers_spherical_expansion)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create dummy structures to test if the calculator outputs correct radial functions:\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def get_dummy_structures(r_array):\n dummy_structures = []\n for r in r_array:\n dummy_structures.append(ase.Atoms(\"CH\", positions=[(0, 0, 0), (0, 0, r)]))\n return dummy_structures\n\n\nr = np.linspace(0.1, 4.9, 20)\nstructures = get_dummy_structures(r)\nspherical_expansion_coefficients = calculator.compute(structures)\n\n# Extract l = 0 features and check that the n = 2 predictions are the same:\nblock_C_l0 = spherical_expansion_coefficients.block(\n species_center=6, spherical_harmonics_l=0, species_neighbor=1\n)\nblock_C_l0_n2 = block_C_l0.values[:, :, 2].flatten()\nspherical_harmonics_0 = 1.0 / np.sqrt(4.0 * np.pi)\n\n# radial function = feature / spherical harmonics function\nrascaline_output_radial_function = block_C_l0_n2 / spherical_harmonics_0\n\nassert np.allclose(\n rascaline_output_radial_function,\n laplacian_eigenstate_basis(2, 0, r),\n atol=1e-5,\n)\nprint(\"Assertion passed successfully!\")" + ] + }, + { + "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.11.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..d1b5e1291 --- /dev/null +++ b/latest/_downloads/536e92230d631426c3c8630f4db8a141/first-calculation.py @@ -0,0 +1,320 @@ +""" +.. _userdoc-tutorials-get-started: + +First descriptor computation +============================ + +This is an introduction to the rascaline 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 rascaline to compute representations. Afterward +# we will load the dataset using chemfiles. + +import chemfiles +import numpy as np + +from rascaline 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 rascaline 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 rascaline 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 +# `_. The effect of changing some hyper +# parameters is discussed in a :ref:`second tutorial +# `. + +HYPER_PARAMETERS = { + "cutoff": 4.5, + "max_radial": 9, + "max_angular": 6, + "atomic_gaussian_width": 0.3, + "center_atom_weight": 1.0, + "radial_basis": {"Gto": {"spline_accuracy": 1e-6}}, + "cutoff_function": {"ShiftedCosine": {"width": 0.5}}, + "radial_scaling": {"Willatt2018": {"scale": 2.0, "rate": 1.0, "exponent": 4}}, +} + +# %% +# +# After we set the hyper parameters we initialize a +# :class:`rascaline.calculators.SphericalExpansion` object with hyper parameters +# defined above and run the +# :py:func:`rascaline.calculators.CalculatorBase.compute()` method. + +calculator = SphericalExpansion(**HYPER_PARAMETERS) +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 ``spherical_harmonics_l``, the central atom +# species ``species_center`` and neighbor atom species labeled by +# ``species_neighbor``. Different atomic species 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 species 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 ``spherical_harmonics_m`` is :math:`2l + 1`, where +# :math:`l` is the current ``spherical_harmonics_l`` of the block. Here, its +# dimension is three because we are looking at the ``spherical_harmonics_l=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. +# +# Rascaline 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:`rascaline.calculators.SphericalExpansion` shown here check out the +# :ref:`userdoc-references` section. +# +# Computing gradients +# ------------------- +# +# Additionally, rascaline 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:`rascaline.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 rascaline 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 `spherical_harmonics_m` 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) + +# %% +# +# Rascaline can also calculate gradients with respect to the cell. For this, you +# have to add ``"cell"`` to the list parsed to the ``gradients`` parameter of +# the :py:func:`rascaline.calculators.CalculatorBase.compute()` method. Cell +# gradients 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/5fc41c52f18084e21db68b260d315ac3/sample-selection.ipynb b/latest/_downloads/5fc41c52f18084e21db68b260d315ac3/sample-selection.ipynb new file mode 100644 index 000000000..c8862de0f --- /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 rascaline 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\": 5.0,\n \"max_radial\": 6,\n \"max_angular\": 4,\n \"atomic_gaussian_width\": 0.3,\n \"center_atom_weight\": 1.0,\n \"radial_basis\": {\n \"Gto\": {},\n },\n \"cutoff_function\": {\n \"ShiftedCosine\": {\"width\": 0.5},\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 rascaline (here,\nonly atoms from structures 0, 2, and 3)\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "selection = Labels(\n names=[\"structure\"],\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(\"species_center\")\ndescriptor_selected = descriptor_selected.keys_to_properties(\n [\"species_neighbor_1\", \"species_neighbor_2\"]\n)\n\nsamples = descriptor_selected.block().samples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The first block should have ``[0, 2, 3]`` as ``samples[\"structure\"]``\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(f\"we have the following structures: {np.unique(samples['structure'])}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we want to select not only based on the structure indexes but also atomic\nindexes, we can do the following (here we select atom 0 in the first structure\nand atom 1 in the third structure):\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "selection = Labels(\n names=[\"structure\", \"center\"],\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(\"species_center\")\ndescriptor_selected = descriptor_selected.keys_to_properties(\n [\"species_neighbor_1\", \"species_neighbor_2\"]\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.11.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/latest/_downloads/79a7c08af4248e467d582409b4cc073c/compute-soap.ipynb b/latest/_downloads/79a7c08af4248e467d582409b4cc073c/compute-soap.ipynb new file mode 100644 index 000000000..07b61ad9b --- /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 rascaline import SoapPowerSpectrum" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Read structures 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 frames = [f for f in trajectory]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Rascaline can also handles structures read by [ASE](https://wiki.fysik.dtu.dk/ase/) using\n\n``frames = 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\": 5.0,\n \"max_radial\": 6,\n \"max_angular\": 4,\n \"atomic_gaussian_width\": 0.3,\n \"center_atom_weight\": 1.0,\n \"radial_basis\": {\n \"Gto\": {},\n },\n \"cutoff_function\": {\n \"ShiftedCosine\": {\"width\": 0.5},\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(frames, 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(\"species_center\")\ndescriptor = descriptor.keys_to_properties([\"species_neighbor_1\", \"species_neighbor_2\"])\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.11.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/latest/_downloads/a61b9667afd1dd08cd2729044cdfcc9a/profiling.ipynb b/latest/_downloads/a61b9667afd1dd08cd2729044cdfcc9a/profiling.ipynb new file mode 100644 index 000000000..215aae94b --- /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 rascaline\nfrom rascaline 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\": 5.0,\n \"max_radial\": 6,\n \"max_angular\": 4,\n \"atomic_gaussian_width\": 0.3,\n \"center_atom_weight\": 1.0,\n \"radial_basis\": {\n \"Gto\": {},\n },\n \"cutoff_function\": {\n \"ShiftedCosine\": {\"width\": 0.5},\n },\n }\n\n calculator = SoapPowerSpectrum(**HYPER_PARAMETERS)\n descriptor = calculator.compute(frames, gradients=[\"positions\"])\n descriptor = descriptor.keys_to_samples(\"species_center\")\n descriptor = descriptor.keys_to_properties(\n [\"species_neighbor_1\", \"species_neighbor_2\"]\n )\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 rascaline.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.11.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..a2df16da3 --- /dev/null +++ b/latest/_downloads/b1679995c5f5a7c97fd29b7a3990fedc/compute-soap.py @@ -0,0 +1,75 @@ +""" +Computing SOAP features +======================= + +.. start-body +""" + +import chemfiles + +from rascaline import SoapPowerSpectrum + + +# %% +# +# Read structures 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: + frames = [f for f in trajectory] + +# %% +# +# Rascaline can also handles structures read by `ASE +# `_ using +# +# ``frames = ase.io.read("dataset.xyz", ":")``. +# +# We can now define hyper parameters for the calculation + +HYPER_PARAMETERS = { + "cutoff": 5.0, + "max_radial": 6, + "max_angular": 4, + "atomic_gaussian_width": 0.3, + "center_atom_weight": 1.0, + "radial_basis": { + "Gto": {}, + }, + "cutoff_function": { + "ShiftedCosine": {"width": 0.5}, + }, +} + +calculator = SoapPowerSpectrum(**HYPER_PARAMETERS) + +# %% +# +# And then run the actual calculation, including gradients with respect to positions + +descriptor = calculator.compute(frames, 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("species_center") +descriptor = descriptor.keys_to_properties(["species_neighbor_1", "species_neighbor_2"]) +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..24432d7d4 --- /dev/null +++ b/latest/_downloads/b957f733884c5245e2a56cba651d0969/splined-radial-integral.py @@ -0,0 +1,184 @@ +""" +.. _example-splines: + +Splined radial integrals +======================== + +.. start-body +""" + +# %% +# +# This script illustrates how to generate splined radial basis +# functions/integrals, using a "rectangular" Laplacian eigenstate (LE, +# https://doi.org/10.1063/5.0124363) basis as the example, i.e, a LE basis +# truncated with l_max, n_max hyper-parameters. + + +import ase +import numpy as np +import scipy as sp +import scipy.optimize +from scipy.special import jv +from scipy.special import spherical_jn as j_l + +from rascaline import SphericalExpansion +from rascaline.utils import RadialIntegralFromFunction + + +# %% +# +# Set some hyper-parameters: +max_angular = 6 +max_radial = 8 +cutoff = 5.0 # This is also the radius of the LE sphere + +# %% +# +# Spherical Bessel zeros (from the scipy cookbook) + + +def Jn(r, n): + return np.sqrt(np.pi / (2 * r)) * jv(n + 0.5, r) + + +def Jn_zeros(n, nt): + zeros_j = np.zeros((n + 1, nt), dtype=np.float64) + zeros_j[0] = np.arange(1, nt + 1) * np.pi + points = np.arange(1, nt + n + 1) * np.pi + roots = np.zeros(nt + n, dtype=np.float64) + for i in range(1, n + 1): + for j in range(nt + n - i): + roots[j] = scipy.optimize.brentq(Jn, points[j], points[j + 1], (i,)) + points = roots + zeros_j[i][:nt] = roots[:nt] + return zeros_j + + +z_ln = Jn_zeros(max_angular, max_radial) +z_nl = z_ln.T + + +# %% +# +# Define the radial basis functions: + + +def R_nl(n, el, r): + # Un-normalized LE radial basis functions + return j_l(el, z_nl[n, el] * r / cutoff) + + +def N_nl(n, el): + # Normalization factor for LE basis functions, excluding the a**(-1.5) factor + def function_to_integrate_to_get_normalization_factor(x): + return j_l(el, x) ** 2 * x**2 + + integral, _ = sp.integrate.quadrature( + function_to_integrate_to_get_normalization_factor, 0.0, z_nl[n, el] + ) + return (1.0 / z_nl[n, el] ** 3 * integral) ** (-0.5) + + +def laplacian_eigenstate_basis(n, el, r): + R = np.zeros_like(r) + for i in range(r.shape[0]): + R[i] = R_nl(n, el, r[i]) + return N_nl(n, el) * R * cutoff ** (-1.5) + + +# %% +# +# Quick normalization check: +normalization_check_integral, _ = sp.integrate.quadrature( + lambda x: laplacian_eigenstate_basis(1, 1, x) ** 2 * x**2, + 0.0, + cutoff, +) +print(f"Normalization check (needs to be close to 1): {normalization_check_integral}") + + +# %% +# +# Now the derivatives (by finite differences): +def laplacian_eigenstate_basis_derivative(n, el, r): + delta = 1e-6 + all_derivatives_except_at_zero = ( + laplacian_eigenstate_basis(n, el, r[1:] + delta) + - laplacian_eigenstate_basis(n, el, r[1:] - delta) + ) / (2.0 * delta) + derivative_at_zero = ( + laplacian_eigenstate_basis(n, el, np.array([delta / 10.0])) + - laplacian_eigenstate_basis(n, el, np.array([0.0])) + ) / (delta / 10.0) + return np.concatenate([derivative_at_zero, all_derivatives_except_at_zero]) + + +# %% +# +# The radial basis functions and their derivatives can be input into a spline +# generator class. This will output the positions of the spline points, the +# values of the basis functions evaluated at the spline points, and the +# corresponding derivatives. +spliner = RadialIntegralFromFunction( + radial_integral=laplacian_eigenstate_basis, + radial_integral_derivative=laplacian_eigenstate_basis_derivative, + spline_cutoff=cutoff, + max_radial=max_radial, + max_angular=max_angular, + accuracy=1e-5, +) + +# %% +# +# The, we feed the splines to the Rust calculator: +# (IMPORTANT: "atomic_gaussian_width" will be ignored) + +hypers_spherical_expansion = { + "cutoff": cutoff, + "max_radial": max_radial, + "max_angular": max_angular, + "center_atom_weight": 0.0, + "radial_basis": spliner.compute(), + "atomic_gaussian_width": 1.0, # ignored + "cutoff_function": {"Step": {}}, +} +calculator = SphericalExpansion(**hypers_spherical_expansion) + +# %% +# +# Create dummy structures to test if the calculator outputs correct radial functions: + + +def get_dummy_structures(r_array): + dummy_structures = [] + for r in r_array: + dummy_structures.append(ase.Atoms("CH", positions=[(0, 0, 0), (0, 0, r)])) + return dummy_structures + + +r = np.linspace(0.1, 4.9, 20) +structures = get_dummy_structures(r) +spherical_expansion_coefficients = calculator.compute(structures) + +# Extract l = 0 features and check that the n = 2 predictions are the same: +block_C_l0 = spherical_expansion_coefficients.block( + species_center=6, spherical_harmonics_l=0, species_neighbor=1 +) +block_C_l0_n2 = block_C_l0.values[:, :, 2].flatten() +spherical_harmonics_0 = 1.0 / np.sqrt(4.0 * np.pi) + +# radial function = feature / spherical harmonics function +rascaline_output_radial_function = block_C_l0_n2 / spherical_harmonics_0 + +assert np.allclose( + rascaline_output_radial_function, + laplacian_eigenstate_basis(2, 0, r), + atol=1e-5, +) +print("Assertion passed successfully!") + + +# %% +# +# .. 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..15253fa4b --- /dev/null +++ b/latest/_downloads/bbdfa9e1459a8f3df5a34d118d90df12/keys-selection.py @@ -0,0 +1,136 @@ +""" +Keys Selection +============== + +.. start-body +""" + +import chemfiles +import numpy as np +from metatensor import Labels, TensorBlock, TensorMap + +from rascaline 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": 5.0, + "max_radial": 6, + "max_angular": 4, + "atomic_gaussian_width": 0.3, + "center_atom_weight": 1.0, + "radial_basis": { + "Gto": {}, + }, + "cutoff_function": { + "ShiftedCosine": {"width": 0.5}, + }, +} + +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 rascaline. Here, only blocks with +# keys ``[1,1,1]`` and ``[4,4,4]`` will be calculated. + +selection = Labels( + names=["species_center", "species_neighbor_1", "species_neighbor_2"], + 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", "n1", "n2"], values=np.array([[0, 0, 0]])), + Labels(names=["l", "n1", "n2"], 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=["species_center", "species_neighbor_1", "species_neighbor_2"], + 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=["species_center", "species_neighbor_1", "species_neighbor_2"], + 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..568d083bb Binary files /dev/null and b/latest/_downloads/bc82bea3a5dd7bdba60b65220891d9e5/examples_python.zip differ diff --git a/latest/_downloads/fb625db3c50d423b1b7881136ffdeec8/examples_jupyter.zip b/latest/_downloads/fb625db3c50d423b1b7881136ffdeec8/examples_jupyter.zip new file mode 100644 index 000000000..7fc6f027c 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..6191b4899 --- /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 rascaline 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\": 5.0,\n \"max_radial\": 6,\n \"max_angular\": 4,\n \"atomic_gaussian_width\": 0.3,\n \"center_atom_weight\": 1.0,\n \"radial_basis\": {\n \"Gto\": {},\n },\n \"cutoff_function\": {\n \"ShiftedCosine\": {\"width\": 0.5},\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 rascaline. 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=[\"species_center\", \"species_neighbor_1\", \"species_neighbor_2\"],\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\", \"n1\", \"n2\"], values=np.array([[0, 0, 0]])),\n Labels(names=[\"l\", \"n1\", \"n2\"], 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=[\"species_center\", \"species_neighbor_1\", \"species_neighbor_2\"],\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=[\"species_center\", \"species_neighbor_1\", \"species_neighbor_2\"],\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.11.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/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/rascaline-python.svg b/latest/_images/rascaline-python.svg new file mode 100644 index 000000000..629c35d52 --- /dev/null +++ b/latest/_images/rascaline-python.svg @@ -0,0 +1 @@ +librascaline.sorascaline-c-apicbindgenrascaline.hpycparserrascalinePython module_rascaline.pycallsgenerates \ No newline at end of file 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_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_thumb.png b/latest/_images/sphx_glr_splined-radial-integral_thumb.png new file mode 100644 index 000000000..8a5fed589 Binary files /dev/null and b/latest/_images/sphx_glr_splined-radial-integral_thumb.png differ diff --git a/latest/_images/sphx_glr_understanding-hypers_001.png b/latest/_images/sphx_glr_understanding-hypers_001.png new file mode 100644 index 000000000..eeab21cd4 Binary files /dev/null and b/latest/_images/sphx_glr_understanding-hypers_001.png differ diff --git a/latest/_images/sphx_glr_understanding-hypers_002.png b/latest/_images/sphx_glr_understanding-hypers_002.png new file mode 100644 index 000000000..40d6c9599 Binary files /dev/null and b/latest/_images/sphx_glr_understanding-hypers_002.png differ diff --git a/latest/_images/sphx_glr_understanding-hypers_003.png b/latest/_images/sphx_glr_understanding-hypers_003.png new file mode 100644 index 000000000..2bca7a1b3 Binary files /dev/null and b/latest/_images/sphx_glr_understanding-hypers_003.png differ diff --git a/latest/_images/sphx_glr_understanding-hypers_thumb.png b/latest/_images/sphx_glr_understanding-hypers_thumb.png new file mode 100644 index 000000000..77bab4dd8 Binary files /dev/null and b/latest/_images/sphx_glr_understanding-hypers_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..fdbe213f6 --- /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: + +- ``rascaline/`` contains the main Rust implementation of all calculators, and + the corresponding unit and regression tests; +- ``rascaline-c-api/`` is a Rust crate containing the implementation of the + rascaline C API; +- ``python/`` contains the Python interface to rascaline, and the corresponding + tests + +Finally, ``docs/`` contains the documentation for everything related to +rascaline. + +The main rascaline crate +^^^^^^^^^^^^^^^^^^^^^^^^ + +Inside the main rascaline crate, the following code organization is used: + +- ``rascaline/benches``: benchmarks of the code on some simple systems; +- ``rascaline/tests``: regression tests for all calculators; +- ``rascaline/src/system/``: definition of everything related to systems: + ``UnitCell``, the ``System`` trait and ``SimpleSystem`` implementation; +- ``rascaline/src/calculator.rs``: convenience wrapper around implementations of + ``CalculatorBase`` that setup everything before a calculation; +- ``rascaline/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..9ccd23922 --- /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 +rascaline. Technical facts and some tidbits of useful information are found here +to give you more clarity and understanding of what rascaline 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..d0d27267d --- /dev/null +++ b/latest/_sources/devdoc/explanations/interfaces.rst.txt @@ -0,0 +1,69 @@ +Python and C interface +====================== + +How is the C interface exported +------------------------------- + +Rascaline exports a C interface, defined in ``rascaline-c-api``. This C +interface is created directly in Rust, without involving any C code. + +This is done by marking functions as ``#[no_mangle] extern pub fn `` in +``rascaline-c-api``, 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. + +``rascaline-c-api`` is then compiled to a shared library (``librascaline.so`` / +``librascaline.dylib`` / ``librascaline.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 ``rascaline-c-api/rascaline.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 ``rascaline-c-api/rascaline.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/rascaline/_rascaline.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 `rascaline-c-api`. + +The schematic below describes all the relationships between the components +involved in creating the Python interface. + +.. figure:: ../../../static/images/rascaline-python.* + :width: 400px + :align: center + + Schematic representation of all components in the Python interface. The rust + crate ``rascaline-c-api`` is compiled to a shared library + (``librascaline.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..c17f5a901 --- /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-splined-radial-integral`. 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 center atom :math:`i` in + the structure, 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 ommit the +chemical species 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 center 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 rascaline, 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..b11ac3545 --- /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 species 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 species +: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 +rascaline itself. + +We will also assume that you have a local copy of the rascaline 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/rascaline/index.html + +The traits we'll use +-------------------- + +Two of the three :ref:`core concepts ` in rascaline 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/rascaline/systems/trait.System.html +.. _CalculatorBase: ../reference/rust/rascaline/calculators/trait.CalculatorBase.html +.. _Calculator: ../reference/rust/rascaline/struct.Calculator.html +.. _TensorMap: ../reference/rust/metatensor/tensor/struct.TensorMap.html + +Implementation +-------------- + +Let's start by creating a new file in ``rascaline/src/calculators/moments.rs``, +and importing everything we'll need. Everything in here will be explained when +we get to using it. + +.. literalinclude:: ../../../../rascaline/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:: ../../../../rascaline/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:: ../../../../rascaline/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:: ../../../../rascaline/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 rascaline, 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:: ../../../../rascaline/src/tutorials/moments/s2_metadata.rs + :language: rust + :start-after: [struct] + :end-before: [struct] + +.. literalinclude:: ../../../../rascaline/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:: ../../../../rascaline/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 center atom species and the +neighbor atom species as keys. This allow to only store data if a given neighbor +is actually present around a given center. + +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 species keys. Here we use +``CenterSingleNeighborsSpeciesKeys`` to create a set of keys containing the +center species and one neighbor species. 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:: ../../../../rascaline/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:: ../../../../rascaline/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:: ../../../../rascaline/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:: ../../../../rascaline/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"`` or ``"cell"``. Here we only support computing the gradients with +respect to positions. + +.. literalinclude:: ../../../../rascaline/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 ``[direction, first, +second]``, where ``direction`` contains 3 entries (x/y/z). The ``"cell"`` +gradients would use ``[direction_1, direction_2, first, second]``, with +``direction_1`` and ``direction_2`` containing 3 entries (x/y/z) each. + +Finally, the samples needs to be defined. For the ``"cell"`` 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 +structure 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:: ../../../../rascaline/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:: ../../../../rascaline/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:: ../../../../rascaline/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 species values), 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 :py:obj:`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 species +with ``system.species()`` 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:: ../../../../rascaline/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:: ../../../../rascaline/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:: ../../../../rascaline/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:: ../../../../rascaline/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}")``, rascaline 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 ``rascaline/src/calculator.rs``. The registry looks like this: + +.. literalinclude:: ../../../../rascaline/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/rascaline/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 rascaline import GeometricMoments + calculator = GeometricMoments(cutoff=3.5, max_moment=6, gradients=False) + + # instead of + from rascaline.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, rascaline 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 ``rascaline/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 ``rascaline/tests`` is associated with a Python file in +``rascaline/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 species over the total number of +neighbors. A test checking this property would look like this: + +.. literalinclude:: ../../../../rascaline/src/tutorials/moments/moments.rs + :language: rust + :start-after: [property-test] + :end-before: [property-test] + +The ``rascaline::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. +Rascaline 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:: ../../../../rascaline/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. Rascaline +provides ``calculators::tests_utils::finite_difference`` to help check this. + +.. literalinclude:: ../../../../rascaline/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..d366ab2d7 --- /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, rascaline 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:: ../../../../rascaline/examples/profiling.rs + :language: rust + + .. group-tab:: C++ + + .. literalinclude:: ../../../../rascaline-c-api/examples/profiling.cpp + :language: c++ + + .. group-tab:: C + + .. literalinclude:: ../../../../rascaline-c-api/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..7d48d384e --- /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 rascaline; +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 rascaline; + +.. 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..17a2204d4 --- /dev/null +++ b/latest/_sources/examples/compute-soap.rst.txt @@ -0,0 +1,200 @@ + +.. 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 rascaline import SoapPowerSpectrum + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 14-16 + +Read structures 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: + frames = [f for f in trajectory] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 22-28 + +Rascaline can also handles structures read by `ASE +`_ using + +``frames = ase.io.read("dataset.xyz", ":")``. + +We can now define hyper parameters for the calculation + +.. GENERATED FROM PYTHON SOURCE LINES 29-46 + +.. code-block:: Python + + + HYPER_PARAMETERS = { + "cutoff": 5.0, + "max_radial": 6, + "max_angular": 4, + "atomic_gaussian_width": 0.3, + "center_atom_weight": 1.0, + "radial_basis": { + "Gto": {}, + }, + "cutoff_function": { + "ShiftedCosine": {"width": 0.5}, + }, + } + + calculator = SoapPowerSpectrum(**HYPER_PARAMETERS) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 47-48 + +And then run the actual calculation, including gradients with respect to positions + +.. GENERATED FROM PYTHON SOURCE LINES 49-52 + +.. code-block:: Python + + + descriptor = calculator.compute(frames, gradients=["positions"]) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 53-57 + +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 58-65 + +.. code-block:: Python + + + print("before: ", len(descriptor.keys)) + + descriptor = descriptor.keys_to_samples("species_center") + descriptor = descriptor.keys_to_properties(["species_neighbor_1", "species_neighbor_2"]) + print("after: ", len(descriptor.keys)) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + before: 40 + after: 1 + + + + +.. GENERATED FROM PYTHON SOURCE LINES 66-68 + +you can now use ``descriptor.block().values`` as the input of a machine +learning algorithm + +.. GENERATED FROM PYTHON SOURCE LINES 69-73 + +.. code-block:: Python + + + print(descriptor.block().values.shape) + + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + (1380, 1800) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 74-75 + +.. 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 ` + + +.. 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..ac8df50e9 --- /dev/null +++ b/latest/_sources/examples/first-calculation.rst.txt @@ -0,0 +1,869 @@ + +.. 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 rascaline 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 rascaline 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 rascaline 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 rascaline 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-88 + +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 rascaline 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 +`_. The effect of changing some hyper +parameters is discussed in a :ref:`second tutorial +`. + +.. GENERATED FROM PYTHON SOURCE LINES 89-101 + +.. code-block:: Python + + + HYPER_PARAMETERS = { + "cutoff": 4.5, + "max_radial": 9, + "max_angular": 6, + "atomic_gaussian_width": 0.3, + "center_atom_weight": 1.0, + "radial_basis": {"Gto": {"spline_accuracy": 1e-6}}, + "cutoff_function": {"ShiftedCosine": {"width": 0.5}}, + "radial_scaling": {"Willatt2018": {"scale": 2.0, "rate": 1.0, "exponent": 4}}, + } + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 102-106 + +After we set the hyper parameters we initialize a +:class:`rascaline.calculators.SphericalExpansion` object with hyper parameters +defined above and run the +:py:func:`rascaline.calculators.CalculatorBase.compute()` method. + +.. GENERATED FROM PYTHON SOURCE LINES 107-112 + +.. code-block:: Python + + + calculator = SphericalExpansion(**HYPER_PARAMETERS) + descriptor0 = calculator.compute(frame0) + print(type(descriptor0)) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 113-120 + +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 121-125 + +.. code-block:: Python + + + + print(descriptor0) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + TensorMap with 112 blocks + keys: spherical_harmonics_l species_center species_neighbor + 0 1 1 + 1 1 1 + 2 1 1 + 3 1 1 + 4 1 1 + 5 1 1 + 6 1 1 + 0 1 6 + 1 1 6 + 2 1 6 + 3 1 6 + 4 1 6 + 5 1 6 + 6 1 6 + 0 1 7 + 1 1 7 + 2 1 7 + 3 1 7 + 4 1 7 + 5 1 7 + 6 1 7 + 0 1 8 + 1 1 8 + 2 1 8 + 3 1 8 + 4 1 8 + 5 1 8 + 6 1 8 + 0 6 1 + 1 6 1 + 2 6 1 + 3 6 1 + 4 6 1 + 5 6 1 + 6 6 1 + 0 6 6 + 1 6 6 + 2 6 6 + 3 6 6 + 4 6 6 + 5 6 6 + 6 6 6 + 0 6 7 + 1 6 7 + 2 6 7 + 3 6 7 + 4 6 7 + 5 6 7 + 6 6 7 + 0 6 8 + 1 6 8 + 2 6 8 + 3 6 8 + 4 6 8 + 5 6 8 + 6 6 8 + 0 7 1 + 1 7 1 + 2 7 1 + 3 7 1 + 4 7 1 + 5 7 1 + 6 7 1 + 0 7 6 + 1 7 6 + 2 7 6 + 3 7 6 + 4 7 6 + 5 7 6 + 6 7 6 + 0 7 7 + 1 7 7 + 2 7 7 + 3 7 7 + 4 7 7 + 5 7 7 + 6 7 7 + 0 7 8 + 1 7 8 + 2 7 8 + 3 7 8 + 4 7 8 + 5 7 8 + 6 7 8 + 0 8 1 + 1 8 1 + 2 8 1 + 3 8 1 + 4 8 1 + 5 8 1 + 6 8 1 + 0 8 6 + 1 8 6 + 2 8 6 + 3 8 6 + 4 8 6 + 5 8 6 + 6 8 6 + 0 8 7 + 1 8 7 + 2 8 7 + 3 8 7 + 4 8 7 + 5 8 7 + 6 8 7 + 0 8 8 + 1 8 8 + 2 8 8 + 3 8 8 + 4 8 8 + 5 8 8 + 6 8 8 + + + + +.. GENERATED FROM PYTHON SOURCE LINES 126-139 + +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 ``spherical_harmonics_l``, the central atom +species ``species_center`` and neighbor atom species labeled by +``species_neighbor``. Different atomic species 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 species 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 140-145 + +.. code-block:: Python + + + block = descriptor0.block(1) + print(descriptor0.keys[1]) + + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + LabelsEntry(spherical_harmonics_l=1, species_center=1, species_neighbor=1) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 146-153 + +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 154-158 + +.. code-block:: Python + + + + print(block.values.shape) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + (8, 3, 9) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 159-168 + +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 169-172 + +.. code-block:: Python + + + print(block.samples) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Labels( + structure center + 0 12 + 0 13 + ... + 0 18 + 0 19 + ) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 173-175 + +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 176-179 + +.. code-block:: Python + + + print(block.samples.names) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + ['structure', 'center'] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 180-186 + +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 187-190 + +.. code-block:: Python + + + print(block.components) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [Labels( + spherical_harmonics_m + -1 + 0 + 1 + )] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 191-202 + +Here, the components are associated with the angular channels of the +representation. The size of ``spherical_harmonics_m`` is :math:`2l + 1`, where +:math:`l` is the current ``spherical_harmonics_l`` of the block. Here, its +dimension is three because we are looking at the ``spherical_harmonics_l=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 203-206 + +.. 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 207-208 + +containing a tuple of only one value ranging from 0 to 8. The name of this entry is + +.. GENERATED FROM PYTHON SOURCE LINES 209-212 + +.. code-block:: Python + + + print(block.properties.names) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + ['n'] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 213-218 + +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 219-222 + +.. code-block:: Python + + + print(block.values[0, 0, :]) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [-0.00102818 0.00860425 -0.02339817 -0.11691264 -0.04411467 -0.02857226 + -0.02109534 -0.00712789 -0.00230597] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 223-230 + +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. + +Rascaline 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 231-237 + +.. 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 238-255 + +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:`rascaline.calculators.SphericalExpansion` shown here check out the +:ref:`userdoc-references` section. + +Computing gradients +------------------- + +Additionally, rascaline 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:`rascaline.calculators.CalculatorBase.compute()` method to +``["positions"]``. + +.. GENERATED FROM PYTHON SOURCE LINES 256-264 + +.. 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 265-281 + +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 rascaline 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 282-285 + +.. code-block:: Python + + + print(gradient_position.samples) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Labels( + sample structure atom + 0 0 12 + 0 0 13 + ... + 7 0 18 + 7 0 19 + ) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 286-287 + +Note that we have a tuple of three with the names + +.. GENERATED FROM PYTHON SOURCE LINES 288-291 + +.. code-block:: Python + + + print(gradient_position.samples.names) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + ['sample', 'structure', 'atom'] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 292-296 + +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 297-300 + +.. code-block:: Python + + + print(gradient_position.components) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [Labels( + direction + 0 + 1 + 2 + ), Labels( + spherical_harmonics_m + 0 + )] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 301-307 + +we find two of them. Besides the `spherical_harmonics_m` 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 308-311 + +.. 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 312-320 + +Rascaline can also calculate gradients with respect to the cell. For this, you +have to add ``"cell"`` to the list parsed to the ``gradients`` parameter of +the :py:func:`rascaline.calculators.CalculatorBase.compute()` method. Cell +gradients 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 ` + + +.. 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..777802733 --- /dev/null +++ b/latest/_sources/examples/index.rst.txt @@ -0,0 +1,187 @@ +:orphan: + +Rascaline Python Examples +========================= + +This folder consists of introductory examples and examples demonstrating +specific features of rascaline using its Python API. + + + +.. raw:: html + +
+ + +.. 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_understanding-hypers_thumb.png + :alt: + + :ref:`sphx_glr_examples_understanding-hypers.py` + +.. raw:: html + +
Changing SOAP hyper parameters
+
+ + +.. 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/understanding-hypers + + +.. 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..5d3fb4d52 --- /dev/null +++ b/latest/_sources/examples/keys-selection.rst.txt @@ -0,0 +1,346 @@ + +.. 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 rascaline 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-42 + +.. code-block:: Python + + + HYPER_PARAMETERS = { + "cutoff": 5.0, + "max_radial": 6, + "max_angular": 4, + "atomic_gaussian_width": 0.3, + "center_atom_weight": 1.0, + "radial_basis": { + "Gto": {}, + }, + "cutoff_function": { + "ShiftedCosine": {"width": 0.5}, + }, + } + + calculator = SoapPowerSpectrum(**HYPER_PARAMETERS) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 43-45 + +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 46-50 + +.. code-block:: Python + + + descriptor = calculator.compute(frames) + print("keys names:", descriptor.keys.names) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + keys names: ['species_center', 'species_neighbor_1', 'species_neighbor_2'] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 51-54 + +We can use these names to define a selection, and only blocks matching the +labels in this selection will be used by rascaline. Here, only blocks with +keys ``[1,1,1]`` and ``[4,4,4]`` will be calculated. + +.. GENERATED FROM PYTHON SOURCE LINES 55-62 + +.. code-block:: Python + + + selection = Labels( + names=["species_center", "species_neighbor_1", "species_neighbor_2"], + 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 63-64 + +We get a TensorMap with 2 blocks, corresponding to the requested keys + +.. GENERATED FROM PYTHON SOURCE LINES 65-68 + +.. code-block:: Python + + + print(selected_descriptor.keys) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Labels( + species_center species_neighbor_1 species_neighbor_2 + 1 1 1 + 4 4 4 + ) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 69-71 + +The block for ``[1, 1, 1]`` will be exactly the same as the one in the full +``TensorMap`` + +.. GENERATED FROM PYTHON SOURCE LINES 72-75 + +.. 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 76-78 + +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 79-82 + +.. code-block:: Python + + + print(selected_descriptor.block(1).values.shape) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + (0, 180) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 83-86 + +``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 87-110 + +.. code-block:: Python + + + selection = [ + Labels(names=["l", "n1", "n2"], values=np.array([[0, 0, 0]])), + Labels(names=["l", "n1", "n2"], 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=["species_center", "species_neighbor_1", "species_neighbor_2"], + values=np.array([[1, 1, 1], [8, 8, 8]], dtype=np.int32), + ) + + selected_properties = TensorMap(keys, blocks) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 111-113 + +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 114-126 + +.. code-block:: Python + + + selected_keys = Labels( + names=["species_center", "species_neighbor_1", "species_neighbor_2"], + 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 127-129 + +As expected, we get 1 block with values of the form (420, 1), i.e. with only 1 +property. + +.. GENERATED FROM PYTHON SOURCE LINES 130-134 + +.. 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( + species_center species_neighbor_1 species_neighbor_2 + 1 1 1 + ) + (420, 1) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 135-136 + +.. 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 ` + + +.. 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..9e4b3b155 --- /dev/null +++ b/latest/_sources/examples/profiling.rst.txt @@ -0,0 +1,184 @@ + +.. 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 rascaline + from rascaline 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": 5.0, + "max_radial": 6, + "max_angular": 4, + "atomic_gaussian_width": 0.3, + "center_atom_weight": 1.0, + "radial_basis": { + "Gto": {}, + }, + "cutoff_function": { + "ShiftedCosine": {"width": 0.5}, + }, + } + + calculator = SoapPowerSpectrum(**HYPER_PARAMETERS) + descriptor = calculator.compute(frames, gradients=["positions"]) + descriptor = descriptor.keys_to_samples("species_center") + descriptor = descriptor.keys_to_properties( + ["species_neighbor_1", "species_neighbor_2"] + ) + + 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 rascaline.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 ║ — ║ 430.38ms ║ 430.38ms ║ + ╠════╬══════════════════════════════════════════════╬════════════╬═══════════╬══════════╬═════════════╣ + ║ 5 ║ SphericalExpansion::compute ║ 1 ║ 4 ║ 211.59ms ║ 211.59ms ║ + ╠════╬══════════════════════════════════════════════╬════════════╬═══════════╬══════════╬═════════════╣ + ║ 1 ║ SoapRadialIntegralSpline::with_accuracy ║ 6 ║ 5 ║ 52.40ms ║ 8.73ms ║ + ╠════╬══════════════════════════════════════════════╬════════════╬═══════════╬══════════╬═════════════╣ + ║ 0 ║ GtoRadialIntegral::compute ║ 3846 ║ 1 ║ 49.08ms ║ 12.76µs ║ + ╠════╬══════════════════════════════════════════════╬════════════╬═══════════╬══════════╬═════════════╣ + ║ 3 ║ Calculator::prepare ║ 2 ║ 4 ║ 69.54ms ║ 34.77ms ║ + ╠════╬══════════════════════════════════════════════╬════════════╬═══════════╬══════════╬═════════════╣ + ║ 2 ║ NeighborsList ║ 40 ║ 3 ║ 10.44ms ║ 261.09µs ║ + ╠════╬══════════════════════════════════════════════╬════════════╬═══════════╬══════════╬═════════════╣ + ║ 6 ║ SplinedRadialIntegral::compute ║ 35351 ║ 5 ║ 19.62ms ║ 554.00ns ⚠️ ║ + ╠════╬══════════════════════════════════════════════╬════════════╬═══════════╬══════════╬═════════════╣ + ║ 7 ║ SphericalHarmonics::compute ║ 35351 ║ 5 ║ 20.93ms ║ 592.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":{"rascaline::calculators::soap::radial_integral::gto::GtoRadialIntegral::compute":{"id":0,"elapsed":"49.084843ms","called":3846},"rascaline::calculators::soap::radial_integral::spline::SoapRadialIntegralSpline::with_accuracy":{"id":1,"elapsed":"52.398961ms","called":6},"rascaline::systems::neighbors::NeighborsList":{"id":2,"elapsed":"10.443493ms","called":40},"rascaline::calculator::Calculator::prepare":{"id":3,"elapsed":"69.535074ms","called":2},"rascaline::calculators::soap::power_spectrum::SoapPowerSpectrum::compute":{"id":4,"elapsed":"430.382563ms","called":1},"rascaline::calculators::soap::spherical_expansion::SphericalExpansion::compute":{"id":5,"elapsed":"211.590445ms","called":1},"rascaline::calculators::soap::radial_integral::spline::SplinedRadialIntegral::compute":{"id":6,"elapsed":"19.615698ms","called":35351},"rascaline::math::spherical_harmonics::SphericalHarmonics::compute":{"id":7,"elapsed":"20.9287ms","called":35351}},"calls":[{"caller":0,"callee":1,"count":3846},{"caller":2,"callee":3,"count":40},{"caller":3,"callee":4,"count":1},{"caller":1,"callee":5,"count":1},{"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 ` + + +.. 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..06679d0fd --- /dev/null +++ b/latest/_sources/examples/property-selection.rst.txt @@ -0,0 +1,376 @@ + +.. 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 rascaline 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-45 + +.. code-block:: Python + + + HYPER_PARAMETERS = { + "cutoff": 5.0, + "max_radial": 6, + "max_angular": 4, + "atomic_gaussian_width": 0.3, + "center_atom_weight": 1.0, + "radial_basis": { + "Gto": {}, + }, + "cutoff_function": { + "ShiftedCosine": {"width": 0.5}, + }, + } + + calculator = SoapPowerSpectrum(**HYPER_PARAMETERS) + + descriptor = calculator.compute(frames) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 46-49 + +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 50-53 + +.. code-block:: Python + + + print("property names:", descriptor.property_names) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + property names: ['l', 'n1', 'n2'] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 54-57 + +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 rascaline +(here, only properties with ``l = 0`` will be used) + +.. GENERATED FROM PYTHON SOURCE LINES 58-72 + +.. 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("species_center") + selected_descriptor = selected_descriptor.keys_to_properties( + ["species_neighbor_1", "species_neighbor_2"] + ) + + properties = selected_descriptor.block().properties + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 73-74 + +We expect to get `[0]` as the list of `l` properties + +.. GENERATED FROM PYTHON SOURCE LINES 75-78 + +.. 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 79-82 + +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 83-89 + +.. 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 90-93 + +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 94-101 + +.. 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, 180) + shape of first block of reference: (420, 36) + shape of first block after selection: (420, 36) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 102-108 + +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 109-140 + +.. 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 rascaline 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 141-143 + +We can then apply this function to subselect according to the data contained +in a descriptor + +.. GENERATED FROM PYTHON SOURCE LINES 144-147 + +.. code-block:: Python + + + selection = fps_feature_selection(descriptor, n_to_select=10) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 148-150 + +and use the selection with rascaline, potentially running the calculation on a +different set of systems + +.. GENERATED FROM PYTHON SOURCE LINES 151-154 + +.. code-block:: Python + + + selected_descriptor = calculator.compute(frames, selected_properties=selection) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 155-157 + +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 158-164 + +.. code-block:: Python + + + try: + selected_descriptor.keys_to_samples("species_center") + 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 165-166 + +.. 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 ` + + +.. 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..c02af7482 --- /dev/null +++ b/latest/_sources/examples/sample-selection.rst.txt @@ -0,0 +1,344 @@ + +.. 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 rascaline 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": 5.0, + "max_radial": 6, + "max_angular": 4, + "atomic_gaussian_width": 0.3, + "center_atom_weight": 1.0, + "radial_basis": { + "Gto": {}, + }, + "cutoff_function": { + "ShiftedCosine": {"width": 0.5}, + }, + } + + calculator = SoapPowerSpectrum(**HYPER_PARAMETERS) + + descriptor = calculator.compute(frames) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 45-48 + +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 49-52 + +.. code-block:: Python + + + print("sample names:", descriptor.sample_names) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + sample names: ['structure', 'center'] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 53-56 + +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 rascaline (here, +only atoms from structures 0, 2, and 3) + +.. GENERATED FROM PYTHON SOURCE LINES 57-72 + +.. code-block:: Python + + + selection = Labels( + names=["structure"], + values=np.array([[0], [2], [3]]), + ) + + descriptor_selected = calculator.compute(frames, selected_samples=selection) + + descriptor_selected = descriptor_selected.keys_to_samples("species_center") + descriptor_selected = descriptor_selected.keys_to_properties( + ["species_neighbor_1", "species_neighbor_2"] + ) + + samples = descriptor_selected.block().samples + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 73-74 + +The first block should have ``[0, 2, 3]`` as ``samples["structure"]`` + +.. GENERATED FROM PYTHON SOURCE LINES 75-78 + +.. code-block:: Python + + + print(f"we have the following structures: {np.unique(samples['structure'])}") + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + we have the following structures: [0 2 3] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 79-82 + +If we want to select not only based on the structure indexes but also atomic +indexes, we can do the following (here we select atom 0 in the first structure +and atom 1 in the third structure): + +.. GENERATED FROM PYTHON SOURCE LINES 83-95 + +.. code-block:: Python + + + selection = Labels( + names=["structure", "center"], + values=np.array([[0, 0], [2, 1]]), + ) + + descriptor_selected = calculator.compute(frames, selected_samples=selection) + descriptor_selected = descriptor_selected.keys_to_samples("species_center") + descriptor_selected = descriptor_selected.keys_to_properties( + ["species_neighbor_1", "species_neighbor_2"] + ) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 96-97 + +The values will have 2 rows, since we have two samples: + +.. GENERATED FROM PYTHON SOURCE LINES 98-104 + +.. 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, 1800) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 105-108 + +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 109-113 + +.. code-block:: Python + + + descriptor = calculator.compute(frames) + descriptor_selected = calculator.compute(frames, selected_samples=selection) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 114-115 + +notice how we are passing a TensorMap as the ``selected_samples`` argument: + +.. GENERATED FROM PYTHON SOURCE LINES 116-122 + +.. 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 123-126 + +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 127-138 + +.. 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, 180) + shape of first block of reference: (0, 180) + shape of first block after selection: (0, 180) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 139-140 + +.. 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 ` + + +.. 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..b66dd5a1b --- /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:05.557** 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_compute-soap.py` (``compute-soap.py``) + - 00:01.888 + - 0.0 + * - :ref:`sphx_glr_examples_splined-radial-integral.py` (``splined-radial-integral.py``) + - 00:00.946 + - 0.0 + * - :ref:`sphx_glr_examples_profiling.py` (``profiling.py``) + - 00:00.877 + - 0.0 + * - :ref:`sphx_glr_examples_property-selection.py` (``property-selection.py``) + - 00:00.755 + - 0.0 + * - :ref:`sphx_glr_examples_understanding-hypers.py` (``understanding-hypers.py``) + - 00:00.515 + - 0.0 + * - :ref:`sphx_glr_examples_sample-selection.py` (``sample-selection.py``) + - 00:00.322 + - 0.0 + * - :ref:`sphx_glr_examples_keys-selection.py` (``keys-selection.py``) + - 00:00.169 + - 0.0 + * - :ref:`sphx_glr_examples_first-calculation.py` (``first-calculation.py``) + - 00:00.086 + - 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..e6fff596d --- /dev/null +++ b/latest/_sources/examples/splined-radial-integral.rst.txt @@ -0,0 +1,348 @@ + +.. 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: + + +.. _example-splines: + +Splined radial integrals +======================== + +.. start-body + +.. GENERATED FROM PYTHON SOURCE LINES 11-15 + +This script illustrates how to generate splined radial basis +functions/integrals, using a "rectangular" Laplacian eigenstate (LE, +https://doi.org/10.1063/5.0124363) basis as the example, i.e, a LE basis +truncated with l_max, n_max hyper-parameters. + +.. GENERATED FROM PYTHON SOURCE LINES 16-29 + +.. code-block:: Python + + + + import ase + import numpy as np + import scipy as sp + import scipy.optimize + from scipy.special import jv + from scipy.special import spherical_jn as j_l + + from rascaline import SphericalExpansion + from rascaline.utils import RadialIntegralFromFunction + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 30-31 + +Set some hyper-parameters: + +.. GENERATED FROM PYTHON SOURCE LINES 32-36 + +.. code-block:: Python + + max_angular = 6 + max_radial = 8 + cutoff = 5.0 # This is also the radius of the LE sphere + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 37-38 + +Spherical Bessel zeros (from the scipy cookbook) + +.. GENERATED FROM PYTHON SOURCE LINES 39-62 + +.. code-block:: Python + + + + def Jn(r, n): + return np.sqrt(np.pi / (2 * r)) * jv(n + 0.5, r) + + + def Jn_zeros(n, nt): + zeros_j = np.zeros((n + 1, nt), dtype=np.float64) + zeros_j[0] = np.arange(1, nt + 1) * np.pi + points = np.arange(1, nt + n + 1) * np.pi + roots = np.zeros(nt + n, dtype=np.float64) + for i in range(1, n + 1): + for j in range(nt + n - i): + roots[j] = scipy.optimize.brentq(Jn, points[j], points[j + 1], (i,)) + points = roots + zeros_j[i][:nt] = roots[:nt] + return zeros_j + + + z_ln = Jn_zeros(max_angular, max_radial) + z_nl = z_ln.T + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 63-64 + +Define the radial basis functions: + +.. GENERATED FROM PYTHON SOURCE LINES 65-90 + +.. code-block:: Python + + + + def R_nl(n, el, r): + # Un-normalized LE radial basis functions + return j_l(el, z_nl[n, el] * r / cutoff) + + + def N_nl(n, el): + # Normalization factor for LE basis functions, excluding the a**(-1.5) factor + def function_to_integrate_to_get_normalization_factor(x): + return j_l(el, x) ** 2 * x**2 + + integral, _ = sp.integrate.quadrature( + function_to_integrate_to_get_normalization_factor, 0.0, z_nl[n, el] + ) + return (1.0 / z_nl[n, el] ** 3 * integral) ** (-0.5) + + + def laplacian_eigenstate_basis(n, el, r): + R = np.zeros_like(r) + for i in range(r.shape[0]): + R[i] = R_nl(n, el, r[i]) + return N_nl(n, el) * R * cutoff ** (-1.5) + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 91-92 + +Quick normalization check: + +.. GENERATED FROM PYTHON SOURCE LINES 93-101 + +.. code-block:: Python + + normalization_check_integral, _ = sp.integrate.quadrature( + lambda x: laplacian_eigenstate_basis(1, 1, x) ** 2 * x**2, + 0.0, + cutoff, + ) + print(f"Normalization check (needs to be close to 1): {normalization_check_integral}") + + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + /home/runner/work/rascaline/rascaline/python/rascaline/examples/splined-radial-integral.py:93: DeprecationWarning: `scipy.integrate.quadrature` is deprecated as of SciPy 1.12.0and will be removed in SciPy 1.15.0. Please use`scipy.integrate.quad` instead. + normalization_check_integral, _ = sp.integrate.quadrature( + /home/runner/work/rascaline/rascaline/python/rascaline/examples/splined-radial-integral.py:77: DeprecationWarning: `scipy.integrate.quadrature` is deprecated as of SciPy 1.12.0and will be removed in SciPy 1.15.0. Please use`scipy.integrate.quad` instead. + integral, _ = sp.integrate.quadrature( + Normalization check (needs to be close to 1): 0.9999999999999999 + + + + +.. GENERATED FROM PYTHON SOURCE LINES 102-103 + +Now the derivatives (by finite differences): + +.. GENERATED FROM PYTHON SOURCE LINES 104-117 + +.. code-block:: Python + + def laplacian_eigenstate_basis_derivative(n, el, r): + delta = 1e-6 + all_derivatives_except_at_zero = ( + laplacian_eigenstate_basis(n, el, r[1:] + delta) + - laplacian_eigenstate_basis(n, el, r[1:] - delta) + ) / (2.0 * delta) + derivative_at_zero = ( + laplacian_eigenstate_basis(n, el, np.array([delta / 10.0])) + - laplacian_eigenstate_basis(n, el, np.array([0.0])) + ) / (delta / 10.0) + return np.concatenate([derivative_at_zero, all_derivatives_except_at_zero]) + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 118-122 + +The radial basis functions and their derivatives can be input into a spline +generator class. This will output the positions of the spline points, the +values of the basis functions evaluated at the spline points, and the +corresponding derivatives. + +.. GENERATED FROM PYTHON SOURCE LINES 123-132 + +.. code-block:: Python + + spliner = RadialIntegralFromFunction( + radial_integral=laplacian_eigenstate_basis, + radial_integral_derivative=laplacian_eigenstate_basis_derivative, + spline_cutoff=cutoff, + max_radial=max_radial, + max_angular=max_angular, + accuracy=1e-5, + ) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 133-135 + +The, we feed the splines to the Rust calculator: +(IMPORTANT: "atomic_gaussian_width" will be ignored) + +.. GENERATED FROM PYTHON SOURCE LINES 136-148 + +.. code-block:: Python + + + hypers_spherical_expansion = { + "cutoff": cutoff, + "max_radial": max_radial, + "max_angular": max_angular, + "center_atom_weight": 0.0, + "radial_basis": spliner.compute(), + "atomic_gaussian_width": 1.0, # ignored + "cutoff_function": {"Step": {}}, + } + calculator = SphericalExpansion(**hypers_spherical_expansion) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 149-150 + +Create dummy structures to test if the calculator outputs correct radial functions: + +.. GENERATED FROM PYTHON SOURCE LINES 151-182 + +.. code-block:: Python + + + + def get_dummy_structures(r_array): + dummy_structures = [] + for r in r_array: + dummy_structures.append(ase.Atoms("CH", positions=[(0, 0, 0), (0, 0, r)])) + return dummy_structures + + + r = np.linspace(0.1, 4.9, 20) + structures = get_dummy_structures(r) + spherical_expansion_coefficients = calculator.compute(structures) + + # Extract l = 0 features and check that the n = 2 predictions are the same: + block_C_l0 = spherical_expansion_coefficients.block( + species_center=6, spherical_harmonics_l=0, species_neighbor=1 + ) + block_C_l0_n2 = block_C_l0.values[:, :, 2].flatten() + spherical_harmonics_0 = 1.0 / np.sqrt(4.0 * np.pi) + + # radial function = feature / spherical harmonics function + rascaline_output_radial_function = block_C_l0_n2 / spherical_harmonics_0 + + assert np.allclose( + rascaline_output_radial_function, + laplacian_eigenstate_basis(2, 0, r), + atol=1e-5, + ) + print("Assertion passed successfully!") + + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Assertion passed successfully! + + + + +.. GENERATED FROM PYTHON SOURCE LINES 183-184 + +.. 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 ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/latest/_sources/examples/understanding-hypers.rst.txt b/latest/_sources/examples/understanding-hypers.rst.txt new file mode 100644 index 000000000..b70693ed2 --- /dev/null +++ b/latest/_sources/examples/understanding-hypers.rst.txt @@ -0,0 +1,673 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples/understanding-hypers.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_understanding-hypers.py: + + +.. _userdoc-tutorials-understanding-hypers: + +Changing SOAP hyper parameters +============================== + +In the first :ref:`tutorial ` we show how to +calculate a descriptor using default hyper parameters. Here we will look at how the +change of some hyper parameters affects the values of the descriptor. The +definition of every hyper parameter is given in the :ref:`userdoc-calculators` and +background on the mathematical foundation of the spherical expansion is given in +the :ref:`userdoc-explanations` section. + +.. GENERATED FROM PYTHON SOURCE LINES 16-19 + +We use the same molecular crystals dataset as in the first +:ref:`tutorial ` which can downloaded from our +:download:`website <../../static/dataset.xyz>`. + +.. GENERATED FROM PYTHON SOURCE LINES 20-38 + +.. code-block:: Python + + + # We first import the crucial packages, load the dataset using chemfiles and + # save the first frame in a variable. + + import time + + import chemfiles + import matplotlib.pyplot as plt + import numpy as np + + from rascaline import SphericalExpansion + + + with chemfiles.Trajectory("dataset.xyz") as trajectory: + frames = [frame for frame in trajectory] + + frame0 = frames[0] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 39-47 + +Increasing ``max_radial`` and ``max_angular`` +--------------------------------------------- + +As mentioned above changing ``max_radial`` has an effect on the accuracy of +the descriptor and on the computation time. We now will increase the number of +radial channels and angular channels. Note, that here we directly pass the +parameters into the ``SphericalExpansion`` class without defining a +``HYPERPARAMETERS`` dictionary like we did in the previous tutorial. + +.. GENERATED FROM PYTHON SOURCE LINES 48-62 + +.. code-block:: Python + + + calculator_ext = SphericalExpansion( + cutoff=4.5, + max_radial=12, + max_angular=8, + atomic_gaussian_width=0.3, + center_atom_weight=1.0, + radial_basis={"Gto": {"spline_accuracy": 1e-6}}, + cutoff_function={"ShiftedCosine": {"width": 0.5}}, + radial_scaling={"Willatt2018": {"scale": 2.0, "rate": 1.0, "exponent": 4}}, + ) + + descriptor_ext = calculator_ext.compute(frame0) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 63-65 + +Compared to our previous set of hypers we now have 144 blocks instead of 112 +because we increased the number of angular channels. + +.. GENERATED FROM PYTHON SOURCE LINES 66-69 + +.. code-block:: Python + + + print(len(descriptor_ext.blocks())) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + 144 + + + + +.. GENERATED FROM PYTHON SOURCE LINES 70-72 + +The increase of the radial channels to 12 is reflected in the shape of the 0th +block values. + +.. GENERATED FROM PYTHON SOURCE LINES 73-76 + +.. code-block:: Python + + + print(descriptor_ext.block(0).values.shape) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + (8, 1, 12) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 77-82 + +Note that the increased number of radial and angular channels can increase the +accuracy of your representation but will increase the computational time +transforming the coordinates into a descriptor. A very simple time measurement +of the computation shows that the extended calculator takes more time for +the computation compared to a calculation using the default hyper parameters + +.. GENERATED FROM PYTHON SOURCE LINES 83-104 + +.. code-block:: Python + + + start_time = time.time() + calculator_ext.compute(frames) + print(f"Extended hypers took {time.time() - start_time:.2f} s.") + + # using smaller max_radial and max_angular, everything else stays the same + calculator_small = SphericalExpansion( + cutoff=4.5, + max_radial=9, + max_angular=6, + atomic_gaussian_width=0.3, + center_atom_weight=1.0, + radial_basis={"Gto": {"spline_accuracy": 1e-6}}, + cutoff_function={"ShiftedCosine": {"width": 0.5}}, + radial_scaling={"Willatt2018": {"scale": 2.0, "rate": 1.0, "exponent": 4}}, + ) + + start_time = time.time() + calculator_small.compute(frames) + print(f"Smaller hypers took {time.time() - start_time:.2f} s.") + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Extended hypers took 0.08 s. + Smaller hypers took 0.06 s. + + + + +.. GENERATED FROM PYTHON SOURCE LINES 105-112 + +Reducing the ``cutoff`` and the ``center_atom_weight`` +------------------------------------------------------ + +The cutoff controls how many neighboring atoms are taken into account for a +descriptor. By decreasing the cutoff from 6 Å to 0.1 Å fewer and fewer atoms +contribute to the descriptor which can be seen by the reduced range of the +features. + +.. GENERATED FROM PYTHON SOURCE LINES 113-130 + +.. code-block:: Python + + + for cutoff in [6.0, 4.5, 3.0, 1.0, 0.1]: + calculator_cutoff = SphericalExpansion( + cutoff=cutoff, + max_radial=6, + max_angular=6, + atomic_gaussian_width=0.3, + center_atom_weight=1.0, + radial_basis={"Gto": {"spline_accuracy": 1e-6}}, + cutoff_function={"ShiftedCosine": {"width": 0.5}}, + radial_scaling={"Willatt2018": {"scale": 2.0, "rate": 1.0, "exponent": 4}}, + ) + + descriptor = calculator_cutoff.compute(frame0) + + print(f"Descriptor for cutoff={cutoff} Å: {descriptor.block(0).values[0]}") + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Descriptor for cutoff=6.0 Å: [[ 0.73192917 -0.29309883 0.20095543 -0.01661829 0.10133933 -0.00659141]] + Descriptor for cutoff=4.5 Å: [[ 0.88696541 -0.27211242 0.12400786 0.03004326 0.13265605 0.00631962]] + Descriptor for cutoff=3.0 Å: [[ 0.99735843 0.02421642 -0.01582201 0.07692315 0.0739584 0.02262702]] + Descriptor for cutoff=1.0 Å: [[0.47066472 0.51914099 0.60560181 0.34760844 0.14044963 0.03946593]] + Descriptor for cutoff=0.1 Å: [[0.00157192 0.00240957 0.00345497 0.00925635 0.00025653 0.02589691]] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 131-139 + +For a ``cutoff`` of 0.1 Å there is no neighboring atom within the cutoff and +one could expect all features to be 0. This is not the case because the +central atom also contributes to the descriptor. We can vary this contribution +using the ``center_atom_weight`` parameter so that the descriptor finally is 0 +everywhere. + +..Add a sophisticated and referenced note on how the ``center_atom_weight`` +could affect ML models. + +.. GENERATED FROM PYTHON SOURCE LINES 140-160 + +.. code-block:: Python + + + for center_weight in [1.0, 0.5, 0.0]: + calculator_cutoff = SphericalExpansion( + cutoff=0.1, + max_radial=6, + max_angular=6, + atomic_gaussian_width=0.3, + center_atom_weight=center_weight, + radial_basis={"Gto": {"spline_accuracy": 1e-6}}, + cutoff_function={"ShiftedCosine": {"width": 0.5}}, + radial_scaling={"Willatt2018": {"scale": 2.0, "rate": 1.0, "exponent": 4}}, + ) + + descriptor = calculator_cutoff.compute(frame0) + + print( + f"Descriptor for center_weight={center_weight}: " + f"{descriptor.block(0).values[0]}" + ) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Descriptor for center_weight=1.0: [[0.00157192 0.00240957 0.00345497 0.00925635 0.00025653 0.02589691]] + Descriptor for center_weight=0.5: [[0.00078596 0.00120479 0.00172749 0.00462817 0.00012826 0.01294846]] + Descriptor for center_weight=0.0: [[0. 0. 0. 0. 0. 0.]] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 161-186 + +Choosing the ``cutoff_function`` +-------------------------------- + +In a naive descriptor approach all atoms within the cutoff are taken in into +account equally and atoms without the cutoff are ignored. This behavior is +implemented using the ``cutoff_function={"Step": {}}`` parameter in each +calculator. However, doing so means that small movements of an atom near the +cutoff result in large changes in the descriptor: there is a discontinuity in +the representation as atoms enter or leave the cutoff. A solution is to use +some smoothing function to get rid of this discontinuity, such as a shifted +cosine function: + +.. math:: + + f(r) = \begin{cases} + 1 &r < r_c - w,\\ + 0.5 + 0.5 \cos[\pi (r - r_c + w) / w] &r_c - w < r <= r_c, \\ + 0 &r_c < r, + \end{cases} + +where :math:`r_\mathrm{c}` is the cutoff distance and :math:`w` the width. +Such smoothing function is used as a multiplicative weight for the +contribution to the representation coming from each neighbor one by one + +The following functions compute such a shifted cosine weighting. + +.. GENERATED FROM PYTHON SOURCE LINES 187-215 + +.. code-block:: Python + + + + def shifted_cosine(r, cutoff, width): + """A shifted cosine switching function. + + Parameters + ---------- + r : float + distance between neighboring atoms in Å + cutoff : float + cutoff distance in Å + width : float + width of the switching in Å + + Returns + ------- + float + weighting of the features + """ + if r <= (cutoff - width): + return 1.0 + elif r >= cutoff: + return 0.0 + else: + s = np.pi * (r - cutoff + width) / width + return 0.5 * (1.0 + np.cos(s)) + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 216-217 + +Let us plot the weighting for different widths. + +.. GENERATED FROM PYTHON SOURCE LINES 218-232 + +.. code-block:: Python + + + r = np.linspace(1e-3, 4.5, num=100) + + plt.plot([0, 4.5, 4.5, 5.0], [1, 1, 0, 0], c="k", label=r"Step function") + + for width in [4.5, 2.5, 1.0, 0.5, 0.1]: + weighting_values = [shifted_cosine(r=r_i, cutoff=4.5, width=width) for r_i in r] + plt.plot(r, weighting_values, label=f"Shifted cosine: $width={width}\\,Å$") + + plt.legend() + plt.xlabel(r"distance $r$ from the central atom in $Å$") + plt.ylabel("feature weighting") + plt.show() + + + + +.. image-sg:: /examples/images/sphx_glr_understanding-hypers_001.png + :alt: understanding hypers + :srcset: /examples/images/sphx_glr_understanding-hypers_001.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 233-236 + +From the plot we conclude that a larger ``width`` of the shifted cosine +function will decrease the feature values already for smaller distances ``r`` +from the central atom. + +.. GENERATED FROM PYTHON SOURCE LINES 239-263 + +Choosing the ``radial_scaling`` +------------------------------- + +As mentioned above all atoms within the cutoff are taken equally for a +descriptor. This might limit the accuracy of a model, so it is sometimes +useful to weigh neighbors that further away from the central atom less than +neighbors closer to the central atom. This can be achieved by a +``radial_scaling`` function with a long-range algebraic decay and smooth +behavior at :math:`r \rightarrow 0`. The ``'Willatt2018'`` radial scaling +available in rascaline corresponds to the function introduced in this +`publication `_: + +.. math:: + + u(r) = \begin{cases} + 1 / (r/r_0)^m & \text{if c=0,} \\ + 1 & \text{if m=0,} \\ + c / (c+(r/r_0)^m) & \text{else}, + \end{cases} + +where :math:`c` is the ``rate``, :math:`r_0` is the ``scale`` parameter and +:math:`m` the ``exponent`` of the RadialScaling function. + +The following functions compute such a radial scaling. + +.. GENERATED FROM PYTHON SOURCE LINES 264-293 + +.. code-block:: Python + + + + def radial_scaling(r, rate, scale, exponent): + """Radial scaling function. + + Parameters + ---------- + r : float + distance between neighboring atoms in Å + rate : float + decay rate of the scaling + scale : float + scaling of the distance between atoms in Å + exponent : float + exponent of the decay + + Returns + ------- + float + weighting of the features + """ + if rate == 0: + return 1 / (r / scale) ** exponent + if exponent == 0: + return 1 + else: + return rate / (rate + (r / scale) ** exponent) + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 294-297 + +In the following we show three different radial scaling functions, where the +first one uses the parameters we use for the calculation of features in the +:ref:`first tutorial `. + +.. GENERATED FROM PYTHON SOURCE LINES 298-317 + +.. code-block:: Python + + + r = np.linspace(1e-3, 4.5, num=100) + + plt.axvline(4.5, c="k", ls="--", label="cutoff") + + radial_scaling_params = {"scale": 2.0, "rate": 1.0, "exponent": 4} + plt.plot(r, radial_scaling(r, **radial_scaling_params), label=radial_scaling_params) + + radial_scaling_params = {"scale": 2.0, "rate": 3.0, "exponent": 6} + plt.plot(r, radial_scaling(r, **radial_scaling_params), label=radial_scaling_params) + + radial_scaling_params = {"scale": 2.0, "rate": 0.8, "exponent": 2} + plt.plot(r, radial_scaling(r, **radial_scaling_params), label=radial_scaling_params) + + plt.legend() + plt.xlabel(r"distance $r$ from the central atom in $Å$") + plt.ylabel("feature weighting") + plt.show() + + + + +.. image-sg:: /examples/images/sphx_glr_understanding-hypers_002.png + :alt: understanding hypers + :srcset: /examples/images/sphx_glr_understanding-hypers_002.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 318-327 + +In the end the total weight is the product of ``cutoff_function`` and the +``radial_scaling`` + +.. math: + + rs(r) = sc(r) \cdot u(r) + +The shape of this function should be a "S" like but the optimal shape depends +on each dataset. + +.. GENERATED FROM PYTHON SOURCE LINES 328-374 + +.. code-block:: Python + + + + def feature_scaling(r, cutoff, width, rate, scale, exponent): + """Features Scaling factor using cosine shifting and radial scaling. + + Parameters + ---------- + r : float + distance between neighboring atoms + cutoff : float + cutoff distance in Å + width : float + width of the decay in Å + rate : float + decay rate of the scaling + scale : float + scaling of the distance between atoms in Å + exponent : float + exponent of the decay + + Returns + ------- + float + weighting of the features + """ + s = radial_scaling(r, rate, scale, exponent) + s *= np.array([shifted_cosine(ri, cutoff, width) for ri in r]) + return s + + + r = np.linspace(1e-3, 4.5, num=100) + + plt.axvline(4.5, c="k", ls="--", label=r"$r_\mathrm{cut}$") + + radial_scaling_params = {} + plt.plot( + r, + feature_scaling(r, scale=2.0, rate=4.0, exponent=6, cutoff=4.5, width=0.5), + label="feature weighting function", + ) + + plt.legend() + plt.xlabel(r"distance $r$ from the central atom $[Å]$") + plt.ylabel("feature weighting") + plt.show() + + + + +.. image-sg:: /examples/images/sphx_glr_understanding-hypers_003.png + :alt: understanding hypers + :srcset: /examples/images/sphx_glr_understanding-hypers_003.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 375-377 + +Finally we see how the magnitude of the features further away from the central +atom reduces when we apply both a ``shifted_cosine`` and a ``radial_scaling``. + +.. GENERATED FROM PYTHON SOURCE LINES 378-419 + +.. code-block:: Python + + + calculator_step = SphericalExpansion( + cutoff=4.5, + max_radial=6, + max_angular=6, + atomic_gaussian_width=0.3, + center_atom_weight=1.0, + radial_basis={"Gto": {"spline_accuracy": 1e-6}}, + cutoff_function={"Step": {}}, + ) + + descriptor_step = calculator_step.compute(frame0) + print(f"Step cutoff: {str(descriptor_step.block(0).values[0]):>97}") + + calculator_cosine = SphericalExpansion( + cutoff=4.5, + max_radial=6, + max_angular=6, + atomic_gaussian_width=0.3, + center_atom_weight=1.0, + radial_basis={"Gto": {"spline_accuracy": 1e-6}}, + cutoff_function={"ShiftedCosine": {"width": 0.5}}, + ) + + descriptor_cosine = calculator_cosine.compute(frame0) + print(f"Cosine smoothing: {str(descriptor_cosine.block(0).values[0]):>92}") + + calculator_rs = SphericalExpansion( + cutoff=4.5, + max_radial=6, + max_angular=6, + atomic_gaussian_width=0.3, + center_atom_weight=1.0, + radial_basis={"Gto": {"spline_accuracy": 1e-6}}, + cutoff_function={"ShiftedCosine": {"width": 0.5}}, + radial_scaling={"Willatt2018": {"scale": 2.0, "rate": 1.0, "exponent": 4}}, + ) + + descriptor_rs = calculator_rs.compute(frame0) + + print(f"cosine smoothing + radial scaling: {str(descriptor_rs.block(0).values[0]):>50}") + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Step cutoff: [[ 0.87386968 -0.24311082 0.12200976 0.41940912 0.80347292 0.26559202]] + Cosine smoothing: [[ 0.8728401 -0.24114056 0.11656053 0.43711707 0.77838565 0.22482755]] + cosine smoothing + radial scaling: [[ 0.88696541 -0.27211242 0.12400786 0.03004326 0.13265605 0.00631962]] + + + + + +.. _sphx_glr_download_examples_understanding-hypers.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: understanding-hypers.ipynb ` + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: understanding-hypers.py ` + + +.. 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..660aba9a0 --- /dev/null +++ b/latest/_sources/explanations/concepts.rst.txt @@ -0,0 +1,83 @@ +.. _core-concepts: + +Core concepts of rascaline +========================== + +Rascaline 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 rascaline is +built upon: systems, calculators and descriptors. + +.. figure:: ../../static/images/core-concepts.* + + Schematic representations of the three core concepts in rascaline: 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 rascaline 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. + +Rascaline 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 rascaline library. + +Calculators: computing representations +-------------------------------------- + +Calculators are provided by rascaline, 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 rascaline, 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. +Rascaline 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 species will have species keys +(for example ``species_center``, ``species_neighbor``, *etc.*), and equivariant +representations will have keys for the different equivariance classes +(``spherical_harmonics_l`` 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..77eb9ffa0 --- /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 +rascaline. The theory behind the calculators and additional useful information +are found here to give you more clarity and understanding of what rascaline is +all about. + +.. toctree:: + :maxdepth: 1 + + concepts + soap + rotation_adapted \ No newline at end of file diff --git a/latest/_sources/explanations/rotation_adapted.rst.txt b/latest/_sources/explanations/rotation_adapted.rst.txt new file mode 100644 index 000000000..e98bb332d --- /dev/null +++ b/latest/_sources/explanations/rotation_adapted.rst.txt @@ -0,0 +1,88 @@ +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 I first rotate the structure and compute the descriptor, I 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 structure 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 m} \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 real spherical harmonics coefficients. \ No newline at end of file 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/index.rst.txt b/latest/_sources/get-started/index.rst.txt new file mode 100644 index 000000000..7c29dfd7e --- /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 rascaline. + +.. toctree:: + :maxdepth: 2 + + rascaline + 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..3c01322b9 --- /dev/null +++ b/latest/_sources/get-started/installation.rst.txt @@ -0,0 +1,179 @@ +Installation +============ + +You can install rascaline 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 rascaline 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/Luthaf/rascaline + cd rascaline + pip install . + + # alternatively, the same thing in a single command + pip install git+https://github.com/Luthaf/rascaline + + +Rascaline 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/temporary-wheels/ rascaline + + +.. _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(rascaline)``. + +.. code-block:: bash + + git clone https://github.com/Luthaf/rascaline + cd rascaline/rascaline-c-api + mkdir build + cd build + cmake .. + make install + +The build and installation can be configures with a few cmake options, using +``-D