コード例 #1
0
    def find_configurations(self):
        """
        Finds the partitions as required by the Hot-Spot method 
        and saves each partition as a system object.
        Saves all systems in the dictionary self.systems

        Parameters
        ----------
        qm_center : list 
            atoms that define the qm center, default is None

        """

        qm = System(qm_indices=self.qm_atoms,
                    qm_residues=self.qm_residues,
                    run_ID=self.run_ID,
                    partition_ID='qm')
        qm.buffer_groups = self.buffer_groups

        # the following only runs if there are groups in the buffer zone
        if self.buffer_groups:

            qm.buffer_groups = deepcopy(self.buffer_groups)

            for i, buf in self.buffer_groups.items():
                qm.qm_residues.append(i)
                for idx in buf.atoms:
                    qm.qm_atoms.append(idx)

        self.systems[self.run_ID] = {}
        self.systems[self.run_ID][qm.partition_ID] = qm
コード例 #2
0
ファイル: qmmm.py プロジェクト: bzhang25/janus
    def run_qmmm(self, main_info, wrapper_type):
        """
        Drives QM/MM computation.
        Updates the positions and topology given in main_info,
        and determines the QM/MM energy and gradients

        Parameters
        ----------
        main_info : dict 
            Contains the energy, forces, topology, and position information 
            for the whole system
        wrapper_type : str
            Defines the program used to obtain main_info
        """

        t0 = time.time()
        self.update_traj(main_info['positions'], main_info['topology'],
                         wrapper_type)

        system = System(qm_indices=self.qm_atoms,
                        qm_residues=None,
                        run_ID=self.run_ID)

        if self.embedding_method == 'Mechanical':
            t_all = self.mechanical(system, main_info)
        elif self.embedding_method == 'Electrostatic':
            t_all = self.electrostatic(system, main_info)
        else:
            print(
                'only mechanical and electrostatic embedding schemes implemented at this time'
            )

        self.systems[self.run_ID] = {}
        self.systems[self.run_ID][system.partition_ID] = system
        self.systems[self.run_ID]['qmmm_forces'] = system.qmmm_forces
        self.systems[self.run_ID]['qmmm_energy'] = system.qmmm_energy
        #self.systems[self.run_ID]['kinetic_energy'] = main_info['kinetic']
        self.systems[
            self.run_ID]['kinetic_energy'] = system.entire_sys['kinetic']

        #if self.run_ID % 10 == 0:
        #print('!', self.run_ID, self.systems[self.run_ID]['qmmm_energy'] + self.systems[self.run_ID]['kinetic_energy'])
        print('! run {} total energy: {}'.format(
            self.run_ID + 1, (self.systems[self.run_ID]['qmmm_energy'] +
                              self.systems[self.run_ID]['kinetic_energy'])))
        print('! run {} total potential energy: {}'.format(
            self.run_ID + 1, self.systems[self.run_ID]['qmmm_energy']))
        # add kinetic in total qmmm_energy

        # updates current step count
        self.run_ID += 1

        # delete the information of 2 runs before, only save current run and previous run information at a time
        if self.run_ID > 1:
            del self.systems[self.run_ID - 2]

        t_end = time.time()
        print('qmmm overhead took {}s'.format(t_end - t0 - t_all))

        return t_all
コード例 #3
0
ファイル: qmmm.py プロジェクト: zhenglz/janus
    def prepare_link_atom(self):
        """
        Identifies where to put link atom.
        Saves the qm and mm atom associated with the bond being cut across the QM/MM boundary
        and computes the g scaling factor for the link atom.
        """

        self.link_atoms = {}
        self.link_atoms['all_mm'] = []
        self.link_atoms['all_outer_bonds'] = []

        for i, bond in enumerate(self.qmmm_boundary_bonds):

            qm = bond[0]
            mm = bond[1]

            self.link_atoms[i] = {}

            self.link_atoms[i]['qm_atom'] = qm
            self.link_atoms[i]['mm_atom'] = mm
            self.link_atoms['all_mm'].append(mm.index)

            self.link_atoms[i]['link_atom'] = self.link_atom_element
            g = System.compute_scale_factor_g(qm.element.symbol,
                                              mm.element.symbol,
                                              self.link_atom_element)
            self.link_atoms[i]['scale_factor'] = g
            # this is in nm
            self.link_atoms[i]['link_positions'] = (1 - g) * self.positions[
                qm.index] + g * self.positions[mm.index]

            if self.boundary_treatment == 'RC' or self.boundary_treatment == 'RCD':
                bonds = []
                # find index of atoms bonded to mm atom
                for bond in self.topology.bonds:
                    if bond[0] == mm or bond[1] == mm:
                        if bond[0] != qm and bond[1] != qm:
                            if bond[0] != mm:
                                bonds.append(bond[0].index)
                            elif bond[1] != mm:
                                bonds.append(bond[1].index)

                self.link_atoms[i]['bonds_to_mm'] = bonds
                self.link_atoms['all_outer_bonds'].append(bonds)
