Beispiel #1
0
def dimer(pot,
          atoms,
          elements,
          folder=None,
          base64=False,
          index=None,
          nsamples=50,
          zoom=False):
    """Plots the potential behavior as the distance between two atoms in a
    dimer.

    .. note:: This produces a **dict** of all possible 2-body interaction between
      distinct element types.

    Args:
        elements (list): list of chemical symbols in the system.
        pot (matdb.calculators.basic.AsyncCalculator): IP to calculate properties with.
        atoms (matdb.atoms.AtomsList): list of atoms from which to calculate correlations.
        folder (str): path to the folder where the saved image should be stored.
        base64 (bool): when True, use a base-64 encoded `src` for the output of
          this image; otherwise, the image is saved to `folder` and only its
          name is returned.
        index (int): integer index of this plot in the parent
          collection.
        nsamples (int): number of samples to take along the trajectory.
        zoom (bool): when True, show a zoomed in view of the potential.

    Returns:

        dict: keys are concatenated element names (e.g. `AgPd`) and values are
        :class:`PointDetailImage` instances.
    """
    #First, determine the set of unique element pairs in the list.
    from itertools import product
    possible = list(product(elements, repeat=2))
    target = list(set(map(lambda l: tuple(sorted(l)), possible)))

    subplot_kw = {"xlabel": "Distance (Ang)", "ylabel": "IP Energy (eV)"}

    result = {}
    for elements in target:
        #Look up the lattice parameters for each of the elements. Use Vegard's
        #law to get a decent domain to plot the energy over.
        rmin, rvegard, rmax = _dimer_range(elements)

        dimer = Atoms(positions=np.zeros((2, 3)), cell=np.eye(3) * 100)
        dimer.positions = 0.
        dimer.set_calculator(pot)
        dimer.set_chemical_symbols(elements)

        if zoom:
            rs = np.linspace(0.7 * rmin, pot.cutoff(), nsamples)
        else:
            rs = np.linspace(0.4 * rmin, pot.cutoff(), nsamples)

        energy = []
        for r in rs:
            dimer.positions[1, 2] = r
            energy.append(dimer.get_potential_energy())

        elemstr = ''.join(elements) + ('z' if zoom else "")
        img = PDI(rs,
                  np.array(energy),
                  "plot",
                  subplot_kw=subplot_kw,
                  index=index,
                  base64=base64,
                  name=elemstr,
                  imgtype=elemstr,
                  folder=folder)
        result[elemstr] = img

    return result
Beispiel #2
0
def trimer(pot,
           atoms,
           elements,
           folder=None,
           base64=False,
           index=None,
           nsamples=50):
    """Plots the potential behavior as the angle between three atoms changes in a
    trimer.

    .. note:: This produces a *dict* of all possible 3-body interactions between
      distinct element types.

    Args:
        elements (list): list of chemical symbols in the system.
        pot (matdb.calculators.basic.AsyncCalculator): IP to calculate properties with.
        atoms (matdb.atoms.AtomsList): list of atoms from which to calculate correlations.
        folder (str): path to the folder where the saved image should be stored.
        base64 (bool): when True, use a base-64 encoded `src` for the output of
          this image; otherwise, the image is saved to `folder` and only its
          name is returned.
        index (int): integer index of this plot in the parent
          collection.
        nsamples (int): number of samples to take along the trajectory.

    Returns:

        dict: keys are concatenated element names (e.g. `AgPd`) and values are
        :class:`PointDetailImage` instances.
    """
    #First, determine the set of unique element pairs in the list.
    from itertools import product
    possible = list(product(elements, repeat=3))
    target = list(set(map(lambda l: tuple(sorted(l)), possible)))

    subplot_kw = {"xlabel": "Angle (Rad)", "ylabel": "IP Energy (eV)"}

    result = {}
    for elements in target:
        #Look up the lattice parameters for each of the elements. Use Vegard's
        #law to get a decent domain to plot the energy over.
        from matdb.data import vegard
        uelements = list(set(elements))
        concdict = [elements.count(e) / 3. for e in uelements]
        rvegard = vegard(uelements, concdict)

        trimer = Atoms(positions=np.zeros((3, 3)), cell=np.eye(3) * 100)
        trimer.positions = 0.
        trimer.set_chemical_symbols(elements)
        trimer.set_calculator(pot)
        #Set the position of the second atom to be at equilibrium with respect
        #to the Vegard's law calculation.
        trimer.positions[1, 2] = rvegard

        #Now, vary the angle of the third atom with respect to the original two
        #and see how the angle changes.
        theta = np.linspace(np.pi / 6, np.pi, nsamples)
        energy = []
        for t in theta:
            x = rvegard * np.cos(t)
            y = rvegard * np.sin(t)
            trimer.positions[1, 2] = x
            trimer.positions[1, 2] = y
            energy.append(trimer.get_potential_energy())

        elemstr = trimer.get_chemical_formula()
        img = PDI(theta,
                  np.array(energy),
                  "plot",
                  subplot_kw=subplot_kw,
                  index=index,
                  base64=base64,
                  name=elemstr,
                  imgtype=elemstr,
                  folder=folder)
        result[elemstr] = img

    return result