Input and output

The main input/output mechanism in Asap is the ASE Trajectories, described in the ASE Manual chapter on Trajectory files.

Trajectory objects are objects storing the temporal evolution of a simulation. A Trajectory file contains one or more Atoms objects, usually representing the time evolution of a molecular dynamics simulation.

It is important that you import the Trajectory objects from asap3.io.trajectory instead of directly from ASE, since you will then get modified versions that work with ASE’s way of parallelizing simulations.

Currently, Asap supports three kinds of Trajectory formats:

Trajectory

This is the default ASE Trajectory format, using ASE’s own file format. Unlike the ASE version, forces are not saved in parallel simulations. Use properties=['forces'] to cause them to be saved. Advantage: Simplicity. Disadvantage: The master node collects all information about the atoms, for very large simulations this can be a problem due to insufficient memory.

BundleTrajectory

A special Trajectory format, where data is stored in a directory rather than in a flat file. Advantage: For sufficiently large simulations, each node writes its own data for better performance and less RAM overhead on the master. Disadvantage: The output “file” is a directory, in some cases this can be a slight inconvenience. Furthermore, this format is inefficient for small simulations.

Using trajectories with simulations on a single processor

These simulations are all shown with the default Trajectory format. Replace Trajectory with BundleTrajectory if you wish to use that format.

Reading a configuration

Usually, you want to read the last (often the only) configuration from a Trajectory file in order to start your simulation. It can be done like this:

from asap3.io.trajectory import *
traj = Trajectory("inputfile.traj")
atoms = traj[-1]
traj.close()

and the atoms object can now be used to run a simulation (but remember to associate an Asap calculator to the atoms with set_calculator(), the calculator is not saved in the trajectory file).

You can also use the ASE function read() to do the same:

atoms = read("inputfile.traj")

Writing a trajectory of a running simulation

Just attach the trajectory to the dynamics object, specifying how often the data should be written. This example creates a trajectory. The initial configuration is automatically written to the file when the trajectory object is created. Then, for every 100 time steps the atoms are written to the file.

# dyn is the dynamics object, e.g. VelocityVerlet
traj = Trajectory("outputfile.traj", "w", atoms)
dyn.attach(traj, interval=100)
dyn.run(nsteps)  # Run the simulation.

Trajectories in parallel simulations

In a parallel simulation, atoms are distributed amongst the processors, but should still be written to and read from the same file. The Asap version of Trajectory supports this automatically when writing. When reading, there are several ways to do it depending on what you want to do, and a new method, get_atoms() has been added to Trajectory, BundleTrajectory and PickleTrajectory.

traj.get_atoms(n, cpus=None):

Return Atoms object number n from the trajectory.

traj.get_atoms(n) is very similar to traj[n], but with the following differences:

In serial simulations traj.get_atoms(n) and traj[n] are equivalent.

In parallel simulations:

traj[n] returns all atoms on all processors

traj.get_atoms(n) returns all atoms on the master, and None on all other processors.

traj.get_atoms(n, cpus) returns a ParallelAtoms object with atoms distributed among the processors, and processor layout given by cpus (three integers or the keyword ‘auto’).

traj.get_atoms_distributed(n, cpus='auto', extra=None, verbose=True):

Reads very large simulation in less memory intensive way.

This version of get_atoms is intended for reading huge simulations in massively parallel simulations, when there is not enough RAM to temporarily store all atoms on the master node.

This ONLY works for a BundleTrajectory written in “split mode”, i.e. written by a large parallel ASAP simulation.

Parameters:

n: The frame number to be read. Use -1 for the last one.

cpus: The CPU layout. Three integers or the keywork ‘auto’.

extra: List of names of extra arrays to be read.

verbose: Write progress info to standard output.

Reading a configuration

To read the atoms from “inputfile.traj” and initialize a parallel simulation running on 2 x 2 x 3 cpus:

traj = PickleTrajectory("inputfile.traj")
atoms = traj.get_atoms(-1, cpus=[2,2,3])
del traj  # release memory on master node.

Writing a trajectory of a running simulation

This is identical to the case of the serial simulation. Trajectory automatically detects a parallel Atoms object, and acts accordingly (if imported from asap and not directly from ase).