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)
Beispiel #2
0
    def standard_velocity_derivative(
            self, direction: int, separation_one: Sequence[float],
            separation_two: Sequence[float]) -> Tuple[float, float, float]:
        """
        Return the space derivative with respect to i, j, and k of the potential along a positive direction parallel to
        one of the cartesian axes for the given separations .

        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 space 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)
Beispiel #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])
Beispiel #4
0
    def standard_velocity_displacement(self, direction: int,
                                       separation: MutableSequence[float],
                                       potential_change: float) -> float:
        """
        Return the required displacement in space of the active unit along the positive direction of motion parallel to
        one of the cartesian axes where 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 required displacement in space of the active unit along its direction of motion 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 standard_velocity_derivative(self, direction: int, separation: Sequence[float]) -> float:
        """
        Return the space derivative of the potential along a positive direction parallel to one of the cartesian axes
        for the given separation.

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

        Returns
        -------
        float
            The space 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)
    def standard_velocity_derivative(self, direction: int, separation: Sequence[float], charge_one: float,
                                     charge_two: float) -> float:
        """
        Return the space derivative of the potential along a positive direction parallel to one of the cartesian axes
        for the given separation and charges.

        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 space derivative.
        """
        return (self._power * separation[direction] / vectors.norm(separation) ** self._power_plus_two
                * self._prefactor * charge_one * charge_two)
Beispiel #8
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)