{
"cells": [
{
"cell_type": "markdown",
"id": "7675f341",
"metadata": {},
"source": [
"(adc-hpc:label)=\n",
"# HPC-QC implementation\n",
"\n",
"To enable large-scale ADC(2) calculations on HPC systems, some considerations need to be taken into account in the implementation. Conventionally, the molecular orbital (MO) integrals, which are essentially tensors with four dimensions, are computed by integral transformation on a single compute node (or workstation). This is unfortunately not practical on HPC clusters, since a cluster node usually has moderate amount of memory which is not enough to store an object with $N^4$ elements (here $N$ is the number of orbitals). Therefore, the MO integral needs to be stored in a distributed way; in other words, each node need to store a portion of the four-dimensional MO integral. It is then natural to distribute the computation of MO integral as well, such that each node only computes part of the integral that needs to be stored locally. This leads to the so-called Fock matrix-driver integral transformation approach, where MO integrals are expressed in terms of Fock-like matrices {cite}`Hohenstein2015, gator`\n",
"\n",
"$$\n",
"\\langle ij || kl \\rangle = \\sum_{\\gamma \\delta}^{N} \\left [ C_{\\gamma k} F_{\\gamma \\delta}^{ij} C_{\\delta l} - C_{\\gamma l} F_{\\gamma \\delta}^{ij} C_{\\delta k} \\right ] \\, ,\n",
"$$\n",
"\n",
"where\n",
"\n",
"$$\n",
"F_{\\gamma \\delta}^{ij} &= \\sum_{\\alpha \\beta}^{N} D_{\\alpha \\beta}^{ij} (\\alpha \\gamma|\\delta \\beta) \\\\\n",
"D_{\\alpha \\beta}^{ij} &= C_{\\alpha i} C_{\\beta j} \\, .\n",
"$$\n",
"\n",
"In practice the $ij$ pairs and the corresponding $kl$ matrices are stored on individual nodes. This also facilitates parallelization of subsequent $\\sigma$-build (matrix-vector multiplication) with minimal amount of communications.\n",
"\n",
"In the HPC-QC implementation of ADC(2), another object that cannot be stored on a cluster node is the excitation vector that involves two particle-hole pairs (i.e., the double excitation part). This is because the vector of double excitation has four indices and its size increases as $O(N^4)$. Fortunately, explicit storage of the double excitation vector can be avoided by converting the standard eigenproblem in single and double space to a nonlinear eigenproblem in single space {cite}`Hattig2006`. By expanding the ADC(2) equation\n",
"\n",
"$$\n",
"\\begin{pmatrix} \\mathbf{M}_{\\text{SS}} & \\mathbf{M}_{\\text{SD}} \\\\ \\mathbf{M}_{\\text{DS}} & \\mathbf{M}_{\\text{DD}} \\end{pmatrix}\n",
"\\begin{pmatrix} \\mathbf{X}_{\\text{S}} \\\\ \\mathbf{X}_{\\text{D}} \\end{pmatrix}\n",
"= \\omega \\begin{pmatrix} \\mathbf{X}_{\\text{S}} \\\\ \\mathbf{X}_{\\text{D}} \\end{pmatrix} \\, ,\n",
"$$\n",
"\n",
"we have\n",
"\n",
"$$\n",
"\\mathbf{M}_{\\text{SS}} \\mathbf{X}_{\\text{S}} + \\mathbf{M}_{\\text{SD}} \\mathbf{X}_{\\text{D}} = \\omega \\mathbf{X}_{\\text{S}}\n",
"$$\n",
"$$\n",
"\\mathbf{M}_{\\text{DS}} \\mathbf{X}_{\\text{S}} + \\mathbf{M}_{\\text{DD}} \\mathbf{X}_{\\text{D}} = \\omega \\mathbf{X}_{\\text{D}} \\, ,\n",
"$$\n",
"\n",
"where $\\omega$ is the excitation energy, and $\\mathbf{X}_{\\text{S}}$ and $\\mathbf{X}_{\\text{D}}$ are the single and double excitation parts of the eigenvectors, respectively. The above two equations can be rewritten as (after eliminating $\\mathbf{X}_{\\text{D}}$)\n",
"\n",
"$$\n",
"\\left[ \\mathbf{M}_{\\text{SS}} + \\mathbf{M}_{\\text{SD}} (\\omega - \\mathbf{M}_{\\text{DD}})^{-1} \\mathbf{M}_{\\text{DS}} \\right] \\mathbf{X}_{\\text{S}} = \\omega \\mathbf{X}_{\\text{S}} \\, .\n",
"$$\n",
"\n",
"Note that $\\mathbf{M}_{\\text{DD}}$ is diagonal in ADC(2). Let\n",
"\n",
"$$\n",
"\\mathbf{M}_{\\text{eff}} = \\mathbf{M}_{\\text{SS}} + \\mathbf{M}_{\\text{SD}} (\\omega - \\mathbf{M}_{\\text{DD}})^{-1} \\mathbf{M}_{\\text{DS}} \\, ,\n",
"$$\n",
"\n",
"we have\n",
"\n",
"$$\n",
"\\mathbf{M}_{\\text{eff}} \\mathbf{X}_{\\text{S}} = \\omega \\mathbf{X}_{\\text{S}} \\, .\n",
"$$\n",
"\n",
"This is a nonlinear eigenproblem since $\\mathbf{M}_{\\text{eff}}$ depends on $\\omega$. The excitation energies and single excitation vectors can then be solved by a nonlinear eigensolver. Note that the resultant single excitation vectors need to be scaled to satisfy the following condition\n",
"\n",
"$$\n",
"\\mathbf{X}_{\\text{S}}^\\dagger \\mathbf{X}_{\\text{S}}^{ } + \\mathbf{X}_{\\text{D}}^\\dagger \\mathbf{X}_{\\text{D}}^{ } = 1 \\, ,\n",
"$$\n",
"\n",
"where $\\mathbf{X}_{\\text{D}}^\\dagger \\mathbf{X}_{\\text{D}}$ can be calculated as\n",
"\n",
"$$\n",
"\\mathbf{X}_{\\text{D}}^\\dagger \\mathbf{X}_{\\text{D}} = \\mathbf{X}_{\\text{S}}^\\dagger \\mathbf{M}_{\\text{SD}} (\\omega - \\mathbf{M}_{\\text{DD}})^{-2} \\mathbf{M}_{\\text{DS}} \\mathbf{X}_{\\text{S}} \\, .\n",
"$$\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "56fdf16a-b7a8-4649-a30c-2727221be846",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.9.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}