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)
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)
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])
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)
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)
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)
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)