ForceBalance API
1.3
Automated optimization of force fields and empirical potentials
|
Base class for all fitting targets. More...
Public Member Functions | |
def | __init__ (self, options, tgt_opts, forcefield) |
All options here are intended to be usable by every conceivable type of target (in other words, only add content here if it's widely applicable.) More... | |
def | get_X (self, mvals=None, customdir=None) |
Computes the objective function contribution without any parametric derivatives. More... | |
def | read_0grads (self) |
Read a file from the target directory containing names of parameters that don't contribute to the gradient. More... | |
def | write_0grads (self, Ans) |
Write a file to the target directory containing names of parameters that don't contribute to the gradient. More... | |
def | get_G (self, mvals=None, customdir=None) |
Computes the objective function contribution and its gradient. More... | |
def | get_H (self, mvals=None, customdir=None) |
Computes the objective function contribution and its gradient / Hessian. More... | |
def | link_from_tempdir (self, absdestdir) |
def | refresh_temp_directory (self) |
Back up the temporary directory if desired, delete it and then create a new one. More... | |
def | get (self, mvals, AGrad=False, AHess=False) |
Every target must be able to return a contribution to the objective function - however, this must be implemented in the specific subclass. More... | |
def | check_files (self, there) |
Check this directory for the presence of readable files when the 'read' option is set. More... | |
def | read (self, mvals, AGrad=False, AHess=False) |
Read data from disk for the initial optimization step if the user has provided the directory to the "read" option. More... | |
def | absrd (self, inum=None) |
Supply the correct directory specified by user's "read" option. More... | |
def | maxrd (self) |
Supply the latest existing temp-directory containing valid data. More... | |
def | maxid (self) |
Supply the latest existing temp-directory. More... | |
def | meta_indicate (self, customdir=None) |
Wrap around the indicate function, so it can print to screen and also to a file. More... | |
def | meta_get (self, mvals, AGrad=False, AHess=False, customdir=None) |
Wrapper around the get function. More... | |
def | submit_jobs (self, mvals, AGrad=False, AHess=False) |
def | stage (self, mvals, AGrad=False, AHess=False, customdir=None, firstIteration=False) |
Stages the directory for the target, and then launches Work Queue processes if any. More... | |
def | wq_complete (self) |
This method determines whether the Work Queue tasks for the current target have completed. More... | |
def | printcool_table (self, data=OrderedDict([]), headings=[], banner=None, footnote=None, color=0) |
Print target information in an organized table format. More... | |
def | serialize_ff (self, mvals, outside=None) |
This code writes a force field pickle file to an folder in "job.tmp/dnm/forcebalance.p", because it takes time to compress and most targets can simply reuse this file. More... | |
Public Attributes | |
rd | |
Root directory of the whole project. More... | |
pgrad | |
Iteration where we turn on zero-gradient skipping. More... | |
tempbase | |
Relative directory of target. More... | |
tempdir | |
rundir | |
self.tempdir = os.path.join('temp',self.name) The directory in which the simulation is running - this can be updated. More... | |
FF | |
Need the forcefield (here for now) More... | |
xct | |
mol2 files that are stored in the forcefield folder need to be included in the list of mol2 files for the target More... | |
gct | |
Counts how often the gradient was computed. More... | |
hct | |
Counts how often the Hessian was computed. More... | |
read_indicate | |
Whether to read indicate.log from file when restarting an aborted run. More... | |
write_indicate | |
Whether to write indicate.log at every iteration (true for all but remote.) More... | |
read_objective | |
Whether to read objective.p from file when restarting an aborted run. More... | |
write_objective | |
Whether to write objective.p at every iteration (true for all but remote.) More... | |
evaluated | |
Create a new temp directory. More... | |
goodstep | |
This flag specifies whether the previous optimization step was good. More... | |
ffpd | |
Base class for all fitting targets.
In ForceBalance a Target is defined as a set of reference data plus a corresponding method to simulate that data using the force field.
The 'computable quantities' may include energies and forces where the reference values come from QM calculations (energy and force matching), energies from an EDA analysis (Maybe in the future, FDA?), molecular properties (like polarizability, refractive indices, multipole moments or vibrational frequencies), relative entropies, and bulk properties. Single-molecule or bulk properties can even come from the experiment!
The central idea in ForceBalance is that each quantity makes a contribution to the overall objective function. So we can build force fields that fit several quantities at once, rather than putting all of our chips behind energy and force matching. In the future ForceBalance may even include multiobjective optimization into the optimizer.
The optimization is done by way of minimizing an 'objective function', which is comprised of squared differences between the computed and reference values. These differences are not computed in this file, but rather in subclasses that use Target as a base class. Thus, the contents of Target itself are meant to be as general as possible, because the pertinent variables apply to all types of fitting targets.
An important node: Target requires that all subclasses have a method get(self,mvals,AGrad=False,AHess=False) that does the following:
Inputs: mvals = The parameter vector, which modifies the force field (Note to self: We include mvals with each Target because we can create copies of the force field and do finite difference derivatives) AGrad, AHess = Boolean switches for computing analytic gradients and Hessians
Outputs: Answer = {'X': Number, 'G': array(NP), 'H': array((NP,NP)) } 'X' = The objective function itself 'G' = The gradient, elements not computed analytically are zero 'H' = The Hessian, elements not computed analytically are zero
This is the only global requirement of a Target. Obviously 'get' itself is not defined here, because its calculation will depend entirely on specifically which target we wish to use. However, this should give us a unified framework which will faciliate rapid implementation of Targets.
Future work: Robert suggested that I could enable automatic detection of which parameters need to be computed by finite difference. Not a bad idea. :)
def src.target.Target.__init__ | ( | self, | |
options, | |||
tgt_opts, | |||
forcefield | |||
) |
All options here are intended to be usable by every conceivable type of target (in other words, only add content here if it's widely applicable.)
If we want to add attributes that are more specific (i.e. a set of reference forces for force matching), they are added in the subclass AbInitio that inherits from Target.
Definition at line 94 of file target.py.
def src.target.Target.absrd | ( | self, | |
inum = None |
|||
) |
def src.target.Target.check_files | ( | self, | |
there | |||
) |
def src.target.Target.get | ( | self, | |
mvals, | |||
AGrad = False , |
|||
AHess = False |
|||
) |
def src.target.Target.get_G | ( | self, | |
mvals = None , |
|||
customdir = None |
|||
) |
Computes the objective function contribution and its gradient.
First the low-level 'get' method is called with the analytic gradient switch turned on. Then we loop through the fd1_pids and compute the corresponding elements of the gradient by finite difference, if the 'fdgrad' switch is turned on. Alternately we can compute the gradient elements and diagonal Hessian elements at the same time using central difference if 'fdhessdiag' is turned on.
In this function we also record which parameters cause a nonzero change in the objective function contribution. Parameters which do not change the objective function will not be differentiated in subsequent calculations. This is recorded in a text file in the targets directory.
Definition at line 301 of file target.py.
def src.target.Target.get_H | ( | self, | |
mvals = None , |
|||
customdir = None |
|||
) |
Computes the objective function contribution and its gradient / Hessian.
First the low-level 'get' method is called with the analytic gradient and Hessian both turned on. Then we loop through the fd1_pids and compute the corresponding elements of the gradient by finite difference, if the 'fdgrad' switch is turned on.
This is followed by looping through the fd2_pids and computing the corresponding Hessian elements by finite difference. Forward finite difference is used throughout for the sake of speed.
Definition at line 326 of file target.py.
def src.target.Target.get_X | ( | self, | |
mvals = None , |
|||
customdir = None |
|||
) |
def src.target.Target.link_from_tempdir | ( | self, | |
absdestdir | |||
) |
def src.target.Target.maxid | ( | self | ) |
def src.target.Target.maxrd | ( | self | ) |
def src.target.Target.meta_get | ( | self, | |
mvals, | |||
AGrad = False , |
|||
AHess = False , |
|||
customdir = None |
|||
) |
Wrapper around the get function.
Create the directory for the target, and then calls 'get'. If we are reading existing data, go into the appropriate read directory and call read() instead. The 'get' method should not worry about the directory that it's running in.
Definition at line 570 of file target.py.
def src.target.Target.meta_indicate | ( | self, | |
customdir = None |
|||
) |
def src.target.Target.printcool_table | ( | self, | |
data = OrderedDict([]) , |
|||
headings = [] , |
|||
banner = None , |
|||
footnote = None , |
|||
color = 0 |
|||
) |
Print target information in an organized table format.
Implemented 6/30 because multiple targets are already printing out tabulated information in very similar ways. This method is a simple wrapper around printcool_dictionary.
The input should be something like:
data | Column contents in the form of an OrderedDict, with string keys and list vals. The key is printed in the leftmost column and the vals are printed in the other columns. If non-strings are passed, they will be converted to strings (not recommended). |
headings | Column headings in the form of a list. It must be equal to the number to the list length for each of the "vals" in OrderedDict, plus one. Use "\n" characters to specify long column names that may take up more than one line. |
banner | Optional heading line, which will be printed at the top in the title. |
footnote | Optional footnote line, which will be printed at the bottom. |
Definition at line 701 of file target.py.
def src.target.Target.read | ( | self, | |
mvals, | |||
AGrad = False , |
|||
AHess = False |
|||
) |
def src.target.Target.read_0grads | ( | self | ) |
Read a file from the target directory containing names of parameters that don't contribute to the gradient.
Note that we are checking the derivatives of the objective function, and not the derivatives of the quantities that go into building the objective function. However, it is the quantities that we actually differentiate. Since there is a simple chain rule relationship, the parameters that do/don't contribute to the objective function/quantities are the same.
However, property gradients do contribute to objective function Hessian elements, so we cannot use the same mechanism for excluding the calculation of property Hessians. This is mostly fine since we rarely if ever calculate an explicit property Hessian.
def src.target.Target.refresh_temp_directory | ( | self | ) |
def src.target.Target.serialize_ff | ( | self, | |
mvals, | |||
outside = None |
|||
) |
This code writes a force field pickle file to an folder in "job.tmp/dnm/forcebalance.p", because it takes time to compress and most targets can simply reuse this file.
Inputs: mvals = Mathematical parameter values outside = Write this file outside the targets directory
def src.target.Target.stage | ( | self, | |
mvals, | |||
AGrad = False , |
|||
AHess = False , |
|||
customdir = None , |
|||
firstIteration = False |
|||
) |
def src.target.Target.submit_jobs | ( | self, | |
mvals, | |||
AGrad = False , |
|||
AHess = False |
|||
) |
def src.target.Target.wq_complete | ( | self | ) |
def src.target.Target.write_0grads | ( | self, | |
Ans | |||
) |
src.target.Target.evaluated |
src.target.Target.gct |
src.target.Target.goodstep |
src.target.Target.hct |
src.target.Target.pgrad |
src.target.Target.rd |
Root directory of the whole project.
Name of the target Type of target Relative weight of the target Switch for finite difference gradients Switch for finite difference Hessians Switch for FD gradients + Hessian diagonals How many seconds to sleep (if any) Parameter types that trigger FD gradient elements Parameter types that trigger FD Hessian elements Finite difference step size Whether to make backup files Directory to read data from.
src.target.Target.read_indicate |
src.target.Target.read_objective |
src.target.Target.rundir |
self.tempdir = os.path.join('temp',self.name) The directory in which the simulation is running - this can be updated.
Directory of the current iteration; if not None, then the simulation runs under temp/target_name/iteration_number The 'customdir' is customizable and can go below anything.
Not expecting more than ten thousand iterations Go into the directory where get() will be executed. Write mathematical parameters to file; will be used to checkpoint calculation. Read in file that specifies which derivatives may be skipped.
src.target.Target.tempbase |
src.target.Target.write_indicate |
src.target.Target.write_objective |
src.target.Target.xct |