예제 #1
0
def changeCore(parent):
    """
    Modify the core
    """
    clus = parent
    eleNames, eleNums, natoms, stride, eleRadii = get_data(clus)
    CoM(clus)
    inout = ran.choice([1, 2])  # inout = 1 muttpe: + core; inout = 2 muttype: - core
    if inout == 1:
        nout = int(0.2 * natoms)
        if nout < 1:
            nout = 1
        icenter = ran.randrange(nout) + 1
        R0 = [0.0, 0.0, 0.0]
        clus = sortR0(clus, R0)
        clus[-icenter].position = [0.1, 0.0, 0.0]
        clus = fixOverlap(clus)

    elif inout == 2:
        ncore = int(0.1 * natoms)
        if ncore < 1:
            ncore = 1
        iout = ran.randrange(ncore)
        R0 = [0.0, 0.0, 0.0]
        clus = sortR0(clus, R0)
        del clus[iout]
        clus = addAtoms(clus, eleNames, eleNums, eleRadii)
        clus = fixOverlap(clus)

    return clus
예제 #2
0
def tunnel(parent):
    """
    Tunnel one of the atoms farthest from the center to
    the other side of the cluster
    """
    clus = parent
    natoms = len(clus)
    CoM(clus)
    w = []
    for atom in clus:
        ele = atom.symbol
        x, y, z = atom.position
        r = np.sqrt(x * x + y * y + z * z)
        w.append([r, ele, x, y, z])
    w.sort()
    for i in range(natoms):
        clus[i].symbol = w[i][1]
        clus[i].x = w[i][2]
        clus[i].y = w[i][3]
        clus[i].z = w[i][4]

    nat = int(round(0.75 * natoms))
    atomNum = ran.randrange(nat, natoms)
    x, y, z = clus[atomNum].x, clus[atomNum].y, clus[atomNum].z
    clus[atomNum].x, clus[atomNum].y, clus[atomNum].z = -x, -y, -z

    clus = fixOverlap(clus)
    return clus
예제 #3
0
def partialInversion(parent):
    """
    Choose a fragment with 30% of the cluster atoms
    nearest to a randomly chosen atom and invert the
    structure with respect to its geometrical center
    """
    clus = parent
    natoms = len(clus)
    CoM(clus)
    nInvert = int(round(0.3 * natoms))
    mAtom = ran.randrange(natoms)
    R0 = clus.get_positions()[mAtom]
    clus = sortR0(clus, R0)

    fc = np.array([0.0, 0.0, 0.0])

    for i in range(nInvert):
        r = clus.get_positions()[i]
        fc += r / nInvert
    for i in range(nInvert):
        x, y, z = (
            clus.get_positions()[i][0],
            clus.get_positions()[i][1],
            clus.get_positions()[i][2],
        )
        r = np.array([x, y, z])
        ri = 2 * fc - r
        clus[i].x = ri[0]
        clus[i].y = ri[1]
        clus[i].z = ri[2]

    clus = fixOverlap(clus)
    return clus
예제 #4
0
def twist(parent):
    """
    Twist the cluster
    """

    clus = parent
    CoM(clus)
    natoms = len(clus)
    phi = ran.uniform(0, 2 * np.pi)
    psi = ran.uniform(0, np.pi)
    vx = np.cos(phi) * np.sin(psi)
    vy = np.sin(phi) * np.sin(psi)
    vz = np.cos(psi)
    vec = [vx, vy, vz]

    v = np.array(vec)
    w = []

    for atom in clus:
        ele = atom.symbol
        x, y, z = atom.position
        r = np.array([x, y, z])
        proj = np.dot(r, v)
        w.append([proj, ele, x, y, z])

    w.sort()

    for i in range(len(clus)):
        clus[i].symbol = w[i][1]
        clus[i].position = w[i][2], w[i][3], w[i][4]

    part = int(round(0.3 * natoms))
    nrot = ran.randrange(part, natoms - part)
    a = ran.uniform(np.pi / 6, 11 * np.pi / 6)

    for i in range(nrot):
        ele = clus[i].symbol
        x, y, z = clus[i].position
        rotY = y * np.cos(a) - z * np.sin(a)
        rotZ = y * np.sin(a) + z * np.cos(a)
        clus[i].symbol = ele
        clus[i].x, clus[i].y, clus[i].z = x, rotY, rotZ

    clus = fixOverlap(clus)
    return clus
예제 #5
0
def rotate_mut(parent):
    """
    Randomly rotate 25%, 50%, 75% of cluster atoms
    """
    clus = parent
    natoms = len(clus)
    CoM(clus)

    a = ran.uniform(0, 2 * np.pi)
    phi = ran.uniform(0, 2 * np.pi)
    psi = ran.uniform(0, np.pi)
    ux = np.cos(phi) * np.sin(psi)
    uy = np.sin(phi) * np.sin(psi)
    uz = np.cos(psi)
    w = 1.0 - np.cos(a)

    rot11 = ux * ux * w + np.cos(a)
    rot12 = ux * uy * w + uz * np.sin(a)
    rot13 = ux * uz * w - uy * np.sin(a)
    rot21 = uy * ux * w - uz * np.sin(a)
    rot22 = uy * uy * w + np.cos(a)
    rot23 = uy * uz * w + ux * np.sin(a)
    rot31 = uz * ux * w + uy * np.sin(a)
    rot32 = uz * uy * w - ux * np.sin(a)
    rot33 = uz * uz * w + np.cos(a)

    n = ran.choice([0.25, 0.50, 0.75])
    rotateNum = int(round(n * natoms))
    atomList = ran.sample(range(natoms), rotateNum)
    for i in atomList:
        ele = clus[i].symbol
        x, y, z = clus[i].position
        rotX = rot11 * x + rot12 * y + rot13 * z
        rotY = rot21 * x + rot22 * y + rot23 * z
        rotZ = rot31 * x + rot32 * y + rot33 * z
        clus[i].x, clus[i].y, clus[i].z = rotX, rotY, rotZ

    clus = fixOverlap(clus)
    return clus
