예제 #1
0
    def setup_coulomb_potential(self):
        """Setups a Coulomb potential between the subsystems.

        Ewald calculation is automatically used for pbc-systems. Non-pbc
        systems use the ProductPotential to reproduce the Coulomb potential.
        """
        parameters = self.info.electrostatic_parameters

        # Check that that should Ewald summation be used and if so, that all the
        # needed parameters are given
        if self.has_pbc:
            needed = ["k_cutoff", "real_cutoff", "sigma"]
            for param in needed:
                if param not in parameters:
                    error(
                        param
                        + " not specified in Interaction.enable_coulomb_potential(). It is needed in order to calculate electrostatic interaction energy with Ewald summation in systems with periodic boundary conditions."
                    )
                    return

            ewald = CoulombSummation()
            ewald.set_parameter_value("epsilon", parameters["epsilon"])
            ewald.set_parameter_value("k_cutoff", parameters["k_cutoff"])
            ewald.set_parameter_value("real_cutoff", parameters["real_cutoff"])
            ewald.set_parameter_value("sigma", parameters["sigma"])
            self.pbc_calculator.set_coulomb_summation(ewald)

        else:
            # Add coulomb force between all charged particles in secondary
            # system, and all atoms in primary system. It is assumed that the
            # combined system will be made so that the primary system comes
            # before the secondary in indexing.
            coulomb_pairs = []
            for i, ai in enumerate(self.primary_subsystem.atoms_for_interaction):
                for j, aj in enumerate(self.secondary_subsystem.atoms_for_interaction):
                    if not np.allclose(aj.charge, 0):
                        coulomb_pairs.append([i, j + self.n_primary])

            # There are no charges in the secondary system, and that can't
            # change unlike the charges in primary system
            if len(coulomb_pairs) is 0:
                warn(
                    "There cannot be electrostatic interaction between the "
                    "subsystems, because the secondary system does not have "
                    "any initial charges",
                    2,
                )
                return

            # The first potential given to the productpotential defines the
            # targets and cutoff
            kc = 1.0 / (4.0 * np.pi * parameters["epsilon"])
            max_cutoff = np.linalg.norm(np.array(self.primary_subsystem.atoms_for_interaction.get_cell()))
            coul1 = Potential("power", indices=coulomb_pairs, parameters=[1, 1, 1], cutoff=max_cutoff)
            coul2 = Potential("charge_pair", parameters=[kc, 1, 1])
            coulomb_potential = ProductPotential([coul1, coul2])

            self.calculator.add_potential(coulomb_potential)

        self.has_coulomb_interaction = True
예제 #2
0
    def setup_hydrogen_links(self, links):
        """Setup the hydrogen link atoms to the primary system.

        Parameters:
            link_parameters: list of tuples
                Contains the link atom parameters from the Interaction-object.
                Each tuple in the list is a link atom specification for a
                covalent bond of different type. The first item in the tuple is
                a list of tuples containing atom index pairs. The second item
                in the tuple is the CHL parameter for these links.
        """
        self.link_atoms = Atoms(pbc=copy(self.full_system.get_pbc()),
                                cell=copy(self.full_system.get_cell()))
        for bond in links:

            pairs = bond[0]
            CHL = bond[1]

            for link in pairs:

                # Extract the position of the boundary atoms
                q1_index = link[0]
                m1_index = link[1]
                iq1 = self.primary_subsystem.index_map.get(q1_index)
                im1 = self.secondary_subsystem.index_map.get(m1_index)

                if iq1 is None:
                    error(("Invalid link: "+str(q1_index)+"-"+str(m1_index)+":\n"
                          "The first index does not point to an atom in the primary system."))
                if im1 is None:
                    error(("Invalid link: "+str(q1_index)+"-"+str(m1_index)+":\n"
                          "The second index does not point to an atom in the secondary system."))

                q1 = self.primary_subsystem.atoms_for_subsystem[iq1]
                rq1 = q1.position

                # Calculate the separation between the host atoms from the full
                # system. We need to do this in the full system because the
                # subsystems may not have the same coordinate systems due to cell
                # size minimization.
                frq1 = self.full_system[q1_index].position
                frm1 = self.full_system[m1_index].position
                distance = CHL*(frm1 - frq1)

                # Calculate position for the hydrogen atom in both the primary
                # subsystem and in the system containing only link atoms. The link
                # atom system is used when calculating link atom corrections.
                r_primary = rq1 + distance
                r_link = frq1 + distance

                # Create a hydrogen atom in the primary subsystem and in the
                # full subsystem
                hydrogen_primary = Atom('H', position=r_primary)
                hydrogen_link = Atom('H', position=r_link)
                self.primary_subsystem.atoms_for_subsystem.append(hydrogen_primary)
                self.link_atoms.append(hydrogen_link)

        # Update the cell size after adding link atoms
        if self.primary_subsystem.cell_size_optimization_enabled:
            self.primary_subsystem.optimize_cell()
