Esempio n. 1
0
 def submit_jobs(self, mvals, AGrad=False, AHess=False):
     n=0
     id_string = "%s_%i-%i" % (self.name, Counter(), n)
     
     while os.path.exists('%s.out' % id_string):
         n+=1
         id_string = "%s_%i-%i" % (self.name, Counter(), n)
     
     with wopen('forcebalance.p') as f: forcebalance.nifty.lp_dump((mvals, AGrad, AHess, id_string, self.r_options, self.r_tgt_opts, self.FF),f)
     
     forcebalance.nifty.LinkFile(os.path.join(os.path.split(__file__)[0],"data","rtarget.py"),"rtarget.py")
     forcebalance.nifty.LinkFile(os.path.join(self.root,"temp", self.name, "target.tar.bz2"),"%s.tar.bz2" % self.name)
     
     wq = getWorkQueue()
     
     logger.info("Sending target '%s' to work queue for remote evaluation\n" % self.name)
     # input:
     #   forcebalance.p: pickled mvals, options, and forcefield
     #   rtarget.py: remote target evaluation script
     #   target.tar.bz2: tarred target
     # output:
     #   objective.p: pickled objective function dictionary
     #   indicate.log: results of target.indicate() written to file
     forcebalance.nifty.queue_up(wq, "python rtarget.py > %s.out 2>&1" % id_string,
         ["forcebalance.p", "rtarget.py", "%s.tar.bz2" % self.name],
         ['objective_%s.p' % id_string, 'indicate_%s.log' % id_string, '%s.out' % id_string],
         tgt=self)
         
     self.id_string = id_string
Esempio n. 2
0
    def setopts(self, **kwargs):
        """ Called by __init__ ; Set AMBER-specific options. """

        ## The directory containing TINKER executables (e.g. dynamic)
        if 'amberhome' in kwargs:
            self.amberhome = kwargs['amberhome']
            if not os.path.exists(os.path.join(self.amberhome, "sander")):
                warn_press_key("The 'sander' executable indicated by %s doesn't exist! (Check amberhome)" \
                                   % os.path.join(self.amberhome,"sander"))
        else:
            warn_once(
                "The 'amberhome' option was not specified; using default.")
            if which('sander') == '':
                warn_press_key(
                    "Please add AMBER executables to the PATH or specify amberhome."
                )
            self.amberhome = os.path.split(which('sander'))[0]

        with wopen('.quit.leap') as f:
            print >> f, 'quit'

        # AMBER search path
        self.spath = []
        for line in self.callamber('tleap -f .quit.leap'):
            if 'Adding' in line and 'to search path' in line:
                self.spath.append(line.split('Adding')[1].split()[0])
        os.remove('.quit.leap')
Esempio n. 3
0
 def driver(self):
     ## Actually run PSI4.
     if not in_fd() and CheckBasis():
         logger.info("Now checking for linear dependencies.\n")
         _exec("cp %s %s.bak" % (self.GBSfnm, self.GBSfnm), print_command=False)
         ln0 = self.write_nested_destroy(self.GBSfnm, self.FF.linedestroy_save)
         o = wopen(".lindep.dat")
         for line in open(self.DATfnm).readlines():
             s = line.split("#")[0].split()
             if len(s) == 3 and s[0].lower() == 'basis' and s[1].lower() == 'file':
                 print >> o, "basis file %s" % self.GBSfnm
             else:
                 print >> o, line,
         o.close()
         _exec("mv .lindep.dat %s" % self.DATfnm, print_command=False)
         _exec("psi4 %s" % self.DATfnm, print_command=False)
         LI = GBS_Reader()
         LI_lines = {}
         ## Read in the commented linindep.gbs file and ensure that these same lines are commented in the new .gbs file
         for line in open('linindep.gbs'):
             LI.feed(line,linindep=True)
             key = '.'.join([str(i) for i in LI.element,LI.amom,LI.basis_number[LI.element],LI.contraction_number])
             if LI.isdata:
                 if key in LI_lines:
                     logger.info("Duplicate key found:\n")
                     logger.info("%s\n" % key)
                     logger.info(str(LI_lines[key]))
                     logger.info(line)
                     warn_press_key("In %s, the LI_lines dictionary should not contain repeated keys!" % __file__)
                 LI_lines[key] = (line, LI.destroy)
Esempio n. 4
0
 def submit_psi(this_apath, mname, these_mvals):
     """ Create a grid file and a psi4 input file in the absolute path and submit it to the work queue. """
     cwd = os.getcwd()
     if not os.path.exists(this_apath) : os.makedirs(this_apath)
     os.chdir(this_apath)
     self.FF.make(these_mvals)
     o = wopen('objective.dat')
     for line in self.objfiles[d]:
         s = line.split()
         if len(s) > 2 and s[0] == 'path' and s[1] == '=':
             print >> o, "path = '%s'" % os.getcwd()
         elif len(s) > 2 and s[0] == 'set' and s[1] == 'objective_path':
             print >> o, "opath = '%s'" % os.getcwd()
             print >> o, "set objective_path $opath"
         else:
             print >> o, line,
     o.close()
     os.system("rm -f objective.out")
     if wq == None:
         logger.info("There is no Work Queue!!!\n")
         sys.exit()
     else:
         input_files = [(os.path.join(this_apath, i), i) for i in glob.glob("*")]
         # input_files += [(os.path.join(self.tgtdir,d,"build.dat"), "build.dat")]
         input_files += [(os.path.join(os.path.split(__file__)[0],"data","run_psi_rdvr3_objective.sh"), "run_psi_rdvr3_objective.sh")]
         logger.info("\r")
         queue_up_src_dest(wq,"sh run_psi_rdvr3_objective.sh %s &> run_psi_rdvr3_objective.log" % mname,
                           input_files=input_files,
                           output_files=[(os.path.join(this_apath, i),i) for i in ["run_psi_rdvr3_objective.log", "output.dat"]], verbose=False)
     os.chdir(cwd)
Esempio n. 5
0
 def driver(self, mvals, d):
     ## Create the force field file.
     pvals = self.FF.make(mvals)
     ## Actually run PSI4.
     odir = os.path.join(os.getcwd(),d)
     #if os.path.exists(odir):
     #    shutil.rmtree(odir)
     if not os.path.exists(odir): os.makedirs(odir)
     os.chdir(odir)
     o = wopen('objective.dat')
     for line in self.objfiles[d]:
         s = line.split()
         if len(s) > 2 and s[0] == 'path' and s[1] == '=':
             print >> o, "path = '%s'" % self.tdir
         elif len(s) > 2 and s[0] == 'set' and s[1] == 'objective_path':
             print >> o, "opath = '%s'" % os.getcwd()
             print >> o, "set objective_path $opath"
         else:
             print >> o, line,
     o.close()
     os.system("rm -f objective.out")
     _exec("psi4 objective.dat", print_command=False)
     answer = float(open('objective.out').readlines()[0].split()[1])*self.factor
     os.chdir('..')
     return answer
Esempio n. 6
0
 def driver(self, mvals, d):
     ## Create the force field file.
     pvals = self.FF.make(mvals)
     ## Actually run PSI4.
     odir = os.path.join(os.getcwd(), d)
     #if os.path.exists(odir):
     #    shutil.rmtree(odir)
     if not os.path.exists(odir): os.makedirs(odir)
     os.chdir(odir)
     o = wopen('objective.dat')
     for line in self.objfiles[d]:
         s = line.split()
         if len(s) > 2 and s[0] == 'path' and s[1] == '=':
             print("path = '%s'" % self.tdir, file=o)
         elif len(s) > 2 and s[0] == 'set' and s[1] == 'objective_path':
             print("opath = '%s'" % os.getcwd(), file=o)
             print("set objective_path $opath", file=o)
         else:
             print(line, end=' ', file=o)
     o.close()
     os.system("rm -f objective.out")
     _exec("psi4 objective.dat", print_command=False)
     answer = float(
         open('objective.out').readlines()[0].split()[1]) * self.factor
     os.chdir('..')
     return answer
Esempio n. 7
0
    def setopts(self, **kwargs):
        
        """ Called by __init__ ; Set AMBER-specific options. """

        ## The directory containing TINKER executables (e.g. dynamic)
        if 'amberhome' in kwargs:
            self.amberhome = kwargs['amberhome']
            if not os.path.exists(os.path.join(self.amberhome,"sander")):
                warn_press_key("The 'sander' executable indicated by %s doesn't exist! (Check amberhome)" \
                                   % os.path.join(self.amberhome,"sander"))
        else:
            warn_once("The 'amberhome' option was not specified; using default.")
            if which('sander') == '':
                warn_press_key("Please add AMBER executables to the PATH or specify amberhome.")
            self.amberhome = os.path.split(which('sander'))[0]
        
        with wopen('.quit.leap') as f:
            print >> f, 'quit'

        # AMBER search path
        self.spath = []
        for line in self.callamber('tleap -f .quit.leap'):
            if 'Adding' in line and 'to search path' in line:
                self.spath.append(line.split('Adding')[1].split()[0])
        os.remove('.quit.leap')
Esempio n. 8
0
    def submit_jobs(self, mvals, AGrad=True, AHess=True):
        """This routine is called by Objective.stage() and will run before "get".
        It submits the jobs and the stage() function will wait for jobs
        to complete.

        Parameters
        ----------
        mvals : list
            Mathematical parameter values.
        AGrad : Boolean
            Switch to turn on analytic gradient.
        AHess : Boolean
            Switch to turn on analytic Hessian.

        Returns
        -------
        Nothing.
        
        """
        # Set up and run the simulation chain on all points.
        for pt in self.points:
            # Create subdir
            try:
                os.makedirs(str(pt.idnr))
            except OSError as exception:
                if exception.errno != errno.EEXIST:
                    raise            
                
            # Goto subdir
            os.chdir(str(pt.idnr))

            # Link dir contents from target subdir to current temp directory.
            for f in self.scripts:
                LinkFile(os.path.join(self.root, self.tempdir, f),
                         os.path.join(os.getcwd(), f))
                
            link_dir_contents(os.path.join(self.root, self.tgtdir,
                                           str(pt.idnr)), os.getcwd())
            
            # Dump the force field to a pickle file
            with wopen('forcebalance.p') as f:
                lp_dump((self.FF, mvals, self.OptionDict, AGrad), f)
                
            # Run the simulation chain for point.        
            cmdstr = ("%s python md_chain.py " % self.mdpfx +
                      " ".join(self.quantities) + " " +
                      "--engine %s " % self.engname +
                      "--length %d " % self.n_sim_chain + 
                      "--name %s " % self.simpfx +
                      "--temperature %f " % pt.temperature +
                      "--pressure %f " % pt.pressure +
                      "--nequil %d " % self.eq_steps +
                      "--nsteps %d " % self.md_steps)
            _exec(cmdstr, copy_stderr=True, outfnm='md_chain.out')
        
            os.chdir('..')
Esempio n. 9
0
    def evaluate_(self, crdin, force=False):
        """ 
        Utility function for computing energy and forces using AMBER. 
        
        Inputs:
        crdin: AMBER .mdcrd file name.
        force: Switch for parsing the force. (Currently it always calculates the forces.)

        Outputs:
        Result: Dictionary containing energies (and optionally) forces.
        """

        force_mdin = """Loop over conformations and compute energy and force (use ioutfnm=1 for netcdf, ntb=0 for no box)
&cntrl
imin = 5, ntb = 0, cut=9, nstlim = 0, nsnb = 0
/
&debugf
do_debugf = 1, dumpfrc = 1
/
"""
        with wopen("%s-force.mdin" % self.name) as f:
            print >> f, force_mdin

        ## This line actually runs AMBER.
        self.leap(delcheck=True)
        self.callamber(
            "sander -i %s-force.mdin -o %s-force.mdout -p %s.prmtop -c %s.inpcrd -y %s -O"
            % (self.name, self.name, self.name, self.name, crdin))
        ParseMode = 0
        Result = {}
        Energies = []
        Forces = []
        Force = []
        for line in open('forcedump.dat'):
            line = line.strip()
            sline = line.split()
            if ParseMode == 1:
                if len(sline) == 1 and isfloat(sline[0]):
                    Energies.append(float(sline[0]) * 4.184)
                    ParseMode = 0
            if ParseMode == 2:
                if len(sline) == 3 and all(
                        isfloat(sline[i]) for i in range(3)):
                    Force += [float(sline[i]) * 4.184 * 10 for i in range(3)]
                if len(Force) == 3 * self.qmatoms:
                    Forces.append(np.array(Force))
                    Force = []
                    ParseMode = 0
            if line == '0 START of Energies':
                ParseMode = 1
            elif line == '1 Total Force':
                ParseMode = 2

        Result["Energy"] = np.array(Energies[1:])
        Result["Force"] = np.array(Forces[1:])
        return Result
