{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Methods to calculate neighbors of a particle" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "pyscal includes different methods to explore the local environment of a\n", "particle that rely on the calculation of nearest neighbors. Various\n", "approaches to compute the neighbors of particles are discussed here.\n", "\n", "## Fixed cutoff method\n", "\n", "The most common method to calculate the nearest neighbors of an atom is\n", "using a cutoff radius. The neighborhood of an atom for calculation of\n", "Steinhardt\\'s parameters {cite}`Steinhardt1983` is often carried out using this method.\n", "Commonly, a cutoff is selected as the first minimum of the radial\n", "distribution functions. Once a cutoff is selected, the neighbors of an\n", "atom are those that fall within this selected radius. The following code\n", "snippet will use the cutoff method to calculate neighbors. In this example, `conf.dump` is assumed to\n", "be the input configuration of the system. A cutoff radius of 3 is\n", "assumed for calculation of neighbors.\n", "\n", "``` python\n", "import pyscal.core as pc\n", "sys = pc.System()\n", "sys.read_inputfile('conf.dump')\n", "sys.find_neighbors(method='cutoff', cutoff=3)\n", "```\n", "\n", "\n", "## Adaptive cutoff methods\n", "\n", "A fixed cutoff radius can introduce limitations to explore the local\n", "environment of the particle in some cases:\n", "\n", "- At finite temperatures, when thermal fluctuations take place, the\n", " selection of a fixed cutoff may result in an inaccurate description\n", " of the local environment.\n", "- If there is more than one structure present in the system, for\n", " example, bcc and fcc, the selection of cutoff such that it includes\n", " the first shell of both structures can be difficult.\n", "\n", "In order to achieve a more accurate description of the local\n", "environment, various adaptive approaches have been proposed. Two of the\n", "methods implemented in the module are discussed below.\n", "\n", "### Solid angle based nearest neighbor algorithm (SANN)\n", "\n", "SANN algorithm {cite}`VanMeel2012` determines the cutoff radius by counting the solid\n", "angles around an atom and equating it to $4\\pi$. The algorithm solves\n", "the following equation iteratively.\n", "\n", "> $$R_i^{(m)} = \\frac{\\sum_{j=1}^m r_{i,j}}{m-2} < r_{i, m+1}$$\n", "\n", "where $i$ is the host atom, $j$ are its neighbors with $r_{ij}$ is the\n", "distance between atoms $i$ and $j$. $R_i$ is the cutoff radius for each\n", "particle $i$ which is found by increasing the neighbor of neighbors $m$\n", "iteratively. For a description of the algorithm and more details, please\n", "check the reference {cite}`VanMeel2012`. SANN algorithm can be used to find the\n", "neighbors by,\n", "\n", "``` python\n", "import pyscal.core as pc\n", "sys = pc.System()\n", "sys.read_inputfile('conf.dump')\n", "sys.find_neighbors(method='cutoff', cutoff='sann')\n", "```\n", "\n", "Since SANN algorithm involves sorting, a sufficiently large cutoff is\n", "used in the beginning to reduce the number entries to be sorted. This\n", "parameter is calculated by,\n", "\n", "> $$r_{initial} = \\mathrm{threshold} \\times \\bigg(\\frac{\\mathrm{Simulation~box~volume}}{\\mathrm{Number~of~particles}}\\bigg)^{\\frac{1}{3}}$$\n", "\n", "a tunable `threshold` parameter can be set through function arguments.\n", "\n", "### Adaptive cutoff method\n", "\n", "An adaptive cutoff specific for each atom can also be found using an\n", "algorithm similar to adaptive common neighbor analysis {cite}`Stukowski2012`. This\n", "adaptive cutoff is calculated by first making a list of all neighbor\n", "distances for each atom similar to SANN method. Once this list is\n", "available, then the cutoff is calculated from,\n", "\n", "> $$r_{cut}(i) = \\mathrm{padding}\\times \\bigg(\\frac{1}{\\mathrm{nlimit}} \\sum_{j=1}^{\\mathrm{nlimit}} r_{ij} \\bigg)$$\n", "\n", "This method can be chosen by,\n", "\n", "``` python\n", "import pyscal.core as pc\n", "sys = pc.System()\n", "sys.read_inputfile('conf.dump')\n", "sys.find_neighbors(method='cutoff', cutoff='adaptive')\n", "```\n", "\n", "The `padding` and `nlimit` parameters in the above equation can be tuned\n", "using the respective keywords.\n", "\n", "Either of the adaptive method can be used to find neighbors, which can\n", "then be used to calculate Steinhardt\\'s parameters or their averaged\n", "version.\n", "\n", "## Voronoi tessellation\n", "\n", "[Voronoi tessellation](https://en.wikipedia.org/wiki/Voronoi_diagram)\n", "provides a completely parameter free geometric approach for calculation\n", "of neighbors. [Voro++](http://math.lbl.gov/voro++/) code is used for\n", "Voronoi tessellation. Neighbors can be calculated using this method by,\n", "\n", "``` python\n", "import pyscal.core as pc\n", "sys = pc.System()\n", "sys.read_inputfile('conf.dump')\n", "sys.find_neighbors(method='voronoi')\n", "```\n", "\n", "Finding neighbors using Voronoi tessellation also calculates a weight\n", "for each neighbor. The weight of a neighbor $j$ towards a host atom $i$\n", "is given by,\n", "\n", "> $$W_{ij} = \\frac{A_{ij}}{\\sum_{j=1}^N A_{ij}}$$\n", "\n", "where $A_{ij}$ is the area of Voronoi facet between atom $i$ and $j$,\n", "$N$ are all the neighbors identified through Voronoi tessellation. This\n", "weight can be used later for calculation of weighted Steinhardt\\'s\n", "parameters. Optionally, it is possible to choose the exponent for this\n", "weight. Option `voroexp` is used to set this option. For example if\n", "`voroexp=2`, the weight would be calculated as,\n", "\n", "> $$W_{ij} = \\frac{A_{ij}^2}{\\sum_{j=1}^N A_{ij}^2}$$\n", "\n", "## References\n", "\n", "```{bibliography} ../references.bib\n", ":filter: docname in docnames\n", ":style: unsrt\n", "```" ] } ], "metadata": { "kernelspec": { "display_name": "py3", "language": "python", "name": "py3" }, "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.9.1" } }, "nbformat": 4, "nbformat_minor": 4 }