{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Distinction of solid liquid atoms and clustering " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this example, we will take one snapshot from a molecular dynamics simulation which has a solid cluster in liquid. The task is to identify solid atoms and cluster them. More details about the method can be found [here](https://pyscal.readthedocs.io/en/latest/solidliquid.html).\n", "\n", "The first step is, of course, importing all the necessary module. For visualisation, we will use [Ovito](https://www.ovito.org/)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![alt text](system1.png \"original system\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The above image shows a visualisation of the system using Ovito. Importing modules," ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import pyscal.core as pc" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we will set up a System with this input file, and calculate neighbors. Here we will use a cutoff method to find neighbors. More details about finding neighbors can be found [here](https://pyscal.readthedocs.io/en/latest/nearestneighbormethods.html#)." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "sys = pc.System()\n", "sys.read_inputfile('cluster.dump')\n", "sys.find_neighbors(method='cutoff', cutoff=3.63)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once we compute the neighbors, the next step is to find solid atoms. This can be done using `System.find_solids` method. There are few parameters that can be set, which can be found in detail here." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "sys.find_solids(bonds=6, threshold=0.5, avgthreshold=0.6, cluster=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The above statement found all the solid atoms. Solid atoms can be identified by the value of the `solid` attribute. For that we first get the atom objects and select those with `solid` value as True." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "203" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "atoms = sys.atoms\n", "solids = [atom for atom in atoms if atom.solid]\n", "len(solids)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are 202 solid atoms in the system. In order to visualise in Ovito, we need to first write it out to a trajectory file. This can be done with the help of `to_file` method of System. This method can help to save any attribute of the atom or ant Steinhardt parameter value. " ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "sys.to_file('sys.solid.dat', customkeys = ['solid'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can now visualise this file in Ovito. After opening the file in Ovito, the modifier [compute property](https://ovito.org/manual/particles.modifiers.compute_property.html) can be selected. The `Output property` should be `selection` and in the expression field, `solid==0` can be selected to select all the non solid atoms. Applying a modifier [delete selected particles](https://ovito.org/manual/particles.modifiers.delete_selected_particles.html) can be applied to delete all the non solid particles. The system after removing all the liquid atoms is shown below." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![alt text](system2.png \"system with only solid\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Clustering algorithm\n", "\n", "You can see that there is a cluster of atom. The clustering functions that pyscal offers helps in this regard. If you used `find_clusters` with `cluster=True`, the clustering is carried out. Since we did used `cluster=False` above, we will rerun the function" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "176" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sys.find_solids(bonds=6, threshold=0.5, avgthreshold=0.6, cluster=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can see that the above function call returned the number of atoms belonging to the largest cluster as an output. In order to extract atoms that belong to the largest cluster, we can use the `largest_cluster` attribute of the atom." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "176" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "atoms = sys.atoms\n", "largest_cluster = [atom for atom in atoms if atom.largest_cluster]\n", "len(largest_cluster)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The value matches that given by the function. Once again we will save this information to a file and visualise it in Ovito. " ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "sys.to_file('sys.cluster.dat', customkeys = ['solid', 'largest_cluster'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The system visualised in Ovito following similar steps as above is shown below." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![alt text](system3.png \"system with only largest solid cluster\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is clear from the image that the largest cluster of solid atoms was successfully identified. Clustering can be done over any property. The following example with the same system will illustrate this." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Clustering based on a custom property" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In pyscal, clustering can be done based on any property. The following example illustrates this. To find the clusters based on a custom property, the `System.clusters_atoms` method has to be used. The simulation box shown above has the centre roughly at (25, 25, 25). For the custom clustering, we will cluster all atoms within a distance of 10 from the the rough centre of the box at (25, 25, 25). Let us define a function that checks the above condition." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "def check_distance(atom):\n", " #get position of atom\n", " pos = atom.pos\n", " #calculate distance from (25, 25, 25)\n", " dist = ((pos[0]-25)**2 + (pos[1]-25)**2 + (pos[2]-25)**2)**0.5\n", " #check if dist < 10\n", " return (dist <= 10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The above function would return True or False depending on a condition and takes the Atom as an argument. These are the two important conditions to be satisfied. Now we can pass this function to cluster. First, set up the system and find the neighbors. " ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "sys = pc.System()\n", "sys.read_inputfile('cluster.dump')\n", "sys.find_neighbors(method='cutoff', cutoff=3.63)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now cluster" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "242" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sys.cluster_atoms(check_distance)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are 242 atoms in the cluster! Once again we can check this, save to a file and visualise in ovito." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "242" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "atoms = sys.atoms\n", "largest_cluster = [atom for atom in atoms if atom.largest_cluster]\n", "len(largest_cluster)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "sys.to_file('sys.dist.dat', customkeys = ['solid', 'largest_cluster'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![alt text](system4.png \"custom clustering\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This example illustrates that any property can be used to cluster the atoms!" ] } ], "metadata": { "kernelspec": { "display_name": "pyscal-test", "language": "python", "name": "pyscal-test" }, "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.7" } }, "nbformat": 4, "nbformat_minor": 4 }