def write(self, extracted_global_state: Sequence[Node]) -> None:
        """
        Extract the bond lengths and bond angles of all water molecules and write them to the temporary files.

        Parameters
        ----------
        extracted_global_state : Sequence[base.node.Node]
            The extracted global state.

        Raises
        ------
        AssertionError
            If not each root node contains three children.
        """
        super().write(extracted_global_state)
        for root_cnode in extracted_global_state:
            assert len(root_cnode.children) == 3
            hydrogen_one_position = root_cnode.children[0].value.position
            oxygen_position = root_cnode.children[1].value.position
            hydrogen_two_position = root_cnode.children[2].value.position
            vector_oh_one = setting.periodic_boundaries.separation_vector(
                oxygen_position, hydrogen_one_position)
            vector_oh_two = setting.periodic_boundaries.separation_vector(
                oxygen_position, hydrogen_two_position)
            print(vectors.norm(vector_oh_one), file=self._file_bond_lengths)
            print(vectors.norm(vector_oh_two), file=self._file_bond_lengths)
            print(vectors.angle_between_two_vectors(vector_oh_one,
                                                    vector_oh_two),
                  file=self._file_bond_angles)
Exemplo n.º 2
0
    def derivative(
            self, direction: int, separation_one: Sequence[float],
            separation_two: Sequence[float]) -> Tuple[float, float, float]:
        """
        Return the derivative of the potential along a direction with respect to i, j, and k.
        
        Parameters
        ----------
        direction : int
            The direction of the derivative.
        separation_one : Sequence[float]
            The separation vector r_i - r_j.
        separation_two : Sequence[float]
            The separation vector r_k - r_j.

        Returns
        -------
        (float, float, float)
            The derivatives with respect to i, j, and k.
        """
        separation_norm_one = vectors.norm(separation_one)
        separation_norm_two = vectors.norm(separation_two)
        cosine_of_angle = (sum(separation_one[i] * separation_two[i]
                               for i in range(setting.dimension)) /
                           separation_norm_one / separation_norm_two)
        angle = math.acos(cosine_of_angle)

        d_potential_by_d_angle = self._prefactor * (angle -
                                                    self._equilibrium_angle)
        d_angle_by_d_cosine_of_angle = -1.0 / math.sin(angle)
        d_cosine_by_d_separation_one = (
            separation_two[direction] / separation_norm_one /
            separation_norm_two - cosine_of_angle * separation_one[direction] /
            separation_norm_one**2)
        d_cosine_by_d_separation_two = (
            separation_one[direction] / separation_norm_one /
            separation_norm_two - cosine_of_angle * separation_two[direction] /
            separation_norm_two**2)

        d_potential_by_d_separation_one = (d_potential_by_d_angle *
                                           d_angle_by_d_cosine_of_angle *
                                           d_cosine_by_d_separation_one)
        d_potential_by_d_separation_two = (d_potential_by_d_angle *
                                           d_angle_by_d_cosine_of_angle *
                                           d_cosine_by_d_separation_two)

        return (d_potential_by_d_separation_one,
                -d_potential_by_d_separation_one -
                d_potential_by_d_separation_two,
                d_potential_by_d_separation_two)
Exemplo n.º 3
0
    def write(self, extracted_global_state: Sequence[Node]) -> None:
        """
        Extract the shortest separations between all leaf unit pairs in different composite objects and write them to
        the temporary files.

        Parameters
        ----------
        extracted_global_state : Sequence[base.node.Node]
            The extracted global state.
        """
        super().write(extracted_global_state)
        for first_root_cnode_index, first_root_cnode in enumerate(
                extracted_global_state):
            for second_root_cnode_index in range(first_root_cnode_index + 1,
                                                 len(extracted_global_state)):
                second_root_cnode = extracted_global_state[
                    second_root_cnode_index]
                for first_leaf_node in yield_leaf_nodes(first_root_cnode):
                    for second_leaf_node in yield_leaf_nodes(
                            second_root_cnode):
                        first_leaf_identifier = first_leaf_node.value.identifier[
                            -1]
                        second_leaf_identifier = second_leaf_node.value.identifier[
                            -1]
                        identifier_distance = (
                            abs(first_leaf_identifier - second_leaf_identifier)
                            if setting.number_of_node_levels > 1 else 0)
                        separation = setting.periodic_boundaries.separation_vector(
                            first_leaf_node.value.position,
                            second_leaf_node.value.position)
                        print(vectors.norm(separation),
                              file=self._files[identifier_distance])
Exemplo n.º 4
0
    def write(self, extracted_global_state: Sequence[Node]) -> None:
        """
        Extract the shortest separations of the second child of each root node and write it to the temporary file.

        Parameters
        ----------
        extracted_global_state : Sequence[base.node.Node]
            The extracted global state.

        Raises
        ------
        AssertionError
            If not each root node contains three children.
        """
        super().write(extracted_global_state)
        assert all(
            len(root_cnode.children) == 3
            for root_cnode in extracted_global_state)
        oxygen_positions = [
            root_cnode.children[1].value.position
            for root_cnode in extracted_global_state
        ]
        for first_index, first_oxygen_position in enumerate(oxygen_positions):
            for second_index in range(first_index + 1, len(oxygen_positions)):
                oxygen_separation = setting.periodic_boundaries.separation_vector(
                    first_oxygen_position, oxygen_positions[second_index])
                print(vectors.norm(oxygen_separation), file=self._file)
