{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Running a wavelet computation on a methane molecule\n", "\n", "The purpose of this lesson is to get familiar with the basic variables needed to run a wavelet computation in isolated boundary conditions. At the end of the lesson, you can run a wavelet run, check the amount of needed memory and understand the important part of the output.\n", "We propose to use python in a Jupyter notebook to simplify the use of the `bigdft` executable and to have tools to combine pre-processing, execution, post-processing and analysis.\n", "\n", "## An initial run on the methane molecule\n", "\n", "As already explained in the [N2 molecule tutorial](./N2.ipynb), BigDFT uses dictionaries (a collection of pairs of key and value) for the input and output which are serialized by means of the yaml format.\n", "This allows us to manipulate dictionaries instead of files and define simple actions on them for the basic code operations, instead of manually modifying the input keys.\n", "\n", "We here introduce the `BigDFT.Inputfiles.Inpufile` class, which is a generalisation of a python dictionary and that has as class methods the _same_ methods that are available in the `BigDFT.InputActions` module.\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "scrolled": true }, "outputs": [], "source": [ "from BigDFT import Inputfiles as I\n", "\n", "inp = I.Inputfile()\n", "inp.set_hgrid(0.55)\n", "inp.set_rmult([3.5,9.0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Beside a default input file called **input.yaml**, BigDFT requires the atomic positions for the studied system and optionaly the pseudo-potential files. \n", "For the following tutorial, a methane molecule will be used. \n", "The position file is a simple XYZ file named [CH4_posinp.xyz](CH4_posinp.xyz):\n", "
\n",
"5 angstroemd0 # methane molecule\n",
"free\n",
"C 0 0 0\n",
"H -0.63169789 -0.63169789 -0.63169789\n",
"H +0.63169789 +0.63169789 -0.63169789\n",
"H +0.63169789 -0.63169789 +0.63169789\n",
"H -0.63169789 +0.63169789 +0.63169789\n",
"\n",
"\n",
"We can copy this file into the default posinp file **posinp.xyz** as ``cp CH4_posinp.xyz posinp.xyz`` or indicate it \n",
"in the `posinp` keyword of the calculator options"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Running BigDFT is done using the ``bigdft`` executable in a standard Unix way.\n",
"In this notebook, we use the SystemCalculator class:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" \n",
" - Symbol : C #Type No. 01\n",
" No. of Electrons : 4\n",
" No. of Atoms : 1\n",
" Radii of active regions (AU):\n",
" Coarse : 1.58437\n",
" Fine : 0.30452\n",
" Coarse PSP : 1.30510\n",
" Source : Hard-Coded\n",
" - Symbol : H #Type No. 02\n",
" No. of Electrons : 1\n",
" No. of Atoms : 4\n",
" Radii of active regions (AU):\n",
" Coarse : 1.46342\n",
" Fine : 0.20000\n",
" Coarse PSP : 0.00000\n",
" Source : Hard-Coded"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Analysing the output\n",
"\n",
"The output of BigDFT is divided into four parts:\n",
"- Input values are printed out, including a summary of the\n",
" different input files (DFT calculation parameters, atom positions,\n",
" pseudo-potential values...);\n",
"- Input wavefunction creation, usually called \"input guess\";\n",
"- The SCF (Self-Consistent Field) loop itself;\n",
"- The post SCF calculations including the forces calculation and\n",
" other possible treatment like a finite size effect estimation or a\n",
" virtual states determination.\n",
"\n",
"### The system parameters output\n",
"\n",
"All the read values from the different input files are printed\n",
"out at the program startup. Some additional values are provided there\n",
"also, like the memory consumption. Values are given for one process,\n",
"which corresponds to one core in an MPI environment."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Memory {'Accumulated memory requirements during principal run stages (MiB.KiB)': {'Kernel calculation': 39.271, 'Density Construction': 23.692, 'Poisson Solver': 36.173, 'Hamiltonian application': 23.891, 'Orbitals Orthonormalization': 23.891}, 'Memory requirements for principal quantities (MiB.KiB)': {'Subspace Matrix': 0.1, 'Single orbital': 0.94, 'All (distributed) orbitals': 0.745, 'Wavefunction storage size': 5.92, 'Nonlocal Pseudopotential Arrays': 0.46, 'Full Uncompressed (ISF) grid': 3.224, 'Workspaces storage size': 0.211}, 'Estimated Memory Peak (MB)': 39}\n",
"Estimated Memory Peak 39 MB\n"
]
}
],
"source": [
"print('Memory',ch4.memory)\n",
"print('Estimated Memory Peak',ch4.memory_peak,'MB')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The overall memory requirement needed for this calculation is thus: 39 MB (Estimated Memory Peak) which is provided by the`memory_peak` attribute.\n",
"\n",
"In this example, the memory requirement is given for one process run and the peak of memory will be in the initialisation during the Kernel calculation, while the SCF loop will reach 36MB during the Poisson solver calculation. For bigger systems, with more orbitals, the peak of memory is usually reached during the Hamiltonian application.\n",
"\n",
"### Exercise\n",
"\n",
"Run a script to estimate the memory requirement of a run before submitting it to the queue system of a super-computer\n",
"using the `dry_run` option.\n",
"\n",
"It reads the same input, and is thus convenient to validate inputs.\n",
"\n",
"Try several values from 1 to 6 and discuss the memory distribution.\n",
"\n",
"### Solution"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" \n",
"Input Guess Overlap Matrices: {Calculated: true, Diagonalized: true}\n",
"Orbitals:\n",
"- {e: -0.6493539153869, f: 2.0}\n",
"- {e: -0.3625626366055, f: 2.0}\n",
"- {e: -0.3624675839372, f: 2.0}\n",
"- {e: -0.3624675839372, f: 2.0} -- Last InputGuess eval, H-L IG gap: 20.6959 eV\n",
"- {e: 0.3980916655348, f: 0.0} -- First virtual eval\n",
"- {e: 0.3983087771728, f: 0.0}\n",
"- {e: 0.3983087771728, f: 0.0}\n",
"- {e: 0.5993393223683, f: 0.0}\n",
"\n",
"\n",
"### The SCF loop\n",
"\n",
"The SCF loop follows a direct minimisation scheme and is made of the following steps:\n",
"- Calculate the charge density from the previous wavefunctions.\n",
"- Apply the Poisson solver to obtain the Hartree potential from the\n",
" charges and calculate the exchange-correlation energy and the energy\n",
" of the XC potential thanks to the chosen functional.\n",
"- Apply the resulting hamiltonian on the current wavefunctions.\n",
"- Precondition the result and apply a steepest descent or a DIIS\n",
" history method. This depends on ``idsx``, not specified in the\n",
" present input. It is therefore set to the default\n",
" value, which is 6 (for an history of 6 previous set of vectors. To perform a SD \n",
" minimisation one should add \"``idsx: 0``\" to the *dft* dictionary of *inp*.\n",
"- Orthogonalise the new wavefunctions.\n",
"\n",
"Finally the total energy and the square norm of the residue\n",
"(gnrm) are printed out. The *gnrm* value is the stopping criterion. \n",
"It can be chosen using `gnrm_cv` in the *dft* dictionary. \n",
"The default value (1e-4) is used here and a good value can reach 1e-5."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"gnrm_cv by default 0.0001\n"
]
}
],
"source": [
"print('gnrm_cv by default',ch4.gnrm_cv)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The minimisation scheme coupled with DIIS (and thanks to the good preconditioner) \n",
"is a very efficient way to obtain convergence for systems with a gap, even with a very small one. \n",
"Usual run should reach the 1e-4 stop criterion within 15 to 25 iterations. \n",
"Otherwise, there is an issue with the system, either there is no gap, \n",
"or the input guess is too symmetric due to the LCAO diagonalization, specific spin polarization..."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAXwAAAD4CAYAAADvsV2wAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAAsTAAALEwEAmpwYAAAovUlEQVR4nO3deXxNd/7H8dc3i0QI2gi1NtTW2EJCLa2ltEWly1BLi6JotZRWZ1od2pmfbtNSaqaxtCUtxjJoiaVVZigVU0JK0VB7WnvVFksS398fwViiiSQ35+be9/Px8Hj0nnvvJ+9e8ck353zOOcZai4iIeD4fpwOIiEj+UMMXEfESavgiIl5CDV9ExEuo4YuIeAk/pwP8npIlS9qwsDCnY4iI5JukpCQAqlevnuMaCQkJR6y1oddud8uGb4yJBqKrVKnCunXrnI4jIpJvWrRoAcDy5ctzXMMYsyez7W65S8daG2et7Ve8eHGno4iIeAy3XOGLiHirYcOGuay2Gr6IiBtp3bq1y2qr4YsIAKmpqSQnJ3P27Fmno3i18+fPA1CoUKEsXxsYGEj58uXx9/fPVm01fBEBIDk5meDgYMLCwjDGOB3Ha2V3Ssday9GjR0lOTqZSpUrZqu2WB21FJP+dPXuWkJAQNfsCwhhDSEjITf1GpoYvIpep2RcsN/v35ZENf+X2w0yJ340u/Swi8j8e2fDnJ/7C8Hmb6RW7lkMndQBKpCCaPn06b775JrGxsQwYMCDP6n722WfUqlWLmjVrEh4ezsiRIwHo2bMns2fPvuq1RYsWverxiRMnKFeuXJ7myY6wsDCOHDmS6zpu2fCNMdHGmInHjx/P0fvf7ViH/3u4JvE7jtJmzEq+2nwgjxOKiKt9+eWXtGnTJk9rLl68mDFjxrBkyRI2b97M+vXruZkTPIcPH07z5s3zNNO1ypUrR7ly5VxS2y0bfm7PtDXG0KNxGAufv4eyJQJ5ekoCL8/eyKlzaXmcVERcwVpLYmIi9evXv2r7nj17aNWqFXXq1KFVq1bs3bsXgB07dtCoUSMaNGjAa6+9dt3K/JK3336bkSNHUrZsWSBjrLFv377ZypSQkMDBgwe5//77M33+5MmTVKpUidTUVCDjt4GwsDBSU1P56KOPaNCgAXXr1qVDhw6kpKQAGb9V9O/fn5YtW1K5cmVWrFjB888/T4MGDejZs2e2ct0Mjx7LrFKqKHP7N+WDZdsYt3wH8TuPMrpzBJG33+J0NBG39te4zWz55USe1gwvW4zXo2tm67UbNmygbt261x2UHDBgAD169ODJJ59k0qRJPP/883zxxRcMGjSIQYMG0bVrV8aPH3/Duj/88AORkZE3fP6Pf/wjb7zxxnXbL1y4wJAhQ5gyZQrLli3L9L3BwcG0aNGChQsX8sgjjzBjxgw6dOiAv78/f/jDHy7/YBk2bBiffPIJAwcOBODYsWP8+9//Zv78+URHR/P1118zZswYWrZsSWJiIhEREVl9XNnmliv8vFTIz4c/PlCDmU835oK1PDZ+Ne8vSSI1/YLT0UTkBr788kvatm173fb4+Hgef/xxALp3786qVasub3/ssccALj+fE++99x6JiYmX/1wSExNDu3btqFChwu++v0+fPkyePBmAyZMn06tXLyDjB80999xD7dq1mTZtGps3b778nujoaIwx1K5dm9KlS1OiRAn2799PzZo12b17d47/XzLj0Sv8KzUIu5XFg+7hr3FbGPvvn1ix7TCjO0dQOTTzX/1EvFl2V+KusmTJEubMmZPl67IaS/zzn//MwoULAUhMTKRmzZokJCRw77333lSe+Ph4Vq5cSUxMDKdOneL8+fMULVqUd95556rXNW3alN27d7NixQrS09OpVasWkLHr5osvvqBu3brExsZedSXMgIAAAHx8fC7/96XHaWl5uxva41f4VwoO9GfkY3UZ90R99vyaQruxK5m6Zo/GN0XcyPHjx0lLSyMkJOS655o0acKMGTMAmDZtGnfffTcAjRo1uvwD4tLzAG+++eZVq/WhQ4fypz/9iQMHMgY5zp07x9ixY7PMNG3aNPbu3cvu3bsZOXIkPXr0uK7ZX9KjRw+6du16eXUPGfv3y5QpQ2pqKtOmTcvGp+AaXtXwL2lbuwxfDW5Gw0ohDPviB576dB2HT55zOpaI12vXrh3z5s274QXExo4dy+TJk6lTpw5Tpkzhgw8+AGDMmDG8//77NGzYkP37999w8qZdu3Y899xztG7dmpo1axIZGZnrVfRrr73G/PnzLz9+4oknOHbsGF27dr28bcSIEdx1113cd9991KhRI1dfLzeMO69uo6KirCtvgGKt5bP4Pby1aCtFA/x4p0Md7gsv7bKvJ+LOtm7dyp133ul0DPr06UOfPn1o1KhRtt+T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\n",
"text/plain": [
"