Example #1
0
def write(struct,
          filename=None,
          comments=None,
          direct=True,
          distinct_by_ox=False,
          vasp4=False,
          **kwargs):
    """
    Write a :mod:`~qmpy.Structure` to a file or string.

    Arguments:
        struct: A `~qmpy.Structure` object.

    Keyword Arguments:
        filename:
            If None, returns a string.

        direct:
            If True, write POSCAR in fractional coordinates. If False, returns
            a POSCAR in cartesian coordinates.

        distinct_by_ox:
            If True, elements with different specified oxidation states will be
            treated as different species. i.e. the elements line of Fe3O4 would
            read Fe Fe O (Fe3+, Fe4+, O2-). This can be useful for breaking
            symmetry, or for specifying different U-values for different
            oxidation state elements.

        vasp4:
            If True, omits the species line.

    Examples::

        >>> s = io.read(INSTALL_PATH+'/io/files/POSCAR_BCC')
        >>> print io.poscar.write(s)
        Cu
         1.0
        3.000000 0.000000 0.000000
        0.000000 3.000000 0.000000
        0.000000 0.000000 3.000000
        Cu
        2
        direct
         0.0000000000 0.0000000000 0.0000000000
         0.5000000000 0.5000000000 0.5000000000

        >>> io.poscar.write(s, '/tmp/POSCAR')

    """
    comp = struct.comp
    struct.atoms = atom_sort(struct.atoms)

    cdict = defaultdict(int)
    if not distinct_by_ox:
        ordered_keys = sorted(comp.keys())
        for a in struct:
            cdict[a.element_id] += 1
        counts = [int(cdict[k]) for k in ordered_keys]
    else:
        for a in struct.atoms:
            if int(a.oxidation_state) != a.oxidation_state:
                cdict['%s%+f' % (a.element_id, a.oxidation_state)] += 1
            else:
                cdict['%s%+d' % (a.element_id, a.oxidation_state)] += 1
        ordered_keys = sorted([k for k in cdict.keys()])
        counts = [int(cdict[k]) for k in ordered_keys]

    if comments is not None:
        poscar = '# %s \n1.0\n' % (comments)
    else:
        poscar = ' '.join(set(a.element_id for a in struct.atoms)) + '\n1.0\n'
    cell = '\n'.join(
        [' '.join(['%16.12f' % v for v in vec]) for vec in struct.cell])
    poscar += cell + '\n'
    names = ' '.join(a for a in ordered_keys) + '\n'
    ntypes = ' '.join(str(n) for n in counts) + '\n'
    if not vasp4:
        poscar += names
    poscar += ntypes
    if direct:
        poscar += 'Direct\n'
        for x, y, z in struct.coords:
            poscar += '%16.12f %16.12f %16.12f\n' % (x, y, z)
    else:
        poscar += 'Cartesian\n'
        for x, y, z in struct.cartesian_coords:
            poscar += ' %16.12f %16.12f %16.12f\n' % (x, y, z)

    if filename:
        open(filename, 'w').write(poscar)
    else:
        return poscar
Example #2
0
def write(struct, filename=None, comments=None, direct=True, 
            distinct_by_ox=False, vasp4=False, **kwargs):
    """
    Write a :mod:`~qmpy.Structure` to a file or string.

    Arguments:
        struct: A `~qmpy.Structure` object.

    Keyword Arguments:
        filename:
            If None, returns a string.

        direct:
            If True, write POSCAR in fractional coordinates. If False, returns
            a POSCAR in cartesian coordinates. 

        distinct_by_ox: 
            If True, elements with different specified oxidation states will be
            treated as different species. i.e. the elements line of Fe3O4 would
            read Fe Fe O (Fe3+, Fe4+, O2-). This can be useful for breaking
            symmetry, or for specifying different U-values for different
            oxidation state elements.

        vasp4:
            If True, omits the species line.

    Examples::
        
        >>> s = io.read(INSTALL_PATH+'/io/files/POSCAR_BCC')
        >>> print io.poscar.write(s)
        Cu
         1.0
        3.000000 0.000000 0.000000
        0.000000 3.000000 0.000000
        0.000000 0.000000 3.000000
        Cu
        2
        direct
         0.0000000000 0.0000000000 0.0000000000
         0.5000000000 0.5000000000 0.5000000000

        >>> io.poscar.write(s, '/tmp/POSCAR')

    """
    comp = struct.comp
    struct.atoms = atom_sort(struct.atoms)

    cdict = defaultdict(int)
    if not distinct_by_ox:
        ordered_keys = sorted(comp.keys())
        for a in struct:
            cdict[a.element_id] += 1
        counts = [ int(cdict[k]) for k in ordered_keys ]
    else:
        for a in struct.atoms:
            if int(a.oxidation_state) != a.oxidation_state:
                cdict['%s%+f' % (a.element_id, a.oxidation_state)] += 1
            else:
                cdict['%s%+d' % (a.element_id, a.oxidation_state)] += 1
        ordered_keys = sorted([ k for k in cdict.keys() ])
        counts = [ int(cdict[k]) for k in ordered_keys ]

    if comments is not None:
        poscar = '# %s \n 1.0\n' %(comments)
    else:
        poscar = ' '.join(set(a.element_id for a in struct.atoms)) + '\n 1.0\n'
    cell = '\n'.join([ ' '.join([ '%f' % v  for v in vec ]) for vec in
        struct.cell ])
    poscar += cell +'\n'
    names = ' '.join( a for a in ordered_keys ) + '\n'
    ntypes = ' '.join( str(n) for n in counts ) + '\n'
    if not vasp4:
        poscar += names
    poscar += ntypes
    if direct:
        poscar += 'direct\n'
        for x,y,z in struct.coords:
            poscar += ' %.10f %.10f %.10f\n' % (x,y,z)
    else:
        poscar += 'cartesian\n'
        for x, y, z in struct.cartesian_coords:
            poscar += ' %.10f %.10f %.10f\n' % (x,y,z)

    if filename:
        open(filename, 'w').write(poscar)
    else:
        return poscar