Simpatico  v1.10
4.4 Potential Energy Classes

4.3 Factory Classes (Prev)         4.5 Sub-Factories (Next)

Overview

Subclass of potential energy classes are implemented somewhat differently than other polymorphic classes. Each subclass of a potential energy class is implemented by a class template that takes a simpler "interaction" class as an argument. Each "interaction" class defines a specific potential energy function (e.g., a harmonic bond potential) and provides functions that implement the core calculations of forces and energies for a small group of atoms (e.g., a single bonded pair). The class templates that are used to define potential energy subclasses implement algorithms that require looping over such groups (e.g., over all bonds or all nonbonded pairs) in order to calculate contributions to the system energy or forces on all atoms.

For example, the subclass of DdMd::BondPotential that implements a harmonic bond potential is given by a template instantiation DdMd::BondPotentialImpl<Simp::HarmonicBond>. In this example, Simp::HarmonicBond is an interaction class that implements the calculation of harmonic bond energy and forces for a single pair of bonded atoms. DdMd::BondPotentialImpl is a class template that implements the loops over bonds required calculate total bond energy for a system, or to calculate bond forces on all atoms. Analogous sets of potential energy abstract base classes and implementation templates are defined in the McMd and DdMd namespaces for different types of potential energy (pair, angle, etc.), as discussed below in more detail.

Because of this use of templates, the procedure required to add a new potential energy class is slightly different than the procedure required for other abstract base classes. Briefly, one must:

Each of these steps is discussed in greater detail below.

Potential energy base classes

The mcSim and mdSim programs use the following set of abstract base classes for potential energies, which are defined in the McMd namespace:

The ddSim program uses an analogous set of base classes, which are defined in the DdMd namespace:

Most names are self-explanatory: Pair potentials represented non-bonded two body interactions. Bond, Angle, and Dihedral potentials represent 2-body bond, 3-body angle, and 4-body dihedral covalent interactions. An ExternalPotential represents a one-body potential in which the energy depends upon the position and type of a single atom.

The main difference between the sets of potential energy classes in the DdMd and McMd namespaces is that that McMd namespace contains two different base classes for nonbonded pair interactions for MC and MD simulations, named McPairPotential and MdPairPotential, while the DdMd contains only a single such class, named PairPotential. Different base classes are defined in the McMd namespace because MC and MD simulations require different interfaces and different underlying data structures. Only MC requires the ability to efficiently calculate the pair energy of a single atom, and the Verlet-list data structure used in the implementation of McMd::MdPairPotential MD does not provide an efficient way to implement this calculation. For all other potential energy types (i.e., for bond, angle, dihedral, and external potentials), a single McMd base provides an interface suitable for both MD and MC simulations.

Each of the above potential energy base classes declare two different types of functions to calculate energies and forces:

Every class that is intended for use in MD simulation (i.e., all the DdMd potentials and all of the McMd potentials except McPairPotential) declares a function that calculate the forces exerted on all atoms in a System by the associated potential energy (e.g., all nonbonded pair forces). Every McMd potential energy classes that is intended for use in MC simulations (i.e,. all except MdPairPotential) declares a function that calculates the corresponding energy contribution for a specific atom.

Interaction classes

Concrete subclasses of these abstract potential energy classes are implemented using a set of "interaction" classes. The interaction classes are defined in the Simp namespace. Each interaction class represents a specific functional form for a specific type of potential energy contribution that involves a small group of 1, 2, 3, or 4 atoms. For example, Simp::LJPair is a pair interaction class the implements a Lennard-Jones part potential, while Simp::HarmonicBond is a covalent bond interaction that implements a harmonic bond potential. The interaction classes provide non-virtual functions to calculate the energy and forces for a single group of interacting atoms, such as a single pair of nonbonded or bonded atoms. Different interaction classes of the same type are not descended from a common base class, and are thus not polymorphic, but must implement the same interface in order to be used in the same potential energy templates. Unlike potential energy classes, interaction classes do not provide system-wide calculations that involve, e.g., looping over nonbonded-pairs or covalent groups of an associated system.

Interaction classes should be derived from ParamComposite. Each such class must invoke ParamComposite::setClassName(std::string& ) in its constructor.

Implementation templates

Subclasses of the potential energy base classes are implemented by templates. The name of each such class template ends with the suffix "Impl", for "implementation". Each such class template takes an interaction class as a template argument, and is defined as a subclass of the associated potential energy base class. The McMd and DdMd namespaces contain separate but analogous sets of potential energy implementation templates.

