ParallelEnergyAndForces(configurations, processes_per_configuration, filenames=None, master_only=True)¶
Evaluates the energy and forces for a list of configurations in parallel.
- configurations (list of configurations
DeviceConfiguration)) – A list of configurations with attached calculators.
- processes_per_configuration (int) – The number of MPI processes to use for calculating the energy and forces on each configuration.
- log_filenames (list of strings) – A list of filenames to log each calculation to. It must
be the same length as the configurations argument. If None
is given, then logging will be performed to stdout.
All calculations are logged to stdout
- master_only (bool) – Controls if the master process should be the only
rank allowed to write to the log.
A tuple of energies and forces as PhysicalQuantity arrays.
- configurations (list of configurations (
Calculate the potential energy curve and forces for a hydrogen molecule in parallel. At the end of the script, a table of internuclear distances, energies, and the force is printed to the screen.
# Make a list to hold the configurations. configurations =  # Loop over a list of distances between 0.3 and 5.0 Angstrom. distances = numpy.linspace(0.3, 5.0, 20) for distance in distances: # Define elements elements = [Hydrogen, Hydrogen] # Define coordinates cartesian_coordinates = [[ 0.0, 0.0, 0.0 ], [ distance, 0.0, 0.0 ]]*Angstrom # Set up configuration molecule_configuration = MoleculeConfiguration( elements=elements, cartesian_coordinates=cartesian_coordinates ) # Define a calculator molecule_configuration.setCalculator(LCAOCalculator()) # Add the configuration to the list of configurations. configurations.append(molecule_configuration) def task_function(configuration, index): # Compute the total energy. total_energy = TotalEnergy(configuration) # Save the result to a file. nlsave('total_energy_%i.hdf5'%index, configuration) # Return the calculated total energy. return total_energy.evaluate() # Define a list of filenames to save the logging output from each calculation to. filenames = [ 'total_energy_%i.log' % i for i in range(len(configurations)) ] # Calculate the energy of each configuration. Each calculation will use 2 MPI processes. energies = ParallelMapConfigurations( task_function, configurations, processes_per_configuration=2, filenames=filenames, ) # Only print on the master process. This prevents the table from being printed multiple times. if processIsMaster(): print('%10s %12s' % ('distance', 'energy')) for i in range(len(configurations)): print('%10.4f %12.3e' % (distances[i], energies[i].inUnitsOf(eV)))
It is important to properly coordinate the total number of MPI processes, the
processes_per_configuration argument, and the number of configurations. When
ParallelEnergyAndForces is called, the MPI processes are divided up into
processes_per_configuration sized groups. For example, if there are 8 MPI processes and
processes_per_configuration=2, then 4 groups will be made. However, if there are only 2 configurations in the
configurations list then 2 of those groups will be idle.
Ideally, one would pick
processes_per_configuration to be the largest number of processes that a single DFT calculation runs efficiently on. This generally depends on a number of variables including the number of atoms, basis set size, computer hardware, etc. Then, the total number of MPI processes should be an integer multiple of
This function can be used with ATK-ForceFiled calculators as well.
However, ATK-ForceField does not currently make use of MPI.
This means that
processes_per_configuration should always be set to 1 in order not to
have idle processes.
See also, Notes.