1 """ @package forcebalance.moments Multipole moment fitting module 6 from __future__
import division
8 from builtins
import zip
12 from forcebalance.nifty import col, eqcgmx, flat, floatornan, fqcgmx, invert_svd, kb, printcool, printcool_dictionary, bohr2ang, warn_press_key
13 from forcebalance.target
import Target
15 from re
import match, sub
18 from subprocess
import PIPE
20 from collections
import OrderedDict
22 from forcebalance.output
import getLogger
23 logger = getLogger(__name__)
27 """ Subclass of Target for fitting force fields to multipole moments (from experiment or theory). 29 Currently Tinker is supported. 33 def __init__(self,options,tgt_opts,forcefield):
37 super(Moments,self).
__init__(options,tgt_opts,forcefield)
42 self.set_option(tgt_opts,
'dipole_denom')
43 self.set_option(tgt_opts,
'quadrupole_denom')
44 self.set_option(tgt_opts,
'polarizability_denom')
45 self.set_option(tgt_opts,
'optimize_geometry')
48 self.
denoms[
'dipole'] = self.dipole_denom
49 self.
denoms[
'quadrupole'] = self.quadrupole_denom
50 self.
denoms[
'polarizability'] = self.polarizability_denom
59 self.
mfnm = os.path.join(self.tgtdir,
"mdata.txt")
65 engine_args = OrderedDict(list(self.OptionDict.items()) + list(options.items()))
66 engine_args.pop(
'name',
None)
68 self.
engine = self.engine_(target=self, **engine_args)
71 """ Read the reference data from a file. """ 82 for line
in open(self.
mfnm):
83 line = line.split(
'#')[0]
87 elif len(s) == 1
and self.
na == -1:
89 xyz = np.zeros((self.
na, 3))
93 elif an < self.
na and len(s) == 4:
94 xyz[an, :] = np.array([float(i)
for i
in s[1:]])
96 elif an == self.
na and s[0].lower() ==
'dipole':
99 self.
ref_moments[
'dipole'] = OrderedDict(zip([
'x',
'y',
'z'],[float(i)
for i
in s]))
100 elif an == self.
na and s[0].lower()
in [
'quadrupole',
'quadrapole']:
103 self.
ref_moments[
'quadrupole'] = OrderedDict([(
'xx',float(s[0]))])
104 elif qn > 0
and ln == qn + 1:
107 elif qn > 0
and ln == qn + 2:
111 elif an == self.
na and s[0].lower()
in [
'polarizability',
'alpha']:
114 self.
ref_moments[
'polarizability'] = OrderedDict([(
'xx',float(s[0]))])
115 self.
ref_moments[
'polarizability'][
'yx'] = float(s[1])
116 self.
ref_moments[
'polarizability'][
'zx'] = float(s[2])
117 elif pn > 0
and ln == pn + 1:
118 self.
ref_moments[
'polarizability'][
'xy'] = float(s[0])
119 self.
ref_moments[
'polarizability'][
'yy'] = float(s[1])
120 self.
ref_moments[
'polarizability'][
'zy'] = float(s[2])
121 elif pn > 0
and ln == pn + 2:
122 self.
ref_moments[
'polarizability'][
'xz'] = float(s[0])
123 self.
ref_moments[
'polarizability'][
'yz'] = float(s[1])
124 self.
ref_moments[
'polarizability'][
'zz'] = float(s[2])
126 logger.info(
"%s\n" % line)
127 logger.error(
"This line doesn't comply with our multipole file format!\n")
140 """ Print qualitative indicator. """ 141 logger.info(
"\rTarget: %-15s\n" % self.name)
149 PrintDict = OrderedDict()
154 PrintDict[
"%s-%s" % (Ord, Comp)] =
"% 9.3f % 9.3f % 9.3f % 12.5f" % (self.
calc_moments[Ord][Comp],
157 (ref_momvals[i] - calc_momvals[i])**2)
161 printcool_dictionary(PrintDict,title=
"Moments and/or Polarizabilities, Objective = % .5e\n %-20s %9s %9s %9s %11s" %
162 (self.
objective,
"Component",
"Calc.",
"Ref.",
"Delta",
"Term"))
167 answer = np.array(list(itertools.chain(*[[dct[i]/self.
denoms[ord]
if self.
denoms[ord] != 0.0
else 0.0
for i
in dct]
for ord,dct
in moment_dict.items()])))
170 def get(self, mvals, AGrad=False, AHess=False):
171 """ Evaluate objective function. """ 172 Answer = {
'X':0.0,
'G':np.zeros(self.FF.np),
'H':np.zeros((self.FF.np, self.FF.np))}
173 def get_momvals(mvals_):
175 moments = self.
engine.multipole_moments(polarizability=
'polarizability' in self.
ref_moments, optimize=self.optimize_geometry)
181 calc_moments = self.
engine.multipole_moments(polarizability=
'polarizability' in self.
ref_moments, optimize=self.optimize_geometry)
184 D = calc_momvals - ref_momvals
185 dV = np.zeros((self.FF.np,len(calc_momvals)))
189 dV[p,:], _ =
f12d3p(
fdwrap(get_momvals, mvals, p), h = self.h, f0 = calc_momvals)
191 Answer[
'X'] = np.dot(D,D)
193 Answer[
'G'][p] = 2*np.dot(D, dV[p,:])
195 Answer[
'H'][p,q] = 2*np.dot(dV[p,:], dV[q,:])
Nifty functions, intended to be imported by any module within ForceBalance.
engine
Read in the reference data.
def in_fd()
Invoking this function from anywhere will tell us whether we're being called by a finite-difference f...
mfnm
The mdata.txt file that contains the moments.
def fdwrap(func, mvals0, pidx, key=None, kwargs)
A function wrapper for finite difference designed for differentiating 'get'-type functions.
ref_moments
Dictionary of reference multipole moments.
Subclass of Target for fitting force fields to multipole moments (from experiment or theory)...
def __init__(self, options, tgt_opts, forcefield)
Initialization.
def printcool_dictionary(Dict, title="Dictionary Keys : Values", bold=False, color=2, keywidth=25, topwidth=50, center=True, leftpad=0)
See documentation for printcool; this is a nice way to print out keys/values in a dictionary...
def indicate(self)
Print qualitative indicator.
def f12d3p(f, h, f0=None)
A three-point finite difference stencil.
loop_over_snapshots
LPW 2018-02-11: This is set to True if the target calculates a single-point property over several exi...
def get(self, mvals, AGrad=False, AHess=False)
Evaluate objective function.
def read_reference_data(self)
Read the reference data from a file.
def unpack_moments(self, moment_dict)