Exemplo n.º 5
0
    def displacement(self, direction: int, separation: MutableSequence[float],
                     potential_change: float) -> float:
        """
        Return the displacement of the active unit i until the cumulative event rate of the potential equals the given
        potential change.

        This method determines whether the active unit is behind or in front of the target unit, and whether the
        the absolute value of the separation is larger than r_0 ('outside sphere') or smaller ('inside sphere').
        This is used to call one of the four corresponding methods.

        Parameters
        ----------
        direction : int
            The direction of motion of the active unit i.
        separation : MutableSequence[float]
            The separation vector r_ij.
        potential_change : float
            The sampled potential change.

        Returns
        -------
        float
            The displacement of the active unit i where the cumulative event rate equals the sampled potential change.
        """
        norm_of_separation = vectors.norm(separation)
        # Active unit is outside of the minimum potential shell
        if norm_of_separation > self._equilibrium_separation:
            # Active unit is in front of target unit
            if separation[direction] < 0.0:
                current_potential = self._potential(separation)
                displacement = self._displacement_front_outside_sphere(
                    direction, current_potential, potential_change, separation)
            # Active unit is behind of target unit
            else:
                displacement = self._displacement_behind_outside_sphere(
                    direction, potential_change, separation)
        # Active unit is inside of the minimum potential shell
        else:
            # Active unit is in front of target unit
            if separation[direction] < 0.0:
                displacement = self._displacement_front_inside_sphere(
                    direction, potential_change, separation)
            # Active unit is behind of target unit
            else:
                current_potential = self._potential(separation)
                displacement = self._displacement_behind_inside_sphere(
                    direction, current_potential, potential_change, separation)
        return displacement
    def _potential(self, separation: Sequence[float]) -> float:
        """
        Return the potential for the given separation.

        Parameters
        ----------
        separation : Sequence[float]
            The separation vector r_ij.

        Returns
        -------
        float
            The potential.
        """
        distance_from_minimum = vectors.norm(
            separation) - self._equilibrium_separation
        return self._prefactor * distance_from_minimum**self._power
    def derivative(self, direction: int, separation: Sequence[float]) -> float:
        """
        Return the derivative of the potential along a direction.

        Parameters
        ----------
        direction : int
            The direction of the derivative.
        separation : Sequence[float]
            The separation vector r_ij.

        Returns
        -------
        float
            The derivative.
        """
        norm_of_separation = vectors.norm(separation)
        return (-self._power * self._prefactor *
                (norm_of_separation - self._equilibrium_separation)
                **(self._power - 1) * separation[direction] /
                norm_of_separation)
Exemplo n.º 8
0
    def derivative(self, direction: int, separation: Sequence[float],
                   charge_one: float, charge_two: float) -> float:
        """
        Return the derivative of the potential along a direction.

        Parameters
        ----------
        direction : int
            The direction of the derivative.
        separation : Sequence[float]
            The separation vector r_ij.
        charge_one : float
            The charge c_i.
        charge_two : float
            The charge c_j.

        Returns
        -------
        float
            The derivative.
        """
        return (self._power * separation[direction] /
                vectors.norm(separation)**self._power_plus_two *
                self._prefactor * charge_one * charge_two)
Exemplo n.º 9
0
 def test_norm(self):
     self.assertAlmostEqual(vectors.norm([0.1, 0.2, 0.3]), 0.3741657386773941, places=13)
     self.assertAlmostEqual(vectors.norm([0.1, 0.0, 0.0]), 0.1, places=13)
     self.assertAlmostEqual(vectors.norm([0.0, 0.2, 0.0]), 0.2, places=13)
     self.assertAlmostEqual(vectors.norm([0.0, 0.0, -0.3]), 0.3, places=13)
     self.assertAlmostEqual(vectors.norm([0.4, 1.5, 2.3]), 2.774887385102321, places=12)
     self.assertAlmostEqual(vectors.norm([0.4, 1.5, -2.3]), 2.774887385102321, places=12)
     self.assertAlmostEqual(vectors.norm([0.4, -1.5, 2.3]), 2.774887385102321, places=12)
     self.assertAlmostEqual(vectors.norm([0.4, -1.5, -2.3]), 2.774887385102321, places=12)
     self.assertAlmostEqual(vectors.norm([-0.4, 1.5, -2.3]), 2.774887385102321, places=12)
     self.assertAlmostEqual(vectors.norm([-0.4, 1.5, 2.3]), 2.774887385102321, places=12)
     self.assertAlmostEqual(vectors.norm([-0.4, -1.5, -2.3]), 2.774887385102321, places=12)
     self.assertAlmostEqual(vectors.norm([-0.4, -1.5, 2.3]), 2.774887385102321, places=12)
     self.assertAlmostEqual(vectors.norm([0.1, 0.0]), 0.1, places=13)
     self.assertAlmostEqual(vectors.norm([0.0, 0.0, 0.0, 0.2]), 0.2, places=13)