{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Analytic Dynamic Tensor\n", "\n", "By forming the dynamic tensor analytically at a given Q, we not only can easily determine how to execute first-principle calculations to obtain the actual dynamic tensor most efficiently, but also are capable of performing analytic analysis with the tensor without the need of any first-principles calculations at all, using solely group theory.\n", "\n", "This version of the analytic tensor uses the little group analysis method, \n", "it does not accounts for all space group symmetry but only a subset. \n", "This method is easy to execute and serves as the foundation of the full-group approach.\n", "\n", "The basic structure of the code is sound, albeit the renaming of some attributes is required.\n", "There is a working version that uses sparse tensor instead of numpy tensor, \n", "this should be considered as an alternative feature to save memory, \n", "though some linear algebra operations on the sparse tensor (e.g. SVD) might not be available right now.\n", "\n", "Here we will show examples for the analytic tensor for both little group approach and the current implementation of full group approach." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from analytic_dynamic_tensor import analytic_dynamic_tensor\n", "from sym_analytic_dynamic_tensor import sym_analytic_dynamic_tensor\n", "from coordinate_tools import coord_to_string as c2s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Our example will use graphene as our sample system." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "poscar = \"\"\"\\\n", "graphene \n", " 1.00000000000000 \n", " 2.1217113285639000 1.2249706066897641 0.0000000000000000\n", " 2.1217113285639000 -1.2249706066897641 0.0000000000000000\n", " 0.0000000000000000 0.0000000000000000 -15.0000000000000000\n", " 2 \n", "Direct\n", " 0.00000000 0.00000000 0.0000000000000000 C:p\n", " 0.33333333 0.33333333 0.0000000000000000 C:p\n", "\"\"\".strip()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Little group approach" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "((0, 0, 0), (0, 0, 0))\n" ] }, { "data": { "text/plain": [ "analytic_dynamic_tensor(graphene \n", " 1.00000000000000 \n", " 2.1217113285639000 1.2249706066897641 0.0000000000000000\n", " 2.1217113285639000 -1.2249706066897641 0.0000000000000000\n", " 0.0000000000000000 0.0000000000000000 -15.0000000000000000\n", " 2 \n", "Direct\n", " 0.00000000 0.00000000 0.0000000000000000 C:p\n", " 0.33333333 0.33333333 0.0000000000000000 C:p, D6h, pg_loc=1/3 1/3 0, kset=((0, 0, 0), (0, 0, 0)))" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "adt = analytic_dynamic_tensor(\n", " pos=poscar, # primitive structure\n", " pgn='D6h', # point group\n", " pg_loc='1/3 1/3 0', # The site of the symmetry\n", " kset='0 0 0; 0 0 0', # The Q of interest (the number of q-vectors equals to the order of the derivtive)\n", ")\n", "adt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The vectorized analytic tensor in the symmetrized basis is stored in the `vtensor` attribute, and the list of irreducible derivatives the tensor represents is store in `globalvar` attribute. One can change the `globalvar` list, and `_vtensor` attribute needs to be deleted to create the updated vtensor that uses the update list.\n", "\n", "The tensor in naive basis is stored in `rotated_tensor`." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['((((0, 0, 0), B2g), ((0, 0, 0), B2g)), (A1g, 0))', '((((0, 0, 0), E2g), ((0, 0, 0), E2g)), (A1g, 0))']\n", "(6, 6, 2)\n", "(6, 6, 2)\n" ] } ], "source": [ "print map(c2s, adt.globalvar)\n", "print adt.vtensor.shape\n", "print adt.rotated_tensor.shape" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The dynamic tensor in symmetrized basis with the contribution of the irreducible derivative:\n", " ((((0, 0, 0), B2g), ((0, 0, 0), B2g)), (A1g, 0))\n", "[[1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]]\n", "The dynamic tensor in symmetrized basis with the contribution of the irreducible derivative:\n", " ((((0, 0, 0), E2g), ((0, 0, 0), E2g)), (A1g, 0))\n", "[[0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]]\n" ] } ], "source": [ "for i in range(len(adt.globalvar)):\n", " print \"The dynamic tensor in symmetrized basis with the contribution of the irreducible derivative:\"\n", " print \" \", c2s(adt.globalvar[i])\n", " print adt.vtensor[:, :, i]" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The dynamic tensor in naive basis with the contribution of the irreducible derivative:\n", " ((((0, 0, 0), B2g), ((0, 0, 0), B2g)), (A1g, 0))\n", "[[ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [ 0. +0.j 0. +0.j 0.5+0.j 0. +0.j 0. +0.j -0.5+0.j]\n", " [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [ 0. +0.j 0. +0.j -0.5+0.j 0. +0.j 0. +0.j 0.5+0.j]]\n", "The dynamic tensor in naive basis with the contribution of the irreducible derivative:\n", " ((((0, 0, 0), E2g), ((0, 0, 0), E2g)), (A1g, 0))\n", "[[ 0.5+0.j 0. +0.j 0. +0.j -0.5+0.j 0. +0.j 0. +0.j]\n", " [ 0. +0.j 0.5+0.j 0. +0.j 0. +0.j -0.5+0.j 0. +0.j]\n", " [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [-0.5+0.j 0. +0.j 0. +0.j 0.5+0.j 0. +0.j 0. +0.j]\n", " [ 0. +0.j -0.5+0.j 0. +0.j 0. +0.j 0.5+0.j 0. +0.j]\n", " [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]]\n" ] } ], "source": [ "for i in range(len(adt.globalvar)):\n", " print \"The dynamic tensor in naive basis with the contribution of the irreducible derivative:\"\n", " print \" \", c2s(adt.globalvar[i])\n", " print adt.rotated_tensor[:, :, i]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Full group approach\n", "\n", "Almost everything except the symmetry analysis is the same as the little group approach.\n", "\n", "One small difference is that in the symmetrized basis, the full group approach does not keep placeholder for the removed acoustic does, contrary to the little group apprach. There is no significant difference either way, but it's a good experiment to have both implemented. Thus choice which will go to the new version can be discussed." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "((0, 0, 0), (0, 0, 0))\n" ] }, { "data": { "text/plain": [ "sym_analytic_dynamic_tensor(graphene \n", " 1.00000000000000 \n", " 2.1217113285639000 1.2249706066897641 0.0000000000000000\n", " 2.1217113285639000 -1.2249706066897641 0.0000000000000000\n", " 0.0000000000000000 0.0000000000000000 -15.0000000000000000\n", " 2 \n", "Direct\n", " 0.00000000 0.00000000 0.0000000000000000 C:p\n", " 0.33333333 0.33333333 0.0000000000000000 C:p, D6h, pg_loc=1/3 1/3 0, kset=((0, 0, 0), (0, 0, 0)))" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sadt = sym_analytic_dynamic_tensor(\n", " pos=poscar, # primitive structure\n", " pgn='D6h', # point group\n", " pg_loc='1/3 1/3 0', # The site of the symmetry\n", " kset='0 0 0; 0 0 0', # The Q of interest (the number of q-vectors equals to the order of the derivtive)\n", ")\n", "sadt" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['((((0, 0, 0), (B2g, ((B2g, 0), 0))), ((0, 0, 0), (B2g, ((B2g, 0), 0)))), (A1g, 0))', '((((0, 0, 0), (E2g, ((E2g, 0), 0))), ((0, 0, 0), (E2g, ((E2g, 0), 0)))), (A1g, 0))']\n", "\n", "The dynamic tensor in symmetrized basis with the contribution of the irreducible derivative:\n", " ((((0, 0, 0), (B2g, ((B2g, 0), 0))), ((0, 0, 0), (B2g, ((B2g, 0), 0)))), (A1g, 0))\n", "[[1.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j]]\n", "\n", "The dynamic tensor in symmetrized basis with the contribution of the irreducible derivative:\n", " ((((0, 0, 0), (E2g, ((E2g, 0), 0))), ((0, 0, 0), (E2g, ((E2g, 0), 0)))), (A1g, 0))\n", "[[0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 1.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 1.+0.j]]\n", "\n", "The dynamic tensor in naive basis with the contribution of the irreducible derivative:\n", " ((((0, 0, 0), (B2g, ((B2g, 0), 0))), ((0, 0, 0), (B2g, ((B2g, 0), 0)))), (A1g, 0))\n", "[[ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [ 0. +0.j 0. +0.j 0.5+0.j 0. +0.j 0. +0.j -0.5+0.j]\n", " [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [ 0. +0.j 0. +0.j -0.5+0.j 0. +0.j 0. +0.j 0.5+0.j]]\n", "\n", "The dynamic tensor in naive basis with the contribution of the irreducible derivative:\n", " ((((0, 0, 0), (E2g, ((E2g, 0), 0))), ((0, 0, 0), (E2g, ((E2g, 0), 0)))), (A1g, 0))\n", "[[ 0.5+0.j 0. +0.j 0. +0.j -0.5+0.j 0. +0.j 0. +0.j]\n", " [ 0. +0.j 0.5+0.j 0. +0.j 0. +0.j -0.5+0.j 0. +0.j]\n", " [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [-0.5+0.j 0. +0.j 0. +0.j 0.5+0.j 0. +0.j 0. +0.j]\n", " [ 0. +0.j -0.5+0.j 0. +0.j 0. +0.j 0.5+0.j 0. +0.j]\n", " [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]]\n", "\n" ] } ], "source": [ "print map(c2s, sadt.globalvar)\n", "print\n", "\n", "for i in range(len(sadt.globalvar)):\n", " print \"The dynamic tensor in symmetrized basis with the contribution of the irreducible derivative:\"\n", " print \" \", c2s(sadt.globalvar[i])\n", " print sadt.vtensor[:, :, i]\n", " print\n", "\n", "for i in range(len(sadt.globalvar)):\n", " print \"The dynamic tensor in naive basis with the contribution of the irreducible derivative:\"\n", " print \" \", c2s(sadt.globalvar[i])\n", " print sadt.rotated_tensor[:, :, i]\n", " print" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.17" } }, "nbformat": 4, "nbformat_minor": 2 }