#!/usr/bin/env python # coding: utf-8 # # Overview of adcc # # ADC-connect – or adcc in short – is a Python-based framework to connect to arbitrary programs and perform calculations based on the algebraic-diagrammatic construction approach (ADC) on top of their existing self-consistent field (SCF) procedures. Four SCF codes can be used with adcc out of the box, namely [molsturm](https://molsturm.org), # [psi4](https://psicode.org/), [PySCF](https://github.com/pyscf/pyscf), and [veloxchem](https://veloxchem.org/), see [01_Backends.ipynb](01_Backends.ipynb). Without expressing any particular preference these notebooks will focus on psi4 and pyscf to obtain an SCF reference, but the other codes work very similar. # # This notebook and the others in the [0_basics](https://github.com/adc-connect/adcc/tree/doc/examples/0_basics) folder will introduce adcc from the practitioners perspective and give an idea of supported features. For a more structured documentation and an API reference, see https://adc-connect.org. In particular for installation instructions see https://adc-connect.org/installation.html. If you cannot be bothered to install adcc just to try these notebooks, just go to https://try.adc-connect.org, which will allow you to play with the notebooks from `0_basics` in your browser. # # In contrast these notebooks will not put a strong emphasis on the theory and numerical methods behind adcc, save a small introduction in [02_Theory.ipynb](02_Theory.ipynb). If you have the desire to dig deeper, a review of ADC literature is provided in https://adc-connect.org/theory.html. # ## A first calculation # Running a simple ADC calculation on top of an HF reference takes pretty much a single line of code. Let's see this in action for computing the excitation spectrum of water in the UV/vis range. First we prepare our reference in psi4 in a cc-pVTZ basis: # In[ ]: import psi4 import adcc # By default adcc uses all cores on the machnine. For the binder VMs we need # to reduce this a little and tell adcc to use two threads (see 03_Tweaks.ipynb) adcc.set_n_threads(2) # Run SCF in Psi4 using a cc-pVTZ basis mol = psi4.geometry(""" O 0 0 0 H 0 0 1.795239827225189 H 1.693194615993441 0 -0.599043184453037 symmetry c1 units au """) psi4.core.be_quiet() psi4.set_options({'basis': "cc-pvtz", }) scf_e, wfn = psi4.energy('SCF', return_wfn=True) # Next we perform an ADC(2) calculation on top, asking for 10 singlet states: # In[ ]: state = adcc.adc2(wfn, n_singlets=10) # We are greeted with a nice convergence table and the result of the calculation is stored in the `state`. Now let's actually look at it: # In[ ]: state # The result is again a table, summarising excitation energies, oscillator strengths as well as `|v1|^2` and `|v2|^2`, the norms of the singles and doubles blocks of the ADC vectors (to be explained in more detail in [02_Theory.ipynb](02_Theory.ipynb)). # # Note: If you are running adcc from a script, than just `print(state)` will not give you the same answer, instead you will have to explicitly call the `state.describe()` function, like so: # In[ ]: print(state.describe()) # With 10 states nicely computed, we want to plot a simulated excitation spectrum, which again can be done in a single function call: # In[ ]: state.plot_spectrum() # The plotted spectrum shows both the exact excitation energies with dashed lines as well as a Lorenzian envelope in solid. Notice that plot spectrum is pretty flexible and takes typical arguments you can pass to a `plt.plot` function call from matplotlib (which it uses under the hood), for example: # In[ ]: from matplotlib import pyplot as plt state.plot_spectrum(color="green", label="ADC(2)") plt.legend() # Another important way to get insight into a result is by looking at the dominating amplitudes (dominating orbital excitations) for each of the states: # In[ ]: print(state.describe_amplitudes()) # The default output is pretty detailed. You can get less printed by increasing the tolerance for printing an amplitude. For example: # In[ ]: print(state.describe_amplitudes(0.1)) # ## Comparing ADC methods # Let us get a feeling for adcc as well as the different ADC methods implemented by comparing the excitation spectra for our water molecule in a single plot. Since visual comparison can certainly not distinguish five digits in the energies we will also lower the convergence tolerance a little to speed up the calculation: # In[ ]: from matplotlib import pyplot as plt n_singlets = 10 state_1 = adcc.adc1(wfn, n_singlets=n_singlets, conv_tol=1e-3) # ADC(1) print() state_2x = adcc.adc2x(state.ground_state, n_singlets=n_singlets, # ADC(2)-x guesses=state.excitation_vectors, conv_tol=1e-3) # use ADC(2) result as guesses print() state_3 = adcc.adc3(state_2x.ground_state, n_singlets=n_singlets, guesses=state_2x.excitation_vectors, conv_tol=1e-3) # ADC(3) # Plot all results in one plot state_1.plot_spectrum(label="ADC(1)") state.plot_spectrum(label="ADC(2)") state_2x.plot_spectrum(label="ADC(2)-x") state_3.plot_spectrum(label="ADC(3)") plt.legend() # One clearly notices the increase in computational time between the methods of the ADC hierarchy. Between ADC(2) and ADC(2)-x the changes are usually most drastic due to an increase in computational scaling (from $O(N^5)$ to $O(N^6)$). # ## Getting help # # Documentation in adcc is still a little sparser than it should. Still most functions are documented and their docstrings can be easily obtained, for example: # In[ ]: get_ipython().run_line_magic('pinfo', 'adcc.adc2') # Last but not least, if you find a bug or need help you are always welcome to file [an issue](https://github.com/adc-connect/adcc/issues) or contact us by mail: developers@adc-connect.org.