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:

from ..interfaces.adfsuite.ams import AMSJob
from ..core.functions import log
import os

__all__ = ['ADFNBOJob']

class ADFNBOJob(AMSJob):

    def prerun(self):
        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):
                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)
            s.save = 'TAPE15'

        if isinstance(self.settings.adfnbo, list):
            adfnbo_input = self.settings.adfnbo
            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:

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)