For example, the template that implements the DdMd::BondPotential interface is called DdMd::BondPotentialImpl. The template instantiation DdMd::BondPotentialImpl<Simp::HarmonicBond> is a subclass of DdMd::BondPotential that can calculate forces, energies, and stress contributions arising from a harmonic bond potential for use in ddSim simulations. This template implements functions that can loop over all bonds in a system, as required to calculate the total bond energy of a system or to calculate bond forces for all atoms. These functions call member functions of the associated interaction class to calculate forces and/or energies for individual bonds. Analogous templates are provided in the McMd and DdMd namespaces for pair, bond, angle, dihedral, and external forces.

For the special case of non-bonded pair potentials, the McMd namespace contains two different class templates, named McMd::McPairPotentialImpl and McMd::MdPairPotentialImpl, that are designed for use in MC and MD simulations, respectively. These use different data structures and algorithms to do the energy and force calculations required in MC and MD simulations. The McPairPotentialImpl template uses a cell list that is optimized for use in MC simulations, while MdPairPotentialImpl uses a Verlet pair list.

Factory classes

Simpatico provides a default factory class for each of the above types of potential energy. The BondFactory, AngleFactory, DihedralFactory, and ExternalFactory classes in the McMd namespace, and analogous classes in the DdMd namesapce, are derived from instantiations of the Util::Factory template. Like other factory classes, these classes each provide a factory() method that takes a string argument and that (if possible) returns a pointer to a new instance of a subclass of the associated base class. In all of the potential energy factory classes, the string that is passed as an argument to the factory method is actually the value of an associated "style" string parameter, such as "pairStyle". The value of the style string is generally the same as the name of the interaction class that implements the relevant potential energy function. For example, if the DdMd::BondFactory::factory(std::string&) method is passed the string "HarmonicBond", it constructs an instance of DdMd::BondPotentialImpl<HarmonicBond>, and returns a "DdMd::HarmonicBond* base class pointer to this newly constructed object.

As an example, here is the relevant part of the source code for the DdMd::BondFactory class:

#include <ddMd/potentials/bond/BondFactory.h>
#include <ddMd/simulation/Simulation.h>
// BondPotential base class and implementation template
#include <ddMd/potentials/bond/BondPotential.h>
#include <ddMd/potentials/bond/BondPotentialImpl.h>
// Bond interaction classes
#include <simp/bond/HarmonicBond.h>
#include <simp/bond/HarmonicL0Bond.h>
namespace DdMd
{
using namespace Simp;
// Return a pointer to a new BondPotential, if possible.
BondPotential* BondFactory::factory(const std::string& name) const
{
BondPotential* ptr = 0;
// Try subfactories first.
ptr = trySubfactories(name);
if (ptr) return ptr;
if (name == "HarmonicBond") {
ptr = new BondPotentialImpl<HarmonicBond>(*simulationPtr_);
} else
if (name == "HarmonicL0Bond") {
ptr = new BondPotentialImpl<HarmonicL0Bond>(*simulationPtr_);
} else
if (name == "FeneBond") {
ptr = new BondPotentialImpl<FeneBond>(*simulationPtr_);
}
return ptr;
}
}

Except for the use of templates for subclasses, the implementation of most potential energy factory classes is quite similar to those of other factory classes.

McMd::PairFactory class

The McMd::PairFactory class is slightly different from the other potential energy factories. This class provides two methods, named mdFactory() and mcFactory(), that each take the name of a pair style string, such as "LJPair", and return an MdPairPotential* or McPairPotential* pointer to a new object, respectively. The signatures of these methods are:

McMd::McPairPotential* mcFactory(std::string& className, McMd::System& );
McMd::MdPairPotential* mdFactory(std::string& className, McMd::System& );

Because McMd::PairFactory does not implement the same interface as the Util::Factory template, it is not derived from an instantiation of the Util::Factory template.

McMd::PairFactory also provides a third factory method that takes an McMd::McPairPotential by reference and returns a pointer to a corresponding McMd::MdPairPotential. This method is used to implement hybrid MC simulations, in which short MD simulations are used as proposed MC moves. It is used to construct an McMd::MdPairPotential for use in the required MD simulations that implements the same pair interaction as the McMd::McPairPotential used by the parent MC simulation.

Developers should consult the implementations of the default McMd::PairFactory method for further guidance. It is straightforward to add new pair potentials to this factory by imitation of the existing code.


4.3 Factory Classes (Prev)         4 Extending Simpatico (Up)         4.5 Sub-Factories (Next)