{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n# Numeric arrays in Python\n\nExamples demonstrating NumPy usage in ASE documentation.\n\nLinks to NumPy's webpage:\n\n* `Numpy and Scipy Documentation`_\n* [Numpy user guide](https://docs.scipy.org/doc/numpy/user/index.html)\n\n\n\nASE makes heavy use of an extension to Python called NumPy. The\nNumPy module defines an ``ndarray`` type that can hold large arrays of\nuniform multidimensional numeric data. An array is similar to a\n``list`` or a ``tuple``, but it is a lot more powerful and efficient.\n\nSome examples from everyday ASE-life here ...\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import numpy as np\n\na = np.zeros((3, 2))\na[:, 1] = 1.0\na[1] = 2.0\nprint(a)\nprint(a.shape)\nprint(a.ndim)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The conventions of numpy's linear algebra package:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# --- Basic array example ---\na = np.zeros((3, 2))\na[:, 1] = 1.0\na[1] = 2.0\nprint('Array a:\\n', a)\nprint('Shape:', a.shape)\nprint('Number of dimensions:', a.ndim)\n\n# --- Linear algebra example ---\n# Make a random Hermitian matrix\nH = np.random.rand(6, 6) + 1.0j * np.random.rand(6, 6)\nH = H + H.T.conj()\n\n# Eigenvalues and eigenvectors\neps, U = np.linalg.eigh(H)\n\n# Sort eigenvalues and corresponding eigenvectors\nsorted_indices = eps.real.argsort()\neps = eps[sorted_indices]\nU = U[:, sorted_indices]\n\n# Verify diagonalization\nprint(\n 'Check diagonalization:\\n', np.dot(np.dot(U.T.conj(), H), U) - np.diag(eps)\n)\nprint('All close?', np.allclose(np.dot(np.dot(U.T.conj(), H), U), np.diag(eps)))\n\n# Check eigenvectors individually\nprint(\n 'Eigenvector check (one column):',\n np.allclose(np.dot(H, U[:, 3]), eps[3] * U[:, 3]),\n)\nprint('Eigenvector check (all):', np.allclose(np.dot(H, U), eps * U))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The rules for multiplying 1D arrays with 2D arrays:\n\n* 1D arrays and treated like shape (1, N) arrays (row vectors).\n* left and right multiplications are treated identically.\n* A length $m$ *row* vector can be multiplied with an $n \\times m$\n matrix, producing the same result as if replaced by a matrix with\n $n$ copies of the vector as rows.\n* A length $n$ *column* vector can be multiplied with\n an $n \\times m$\n matrix, producing the same result as if replaced by a matrix with\n $m$ copies of the vector as columns.\n\nThus, for the arrays below:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# --- 1D vs 2D multiplication rules ---\nM = np.arange(5 * 6).reshape(5, 6) # A matrix of shape (5, 6)\nv5 = np.arange(5) + 10 # A vector of length 5\nv51 = v5[:, None] # Column vector (5, 1)\nv6 = np.arange(6) - 12 # A vector of length 6\nv16 = v6[None, :] # Row vector (1, 6)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The following identities hold::\n\n v6 * M == v16 * M == M * v6 == M * v16 == M * v16.repeat(5, 0)\n v51 * M == M * v51 == M * v51.repeat(6, 1)\n\nThe same rules apply for adding and subtracting 1D arrays to\nfrom 2D arrays.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Identities\nprint('v6 * M == M * v6?', np.allclose(v6 * M, M * v6))\nprint('v16 * M == M * v16?', np.allclose(v16 * M, M * v16))\nprint('v51 * M == M * v51?', np.allclose(v51 * M, M * v51))" ] } ], "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.13.7" } }, "nbformat": 4, "nbformat_minor": 0 }