コード例 #4
0
ファイル: das.py プロジェクト: zhenglz/janus
    def find_configurations(self):
        """
        Finds the QM/MM configurations as required by the PAP method 
        and saves each partition as a system object.
        Saves all systems in the dictionary self.systems

        Parameters
        ----------
        qm_center : list 
            atoms that define the qm center, default is None

        """

        qm = System(qm_indices=self.qm_atoms,
                    qm_residues=self.qm_residues,
                    run_ID=self.run_ID,
                    partition_ID='qm')
        qm.buffer_groups = self.buffer_groups

        self.systems[self.run_ID] = {}
        self.systems[self.run_ID][qm.partition_ID] = qm

        # the following only runs if there are groups in the buffer zone
        if self.buffer_groups:

            self.partitions, sigmas = self.get_combos(list(self.buffer_groups))
            print('partitions', self.partitions)

            for i, part in enumerate(self.partitions):
                sys = System(qm_indices=self.qm_atoms,
                             qm_residues=self.qm_residues,
                             run_ID=self.run_ID,
                             partition_ID=i)
                sys.sigma = sigmas[i]
                for group in part:
                    sys.qm_residues.append(group)
                    for idx in self.buffer_groups[group].atoms:
                        sys.qm_atoms.append(idx)

                # each partition has a copy of its buffer groups -
                # don't know if this is actually needed
                sys.buffer_groups = {k: self.buffer_groups[k] for k in part}
                self.systems[self.run_ID][sys.partition_ID] = sys
コード例 #5
0
ファイル: pap.py プロジェクト: zhenglz/janus
    def find_configurations(self): 
        """
        Finds the partitions as required by the PAP method 
        and saves each partition as a system object.
        Saves all systems in the dictionary self.systems

        Parameters
        ----------
        qm_center : list 
            atoms that define the qm center, default is None

        """
    
        qm = System(qm_indices=self.qm_atoms, qm_residues=self.qm_residues, run_ID=self.run_ID, partition_ID='qm')
        # qm partition contains the original partition information
        qm.buffer_groups = self.buffer_groups

        self.systems[self.run_ID] = {}
        self.systems[self.run_ID][qm.partition_ID] = qm
        

        # the following only runs if there are groups in the buffer zone
        if self.buffer_groups:

            self.partitions = self.get_combos(list(self.buffer_groups))

            for i, part in enumerate(self.partitions):
                sys = System(qm_indices=self.qm_atoms, qm_residues=self.qm_residues, run_ID=self.run_ID, partition_ID=i)
                for group in part:
                    sys.qm_residues.append(group)
                    for idx in self.buffer_groups[group].atoms:
                        sys.qm_atoms.append(idx)
                
                # each partition has a copy of its buffer groups - 
                sys.buffer_groups = {k: self.buffer_groups[k] for k in part}
                self.systems[self.run_ID][sys.partition_ID] = sys
コード例 #6
0
ファイル: das.py プロジェクト: zhenglz/janus
    def run_aqmmm(self):
        """
        Interpolates the energy and gradients from each partition
        according to the PAP method
        """

        qm = self.systems[self.run_ID]['qm']

        if not self.buffer_groups:
            self.systems[self.run_ID]['qmmm_energy'] = qm.qmmm_energy
            self.systems[self.run_ID]['qmmm_forces'] = qm.qmmm_forces

        else:

            # getting first term of ap energy and forces (w/o gradient of switching function)
            qm.aqmmm_energy = deepcopy(qm.qmmm_energy)
            qm.aqmmm_forces = deepcopy(qm.qmmm_forces)

            dis = sorted(self.buffer_distance, key=self.buffer_distance.get)
            sigma = self.buffer_groups[dis[0]].s_i
            qm.aqmmm_energy *= sigma
            qm.aqmmm_forces.update(
                (x, y * sigma) for x, y in qm.aqmmm_forces.items())

            energy = deepcopy(qm.aqmmm_energy)
            qmmm_forces = deepcopy(qm.aqmmm_forces)

            # getting rest of the terms of ap energy and forces (w/o gradient of switching function)
            for i, part in enumerate(self.partitions):

                sys = self.systems[self.run_ID][i]
                sys.aqmmm_energy = sys.qmmm_energy * sys.sigma

                sys.aqmmm_forces = deepcopy(sys.qmmm_forces)
                sys.aqmmm_forces.update(
                    (x, y * sys.sigma) for x, y in sys.aqmmm_forces.items())

                energy += sys.aqmmm_energy

            # combining all forces
            for i, part in enumerate(self.partitions):
                forces = self.systems[self.run_ID][i].aqmmm_forces
                for j, force in forces.items():
                    if j in qmmm_forces:
                        qmmm_forces[j] += force
                    else:
                        qmmm_forces[j] = force

            # need to deal with bookkeeping term
            energy_bk = 0.0
            systems_f = []
            systems_match = []
            if self.run_ID != 0:
                for sys_f in self.systems[self.run_ID]:
                    if isinstance(sys_f, System()):
                        systems_f.append(Counter(sys_f.qm_residues))
                        for sys_i in self.systems[self.run_ID - 1]:
                            if isinstance(sys_i, System()):
                                if Counter(sys_f.qm_residues) == Counter(
                                        sys_i.qm_residues):
                                    systems_match.append(
                                        Counter(sys_f.qm_residues))
                                    energy_bk += sys_f.aqmmm_energy * (
                                        sys_f.sigma - sys_i.sigma)

                for sys in systems_f:
                    if sys not in systems_match:
                        energy_bk += sys_f.aqmmm_energy * sys_f.sigma

            energy -= energy_bk
            self.systems[self.run_ID]['qmmm_energy'] = energy
            self.systems[self.run_ID]['qmmm_forces'] = qmmm_forces