{ "cells": [ { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "# Gradients" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import pandas as pd\n", "import numpy as np\n", "import chemcoord as cc\n", "import sympy\n", "sympy.init_printing()" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true }, "outputs": [], "source": [ "molecule = cc.Cartesian.read_xyz('MIL53_beta.xyz', start_index=1)\n", "r, theta = sympy.symbols('r, theta', real=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's build the construction table in order to bend one of the terephtalic acid ligands." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": true }, "outputs": [], "source": [ "fragment = molecule.get_fragment([(12, 17), (55, 60)])\n", "connection = np.array([[3, 99, 1, 12], [17, 3, 99, 12], [60, 3, 17, 12]])\n", "connection = pd.DataFrame(connection[:, 1:], index=connection[:, 0], columns=['b', 'a', 'd'])\n", "c_table = molecule.get_construction_table([(fragment, connection)])\n", "molecule = molecule.loc[c_table.index]\n", "zmolecule = molecule.get_zmat(c_table)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This gives the following movement:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": true }, "outputs": [], "source": [ "zmolecule_symb = zmolecule.copy()\n", "zmolecule_symb.safe_loc[3, 'angle'] += theta\n", "\n", "cc.xyz_functions.view([zmolecule_symb.subs(theta, a).get_cartesian() for a in [-30, 0, 30]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Gradient for Zmat to Cartesian" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For the gradients it is very illustrating to compare:\n", "$$\n", "f(x + h) \\approx f(x) + f'(x) h\n", "$$\n", "\n", "$f(x + h)$ will be ``zmolecule2``\n", "\n", "and\n", "$h$ will be dist_zmol\n", "\n", "The boolean ``chain`` argument denotes if the movement should be chained or not." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Bond" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": true }, "outputs": [], "source": [ "dist_zmol1 = zmolecule.copy()\n", "\n", "r = 3\n", "\n", "dist_zmol1.unsafe_loc[:, ['bond', 'angle', 'dihedral']] = 0\n", "dist_zmol1.unsafe_loc[3, 'bond'] = r" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": true }, "outputs": [], "source": [ "cc.xyz_functions.view([molecule,\n", " molecule + zmolecule.get_grad_cartesian(chain=False)(dist_zmol1),\n", " molecule + zmolecule.get_grad_cartesian()(dist_zmol1),\n", " (zmolecule + dist_zmol1).get_cartesian()])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Angle" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": true }, "outputs": [], "source": [ "angle = 30" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": true }, "outputs": [], "source": [ "dist_zmol2 = zmolecule.copy()\n", "dist_zmol2.unsafe_loc[:, ['bond', 'angle', 'dihedral']] = 0\n", "dist_zmol2.unsafe_loc[3, 'angle'] = angle" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": true }, "outputs": [], "source": [ "cc.xyz_functions.view([molecule,\n", " molecule + zmolecule.get_grad_cartesian(chain=False)(dist_zmol2),\n", " molecule + zmolecule.get_grad_cartesian()(dist_zmol2),\n", " (zmolecule + dist_zmol2).get_cartesian()])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that the deviation between $f(x + h)$ and $f(x) + h f'(x)$ is not an error in the implementation but a visualisation of the [small angle approximation](https://en.wikipedia.org/wiki/Small-angle_approximation).\n", "\n", "The smaller the angle the better is the linearisation." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Gradient for Cartesian to Zmat" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": true }, "outputs": [], "source": [ "x_dist = 2\n", "\n", "dist_mol = molecule.copy()\n", "dist_mol.loc[:, ['x', 'y', 'z']] = 0.\n", "dist_mol.loc[13, 'x'] = x_dist" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": true }, "outputs": [], "source": [ "zmat_dist = molecule.get_grad_zmat(c_table)(dist_mol)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is immediately obvious, that only the ``['bond', 'angle', 'dihedral']`` of those atoms change,\n", "which are either moved themselves in cartesian space or use moved references." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " | atom | \n", "b | \n", "bond | \n", "a | \n", "angle | \n", "d | \n", "dihedral | \n", "
---|---|---|---|---|---|---|---|
13 | \n", "O | \n", "12 | \n", "1.521692e+00 | \n", "99 | \n", "-1.387881e+01 | \n", "2 | \n", "36.649299 | \n", "
11 | \n", "C | \n", "13 | \n", "-8.852016e-01 | \n", "12 | \n", "-6.848733e+01 | \n", "99 | \n", "112.390250 | \n", "
23 | \n", "C | \n", "11 | \n", "7.771561e-16 | \n", "13 | \n", "-6.350987e+01 | \n", "12 | \n", "-87.668150 | \n", "
21 | \n", "O | \n", "11 | \n", "-3.330669e-16 | \n", "13 | \n", "6.350985e+01 | \n", "12 | \n", "-140.238538 | \n", "
25 | \n", "C | \n", "23 | \n", "9.487976e-17 | \n", "11 | \n", "-2.265493e-15 | \n", "13 | \n", "-54.808771 | \n", "
27 | \n", "C | \n", "23 | \n", "-5.332157e-17 | \n", "11 | \n", "1.255238e-15 | \n", "13 | \n", "-54.808771 | \n", "
50 | \n", "H | \n", "21 | \n", "1.283378e-16 | \n", "11 | \n", "-2.369105e-15 | \n", "13 | \n", "52.372802 | \n", "