예제 #3
0
    def setup_coulomb_potential(self):
        """Setups a Coulomb potential between the subsystems.

        Ewald calculation is automatically used for pbc-systems. Non-pbc
        systems use the ProductPotential to reproduce the Coulomb potential.
        """
        parameters = self.info.electrostatic_parameters

        # Check that that should Ewald summation be used and if so, that all the
        # needed parameters are given
        if self.has_pbc:
            needed = ["k_cutoff", "real_cutoff", "sigma"]
            for param in needed:
                if param not in parameters:
                    error(param + " not specified in Interaction.enable_coulomb_potential(). It is needed in order to calculate electrostatic interaction energy with Ewald summation in systems with periodic boundary conditions.")
                    return

            ewald = CoulombSummation()
            ewald.set_parameter_value('epsilon', parameters['epsilon'])
            ewald.set_parameter_value('k_cutoff', parameters['k_cutoff'])
            ewald.set_parameter_value('real_cutoff', parameters['real_cutoff'])
            ewald.set_parameter_value('sigma', parameters['sigma'])
            self.pbc_calculator.set_coulomb_summation(ewald)

        else:
            # Add coulomb force between all charged particles in secondary
            # system, and all atoms in primary system. It is assumed that the
            # combined system will be made so that the primary system comes
            # before the secondary in indexing.
            coulomb_pairs = []
            for i, ai in enumerate(self.primary_subsystem.atoms_for_interaction):
                for j, aj in enumerate(self.secondary_subsystem.atoms_for_interaction):
                    if not np.allclose(aj.charge, 0):
                        coulomb_pairs.append([i, j+self.n_primary])

            # There are no charges in the secondary system, and that can't
            # change unlike the charges in primary system
            if len(coulomb_pairs) is 0:
                warn("There cannot be electrostatic interaction between the "
                     "subsystems, because the secondary system does not have "
                     "any initial charges", 2)
                return

            # The first potential given to the productpotential defines the
            # targets and cutoff
            kc = 1.0/(4.0*np.pi*parameters['epsilon'])
            max_cutoff = np.linalg.norm(np.array(self.primary_subsystem.atoms_for_interaction.get_cell()))
            coul1 = Potential('power', indices=coulomb_pairs, parameters=[1, 1, 1], cutoff=max_cutoff)
            coul2 = Potential('charge_pair', parameters=[kc, 1, 1])
            coulomb_potential = ProductPotential([coul1, coul2])

            self.calculator.add_potential(coulomb_potential)

        self.has_coulomb_interaction = True
예제 #4
0
    def setup_hydrogen_links(self, links):
        """Setup the hydrogen link atoms to the primary system.

        Parameters:
            link_parameters: list of tuples
                Contains the link atom parameters from the Interaction-object.
                Each tuple in the list is a link atom specification for a
                covalent bond of different type. The first item in the tuple is
                a list of tuples containing atom index pairs. The second item
                in the tuple is the CHL parameter for these links.
        """
        self.link_atoms = Atoms(pbc=copy(self.full_system.get_pbc()), cell=copy(self.full_system.get_cell()))
        for bond in links:

            pairs = bond[0]
            CHL = bond[1]

            for link in pairs:

                # Extract the position of the boundary atoms
                q1_index = link[0]
                m1_index = link[1]
                iq1 = self.primary_subsystem.index_map.get(q1_index)
                im1 = self.secondary_subsystem.index_map.get(m1_index)

                if iq1 is None:
                    error(
                        (
                            "Invalid link: " + str(q1_index) + "-" + str(m1_index) + ":\n"
                            "The first index does not point to an atom in the primary system."
                        )
                    )
                if im1 is None:
                    error(
                        (
                            "Invalid link: " + str(q1_index) + "-" + str(m1_index) + ":\n"
                            "The second index does not point to an atom in the secondary system."
                        )
                    )

                q1 = self.primary_subsystem.atoms_for_subsystem[iq1]
                rq1 = q1.position

                # Calculate the separation between the host atoms from the full
                # system. We need to do this in the full system because the
                # subsystems may not have the same coordinate systems due to cell
                # size minimization.
                frq1 = self.full_system[q1_index].position
                frm1 = self.full_system[m1_index].position
                distance = CHL * (frm1 - frq1)

                # Calculate position for the hydrogen atom in both the primary
                # subsystem and in the system containing only link atoms. The link
                # atom system is used when calculating link atom corrections.
                r_primary = rq1 + distance
                r_link = frq1 + distance

                # Create a hydrogen atom in the primary subsystem and in the
                # full subsystem
                hydrogen_primary = Atom("H", position=r_primary)
                hydrogen_link = Atom("H", position=r_link)
                self.primary_subsystem.atoms_for_subsystem.append(hydrogen_primary)
                self.link_atoms.append(hydrogen_link)

        # Update the cell size after adding link atoms
        if self.primary_subsystem.cell_size_optimization_enabled:
            self.primary_subsystem.optimize_cell()