Source code for npl.optimization.genetic_algoritm.CutAndSpliceOperator

from npl.core import Nanoparticle
from npl.utils.cutting_plane_utilities import SphericalCuttingPlaneGenerator
import numpy as np


[docs] class CutAndSpliceOperator: def __init__(self, max_radius, recompute_neighbor_list=True, normal_dir=None): self.cutting_plane_generator = SphericalCuttingPlaneGenerator(max_radius, 0.0, 0.0, normal_dir) self.recompute_neighbor_list = recompute_neighbor_list
[docs] def cut_and_splice(self, p1, p2, fixed_stoichiometry=True): self.cutting_plane_generator.set_center(p1.get_ase_atoms().get_center_of_mass()) self.cutting_plane_generator.set_max_radius(np.max(p1.get_ase_atoms().get_positions() - p1.get_ase_atoms().get_center_of_mass())) # Ensure that we indeed cut, i.e. take atoms from both particles while True: cutting_plane = self.cutting_plane_generator.generate_new_cutting_plane() atom_indices_in_positive_subspace, _ = cutting_plane.split_atom_indices(p1.get_ase_atoms()) _, atom_indices_in_negative_subspace = cutting_plane.split_atom_indices(p2.get_ase_atoms()) if np.sum(atom_indices_in_negative_subspace) > 0 and np.sum(atom_indices_in_positive_subspace) > 0: break new_particle = Nanoparticle() new_particle.add_atoms(p1.get_ase_atoms().copy()[atom_indices_in_positive_subspace], False) new_particle.add_atoms(p2.get_ase_atoms().copy()[atom_indices_in_negative_subspace], False) if fixed_stoichiometry is True: target_stoichiometry = p1.get_stoichiometry() new_particle.adjust_stoichiometry(target_stoichiometry) if self.recompute_neighbor_list: new_particle.construct_neighbor_list() return new_particle