Esempio n. 10
0
 def prepare_temp_directory(self, options, tgt_opts):
     abstempdir = os.path.join(self.root,self.tempdir)
     o = wopen(os.path.join(abstempdir,"input.dat"))
     for line in open(os.path.join(self.root,self.tgtdir,"input.dat")).readlines():
         s = line.split("#")[0].split()
         if len(s) == 3 and s[0].lower() == 'basis' and s[1].lower() == 'file':
             print >> o, "basis file %s" % self.GBSfnm
         else:
             print >> o, line,
     o.close()
Esempio n. 11
0
    def evaluate_(self, crdin, force=False):

        """ 
        Utility function for computing energy and forces using AMBER. 
        
        Inputs:
        crdin: AMBER .mdcrd file name.
        force: Switch for parsing the force. (Currently it always calculates the forces.)

        Outputs:
        Result: Dictionary containing energies (and optionally) forces.
        """

        force_mdin="""Loop over conformations and compute energy and force (use ioutfnm=1 for netcdf, ntb=0 for no box)
&cntrl
imin = 5, ntb = 0, cut=9, nstlim = 0, nsnb = 0
/
&debugf
do_debugf = 1, dumpfrc = 1
/
"""
        with wopen("%s-force.mdin" % self.name) as f:
            print >> f, force_mdin

        ## This line actually runs AMBER.
        self.leap(delcheck=True)
        self.callamber("sander -i %s-force.mdin -o %s-force.mdout -p %s.prmtop -c %s.inpcrd -y %s -O" % 
                       (self.name, self.name, self.name, self.name, crdin))
        ParseMode = 0
        Result = {}
        Energies = []
        Forces = []
        Force = []
        for line in open('forcedump.dat'):
            line = line.strip()
            sline = line.split()
            if ParseMode == 1:
                if len(sline) == 1 and isfloat(sline[0]):
                    Energies.append(float(sline[0]) * 4.184)
                    ParseMode = 0
            if ParseMode == 2:
                if len(sline) == 3 and all(isfloat(sline[i]) for i in range(3)):
                    Force += [float(sline[i]) * 4.184 * 10 for i in range(3)]
                if len(Force) == 3*self.qmatoms:
                    Forces.append(np.array(Force))
                    Force = []
                    ParseMode = 0
            if line == '0 START of Energies':
                ParseMode = 1
            elif line == '1 Total Force':
                ParseMode = 2

        Result["Energy"] = np.array(Energies[1:])
        Result["Force"] = np.array(Forces[1:])
        return Result
Esempio n. 12
0
 def prepare_temp_directory(self, options, tgt_opts):
     abstempdir = os.path.join(self.root, self.tempdir)
     o = wopen(os.path.join(abstempdir, "input.dat"))
     for line in open(os.path.join(self.root, self.tgtdir,
                                   "input.dat")).readlines():
         s = line.split("#")[0].split()
         if len(s) == 3 and s[0].lower() == 'basis' and s[1].lower(
         ) == 'file':
             print("basis file %s" % self.GBSfnm, file=o)
         else:
             print(line, end=' ', file=o)
     o.close()
Esempio n. 13
0
 def write_nested_destroy(self, fnm, linedestroy):
     ln0 = list(range(len(open(fnm).readlines())))
     for layer in linedestroy:
         f = open(fnm).readlines()
         o = wopen('.tmp.gbs')
         newln = []
         for ln, line in enumerate(f):
             if ln not in layer:
                 print(line, end=' ', file=o)
                 newln.append(ln0[ln])
         ln0 = newln[:]
         _exec("mv .tmp.gbs %s" % fnm, print_command=False)
         o.close()
     return ln0
