Exemplo n.º 1
0
    def __init__(self, system, model, fn_traj=None):
        '''
            **Arguments**

            system
                An instance of the System class and contains all the
                system information

            model
                An instance of the Model class and contains all the info
                to define the total PES and its electrostatic contribution.

            **Optional Arguments**

            fn_traj
                A file name to store the perturbation trajectories to or to
                read the trajectories from if the file exists. The trajectories
                are stored/read after Pickling.
        '''
        self.system = system
        self.model = model
        self.pert_theory = RelaxedGeoPertTheory(system, model)
        self.cost = HessianFCCost(system, model)
        self.fn_traj = fn_traj
        #SHLL 1508
        #-- new attributes for storing potential types
        self.stretch_pot_kind = system.stretch_pot_kind
        self.bend_pot_kind = system.bend_pot_kind
Exemplo n.º 2
0
class Program(object):
    '''
        The central class to manage the entire program.
    '''
    def __init__(self, system, model, fn_traj=None):
        '''
            **Arguments**

            system
                An instance of the System class and contains all the
                system information

            model
                An instance of the Model class and contains all the info
                to define the total PES and its electrostatic contribution.

            **Optional Arguments**

            fn_traj
                A file name to store the perturbation trajectories to or to
                read the trajectories from if the file exists. The trajectories
                are stored/read after Pickling.
        '''
        self.system = system
        self.model = model
        self.pert_theory = RelaxedGeoPertTheory(system, model)
        self.cost = HessianFCCost(system, model)
        self.fn_traj = fn_traj
        #SHLL 1508
        #-- new attributes for storing potential types
        self.stretch_pot_kind = system.stretch_pot_kind
        self.bend_pot_kind = system.bend_pot_kind
        #SHLL end

    def generate_trajectories(self, skip_dihedrals=True, verbose=True):
        '''
            Generate a perturbation trajectory for all ics (dihedrals can be
            excluded and store the coordinates in a dictionary.

            **Optional Arguments**

            skip_dihedrals
                If set to True, the dihedral ff parameters will not
                be calculated.
        '''
        maxlength = max([len(icname) for icname in self.model.val.pot.terms.keys()]) + 2
        #Check if a filename with trajectories is given. If the file exists,
        #read it and return the trajectories
        if self.fn_traj is not None:
            if os.path.isfile(self.fn_traj):
                with open(self.fn_traj,'r') as f:
                    trajectories = cPickle.load(f)
                return trajectories
        #Generate trajectories from scratch
        trajectories = {}
        all_ics = []
        for icname in sorted(self.model.val.pot.terms.keys()):
            if skip_dihedrals and icname.startswith('dihed'):
                continue
            ics = self.system.ics[icname]
            for ic in ics:
                all_ics.append(ic)
            if verbose:
                print '    %s will generate %i trajectories' %(
                    icname+' '*(maxlength-len(icname)), len(ics)
                )
        results = paracontext.map(self.pert_theory.generate, all_ics)
        for i in xrange(len(all_ics)):
            trajectories[all_ics[i].name] = results[i]
        #Check if we need to write the generated trajectories to a file
        if self.fn_traj is not None:
            with open(self.fn_traj,'w') as f:
                cPickle.dump(trajectories,f)
        return trajectories

    #SHLL 1508
    #-- extra parameters not needed anymore
    # def estimate_from_pt(self, trajectories, skip_dihedrals=True, verbose=True, stretch_pot_kind='harmonic', bend_pot_kind='harmonic'):
    #original
    def estimate_from_pt(self, trajectories, skip_dihedrals=True, verbose=True):
    #SHLL end
        '''
            Second Step of force field development: calculate harmonic force field
            parameters for every internal coordinate separately from perturbation
            trajectories.

            **Arguments**

            trajectories
                A dictionairy containing numpy arrays representing perturbation
                trajectories for each icname.

            **Optional Arguments**

            skip_dihedrals
                If set to True, the dihedral ff parameters will not
                be calculated.
        '''
        ff = FFTable()
        #SHLL 1606
        #-- transfer potential info from program to fftable
        ff.stretch_pot_kind = self.stretch_pot_kind
        ff.bend_pot_kind = self.bend_pot_kind
        #SHLL end
        maxlength = max([len(icname) for icname in self.model.val.pot.terms.keys()]) + 2
        for icname in sorted(self.model.val.pot.terms.keys()):
            ics = self.system.ics[icname]
            if skip_dihedrals and icname.startswith('dihed'):
                continue
            ks  = DataArray(unit=ics[0].kunit)
