5.1.2. Dictionary MultiJob

Although by default MultiJob stores its children in a list, it’s often very handy to use a dictionary instead. A simple example on using a MultiJob to easily organize multiple similar calculations:

# Read all molecules from the given folder
molecules = read_molecules('molecules')

# Calculate, for each molecule, the "total" bond order:
for molecule in molecules.values():
    molecule.guess_bonds()
    molecule.properties.total_bond_order = sum([bond.order for bond in molecule.bonds])

# Initialize the common settings:
settings = Settings()
settings.input.Basis.Core = 'None'
settings.input.NumericalQuality = 'Good'
settings.input.Relativistic = 'Scalar ZORA'
settings.input.XC.GGA = 'PBE'

basis = ['SZ', 'DZ', 'DZP', 'TZP', 'TZ2P', 'QZ4P']
reference_basis = 'QZ4P'

# Children jobs stored in this MultiJob will be indexed by pairs (molecule_name, basis)
job = MultiJob(children=dict())

for bas in basis:
    # Add the basis set to the settings:
    settings.input.Basis.Type = bas
    for name, mol in molecules.items():
        job.children[(name,bas)] = ADFJob(name=name+'_'+bas, molecule=mol, settings=settings)

job.run()

# Calculate the average absolute error for each basis set:
for bas in basis:
    if bas != reference_basis:
        errors = []
        for name, mol in molecules.items():
            ref_energy = job.children[(name,reference_basis)].results.get_energy()
            energy = job.children[(name,bas)].results.get_energy()
            errors.append(abs(energy - ref_energy)/mol.properties.total_bond_order)
        avg_error = Units.convert(sum(errors)/len(errors), 'au', 'kcal/mol')
        print('Basis set: {} Average Absolute Error per bond [kcal/mol]: {}'.format(bas, avg_error))