예제 #6
0
def rattle_mut(parent):
    """
    Choose one atom and move 50% or 75% of the cluster atoms
    nearest to that atom a distance between 0 and +/- its radius
    """
    clus = parent
    CoM(clus)
    natoms = len(clus)
    ele_list = clus.get_chemical_symbols()
    radList = [covalent_radii[atomic_numbers[ele]] for ele in ele_list]
    n = ran.choice([0.50, 0.75])
    nMove = int(round(n * natoms))
    mAtom = ran.randrange(natoms)
    ele0 = clus[mAtom].symbol
    x0, y0, z0 = clus[mAtom].position

    w = []
    for i in range(natoms):
        ele = clus[i].symbol
        x, y, z = clus[i].position
        dx = x - x0
        dy = y - y0
        dz = z - z0
        dr = np.sqrt(x ** 2 + y ** 2 + z ** 2)
        w.append([dr, ele, x, y, z])

    w.sort()
    for i in range(natoms):
        clus[i].symbol = w[i][1]
        clus[i].position = w[i][2], w[i][3], w[i][4]

    for i in range(nMove):
        dis = radList[i]
        clus[i].x += ran.uniform(-dis, dis)
        clus[i].y += ran.uniform(-dis, dis)
        clus[i].z += ran.uniform(-dis, dis)

    clus = fixOverlap(clus)
    return clus
예제 #7
0
def skin(parent):
    """
    Keep 80% of the cluster atoms and relocate the remaining
    """
    clus = parent
    eleNames, eleNums, natoms, stride, eleRadii = get_data(clus)
    CoM(clus)
    nfix = int(round(0.8 * natoms))
    R0 = [0.0, 0.0, 0.0]
    clus = sortR0(clus, R0)
    core_pos = []
    core_ele = []
    for i in range(nfix):
        x, y, z = clus[i].position
        core_pos.append((x, y, z))
        ele = clus[i].symbol
        core_ele.append(ele)
    core = Atoms(core_ele, core_pos)
    clus = addAtoms(core, eleNames, eleNums, eleRadii)
    clus = fixOverlap(clus)

    return clus
예제 #8
0
def homotop(parent):
    """
    Choose pair of different elements to swap
    """
    clus = parent
    CoM(clus)
    eleNames, eleNums, natoms, stride, eleRadii = get_data(clus)
    eles = ran.sample(eleNames, 2)
    ele1_index = []
    ele2_index = []
    for i in clus:
        if i.symbol == eles[0]:
            ele1_index.append(i.index)
        if i.symbol == eles[1]:
            ele2_index.append(i.index)

    ele1_position = ran.choice(ele1_index)
    ele2_position = ran.choice(ele2_index)
    clus.positions[[ele1_position, ele2_position]] = clus.positions[
        [ele2_position, ele1_position]
    ]
    clus = fixOverlap(clus)
    return clus
예제 #9
0
def mate(parent1, parent2, fit1, fit2, surfGA=False):
    """
    Randomly selected clusters from tournament selection are passed:
    1. If gas-phase, rotate randomly the clusters.
    2. Weighted cut of the clusters in a plane
       perpendicular to the surface.
    3. Join parts and repare overlaps.
    """

    compositionWrong = True
    clus1 = parent1
    clus2 = parent2
    count = 0
    while compositionWrong:
        count = count+1
        if surfGA == False:
            phi = ran.uniform(0,2*np.pi)
            psi = ran.uniform(0,np.pi)
            vx = np.cos(phi) * np.sin(psi)
            vy = np.sin(phi) * np.sin(psi)
            vz = np.cos(psi)
            vec = [vx,vy,vz] 

        clus1 = sortProj(clus1,vec)
        clus2 = sortProj(clus2,vec)

        child = []
        eleNames, eleNums, natoms, _, _ = get_data(clus1)
        cmax = fit1/(fit1 + fit2)
        cut = np.abs(int(natoms * ran.uniform(0.5,cmax)))
        if cut == 0:
            cut = 1
        elif cut == natoms:
            cut = natoms - 1
        elif cut > natoms:
            cut = natoms - 1

        for i in range(cut):
            child.append(clus1[i])

        for j in range(cut, len(clus2)):
            child.append(clus2[j])
        CheckEle = []
        for ele in eleNames:
            eleCount = 0
            for atom in child:
                if atom.symbol == ele:
                    eleCount += 1
            CheckEle.append(eleCount)

        if CheckEle == eleNums:
            compositionWrong = False

    final_child = Atoms(child[0].symbol, positions=[child[0].position])
    for i in range(1, len(child)):
        c = Atoms(child[i].symbol, positions=[child[i].position])
        final_child += c
    print('Child before fix', final_child)
    print( final_child.get_positions())
    
    final_child = fixOverlap(final_child)
    print('Child after fix', final_child)
    print( final_child.get_positions())
    print( '\n')
    #parent1 = final_child
    #parent2 = parent2
    return final_child