#            print 'kunit:',ics[0].kunit #GBdebug
            q0s = DataArray(unit=ics[0].qunit)
            for ic in ics:
                #SHLL 1508
                #-- estimate spf or harmcos potential params
                if icname.startswith('bond') and self.stretch_pot_kind.lower()=='spf':
                    k, q0 = self.pert_theory.estimate(ic,trajectories[ic.name], pot_kind=self.stretch_pot_kind)
                elif icname.startswith('angle') and self.bend_pot_kind.lower()=='harmcos':
                    k, q0 = self.pert_theory.estimate(ic,trajectories[ic.name], pot_kind=self.bend_pot_kind)
                else:
                    k, q0 = self.pert_theory.estimate(ic,trajectories[ic.name], pot_kind='harmonic')
                #original
                # k, q0 = self.pert_theory.estimate(ic,trajectories[ic.name])
                #SHLL end
                ks.append(k)
                q0s.append(q0)
            ff.add(icname, ks, q0s)
            descr = icname + ' '*(maxlength-len(icname))
            if verbose:
                print '    %s   K = %s    q0 = %s' % (
                    descr, ks.string(), q0s.string()
                )
        self.model.val.update_fftable(ff)
        return ff

    def refine_cost(self, verbose=True):
        '''
            Second step of force field development: refine the force constants
            using a Hessian least squares cost function.
        '''
        fcs = self.cost.estimate()
        self.model.val.update_fcs(fcs)
        fftab = self.model.val.get_fftable()
        #SHLL 1606
        #-- transfer potential info from program to fftable
        fftab.stretch_pot_kind = self.stretch_pot_kind
        fftab.bend_pot_kind = self.bend_pot_kind
        #SHLL end
        if verbose:
            fftab.print_screen()
        return fftab

    def run(self):
        '''
            Run all steps of the QuickFF methodology to derive a covalent
            force field. This method returns an instance of the class
            :class:`quickff.fftable.FFTable`, which contains all force field
            parameters.
        '''
        print header
        print sysinfo()
        print '~'*120+'\n'
        print 'System information:\n'
        self.system.print_atom_info()
        print '\nModel information:\n'
        self.model.print_info()
        print '\nDetermine dihedral potentials\n'
        self.model.val.determine_dihedral_potentials(self.system)
        print '\nDetermine the coordinates of the perturbation trajectories\n'
        self.trajectories = self.generate_trajectories()
        print '\nEstimating all pars for bonds, bends and opdists\n'
        fftab = self.estimate_from_pt(self.trajectories)
        print '\nRefining force constants using a Hessian LSQ cost\n'
        fftab = self.refine_cost()
        print '\n'+'~'*120+'\n'
        print 'Time:           ' + datetime.datetime.now().isoformat().replace('T', ' ') + '\n'
        print footer
        return fftab

    def plot_pt(self, icname, start=None, end=None, steps=51, verbose=True):
        '''
            Generate the perturbation trajectories and plot the energy
            contributions along the trajectory for all ics with a name
            compatible with icname.

            **Arguments**

            icname
                A string describing for which ics the perturbation trajectories
                should be generated.
        '''
        #Logging
        if verbose:
            print header
            print sysinfo()
            print '~'*120+'\n'
            print 'System information:\n'
            self.system.print_atom_info()
            print '\nModel information:\n'
            self.model.print_info()
            print '\nDetermine the coordinates of the perturbation trajectories\n'
        #Reading/generating trajectories
        trajectories = {}
        if self.fn_traj is not None:
            if os.path.isfile(self.fn_traj):
                with open(self.fn_traj,'r') as f:
                    trajectories = cPickle.load(f)
        for i, ic in enumerate(self.system.ics[icname]):
            if ic.name in trajectories.keys():
                #already read
                if verbose:
                    print '    %s Read %2i/%i from %s' %(
                        icname, i+1, len(self.system.ics[icname]), self.fn_traj
                    )
            else:
                #generating
                if verbose:
                    sys.stdout.write('    %s Generating %2i/%i' %(
                        icname, i+1, len(self.system.ics[icname])
                    ))
                    sys.stdout.flush()
                try:
                    trajectories[ic.name] = self.pert_theory.generate(ic, start=start, end=end, steps=51)
                    print ''
                except KeyboardInterrupt:
                    if verbose:
                        sys.stdout.write(' INTERRUPTED\n')
                        sys.stdout.flush()
        #Writing trajectories
        if self.fn_traj is not None:
            with open(self.fn_traj,'w') as f:
                cPickle.dump(trajectories, f)
        #Plotting/writing output
        for ic in self.system.ics[icname]:
            if ic.name in trajectories.keys():
                name = ic.name.replace('/', '-')
                self.pert_theory.plot(ic, trajectories[ic.name], 'energies-'+name+'.pdf')
                self.pert_theory.write(trajectories[ic.name], 'trajectory-'+name+'.xyz')
        #Logging
        if verbose:
            print ''
            print '\n'+'~'*120+'\n'
            print 'Time:           ' + datetime.datetime.now().isoformat().replace('T', ' ') + '\n'
            print footer