NBO with ADF

NBO 6.0 is a tool for Natural Bond order analysis that uses the results of an ADF calculation. More information about NBO can be found in the corresponding section of the ADF manual.

NBO analysis is performed based on a prior ADF calculation (with some special keywords) by using two separate binary executables: adfnbo and gennbo6. In this case no special job type is created for these binaries. Instead of that we extend the AMSJob class in such a way that calls of adfnbo and gennbo6 are appended to the usual ADF runscript. We also make sure that all the required ADF keywords are present in the initial ADF input file. Input keywords for adfnbo are taken from myjob.settings.adfnbo. All this work happens in prerun(). No specialized Results subclass is defined for ADFNBOJob.

The source code of the whole module:

import os

from scm.plams.core.functions import log
from scm.plams.interfaces.adfsuite.ams import AMSJob

__all__ = ["ADFNBOJob"]


class ADFNBOJob(AMSJob):

    def prerun(self):  # noqa F811
        s = self.settings.input.ADF
        s.fullfock = True
        s.aomat2file = True
        s.symmetry = "NoSym"
        s.basis.core = "None"
        if "save" in s:
            if isinstance(s.save, str):
                s.save += " TAPE15"
            elif isinstance(s.save, list):
                s.save.append("TAPE15")
            else:
                log(
                    "WARNING: 'SAVE TAPE15' could not be added to the input settings of {}. Make sure (thisjob).settings.input.save is a string or a list.".format(
                        self.name
                    ),
                    1,
                )
        else:
            s.save = "TAPE15"

        if isinstance(self.settings.adfnbo, list):
            adfnbo_input = self.settings.adfnbo
        else:
            adfnbo_input = ["write", "spherical", "fock"]
            log(
                "WARNING: (thisjob).settings.adfnbo should be a list. Using default settings: write, fock, spherical", 1
            )

        self.settings.runscript.post = (
            'cp "' + os.path.join(self.path, "adf.rkf") + '" TAPE21\n'
            "$AMSBIN/adfnbo <<eor\n" + "\n".join(adfnbo_input) + "\neor\n\n$AMSBIN/gennbo6 FILE47\n"
        )

An example usage: (methane.xyz, adfnbo_test.py)

5

         C      0.000000      0.000000      0.000000
         H      0.631600      0.631600      0.631600
         H      0.631600     -0.631600     -0.631600
         H     -0.631600      0.631600     -0.631600
         H     -0.631600     -0.631600      0.631600
from scm.plams import Settings, Molecule
from scm.plams.recipes.adfnbo import ADFNBOJob

mol = Molecule("methane.xyz")

s = Settings()
s.input.AMS.Task = "SinglePoint"
s.input.ADF.basis.type = "DZP"
s.input.ADF.xc.lda = "SCF VWN"
s.input.ADF.relativity.level = "scalar"
s.adfnbo = ["write", "spherical", "fock"]

j = ADFNBOJob(molecule=mol, settings=s)
r = j.run()

lines = r.get_output_chunk(begin="NATURAL BOND ORBITALS (Summary):", end="Charge unit", inc_begin=True, inc_end=True)
for line in lines:
    print(line)