Esempio n. 14
0
    def 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.
        
        """
        ## 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
        cwd = os.getcwd()
        
        absgetdir = os.path.join(self.root,self.tempdir)
        if Counter() is not None:
            # Not expecting more than ten thousand iterations
            if Counter() > 10000:
                raise RuntimeError('Cannot handle more than 10000 iterations due to current directory structure.  Consider revising code.')
            iterdir = "iter_%04i" % Counter()
            absgetdir = os.path.join(absgetdir,iterdir)
        if customdir is not None:
            absgetdir = os.path.join(absgetdir,customdir)

        if not os.path.exists(absgetdir):
            os.makedirs(absgetdir)
        os.chdir(absgetdir)
        self.link_from_tempdir(absgetdir)
        self.rundir = absgetdir.replace(self.root+'/','')
        ## Read existing information from disk (i.e. when recovering an aborted run)
        if self.rd != None and Counter() == First() and self.read_objective:
            os.chdir(self.absrd())
            logger.info("Reading objective function information from %s\n" % os.getcwd())
            Answer = self.read(mvals, AGrad, AHess)
            os.chdir(absgetdir)
        else:
            ## Evaluate the objective function.
            Answer = self.get(mvals, AGrad, AHess)
            if self.write_objective:
                with wopen('objective.p') as f:
                    forcebalance.nifty.lp_dump(Answer, f)

        ## Save the force field files to this directory, so that it
        ## reflects the objective function and properties that were
        ## printed out.
        if not in_fd_srch(): 
            self.FF.make(mvals)

        os.chdir(cwd)
        
        return Answer
Esempio n. 15
0
 def write_nested_destroy(self, fnm, linedestroy):
     ln0 = range(len(open(fnm).readlines()))
     for layer in linedestroy:
         f = open(fnm).readlines()
         o = wopen('.tmp.gbs')
         newln = []
         for ln, line in enumerate(f):
             if ln not in layer:
                 print >> o, line,
                 newln.append(ln0[ln])
         ln0 = newln[:]
         _exec("mv .tmp.gbs %s" % fnm, print_command=False)
         o.close()
     return ln0
Esempio n. 16
0
 def submit_psi(this_apath, dname, these_mvals):
     """ Create a grid file and a psi4 input file in the absolute path and submit it to the work queue. """
     cwd = os.getcwd()
     if not os.path.exists(this_apath): os.makedirs(this_apath)
     os.chdir(this_apath)
     self.FF.make(these_mvals)
     o = wopen('objective.dat')
     for line in self.objfiles[d]:
         s = line.split()
         if len(s) > 2 and s[0] == 'path' and s[1] == '=':
             print("path = '%s'" % os.getcwd(), file=o)
         elif len(s) > 2 and s[0] == 'set' and s[1] == 'objective_path':
             print("opath = '%s'" % os.getcwd(), file=o)
             print("set objective_path $opath", file=o)
         else:
             print(line, end=' ', file=o)
     o.close()
     os.system("rm -f objective.out")
     if wq is None:
         logger.info("There is no Work Queue!!!\n")
         sys.exit()
     else:
         input_files = [(os.path.join(this_apath, i), i)
                        for i in glob.glob("*")]
         input_files += [(os.path.join(self.root, self.tgtdir, dname,
                                       "build.dat"), "build.dat")]
         input_files += [(os.path.join(
             os.path.split(__file__)[0], "data",
             "run_psi_rdvr3_objective.sh"),
                          "run_psi_rdvr3_objective.sh")]
         logger.info("\r")
         queue_up_src_dest(
             wq,
             "sh run_psi_rdvr3_objective.sh -c %s &> run_psi_rdvr3_objective.log"
             % os.path.join(self.root, self.tgtdir, dname),
             input_files=input_files,
             output_files=[
                 (os.path.join(this_apath, i), i)
                 for i in ["run_psi_rdvr3_objective.log", "output.dat"]
             ],
             verbose=False)
     os.chdir(cwd)
Esempio n. 17
0
    def driver(self):
        ## Actually run PSI4.
        if not in_fd() and CheckBasis():
            logger.info("Now checking for linear dependencies.\n")
            _exec("cp %s %s.bak" % (self.GBSfnm, self.GBSfnm),
                  print_command=False)
            ln0 = self.write_nested_destroy(self.GBSfnm,
                                            self.FF.linedestroy_save)
            o = wopen(".lindep.dat")
            for line in open(self.DATfnm).readlines():
                s = line.split("#")[0].split()
                if len(s) == 3 and s[0].lower() == 'basis' and s[1].lower(
                ) == 'file':
                    print("basis file %s" % self.GBSfnm, file=o)
                else:
                    print(line, end=' ', file=o)
            o.close()
            _exec("mv .lindep.dat %s" % self.DATfnm, print_command=False)
            _exec("psi4 %s" % self.DATfnm, print_command=False)
            LI = GBS_Reader()
            LI_lines = {}
            ## Read in the commented linindep.gbs file and ensure that these same lines are commented in the new .gbs file
            for line in open('linindep.gbs'):
                LI.feed(line, linindep=True)
                key = '.'.join([
                    str(i)
                    for i in (LI.element, LI.amom, LI.basis_number[LI.element],
                              LI.contraction_number)
                ])
                if LI.isdata:
                    if key in LI_lines:
                        logger.info("Duplicate key found:\n")
                        logger.info("%s\n" % key)
                        logger.info(str(LI_lines[key]))
                        logger.info(line)
                        warn_press_key(
                            "In %s, the LI_lines dictionary should not contain repeated keys!"
                            % __file__)
                    LI_lines[key] = (line, LI.destroy)
            ## Now build a "Frankenstein" .gbs file composed of the original .gbs file but with data from the linindep.gbs file!
            FK = GBS_Reader()
            FK_lines = []
            self.FF.linedestroy_this = []
            self.FF.prmdestroy_this = []
            for ln, line in enumerate(open(self.GBSfnm).readlines()):
                FK.feed(line)
                key = '.'.join([
                    str(i)
                    for i in (FK.element, FK.amom, FK.basis_number[FK.element],
                              FK.contraction_number)
                ])
                if FK.isdata and key in LI_lines:
                    if LI_lines[key][1]:
                        logger.info("Destroying line %i (originally %i): " %
                                    (ln, ln0[ln]))
                        logger.info(line)
                        self.FF.linedestroy_this.append(ln)
                        for p_destroy in [
                                i for i, fld in enumerate(self.FF.pfields)
                                if any([
                                    subfld[0] == self.GBSfnm
                                    and subfld[1] == ln0[ln] for subfld in fld
                                ])
                        ]:
                            logger.info(
                                "Destroying parameter %i located at line %i (originally %i) with fields given by: %s"
                                % (p_destroy, ln, ln0[ln],
                                   str(self.FF.pfields[p_destroy])))
                            self.FF.prmdestroy_this.append(p_destroy)
                    FK_lines.append(LI_lines[key][0])
                else:
                    FK_lines.append(line)
            o = wopen('franken.gbs')
            for line in FK_lines:
                print(line, end=' ', file=o)
            o.close()
            _exec("cp %s.bak %s" % (self.GBSfnm, self.GBSfnm),
                  print_command=False)

            if len(
                    list(
                        itertools.chain(*(self.FF.linedestroy_save +
                                          [self.FF.linedestroy_this])))) > 0:
                logger.info("All lines removed: " + self.FF.linedestroy_save +
                            [self.FF.linedestroy_this] + '\n')
                logger.info("All prms removed: " + self.FF.prmdestroy_save +
                            [self.FF.prmdestroy_this] + '\n')

        self.write_nested_destroy(
            self.GBSfnm, self.FF.linedestroy_save + [self.FF.linedestroy_this])
        _exec("psi4", print_command=False, outfnm="psi4.stdout")
        if not in_fd():
            for line in open('psi4.stdout').readlines():
                if "MP2 Energy:" in line:
                    self.MP2_Energy = float(line.split()[-1])
                elif "DF Energy:" in line:
                    self.DF_Energy = float(line.split()[-1])
        Ans = np.array([[float(i) for i in line.split()]
                        for line in open("objective.dat").readlines()])
        os.unlink("objective.dat")
        return Ans
Esempio n. 18
0
    def objective_term(self, quantity):
        """Calculates the contribution to the objective function (the term) for a
        given quantity.

        Parameters
        ----------
        quantity : string
            Calculate the objective term for this quantity.

        Returns
        -------
        term : dict
            `term` is a dict with keys `X`, `G`, `H` and `info`. The values of
            these keys are the objective term itself (`X`), its gradient (`G`),
            its Hessian (`H`), and an OrderedDict with print information on
            individiual data points (`info`).
            
        """
        Objective = 0.0
        Gradient  = np.zeros(self.FF.np)
        Hessian   = np.zeros((self.FF.np, self.FF.np))

        # Grab ref data for quantity        
        qid       = self.quantities.index(quantity)
        Exp       = np.array([pt.ref["refs"][qid] for pt in self.points])
        Weights   = np.array([pt.ref["weights"][qid] for pt in self.points])
        Denom     = self.denoms[quantity]
            
        # Renormalize weights
        Weights /= np.sum(Weights)
        logger.info("Renormalized weights to " + str(np.sum(Weights)) + "\n")
        logger.info(("Physical quantity '%s' uses denominator = %g %s\n" %
                     (quantity.capitalize(), Denom,
                      self.points[0].ref["units"][self.quantities.index(quantity)])))

        # Grab calculated values        
        values = np.array([pt.data["values"][qid] for pt in self.points])
        errors = np.array([pt.data["errors"][qid] for pt in self.points])
        grads  = np.array([pt.data["grads"][qid] for pt in self.points])

        # Calculate objective term using Least-squares function. Evaluate using
        # Einstein summation: W is N-array, Delta is N-array and grads is
        # NxM-array, where N is number of points and M is number of parameters.
        #
        #     X_i   = W_i * Delta2_i (no summed indices)
        #     G_ij  = W_i * Delta_i * grads_ij (no summed indices)
        #     H_ijm = W_i * gradsT_jk * grads_lm (sum over k and l)
        #
        # Result: X is N-array, G is NxM-array and H is NxMxM-array.
        #
        Deltas = values - Exp
        Objs   = np.einsum("i,i->i", Weights, Deltas**2) / Denom / Denom
        Grads  = 2.0*np.einsum("i,i,ij->ij", Weights, Deltas, grads) / Denom / Denom
        Hess   = 2.0*np.einsum("i,jk,lm->ijm", Weights, grads.T, grads) / Denom / Denom
        
        # Average over all points
        Objective += np.sum(Objs, axis=0)
        Gradient  += np.sum(Grads, axis=0)
        Hessian   += np.sum(Hess, axis=0)
        
        # Store gradients and setup print map 
        GradMapPrint = [["#Point"] + self.FF.plist]

        for pt in self.points:
            temp  = pt.temperature
            press = pt.pressure
            GradMapPrint.append([' %8.2f %8.1f' % (temp, press)] +
                                ["% 9.3e" % i for i in grads[pt.idnr-1]])

        o = wopen('gradient_%s.dat' % quantity)
        for line in GradMapPrint:
            print >> o, ' '.join(line)
        o.close()
        
        printer = OrderedDict([("    %-5d %-12.2f %-8.1f"
                                % (pt.idnr, pt.temperature, pt.pressure),
                                ("% -10.3f % -10.3f  +- %-8.3f % -8.3f % -9.5f % -9.5f"
                                 % (Exp[pt.idnr-1], values[pt.idnr-1],
                                    errors[pt.idnr-1], Deltas[pt.idnr-1],
                                    Weights[pt.idnr-1], Objs[pt.idnr-1])))
                                    for pt in self.points])
                
        return { "X": Objective, "G": Gradient, "H": Hessian, "info": printer }
Esempio n. 19
0
def main():
    
    """Usage:
    
    (gmxprefix.sh) md_chain.py <list of quantities>
                               --engine <gromacs>
                               --length <n>
                               --name <name>
                               --temperature <T>
                               --pressure <p>
                               --nequil <nequil>
                               --nsteps <nsteps>
        
    This program is meant to be called automatically by ForceBalance.
    
    """
    printcool("ForceBalance simulation using engine: %s" % engname.upper(),
              color=4, bold=True)
    #----
    # Load the ForceBalance pickle file which contains:
    #----
    # - Force field object
    # - Optimization parameters
    # - Options from the Target object that launched this simulation
    # - Switch for whether to evaluate analytic derivatives.
    FF, mvals, TgtOptions, AGrad = lp_load(open('forcebalance.p'))
    FF.ffdir = '.'
    # Write the force field file.
    FF.make(mvals)

    #----
    # Load the options that are set in the ForceBalance input file.
    #----
    # Finite difference step size
    h = TgtOptions['h']
    
    engines = []
    ## Setup and carry out simulations in chain
    for i in range(args.length):
        # Simulation files
        if engname == "gromacs":
            ndx_flag = False
            coords   = args.name + str(i+1) + ".gro"
            top_file = args.name + str(i+1) + ".top"
            mdp_file = args.name + str(i+1) + ".mdp"
            ndx_file = args.name + str(i+1) + ".ndx"
            if os.path.exists(ndx_file):
                ndx_flag = True
                
        mol = Molecule(coords)
        #----
        # Set coordinates and molecule for engine
        #----
        EngOpts = OrderedDict([("FF", FF),
                               ("pbc", True),
                               ("coords", coords),
                               ("mol", mol)])
    
        if engname == "gromacs":
            # Gromacs-specific options
            EngOpts["gmx_top"] = top_file
            EngOpts["gmx_mdp"] = mdp_file
            if ndx_flag:
                EngOpts["gmx_ndx"] = ndx_file
                
        printcool_dictionary(EngOpts)
                                
        # Create engine objects and store them for subsequent analysis.
        s = Engine(name=args.name+str(i+1), **EngOpts)
                
        #=====================#
        # Run the simulation. #
        #=====================#
        MDOpts = OrderedDict([("nsteps", args.nsteps),
                              ("nequil", args.nequil)])

        printcool("Molecular dynamics simulation", color=4, bold=True)
        s.md(verbose=True, **MDOpts)
                                    
        engines.append(s)
    
    #======================================================================#
    # Extract the quantities of interest from the MD simulations and dump  #
    # the results to file.                                                 #
    # =====================================================================#    
    results = OrderedDict()        
    for q in args.quantities:
        logger.info("Extracting %s...\n" % q)

        # Initialize quantity
        objstr = "Quantity_" + q.capitalize()
        dm     = il.import_module('..quantity',
                                  package='forcebalance.quantity')
            
        Quantity = getattr(dm, objstr)(engname, args.temperature, args.pressure)
            
        Q, Qerr, Qgrad = Quantity.extract(engines, FF, mvals, h, AGrad)
                    
        results.setdefault("values", []).append(Q)
        results.setdefault("errors", []).append(Qerr)
        results.setdefault("grads",  []).append(Qgrad)
            
        logger.info("Finished!\n")
            
        # Print out results for the quantity and its derivative.
        Sep = printcool(("%s: % .4f +- % .4f \nAnalytic Derivative:"
                              % (q.capitalize(), Q, Qerr)))
        FF.print_map(vals=Qgrad)
            
    # Dump results to file
    logger.info("Writing final force field.\n")
    pvals = FF.make(mvals)
    
    logger.info("Writing all simulation data to disk.\n")
    with wopen('md_result.p') as f:
        lp_dump((np.asarray(results["values"]),
                 np.asarray(results["errors"]),
                 np.asarray(results["grads"])), f)
Esempio n. 20
0
    def driver(self):
        ## Actually run PSI4.
        if not in_fd() and CheckBasis():
            logger.info("Now checking for linear dependencies.\n")
            _exec("cp %s %s.bak" % (self.GBSfnm, self.GBSfnm), print_command=False)
            ln0 = self.write_nested_destroy(self.GBSfnm, self.FF.linedestroy_save)
            o = wopen(".lindep.dat")
            for line in open(self.DATfnm).readlines():
                s = line.split("#")[0].split()
                if len(s) == 3 and s[0].lower() == 'basis' and s[1].lower() == 'file':
                    print("basis file %s" % self.GBSfnm, file=o)
                else:
                    print(line, end=' ', file=o)
            o.close()
            _exec("mv .lindep.dat %s" % self.DATfnm, print_command=False)
            _exec("psi4 %s" % self.DATfnm, print_command=False)
            LI = GBS_Reader()
            LI_lines = {}
            ## Read in the commented linindep.gbs file and ensure that these same lines are commented in the new .gbs file
            for line in open('linindep.gbs'):
                LI.feed(line,linindep=True)
                key = '.'.join([str(i) for i in (LI.element,LI.amom,LI.basis_number[LI.element],LI.contraction_number)])
                if LI.isdata:
                    if key in LI_lines:
                        logger.info("Duplicate key found:\n")
                        logger.info("%s\n" % key)
                        logger.info(str(LI_lines[key]))
                        logger.info(line)
                        warn_press_key("In %s, the LI_lines dictionary should not contain repeated keys!" % __file__)
                    LI_lines[key] = (line, LI.destroy)
            ## Now build a "Frankenstein" .gbs file composed of the original .gbs file but with data from the linindep.gbs file!
            FK = GBS_Reader()
            FK_lines = []
            self.FF.linedestroy_this = []
            self.FF.prmdestroy_this = []
            for ln, line in enumerate(open(self.GBSfnm).readlines()):
                FK.feed(line)
                key = '.'.join([str(i) for i in (FK.element,FK.amom,FK.basis_number[FK.element],FK.contraction_number)])
                if FK.isdata and key in LI_lines:
                    if LI_lines[key][1]:
                        logger.info("Destroying line %i (originally %i): " % (ln, ln0[ln]))
                        logger.info(line)
                        self.FF.linedestroy_this.append(ln)
                        for p_destroy in [i for i, fld in enumerate(self.FF.pfields) if any([subfld[0] == self.GBSfnm and subfld[1] == ln0[ln] for subfld in fld])]:
                            logger.info("Destroying parameter %i located at line %i (originally %i) with fields given by: %s" % (p_destroy, ln, ln0[ln], str(self.FF.pfields[p_destroy])))
                            self.FF.prmdestroy_this.append(p_destroy)
                    FK_lines.append(LI_lines[key][0])
                else:
                    FK_lines.append(line)
            o = wopen('franken.gbs')
            for line in FK_lines:
                print(line, end=' ', file=o)
            o.close()
            _exec("cp %s.bak %s" % (self.GBSfnm, self.GBSfnm), print_command=False)
            
            if len(list(itertools.chain(*(self.FF.linedestroy_save + [self.FF.linedestroy_this])))) > 0:
                logger.info("All lines removed: " + self.FF.linedestroy_save + [self.FF.linedestroy_this] + '\n')
                logger.info("All prms removed: " + self.FF.prmdestroy_save + [self.FF.prmdestroy_this] + '\n')

        self.write_nested_destroy(self.GBSfnm, self.FF.linedestroy_save + [self.FF.linedestroy_this])
        _exec("psi4", print_command=False, outfnm="psi4.stdout")
        if not in_fd():
            for line in open('psi4.stdout').readlines():
                if "MP2 Energy:" in line:
                    self.MP2_Energy = float(line.split()[-1])
                elif "DF Energy:" in line:
                    self.DF_Energy = float(line.split()[-1])
        Ans = np.array([[float(i) for i in line.split()] for line in open("objective.dat").readlines()])
        os.unlink("objective.dat")
        return Ans
    #----
    Scd_avg, Scd_e = mean_stderr(Scds)
    Scd_err = flat(Scd_e)
    GScd = mBeta * (((np.mat(G) * Scds) / L) - (np.mat(np.average(G, axis = 1)).T * np.average(Scds, axis = 0)))
    # Print out S_cd and its derivative.
    scd_avgerr = ' '.join('%.4f +- %.4f \n' % F for F in zip(Scd_avg, Scd_err))
    Sep = printcool("Deuterium order parameter: %s \nAnalytic Derivative:" % scd_avgerr)
    FF.print_map(vals=GScd)
    logger.info(Sep)

    def calc_scd(b = None, **kwargs):
        if b == None: b = np.ones(L,dtype=float)
        if 's_' in kwargs:
            s_ = kwargs['s_']
        return bzavg(s_,b)

    # calc_scd(None, **{'s_': Scds})

    logger.info("Writing final force field.\n")
    pvals = FF.make(mvals)

    logger.info("Writing all simulation data to disk.\n")
<<<<<<< HEAD
    with wopen(os.path.join('npt_result.p')) as f: lp_dump((Rhos, Volumes, Potentials, Energies, Dips, G, [GDx, GDy, GDz], Rho_err, Alpha_err, Kappa_err, Cp_err, Eps0_err, NMol, Als, Al_err, Scds, Scd_err, LKappa_err),f)
=======
    lp_dump((Rhos, Volumes, Potentials, Energies, Dips, G, [GDx, GDy, GDz], Rho_err, Alpha_err, Kappa_err, Cp_err, Eps0_err, NMol, Als, Al_err, Scds, Scd_err),'npt_result.p')
>>>>>>> 8b8c6b3f716f0991da16a3906109647307384a39

if __name__ == "__main__":
    main()
def main():
    """
    Usage: (runcuda.sh) npt.py <openmm|gromacs|tinker> <lipid_nsteps> <lipid_timestep (fs)> <lipid_intvl (ps> <temperature> <pressure>

    This program is meant to be called automatically by ForceBalance on
    a GPU cluster (specifically, subroutines in openmmio.py).  It is
    not easy to use manually.  This is because the force field is read
    in from a ForceBalance 'FF' class.

    I wrote this program because automatic fitting of the density (or
    other equilibrium properties) is computationally intensive, and the
    calculations need to be distributed to the queue.  The main instance
    of ForceBalance (running on my workstation) queues up a bunch of these
    jobs (using Work Queue).  Then, I submit a bunch of workers to GPU
    clusters (e.g. Certainty, Keeneland).  The worker scripts connect to.
    the main instance and receives one of these jobs.

    This script can also be executed locally, if you want to (e.g. for
    debugging).  Just make sure you have the pickled 'forcebalance.p'
    file.

    """

    printcool("ForceBalance condensed phase simulation using engine: %s" %
              engname.upper(),
              color=4,
              bold=True)

    #----
    # Load the ForceBalance pickle file which contains:
    #----
    # - Force field object
    # - Optimization parameters
    # - Options from the Target object that launched this simulation
    # - Switch for whether to evaluate analytic derivatives.
    FF, mvals, TgtOptions, AGrad = lp_load(open('forcebalance.p'))
    FF.ffdir = '.'
    # Write the force field file.
    FF.make(mvals)

    #----
    # Load the options that are set in the ForceBalance input file.
    #----
    # Finite difference step size
    h = TgtOptions['h']
    pgrad = TgtOptions['pgrad']
    # MD options; time step (fs), production steps, equilibration steps, interval for saving data (ps)
    lipid_timestep = TgtOptions['lipid_timestep']
    lipid_nsteps = TgtOptions['lipid_md_steps']
    lipid_nequil = TgtOptions['lipid_eq_steps']
    lipid_intvl = TgtOptions['lipid_interval']
    lipid_fnm = TgtOptions['lipid_coords']

    # Number of threads, multiple timestep integrator, anisotropic box etc.
    threads = TgtOptions.get('md_threads', 1)
    mts = TgtOptions.get('mts_integrator', 0)
    force_cuda = TgtOptions.get('force_cuda', 0)
    anisotropic = TgtOptions.get('anisotropic_box', 0)
    minimize = TgtOptions.get('minimize_energy', 1)

    # Print all options.
    printcool_dictionary(TgtOptions, title="Options from ForceBalance")
    lipid_snapshots = (lipid_nsteps * lipid_timestep / 1000) / lipid_intvl
    lipid_iframes = 1000 * lipid_intvl / lipid_timestep
    logger.info("For the condensed phase system, I will collect %i snapshots spaced apart by %i x %.3f fs time steps\n" \
        % (lipid_snapshots, lipid_iframes, lipid_timestep))
    if lipid_snapshots < 2:
        raise Exception('Please set the number of lipid time steps so that you collect at least two snapshots (minimum %i)' \
                            % (2000 * (lipid_intvl/lipid_timestep)))

    #----
    # Loading coordinates
    #----
    ML = Molecule(lipid_fnm)
    # Determine the number of molecules in the condensed phase coordinate file.
    NMol = len(ML.molecules)

    #----
    # Setting up MD simulations
    #----
    EngOpts = OrderedDict()
    EngOpts["lipid"] = OrderedDict([("coords", lipid_fnm), ("mol", ML),
                                    ("pbc", True)])
    GenOpts = OrderedDict([('FF', FF)])
    if engname == "openmm":
        # OpenMM-specific options
        EngOpts["lipid"]["openmm_platform"] = 'CUDA'
        if force_cuda:
            try:
                Platform.getPlatformByName('CUDA')
            except:
                raise RuntimeError(
                    'Forcing failure because CUDA platform unavailable')
        if threads > 1:
            logger.warn(
                "Setting the number of threads will have no effect on OpenMM engine.\n"
            )
    elif engname == "gromacs":
        # Gromacs-specific options
        GenOpts["gmxpath"] = TgtOptions["gmxpath"]
        GenOpts["gmxsuffix"] = TgtOptions["gmxsuffix"]
        EngOpts["lipid"]["gmx_top"] = os.path.splitext(lipid_fnm)[0] + ".top"
        EngOpts["lipid"]["gmx_mdp"] = os.path.splitext(lipid_fnm)[0] + ".mdp"
        if force_cuda:
            logger.warn("force_cuda option has no effect on Gromacs engine.")
        if mts:
            logger.warn(
                "Gromacs not configured for multiple timestep integrator.")
        if anisotropic:
            logger.warn("Gromacs not configured for anisotropic box scaling.")
    elif engname == "tinker":
        # Tinker-specific options
        GenOpts["tinkerpath"] = TgtOptions["tinkerpath"]
        EngOpts["lipid"]["tinker_key"] = os.path.splitext(
            lipid_fnm)[0] + ".key"
        if force_cuda:
            logger.warn("force_cuda option has no effect on Tinker engine.")
        if mts:
            logger.warn(
                "Tinker not configured for multiple timestep integrator.")
    EngOpts["lipid"].update(GenOpts)
    for i in EngOpts:
        printcool_dictionary(EngOpts[i], "Engine options for %s" % i)

    # Set up MD options
    MDOpts = OrderedDict()
    MDOpts["lipid"] = OrderedDict([
        ("nsteps", lipid_nsteps), ("timestep", lipid_timestep),
        ("temperature", "%s %s" % (temperature, temperature)),
        ("pressure", "%s %s" % (pressure, pressure)), ("nequil", lipid_nequil),
        ("minimize", minimize),
        ("nsave", int(1000 * lipid_intvl / lipid_timestep)), ("verbose", True),
        ('save_traj', TgtOptions['save_traj']), ("threads", threads),
        ("anisotropic", anisotropic), ("mts", mts), ("faststep", faststep),
        ("bilayer", True)
    ])

    # Energy components analysis disabled for OpenMM MTS because it uses force groups
    if (engname == "openmm" and mts):
        logger.warn(
            "OpenMM with MTS integrator; energy components analysis will be disabled.\n"
        )

    # Create instances of the MD Engine objects.
    Lipid = Engine(name="lipid", **EngOpts["lipid"])

    #=================================================================#
    # Run the simulation for the full system and analyze the results. #
    #=================================================================#

    printcool("Condensed phase molecular dynamics", color=4, bold=True)

    # This line runs the condensed phase simulation.
    prop_return = Lipid.molecular_dynamics(**MDOpts["lipid"])
    Rhos = prop_return['Rhos']
    Potentials = prop_return['Potentials']
    Kinetics = prop_return['Kinetics']
    Volumes = prop_return['Volumes']
    Dips = prop_return['Dips']
    EDA = prop_return['Ecomps']
    Als = prop_return['Als']
    Scds = prop_return['Scds']

    # Create a bunch of physical constants.
    # Energies are in kJ/mol
    # Lengths are in nanometers.
    L = len(Rhos)
    kB = 0.008314472471220214
    T = temperature
    kT = kB * T
    mBeta = -1.0 / kT
    Beta = 1.0 / kT
    atm_unit = 0.061019351687175
    bar_unit = 0.060221417930000
    # This is how I calculated the prefactor for the dielectric constant.
    # eps0 = 8.854187817620e-12 * coulomb**2 / newton / meter**2
    # epsunit = 1.0*(debye**2) / nanometer**3 / BOLTZMANN_CONSTANT_kB / kelvin
    # prefactor = epsunit/eps0/3
    prefactor = 30.348705333964077

    # Gather some physical variables.
    Energies = Potentials + Kinetics
    Ene_avg, Ene_err = mean_stderr(Energies)
    pV = atm_unit * pressure * Volumes
    pV_avg, pV_err = mean_stderr(pV)
    Rho_avg, Rho_err = mean_stderr(Rhos)
    PrintEDA(EDA, NMol)

    #============================================#
    #  Compute the potential energy derivatives. #
    #============================================#
    logger.info(
        "Calculating potential energy derivatives with finite difference step size: %f\n"
        % h)
    # Switch for whether to compute the derivatives two different ways for consistency.
    FDCheck = False

    # Create a double-precision simulation object if desired (seems unnecessary).
    DoublePrecisionDerivatives = False
    if engname == "openmm" and DoublePrecisionDerivatives and AGrad:
        logger.info(
            "Creating Double Precision Simulation for parameter derivatives\n")
        Lipid = Engine(name="lipid",
                       openmm_precision="double",
                       **EngOpts["lipid"])

    # Compute the energy and dipole derivatives.
    printcool(
        "Condensed phase energy and dipole derivatives\nInitializing array to length %i"
        % len(Energies),
        color=4,
        bold=True)
    G, GDx, GDy, GDz = energy_derivatives(Lipid,
                                          FF,
                                          mvals,
                                          h,
                                          pgrad,
                                          len(Energies),
                                          AGrad,
                                          dipole=True)

    #==============================================#
    #  Condensed phase properties and derivatives. #
    #==============================================#

    #----
    # Density
    #----
    # Build the first density derivative.
    GRho = mBeta * (flat(np.mat(G) * col(Rhos)) / L -
                    np.mean(Rhos) * np.mean(G, axis=1))
    # Print out the density and its derivative.
    Sep = printcool("Density: % .4f +- % .4f kg/m^3\nAnalytic Derivative:" %
                    (Rho_avg, Rho_err))
    FF.print_map(vals=GRho)
    logger.info(Sep)

    def calc_rho(b=None, **kwargs):
        if b == None: b = np.ones(L, dtype=float)
        if 'r_' in kwargs:
            r_ = kwargs['r_']
        return bzavg(r_, b)

    # No need to calculate error using bootstrap, but here it is anyway
    # Rhoboot = []
    # for i in range(numboots):
    #    boot = np.random.randint(N,size=N)
    #    Rhoboot.append(calc_rho(None,**{'r_':Rhos[boot]}))
    # Rhoboot = np.array(Rhoboot)
    # Rho_err = np.std(Rhoboot)

    if FDCheck:
        Sep = printcool("Numerical Derivative:")
        GRho1 = property_derivatives(Lipid, FF, mvals, h, pgrad, kT, calc_rho,
                                     {'r_': Rhos})
        FF.print_map(vals=GRho1)
        Sep = printcool("Difference (Absolute, Fractional):")
        absfrac = [
            "% .4e  % .4e" % (i - j, (i - j) / j) for i, j in zip(GRho, GRho1)
        ]
        FF.print_map(vals=absfrac)

    #----
    # Enthalpy of vaporization.  Removed.
    #----
    H = Energies + pV
    V = np.array(Volumes)

    # Define some things to make the analytic derivatives easier.
    Gbar = np.mean(G, axis=1)

    def deprod(vec):
        return flat(np.mat(G) * col(vec)) / L

    def covde(vec):
        return flat(np.mat(G) * col(vec)) / L - Gbar * np.mean(vec)

    def avg(vec):
        return np.mean(vec)

    #----
    # Thermal expansion coefficient
    #----
    def calc_alpha(b=None, **kwargs):
        if b == None: b = np.ones(L, dtype=float)
        if 'h_' in kwargs:
            h_ = kwargs['h_']
        if 'v_' in kwargs:
            v_ = kwargs['v_']
        return 1 / (kT * T) * (bzavg(h_ * v_, b) -
                               bzavg(h_, b) * bzavg(v_, b)) / bzavg(v_, b)

    Alpha = calc_alpha(None, **{'h_': H, 'v_': V})
    Alphaboot = []
    numboots = 1000
    for i in range(numboots):
        boot = np.random.randint(L, size=L)
        Alphaboot.append(calc_alpha(None, **{'h_': H[boot], 'v_': V[boot]}))
    Alphaboot = np.array(Alphaboot)
    Alpha_err = np.std(Alphaboot) * max([
        np.sqrt(statisticalInefficiency(V)),
        np.sqrt(statisticalInefficiency(H))
    ])

    # Thermal expansion coefficient analytic derivative
    GAlpha1 = -1 * Beta * deprod(H * V) * avg(V) / avg(V)**2
    GAlpha2 = +1 * Beta * avg(H * V) * deprod(V) / avg(V)**2
    GAlpha3 = deprod(V) / avg(V) - Gbar
    GAlpha4 = Beta * covde(H)
    GAlpha = (GAlpha1 + GAlpha2 + GAlpha3 + GAlpha4) / (kT * T)
    Sep = printcool(
        "Thermal expansion coefficient: % .4e +- %.4e K^-1\nAnalytic Derivative:"
        % (Alpha, Alpha_err))
    FF.print_map(vals=GAlpha)
    if FDCheck:
        GAlpha_fd = property_derivatives(Lipid, FF, mvals, h, pgrad, kT,
                                         calc_alpha, {
                                             'h_': H,
                                             'v_': V
                                         })
        Sep = printcool("Numerical Derivative:")
        FF.print_map(vals=GAlpha_fd)
        Sep = printcool("Difference (Absolute, Fractional):")
        absfrac = [
            "% .4e  % .4e" % (i - j, (i - j) / j)
            for i, j in zip(GAlpha, GAlpha_fd)
        ]
        FF.print_map(vals=absfrac)

    #----
    # Isothermal compressibility
    #----
    def calc_kappa(b=None, **kwargs):
        if b == None: b = np.ones(L, dtype=float)
        if 'v_' in kwargs:
            v_ = kwargs['v_']
        return bar_unit / kT * (bzavg(v_**2, b) - bzavg(v_, b)**2) / bzavg(
            v_, b)

    Kappa = calc_kappa(None, **{'v_': V})
    Kappaboot = []
    for i in range(numboots):
        boot = np.random.randint(L, size=L)
        Kappaboot.append(calc_kappa(None, **{'v_': V[boot]}))
    Kappaboot = np.array(Kappaboot)
    Kappa_err = np.std(Kappaboot) * np.sqrt(statisticalInefficiency(V))

    # Isothermal compressibility analytic derivative
    Sep = printcool(
        "Isothermal compressibility:  % .4e +- %.4e bar^-1\nAnalytic Derivative:"
        % (Kappa, Kappa_err))
    GKappa1 = +1 * Beta**2 * avg(V**2) * deprod(V) / avg(V)**2
    GKappa2 = -1 * Beta**2 * avg(V) * deprod(V**2) / avg(V)**2
    GKappa3 = +1 * Beta**2 * covde(V)
    GKappa = bar_unit * (GKappa1 + GKappa2 + GKappa3)
    FF.print_map(vals=GKappa)
    if FDCheck:
        GKappa_fd = property_derivatives(Lipid, FF, mvals, h, pgrad, kT,
                                         calc_kappa, {'v_': V})
        Sep = printcool("Numerical Derivative:")
        FF.print_map(vals=GKappa_fd)
        Sep = printcool("Difference (Absolute, Fractional):")
        absfrac = [
            "% .4e  % .4e" % (i - j, (i - j) / j)
            for i, j in zip(GKappa, GKappa_fd)
        ]
        FF.print_map(vals=absfrac)

    #----
    # Isobaric heat capacity
    #----
    def calc_cp(b=None, **kwargs):
        if b == None: b = np.ones(L, dtype=float)
        if 'h_' in kwargs:
            h_ = kwargs['h_']
        Cp_ = 1 / (NMol * kT * T) * (bzavg(h_**2, b) - bzavg(h_, b)**2)
        Cp_ *= 1000 / 4.184
        return Cp_

    Cp = calc_cp(None, **{'h_': H})
    Cpboot = []
    for i in range(numboots):
        boot = np.random.randint(L, size=L)
        Cpboot.append(calc_cp(None, **{'h_': H[boot]}))
    Cpboot = np.array(Cpboot)
    Cp_err = np.std(Cpboot) * np.sqrt(statisticalInefficiency(H))

    # Isobaric heat capacity analytic derivative
    GCp1 = 2 * covde(H) * 1000 / 4.184 / (NMol * kT * T)
    GCp2 = mBeta * covde(H**2) * 1000 / 4.184 / (NMol * kT * T)
    GCp3 = 2 * Beta * avg(H) * covde(H) * 1000 / 4.184 / (NMol * kT * T)
    GCp = GCp1 + GCp2 + GCp3
    Sep = printcool(
        "Isobaric heat capacity:  % .4e +- %.4e cal mol-1 K-1\nAnalytic Derivative:"
        % (Cp, Cp_err))
    FF.print_map(vals=GCp)
    if FDCheck:
        GCp_fd = property_derivatives(Lipid, FF, mvals, h, pgrad, kT, calc_cp,
                                      {'h_': H})
        Sep = printcool("Numerical Derivative:")
        FF.print_map(vals=GCp_fd)
        Sep = printcool("Difference (Absolute, Fractional):")
        absfrac = [
            "% .4e  % .4e" % (i - j, (i - j) / j) for i, j in zip(GCp, GCp_fd)
        ]
        FF.print_map(vals=absfrac)

    #----
    # Dielectric constant
    #----
    def calc_eps0(b=None, **kwargs):
        if b == None: b = np.ones(L, dtype=float)
        if 'd_' in kwargs:  # Dipole moment vector.
            d_ = kwargs['d_']
        if 'v_' in kwargs:  # Volume.
            v_ = kwargs['v_']
        b0 = np.ones(L, dtype=float)
        dx = d_[:, 0]
        dy = d_[:, 1]
        dz = d_[:, 2]
        D2 = bzavg(dx**2, b) - bzavg(dx, b)**2
        D2 += bzavg(dy**2, b) - bzavg(dy, b)**2
        D2 += bzavg(dz**2, b) - bzavg(dz, b)**2
        return prefactor * D2 / bzavg(v_, b) / T

    Eps0 = calc_eps0(None, **{'d_': Dips, 'v_': V})
    Eps0boot = []
    for i in range(numboots):
        boot = np.random.randint(L, size=L)
        Eps0boot.append(calc_eps0(None, **{'d_': Dips[boot], 'v_': V[boot]}))
    Eps0boot = np.array(Eps0boot)
    Eps0_err = np.std(Eps0boot) * np.sqrt(
        np.mean([
            statisticalInefficiency(Dips[:, 0]),
            statisticalInefficiency(Dips[:, 1]),
            statisticalInefficiency(Dips[:, 2])
        ]))

    # Dielectric constant analytic derivative
    Dx = Dips[:, 0]
    Dy = Dips[:, 1]
    Dz = Dips[:, 2]
    D2 = avg(Dx**2) + avg(Dy**2) + avg(
        Dz**2) - avg(Dx)**2 - avg(Dy)**2 - avg(Dz)**2
    GD2 = 2 * (flat(np.mat(GDx) * col(Dx)) / L - avg(Dx) *
               (np.mean(GDx, axis=1))) - Beta * (covde(Dx**2) -
                                                 2 * avg(Dx) * covde(Dx))
    GD2 += 2 * (flat(np.mat(GDy) * col(Dy)) / L - avg(Dy) *
                (np.mean(GDy, axis=1))) - Beta * (covde(Dy**2) -
                                                  2 * avg(Dy) * covde(Dy))
    GD2 += 2 * (flat(np.mat(GDz) * col(Dz)) / L - avg(Dz) *
                (np.mean(GDz, axis=1))) - Beta * (covde(Dz**2) -
                                                  2 * avg(Dz) * covde(Dz))
    GEps0 = prefactor * (GD2 / avg(V) - mBeta * covde(V) * D2 / avg(V)**2) / T
    Sep = printcool(
        "Dielectric constant:           % .4e +- %.4e\nAnalytic Derivative:" %
        (Eps0, Eps0_err))
    FF.print_map(vals=GEps0)
    if FDCheck:
        GEps0_fd = property_derivatives(Lipid, FF, mvals, h, pgrad, kT,
                                        calc_eps0, {
                                            'd_': Dips,
                                            'v_': V
                                        })
        Sep = printcool("Numerical Derivative:")
        FF.print_map(vals=GEps0_fd)
        Sep = printcool("Difference (Absolute, Fractional):")
        absfrac = [
            "% .4e  % .4e" % (i - j, (i - j) / j)
            for i, j in zip(GEps0, GEps0_fd)
        ]
        FF.print_map(vals=absfrac)

    #----
    # Average area per lipid
    #----
    Al_avg, Al_err = mean_stderr(Als)
    # Build the first A_l derivative.
    GAl = mBeta * (flat(np.mat(G) * col(Als)) / L -
                   np.mean(Als) * np.mean(G, axis=1))
    # Print out A_l and its derivative.
    Sep = printcool(
        "Average Area per Lipid: % .4f +- % .4f nm^2\nAnalytic Derivative:" %
        (Al_avg, Al_err))
    FF.print_map(vals=GAl)
    logger.info(Sep)

    def calc_al(b=None, **kwargs):
        if b == None: b = np.ones(L, dtype=float)
        if 'a_' in kwargs:
            a_ = kwargs['a_']
        return bzavg(a_, b)

    # calc_al(None, **{'a_': Als})

    #----
    # Bilayer Isothermal compressibility
    #----
    kbT = 1.3806488e-23 * T

    def calc_lkappa(b=None, **kwargs):
        if b == None: b = np.ones(L, dtype=float)
        if 'a_' in kwargs:
            a_ = kwargs['a_']
        return (1e3 * 2 * kbT / 128) * (bzavg(a_, b) /
                                        (bzavg(a_**2, b) - bzavg(a_, b)**2))

    # Convert Als time series from nm^2 to m^2
    Als_m2 = Als * 1e-18
    LKappa = calc_lkappa(None, **{'a_': Als_m2})
    al_avg = avg(Als_m2)
    al_sq_avg = avg(Als_m2**2)
    al_avg_sq = al_avg**2
    al_var = al_sq_avg - al_avg_sq

    LKappaboot = []
    for i in range(numboots):
        boot = np.random.randint(L, size=L)
        LKappaboot.append(calc_lkappa(None, **{'a_': Als_m2[boot]}))
    LKappaboot = np.array(LKappaboot)
    LKappa_err = np.std(LKappaboot) * np.sqrt(statisticalInefficiency(Als_m2))

    # Bilayer Isothermal compressibility analytic derivative
    Sep = printcool(
        "Lipid Isothermal compressibility:  % .4e +- %.4e N/nm^-1\nAnalytic Derivative:"
        % (LKappa, LKappa_err))
    GLKappa1 = covde(Als_m2) / al_var
    GLKappa2 = (al_avg / al_var**2) * (covde(Als_m2**2) -
                                       (2 * al_avg * covde(Als_m2)))
    GLKappa = (1e3 * 2 * kbT / 128) * (GLKappa1 - GLKappa2)
    FF.print_map(vals=GLKappa)
    if FDCheck:
        GLKappa_fd = property_derivatives(Lipid, FF, mvals, h, pgrad, kT,
                                          calc_lkappa, {'a_': Als_m2})
        Sep = printcool("Numerical Derivative:")
        FF.print_map(vals=GLKappa_fd)
        Sep = printcool("Difference (Absolute, Fractional):")
        absfrac = [
            "% .4e  % .4e" % (i - j, (i - j) / j)
            for i, j in zip(GLKappa, GLKappa_fd)
        ]
        FF.print_map(vals=absfrac)

    #----
    # Deuterium Order Parameter
    #----
    Scd_avg, Scd_e = mean_stderr(Scds)
    Scd_err = flat(Scd_e)
    GScd = mBeta * (
        ((np.mat(G) * Scds) / L) -
        (np.mat(np.average(G, axis=1)).T * np.average(Scds, axis=0)))
    # Print out S_cd and its derivative.
    scd_avgerr = ' '.join('%.4f +- %.4f \n' % F for F in zip(Scd_avg, Scd_err))
    Sep = printcool("Deuterium order parameter: %s \nAnalytic Derivative:" %
                    scd_avgerr)
    FF.print_map(vals=GScd)
    logger.info(Sep)

    def calc_scd(b=None, **kwargs):
        if b == None: b = np.ones(L, dtype=float)
        if 's_' in kwargs:
            s_ = kwargs['s_']
        return bzavg(s_, b)

    # calc_scd(None, **{'s_': Scds})

    logger.info("Writing final force field.\n")
    pvals = FF.make(mvals)

    logger.info("Writing all simulation data to disk.\n")
    with wopen(os.path.join('npt_result.p')) as f:
        lp_dump((Rhos, Volumes, Potentials, Energies, Dips, G, [GDx, GDy, GDz],
                 Rho_err, Alpha_err, Kappa_err, Cp_err, Eps0_err, NMol, Als,
                 Al_err, Scds, Scd_err, LKappa_err), f)
Esempio n. 23
0
            self.FF.prmdestroy_this = []
            for ln, line in enumerate(open(self.GBSfnm).readlines()):
                FK.feed(line)
                key = '.'.join([str(i) for i in FK.element,FK.amom,FK.basis_number[FK.element],FK.contraction_number])
                if FK.isdata and key in LI_lines:
                    if LI_lines[key][1]:
                        logger.info("Destroying line %i (originally %i): " % (ln, ln0[ln]))
                        logger.info(line)
                        self.FF.linedestroy_this.append(ln)
                        for p_destroy in [i for i, fld in enumerate(self.FF.pfields) if any([subfld[0] == self.GBSfnm and subfld[1] == ln0[ln] for subfld in fld])]:
                            logger.info("Destroying parameter %i located at line %i (originally %i) with fields given by: %s" % (p_destroy, ln, ln0[ln], str(self.FF.pfields[p_destroy])))
                            self.FF.prmdestroy_this.append(p_destroy)
                    FK_lines.append(LI_lines[key][0])
                else:
                    FK_lines.append(line)
            o = wopen('franken.gbs')
            for line in FK_lines:
                print >> o, line,
            o.close()
            _exec("cp %s.bak %s" % (self.GBSfnm, self.GBSfnm), print_command=False)
            
            if len(list(itertools.chain(*(self.FF.linedestroy_save + [self.FF.linedestroy_this])))) > 0:
                logger.info("All lines removed: " + self.FF.linedestroy_save + [self.FF.linedestroy_this] + '\n')
                logger.info("All prms removed: " + self.FF.prmdestroy_save + [self.FF.prmdestroy_this] + '\n')

        self.write_nested_destroy(self.GBSfnm, self.FF.linedestroy_save + [self.FF.linedestroy_this])
        _exec("psi4", print_command=False, outfnm="psi4.stdout")
        if not in_fd():
            for line in open('psi4.stdout').readlines():
                if "MP2 Energy:" in line:
                    self.MP2_Energy = float(line.split()[-1])
Esempio n. 24
0
def write_leap(fnm, mol2=[], frcmod=[], pdb=None, prefix='amber', spath = [], delcheck=False):
    """ Parse and edit an AMBER LEaP input file. Output file is written to inputfile_ (with trailing underscore.) """
    have_fmod = []
    have_mol2 = []
    # The lines that will be printed out to actually run tleap
    line_out = []
    aload = ['loadamberparams', 'source', 'loadoff']
    aload_eq = ['loadmol2']
    spath.append('.')
             
    for line in open(fnm):
        # Skip comment lines
        if line.strip().startswith('#') : continue
        line = line.split('#')[0]
        s = line.split()
        ll = line.lower()
        ls = line.lower().split()
        # Check to see if all files being loaded are in the search path
        if '=' in line:
            if ll.split('=')[1].split()[0] in aload_eq:
                if not any([os.path.exists(os.path.join(d, s[-1])) for d in spath]):
                    logger.error("The file in this line cannot be loaded : " + line.strip())
                    raise RuntimeError
        elif len(ls) > 0 and ls[0] in aload:
            if not any([os.path.exists(os.path.join(d, s[-1])) for d in spath]):
                logger.error("The file in this line cannot be loaded : " + line.strip())
                raise RuntimeError
        if len(s) >= 2 and ls[0] == 'loadamberparams':
            have_fmod.append(s[1])
        if len(s) >= 2 and 'loadmol2' in ll:
            have_mol2.append(s[-1])
        if len(s) >= 2 and 'loadpdb' in ll:
            # Adopt the AMBER molecule name from the loadpdb line.
            ambername = line.split('=')[0].strip()
            # If we pass in our own PDB, then this line is replaced.
            if pdb != None:
                line = '%s = loadpdb %s\n' % (ambername, pdb)
        if len(s) >= 1 and ls[0] == 'check' and delcheck:
            # Skip over check steps if so decreed
            line = "# " + line
        if 'saveamberparm' in ll: 
            # We'll write the saveamberparm line ourselves
            continue
        if len(s) >= 1 and ls[0] == 'quit':
            # Don't write the quit line.
            break
        if not line.endswith('\n') : line += '\n'
        line_out.append(line)
    # Sanity checks: If frcmod and mol2 files are provided to this function,
    # they should be in the leap.cmd file as well.  There should be exactly
    # one PDB file being loaded.
    for i in frcmod:
        if i not in have_fmod:
            warn_press_key("WARNING: %s is not being loaded in %s" % (i, fnm))
    for i in mol2:
        if i not in have_mol2:
            warn_press_key("WARNING: %s is not being loaded in %s" % (i, fnm))

    fout = fnm+'_'
    line_out.append('saveamberparm %s %s.prmtop %s.inpcrd\n' % (ambername, prefix, prefix))
    line_out.append('quit\n')
    with wopen(fout) as f: print >> f, ''.join(line_out)
Esempio n. 25
0
# load pickled variables from forcebalance.p
f=open('forcebalance.p', 'r')
mvals, AGrad, AHess, id_string, options, tgt_opts, forcefield = forcebalance.nifty.lp_load(f)
f.close()

options['root'] = os.getcwd()

# set up forcefield
forcefield.make(mvals)

# set up and evaluate target
tar = tarfile.open("%s.tar.bz2" % tgt_opts["name"], "r")
tar.extractall()
tar.close()

Tgt = forcebalance.objective.Implemented_Targets[tgt_opts['type']](options,tgt_opts,forcefield)
Tgt.submit_jobs(mvals, AGrad = True, AHess = True)

Ans = Tgt.sget(mvals, AGrad=True, AHess=True)

with wopen('objective_%s.p' % id_string) as f:
    forcebalance.nifty.lp_dump(Ans, f)        # or some other method of storing resulting objective

# also run target.indicate()
logger = forcebalance.output.getLogger("forcebalance")
logger.addHandler(forcebalance.output.RawFileHandler('indicate_%s.log' % id_string))
Tgt.indicate()

print "\n"
    
Esempio n. 26
0
options['root'] = os.getcwd()
forcefield.root = os.getcwd()

# set up forcefield
forcefield.make(mvals, printdir="forcefield")

# set up and evaluate target
tar = tarfile.open("target.tar.bz2", "r")
tar.extractall()
tar.close()

Tgt = forcebalance.objective.Implemented_Targets[tgt_opts['type']](options,tgt_opts,forcefield)
Tgt.read_objective = False
Tgt.read_indicate = False
Tgt.write_objective = False
Tgt.write_indicate = False
Tgt.read_0grads()
Tgt.submit_jobs(mvals, AGrad = True, AHess = True)

Ans = Tgt.meta_get(mvals, AGrad=True, AHess=True)

with wopen('objective.p') as f:
    forcebalance.nifty.lp_dump(Ans, f)        # or some other method of storing resulting objective

# also run target.indicate()
logger = forcebalance.output.getLogger("forcebalance")
logger.addHandler(forcebalance.output.RawFileHandler('indicate.log'))
Tgt.indicate()

print "\n"
Esempio n. 27
0
def main():

    """
    Usage: (runcuda.sh) npt.py <openmm|gromacs|tinker> <liquid_nsteps> <liquid_timestep (fs)> <liquid_intvl (ps> <temperature> <pressure>

    This program is meant to be called automatically by ForceBalance on
    a GPU cluster (specifically, subroutines in openmmio.py).  It is
    not easy to use manually.  This is because the force field is read
    in from a ForceBalance 'FF' class.

    I wrote this program because automatic fitting of the density (or
    other equilibrium properties) is computationally intensive, and the
    calculations need to be distributed to the queue.  The main instance
    of ForceBalance (running on my workstation) queues up a bunch of these
    jobs (using Work Queue).  Then, I submit a bunch of workers to GPU
    clusters (e.g. Certainty, Keeneland).  The worker scripts connect to.
    the main instance and receives one of these jobs.

    This script can also be executed locally, if you want to (e.g. for
    debugging).  Just make sure you have the pickled 'forcebalance.p'
    file.

    """

    printcool("ForceBalance condensed phase simulation using engine: %s" % engname.upper(), color=4, bold=True)

    #----
    # Load the ForceBalance pickle file which contains:
    #----
    # - Force field object
    # - Optimization parameters
    # - Options from the Target object that launched this simulation
    # - Switch for whether to evaluate analytic derivatives.
    FF,mvals,TgtOptions,AGrad = lp_load(open('forcebalance.p'))
    FF.ffdir = '.'
    # Write the force field file.
    FF.make(mvals)

    #----
    # Load the options that are set in the ForceBalance input file.
    #----
    # Finite difference step size
    h = TgtOptions['h']
    pgrad = TgtOptions['pgrad']
    # MD options; time step (fs), production steps, equilibration steps, interval for saving data (ps)
    liquid_timestep = TgtOptions['liquid_timestep']
    liquid_nsteps = TgtOptions['liquid_md_steps']
    liquid_nequil = TgtOptions['liquid_eq_steps']
    liquid_intvl = TgtOptions['liquid_interval']
    liquid_fnm = TgtOptions['liquid_coords']
    gas_timestep = TgtOptions['gas_timestep']
    gas_nsteps = TgtOptions['gas_md_steps']
    gas_nequil = TgtOptions['gas_eq_steps']
    gas_intvl = TgtOptions['gas_interval']
    gas_fnm = TgtOptions['gas_coords']

    # Number of threads, multiple timestep integrator, anisotropic box etc.
    threads = TgtOptions.get('md_threads', 1)
    mts = TgtOptions.get('mts_integrator', 0)
    rpmd_beads = TgtOptions.get('rpmd_beads', 0)
    force_cuda = TgtOptions.get('force_cuda', 0)
    anisotropic = TgtOptions.get('anisotropic_box', 0)
    minimize = TgtOptions.get('minimize_energy', 1)

    # Print all options.
    printcool_dictionary(TgtOptions, title="Options from ForceBalance")
    liquid_snapshots = (liquid_nsteps * liquid_timestep / 1000) / liquid_intvl
    liquid_iframes = 1000 * liquid_intvl / liquid_timestep
    gas_snapshots = (gas_nsteps * gas_timestep / 1000) / gas_intvl
    gas_iframes = 1000 * gas_intvl / gas_timestep
    logger.info("For the condensed phase system, I will collect %i snapshots spaced apart by %i x %.3f fs time steps\n" \
        % (liquid_snapshots, liquid_iframes, liquid_timestep))
    if liquid_snapshots < 2:
        raise Exception('Please set the number of liquid time steps so that you collect at least two snapshots (minimum %i)' \
                            % (2000 * (liquid_intvl/liquid_timestep)))
    logger.info("For the gas phase system, I will collect %i snapshots spaced apart by %i x %.3f fs time steps\n" \
        % (gas_snapshots, gas_iframes, gas_timestep))
    if gas_snapshots < 2:
        raise Exception('Please set the number of gas time steps so that you collect at least two snapshots (minimum %i)' \
                            % (2000 * (gas_intvl/gas_timestep)))

    #----
    # Loading coordinates
    #----
    ML = Molecule(liquid_fnm)
    MG = Molecule(gas_fnm)
    # Determine the number of molecules in the condensed phase coordinate file.
    NMol = len(ML.molecules)

    #----
    # Setting up MD simulations
    #----
    EngOpts = OrderedDict()
    EngOpts["liquid"] = OrderedDict([("coords", liquid_fnm), ("mol", ML), ("pbc", True)])
    EngOpts["gas"] = OrderedDict([("coords", gas_fnm), ("mol", MG), ("pbc", False)])
    GenOpts = OrderedDict([('FF', FF)])
    if engname == "openmm":
        # OpenMM-specific options
        EngOpts["liquid"]["platname"] = 'CUDA'
        EngOpts["gas"]["platname"] = 'Reference'
        if force_cuda:
            try: Platform.getPlatformByName('CUDA')
            except: raise RuntimeError('Forcing failure because CUDA platform unavailable')
        if threads > 1: logger.warn("Setting the number of threads will have no effect on OpenMM engine.\n")
    elif engname == "gromacs":
        # Gromacs-specific options
        GenOpts["gmxpath"] = TgtOptions["gmxpath"]
        GenOpts["gmxsuffix"] = TgtOptions["gmxsuffix"]
        EngOpts["liquid"]["gmx_top"] = os.path.splitext(liquid_fnm)[0] + ".top"
        EngOpts["liquid"]["gmx_mdp"] = os.path.splitext(liquid_fnm)[0] + ".mdp"
        EngOpts["gas"]["gmx_top"] = os.path.splitext(gas_fnm)[0] + ".top"
        EngOpts["gas"]["gmx_mdp"] = os.path.splitext(gas_fnm)[0] + ".mdp"
        if force_cuda: logger.warn("force_cuda option has no effect on Gromacs engine.")
        if rpmd_beads > 0: raise RuntimeError("Gromacs cannot handle RPMD.")
        if mts: logger.warn("Gromacs not configured for multiple timestep integrator.")
        if anisotropic: logger.warn("Gromacs not configured for anisotropic box scaling.")
    elif engname == "tinker":
        # Tinker-specific options
        GenOpts["tinkerpath"] = TgtOptions["tinkerpath"]
        EngOpts["liquid"]["tinker_key"] = os.path.splitext(liquid_fnm)[0] + ".key"
        EngOpts["gas"]["tinker_key"] = os.path.splitext(gas_fnm)[0] + ".key"
        if force_cuda: logger.warn("force_cuda option has no effect on Tinker engine.")
        if rpmd_beads > 0: raise RuntimeError("TINKER cannot handle RPMD.")
        if mts: logger.warn("Tinker not configured for multiple timestep integrator.")
    EngOpts["liquid"].update(GenOpts)
    EngOpts["gas"].update(GenOpts)
    for i in EngOpts:
        printcool_dictionary(EngOpts[i], "Engine options for %s" % i)

    # Set up MD options
    MDOpts = OrderedDict()
    MDOpts["liquid"] = OrderedDict([("nsteps", liquid_nsteps), ("timestep", liquid_timestep),
                                    ("temperature", temperature), ("pressure", pressure),
                                    ("nequil", liquid_nequil), ("minimize", minimize),
                                    ("nsave", int(1000 * liquid_intvl / liquid_timestep)),
                                    ("verbose", True), ('save_traj', TgtOptions['save_traj']), 
                                    ("threads", threads), ("anisotropic", anisotropic), ("nbarostat", 10),
                                    ("mts", mts), ("rpmd_beads", rpmd_beads), ("faststep", faststep)])
    MDOpts["gas"] = OrderedDict([("nsteps", gas_nsteps), ("timestep", gas_timestep),
                                 ("temperature", temperature), ("nsave", int(1000 * gas_intvl / gas_timestep)),
                                 ("nequil", gas_nequil), ("minimize", minimize), ("threads", 1), ("mts", mts),
                                 ("rpmd_beads", rpmd_beads), ("faststep", faststep)])

    # Energy components analysis disabled for OpenMM MTS because it uses force groups
    if (engname == "openmm" and mts): logger.warn("OpenMM with MTS integrator; energy components analysis will be disabled.\n")

    # Create instances of the MD Engine objects.
    Liquid = Engine(name="liquid", **EngOpts["liquid"])
    Gas = Engine(name="gas", **EngOpts["gas"])

    #=================================================================#
    # Run the simulation for the full system and analyze the results. #
    #=================================================================#

    printcool("Condensed phase molecular dynamics", color=4, bold=True)

    # This line runs the condensed phase simulation.
    prop_return = Liquid.molecular_dynamics(**MDOpts["liquid"])
    Rhos = prop_return['Rhos']
    Potentials = prop_return['Potentials']
    Kinetics = prop_return['Kinetics']
    Volumes = prop_return['Volumes']
    Dips = prop_return['Dips']
    EDA = prop_return['Ecomps']

    # Create a bunch of physical constants.
    # Energies are in kJ/mol
    # Lengths are in nanometers.
    L = len(Rhos)
    kB = 0.008314472471220214
    T = temperature
    kT = kB * T
    mBeta = -1.0 / kT
    Beta = 1.0 / kT
    atm_unit = 0.061019351687175
    bar_unit = 0.060221417930000
    # This is how I calculated the prefactor for the dielectric constant.
    # eps0 = 8.854187817620e-12 * coulomb**2 / newton / meter**2
    # epsunit = 1.0*(debye**2) / nanometer**3 / BOLTZMANN_CONSTANT_kB / kelvin
    # prefactor = epsunit/eps0/3
    prefactor = 30.348705333964077

    # Gather some physical variables.
    Energies = Potentials + Kinetics
    Ene_avg, Ene_err = mean_stderr(Energies)
    pV = atm_unit * pressure * Volumes
    pV_avg, pV_err = mean_stderr(pV)
    Rho_avg, Rho_err = mean_stderr(Rhos)
    PrintEDA(EDA, NMol)

    #==============================================#
    # Now run the simulation for just the monomer. #
    #==============================================#

    # Run the OpenMM simulation, gather information.

    printcool("Gas phase molecular dynamics", color=4, bold=True)
    mprop_return = Gas.molecular_dynamics(**MDOpts["gas"])
    mPotentials = mprop_return['Potentials']
    mKinetics = mprop_return['Kinetics']
    mEDA = mprop_return['Ecomps']

    mEnergies = mPotentials + mKinetics
    mEne_avg, mEne_err = mean_stderr(mEnergies)
    PrintEDA(mEDA, 1)

    #============================================#
    #  Compute the potential energy derivatives. #
    #============================================#
    logger.info("Calculating potential energy derivatives with finite difference step size: %f\n" % h)
    # Switch for whether to compute the derivatives two different ways for consistency.
    FDCheck = False

    # Create a double-precision simulation object if desired (seems unnecessary).
    DoublePrecisionDerivatives = False
    if engname == "openmm" and DoublePrecisionDerivatives and AGrad:
        logger.info("Creating Double Precision Simulation for parameter derivatives\n")
        Liquid = Engine(name="liquid", openmm_precision="double", **EngOpts["liquid"])
        Gas = Engine(name="gas", openmm_precision="double", **EngOpts["gas"])

    # Compute the energy and dipole derivatives.
    printcool("Condensed phase energy and dipole derivatives\nInitializing array to length %i" % len(Energies), color=4, bold=True)
    G, GDx, GDy, GDz = energy_derivatives(Liquid, FF, mvals, h, pgrad, len(Energies), AGrad, dipole=True)
    printcool("Gas phase energy derivatives", color=4, bold=True)
    mG, _, __, ___ = energy_derivatives(Gas, FF, mvals, h, pgrad, len(mEnergies), AGrad, dipole=False)

    #==============================================#
    #  Condensed phase properties and derivatives. #
    #==============================================#

    #----
    # Density
    #----
    # Build the first density derivative.
    GRho = mBeta * (flat(np.mat(G) * col(Rhos)) / L - np.mean(Rhos) * np.mean(G, axis=1))
    # Print out the density and its derivative.
    Sep = printcool("Density: % .4f +- % .4f kg/m^3\nAnalytic Derivative:" % (Rho_avg, Rho_err))
    FF.print_map(vals=GRho)
    logger.info(Sep)

    def calc_rho(b = None, **kwargs):
        if b == None: b = np.ones(L,dtype=float)
        if 'r_' in kwargs:
            r_ = kwargs['r_']
        return bzavg(r_,b)

    # No need to calculate error using bootstrap, but here it is anyway
    # Rhoboot = []
    # for i in range(numboots):
    #    boot = np.random.randint(N,size=N)
    #    Rhoboot.append(calc_rho(None,**{'r_':Rhos[boot]}))
    # Rhoboot = np.array(Rhoboot)
    # Rho_err = np.std(Rhoboot)

    if FDCheck:
        Sep = printcool("Numerical Derivative:")
        GRho1 = property_derivatives(Liquid, FF, mvals, h, pgrad, kT, calc_rho, {'r_':Rhos})
        FF.print_map(vals=GRho1)
        Sep = printcool("Difference (Absolute, Fractional):")
        absfrac = ["% .4e  % .4e" % (i-j, (i-j)/j) for i,j in zip(GRho, GRho1)]
        FF.print_map(vals=absfrac)

    #----
    # Enthalpy of vaporization
    #----
    H = Energies + pV
    V = np.array(Volumes)

    # Print out the liquid enthalpy.
    logger.info("Liquid enthalpy: % .4f kJ/mol, stdev % .4f ; (% .4f from energy, % .4f from pV)\n" % 
                (np.mean(H), np.std(H), np.mean(Energies), np.mean(pV)))
    numboots = 1000

    # The enthalpy of vaporization in kJ/mol.
    Hvap_avg = mEne_avg - Ene_avg / NMol + kT - np.mean(pV) / NMol
    Hvap_err = np.sqrt(Ene_err**2 / NMol**2 + mEne_err**2 + pV_err**2/NMol**2)

    # Build the first Hvap derivative.
    GHvap = np.mean(G,axis=1)
    GHvap += mBeta * (flat(np.mat(G) * col(Energies)) / L - Ene_avg * np.mean(G, axis=1))
    GHvap /= NMol
    GHvap -= np.mean(mG,axis=1)
    GHvap -= mBeta * (flat(np.mat(mG) * col(mEnergies)) / L - mEne_avg * np.mean(mG, axis=1))
    GHvap *= -1
    GHvap -= mBeta * (flat(np.mat(G) * col(pV)) / L - np.mean(pV) * np.mean(G, axis=1)) / NMol

    Sep = printcool("Enthalpy of Vaporization: % .4f +- %.4f kJ/mol\nAnalytic Derivative:" % (Hvap_avg, Hvap_err))
    FF.print_map(vals=GHvap)

    # Define some things to make the analytic derivatives easier.
    Gbar = np.mean(G,axis=1)
    def deprod(vec):
        return flat(np.mat(G)*col(vec))/L
    def covde(vec):
        return flat(np.mat(G)*col(vec))/L - Gbar*np.mean(vec)
    def avg(vec):
        return np.mean(vec)

    #----
    # Thermal expansion coefficient
    #----
    def calc_alpha(b = None, **kwargs):
        if b == None: b = np.ones(L,dtype=float)
        if 'h_' in kwargs:
            h_ = kwargs['h_']
        if 'v_' in kwargs:
            v_ = kwargs['v_']
        return 1/(kT*T) * (bzavg(h_*v_,b)-bzavg(h_,b)*bzavg(v_,b))/bzavg(v_,b)
    Alpha = calc_alpha(None, **{'h_':H, 'v_':V})
    Alphaboot = []
    for i in range(numboots):
        boot = np.random.randint(L,size=L)
        Alphaboot.append(calc_alpha(None, **{'h_':H[boot], 'v_':V[boot]}))
    Alphaboot = np.array(Alphaboot)
    Alpha_err = np.std(Alphaboot) * max([np.sqrt(statisticalInefficiency(V)),np.sqrt(statisticalInefficiency(H))])

    # Thermal expansion coefficient analytic derivative
    GAlpha1 = -1 * Beta * deprod(H*V) * avg(V) / avg(V)**2
    GAlpha2 = +1 * Beta * avg(H*V) * deprod(V) / avg(V)**2
    GAlpha3 = deprod(V)/avg(V) - Gbar
    GAlpha4 = Beta * covde(H)
    GAlpha  = (GAlpha1 + GAlpha2 + GAlpha3 + GAlpha4)/(kT*T)
    Sep = printcool("Thermal expansion coefficient: % .4e +- %.4e K^-1\nAnalytic Derivative:" % (Alpha, Alpha_err))
    FF.print_map(vals=GAlpha)
    if FDCheck:
        GAlpha_fd = property_derivatives(Liquid, FF, mvals, h, pgrad, kT, calc_alpha, {'h_':H,'v_':V})
        Sep = printcool("Numerical Derivative:")
        FF.print_map(vals=GAlpha_fd)
        Sep = printcool("Difference (Absolute, Fractional):")
        absfrac = ["% .4e  % .4e" % (i-j, (i-j)/j) for i,j in zip(GAlpha, GAlpha_fd)]
        FF.print_map(vals=absfrac)

    #----
    # Isothermal compressibility
    #----
    def calc_kappa(b=None, **kwargs):
        if b == None: b = np.ones(L,dtype=float)
        if 'v_' in kwargs:
            v_ = kwargs['v_']
        return bar_unit / kT * (bzavg(v_**2,b)-bzavg(v_,b)**2)/bzavg(v_,b)
    Kappa = calc_kappa(None,**{'v_':V})
    Kappaboot = []
    for i in range(numboots):
        boot = np.random.randint(L,size=L)
        Kappaboot.append(calc_kappa(None,**{'v_':V[boot]}))
    Kappaboot = np.array(Kappaboot)
    Kappa_err = np.std(Kappaboot) * np.sqrt(statisticalInefficiency(V))

    # Isothermal compressibility analytic derivative
    Sep = printcool("Isothermal compressibility:  % .4e +- %.4e bar^-1\nAnalytic Derivative:" % (Kappa, Kappa_err))
    GKappa1 = +1 * Beta**2 * avg(V**2) * deprod(V) / avg(V)**2
    GKappa2 = -1 * Beta**2 * avg(V) * deprod(V**2) / avg(V)**2
    GKappa3 = +1 * Beta**2 * covde(V)
    GKappa  = bar_unit*(GKappa1 + GKappa2 + GKappa3)
    FF.print_map(vals=GKappa)
    if FDCheck:
        GKappa_fd = property_derivatives(Liquid, FF, mvals, h, pgrad, kT, calc_kappa, {'v_':V})
        Sep = printcool("Numerical Derivative:")
        FF.print_map(vals=GKappa_fd)
        Sep = printcool("Difference (Absolute, Fractional):")
        absfrac = ["% .4e  % .4e" % (i-j, (i-j)/j) for i,j in zip(GKappa, GKappa_fd)]
        FF.print_map(vals=absfrac)

    #----
    # Isobaric heat capacity
    #----
    def calc_cp(b=None, **kwargs):
        if b == None: b = np.ones(L,dtype=float)
        if 'h_' in kwargs:
            h_ = kwargs['h_']
        Cp_  = 1/(NMol*kT*T) * (bzavg(h_**2,b) - bzavg(h_,b)**2)
        Cp_ *= 1000 / 4.184
        return Cp_
    Cp = calc_cp(None,**{'h_':H})
    Cpboot = []
    for i in range(numboots):
        boot = np.random.randint(L,size=L)
        Cpboot.append(calc_cp(None,**{'h_':H[boot]}))
    Cpboot = np.array(Cpboot)
    Cp_err = np.std(Cpboot) * np.sqrt(statisticalInefficiency(H))

    # Isobaric heat capacity analytic derivative
    GCp1 = 2*covde(H) * 1000 / 4.184 / (NMol*kT*T)
    GCp2 = mBeta*covde(H**2) * 1000 / 4.184 / (NMol*kT*T)
    GCp3 = 2*Beta*avg(H)*covde(H) * 1000 / 4.184 / (NMol*kT*T)
    GCp  = GCp1 + GCp2 + GCp3
    Sep = printcool("Isobaric heat capacity:  % .4e +- %.4e cal mol-1 K-1\nAnalytic Derivative:" % (Cp, Cp_err))
    FF.print_map(vals=GCp)
    if FDCheck:
        GCp_fd = property_derivatives(Liquid, FF, mvals, h, pgrad, kT, calc_cp, {'h_':H})
        Sep = printcool("Numerical Derivative:")
        FF.print_map(vals=GCp_fd)
        Sep = printcool("Difference (Absolute, Fractional):")
        absfrac = ["% .4e  % .4e" % (i-j, (i-j)/j) for i,j in zip(GCp,GCp_fd)]
        FF.print_map(vals=absfrac)

    #----
    # Dielectric constant
    #----
    def calc_eps0(b=None, **kwargs):
        if b == None: b = np.ones(L,dtype=float)
        if 'd_' in kwargs: # Dipole moment vector.
            d_ = kwargs['d_']
        if 'v_' in kwargs: # Volume.
            v_ = kwargs['v_']
        b0 = np.ones(L,dtype=float)
        dx = d_[:,0]
        dy = d_[:,1]
        dz = d_[:,2]
        D2  = bzavg(dx**2,b)-bzavg(dx,b)**2
        D2 += bzavg(dy**2,b)-bzavg(dy,b)**2
        D2 += bzavg(dz**2,b)-bzavg(dz,b)**2
        return prefactor*D2/bzavg(v_,b)/T
    Eps0 = calc_eps0(None,**{'d_':Dips, 'v_':V})
    Eps0boot = []
    for i in range(numboots):
        boot = np.random.randint(L,size=L)
        Eps0boot.append(calc_eps0(None,**{'d_':Dips[boot], 'v_':V[boot]}))
    Eps0boot = np.array(Eps0boot)
    Eps0_err = np.std(Eps0boot)*np.sqrt(np.mean([statisticalInefficiency(Dips[:,0]),statisticalInefficiency(Dips[:,1]),statisticalInefficiency(Dips[:,2])]))
 
    # Dielectric constant analytic derivative
    Dx = Dips[:,0]
    Dy = Dips[:,1]
    Dz = Dips[:,2]
    D2 = avg(Dx**2)+avg(Dy**2)+avg(Dz**2)-avg(Dx)**2-avg(Dy)**2-avg(Dz)**2
    GD2  = 2*(flat(np.mat(GDx)*col(Dx))/L - avg(Dx)*(np.mean(GDx,axis=1))) - Beta*(covde(Dx**2) - 2*avg(Dx)*covde(Dx))
    GD2 += 2*(flat(np.mat(GDy)*col(Dy))/L - avg(Dy)*(np.mean(GDy,axis=1))) - Beta*(covde(Dy**2) - 2*avg(Dy)*covde(Dy))
    GD2 += 2*(flat(np.mat(GDz)*col(Dz))/L - avg(Dz)*(np.mean(GDz,axis=1))) - Beta*(covde(Dz**2) - 2*avg(Dz)*covde(Dz))
    GEps0 = prefactor*(GD2/avg(V) - mBeta*covde(V)*D2/avg(V)**2)/T
    Sep = printcool("Dielectric constant:           % .4e +- %.4e\nAnalytic Derivative:" % (Eps0, Eps0_err))
    FF.print_map(vals=GEps0)
    if FDCheck:
        GEps0_fd = property_derivatives(Liquid, FF, mvals, h, pgrad, kT, calc_eps0, {'d_':Dips,'v_':V})
        Sep = printcool("Numerical Derivative:")
        FF.print_map(vals=GEps0_fd)
        Sep = printcool("Difference (Absolute, Fractional):")
        absfrac = ["% .4e  % .4e" % (i-j, (i-j)/j) for i,j in zip(GEps0,GEps0_fd)]
        FF.print_map(vals=absfrac)

    logger.info("Writing final force field.\n")
    pvals = FF.make(mvals)

    logger.info("Writing all simulation data to disk.\n")
    with wopen(os.path.join('npt_result.p')) as f: lp_dump((Rhos, Volumes, Potentials, Energies, Dips, G, [GDx, GDy, GDz], mPotentials, mEnergies, mG, Rho_err, Hvap_err, Alpha_err, Kappa_err, Cp_err, Eps0_err, NMol),f)
Esempio n. 28
0
def write_leap(fnm,
               mol2=[],
               frcmod=[],
               pdb=None,
               prefix='amber',
               spath=[],
               delcheck=False):
    """ Parse and edit an AMBER LEaP input file. Output file is written to inputfile_ (with trailing underscore.) """
    have_fmod = []
    have_mol2 = []
    # The lines that will be printed out to actually run tleap
    line_out = []
    aload = ['loadamberparams', 'source', 'loadoff']
    aload_eq = ['loadmol2']
    spath.append('.')

    for line in open(fnm):
        # Skip comment lines
        if line.strip().startswith('#'): continue
        line = line.split('#')[0]
        s = line.split()
        ll = line.lower()
        ls = line.lower().split()
        # Check to see if all files being loaded are in the search path
        if '=' in line:
            if ll.split('=')[1].split()[0] in aload_eq:
                if not any(
                    [os.path.exists(os.path.join(d, s[-1])) for d in spath]):
                    logger.error("The file in this line cannot be loaded : " +
                                 line.strip())
                    raise RuntimeError
        elif len(ls) > 0 and ls[0] in aload:
            if not any([os.path.exists(os.path.join(d, s[-1]))
                        for d in spath]):
                logger.error("The file in this line cannot be loaded : " +
                             line.strip())
                raise RuntimeError
        if len(s) >= 2 and ls[0] == 'loadamberparams':
            have_fmod.append(s[1])
        if len(s) >= 2 and 'loadmol2' in ll:
            have_mol2.append(s[-1])
        if len(s) >= 2 and 'loadpdb' in ll:
            # Adopt the AMBER molecule name from the loadpdb line.
            ambername = line.split('=')[0].strip()
            # If we pass in our own PDB, then this line is replaced.
            if pdb != None:
                line = '%s = loadpdb %s\n' % (ambername, pdb)
        if len(s) >= 1 and ls[0] == 'check' and delcheck:
            # Skip over check steps if so decreed
            line = "# " + line
        if 'saveamberparm' in ll:
            # We'll write the saveamberparm line ourselves
            continue
        if len(s) >= 1 and ls[0] == 'quit':
            # Don't write the quit line.
            break
        if not line.endswith('\n'): line += '\n'
        line_out.append(line)
    # Sanity checks: If frcmod and mol2 files are provided to this function,
    # they should be in the leap.cmd file as well.  There should be exactly
    # one PDB file being loaded.
    for i in frcmod:
        if i not in have_fmod:
            warn_press_key("WARNING: %s is not being loaded in %s" % (i, fnm))
    for i in mol2:
        if i not in have_mol2:
            warn_press_key("WARNING: %s is not being loaded in %s" % (i, fnm))

    fout = fnm + '_'
    line_out.append('saveamberparm %s %s.prmtop %s.inpcrd\n' %
                    (ambername, prefix, prefix))
    line_out.append('quit\n')
    with wopen(fout) as f:
        print >> f, ''.join(line_out)