Skip to content

Performing a Structure Optimization

This next example shows how to submit a geometry optimization for a single water molecule. Please note that this examples uses the ASE optimizers, not the ones provided by FHI-aims internally. The calculation time for larger systems probably needs to be improved by executing the calculation via an IO-Socket.

The submit script for this task closely resembles the one used for the previous single point calculation. Let us take a look at the parts which are different:

  1. Structure generation: Quite obviously the molecular geometry of water has to be constructed in a different manner than before. Here, an ASE Atoms object is constructed, holding a single water molecule confined to a 4x4x4 cubic cell.

    cell = [[4., 0., 0.], [0., 4., 0.], [0., 0., 4.]]
    water = Atoms('HOH', [(1, 0, 0), (0, 0, 0), (0, 1, 0)], cell=cell)  
    
  2. Defining the calculation parameters: Apart from the input structure, the calculation parameters have to be expanded. First, let us try to obtain more than just the potential energy of the optimized system. For example, we can instruct FHI-aims to calculate the dipole moment, too, by setting the output argument accordingly.

    'calculator':
       ...
       'args': {
           ...
           'output': ['dipole'],
           ...
       }
    ...
    

    As we will be using the built-in ASE optimizers to drive the relaxation, the QuasiNewton method is set up with a modified α parameter. calculation_getters tell AiiDA which results it should try to extract from the calculation output and store in its database. For example, we will retrieve the energy for the spin-polarized system and the atomic dipole moments.

        ...
        'optimizer': {
            'name': 'QuasiNewton',
            'args': {
                'alpha': 0.9
            },
            'run_args': {
                'fmax': 0.05
            }
        },
        'calculator_getters': [
            ['potential_energy', {}],
            'spin_polarized',                             
            ['dipole_moment', ['atoms']]
        ],
    }
    

As one can see, it is rather straigth-forward to generalize an existing AiiDA script or transfer it to a very different task. Please find the full script below.

"""Example script of performing an FHI-aims geometry optimization on water."""

from aiida.engine import submit
from aiida.orm import load_code
from aiida.plugins import DataFactory, CalculationFactory

# ASE imports for structure building.
from ase import Atoms
from ase.calculators.aims import AimsCube
from ase.optimize import QuasiNewton

Dict = DataFactory('dict')
StructureData = DataFactory('structure')
KpointsData = DataFactory('array.kpoints')
AseCalculation = CalculationFactory('ase.ase')

# Change the following value to the ``Code`` that you have configured.
code = 'aseremote2@cs1.1'

# Build the structure.
cell = [[4., 0., 0.], [0., 4., 0.], [0., 0., 4.]]
water = Atoms('HOH', [(1, 0, 0), (0, 0, 0), (0, 1, 0)], cell=cell)  

parameters = {
    'calculator': {
        'name': 'aims.Aims',
        'args': {
            'aims_command': 'AIMS_EXECUTABLE',
            'outfilename': 'aims.out',
            'species_dir': 'PATH/TO/SPECIES/DIRECTORY/',
            'xc': 'PBE',
            'output': ['dipole'],
            'sc_accuracy_etot': 1e-4,
            'sc_accuracy_eev': 1e-2,
            'sc_accuracy_rho': 1e-4,
            'sc_accuracy_forces': 1e-3
        }
    },
    'optimizer': {
        'name': 'QuasiNewton',
        'args': {
            'alpha': 0.9
        },
        'run_args': {
            'fmax': 0.05
        }
    },
    'calculator_getters': [
        ['potential_energy', {}],
        'spin_polarized',                             
        ['dipole_moment', ['atoms']]
    ],
}

metadata = {
    'label': 'H2O with FHIAims',
    'description': 'Test calculation of FHI-aims using `aiida-ase`.',
    'options': {
        'resources': {
            'num_machines': 1,
            'num_mpiprocs_per_machine': 1
        },
        'max_wallclock_seconds': 30 * 60                             
    }
}

codes = load_code(code)
builder = codes.get_builder()
builder.structure = StructureData(ase=water)                       
builder.parameters = Dict(dict=parameters)
builder.metadata = metadata

submit(builder)