예제 #1
0
파일: lammps.py 프로젝트: zari277/pwtools
def struct_str(struct):
    """Convert Structure object to lammps format. 
    
    The returned string can be written to a file and read in a lammps input
    file by ``read_data``.
    
    Parameters
    ----------
    struct : Structure
    
    Returns
    -------
    str : string

    References
    ----------
    ase.calculators.lammpsrun (ASE 3.8).
    """
    # align cell to [[x,0,0],[xy,y,0],[xz, yz, z]] (row format, the transpose
    # is what lammps uses)
    st = struct.copy()
    st.coords = None
    st.cell = None
    st.set_all()
    head_str = "structure written by pwtools {0}".format(time.asctime())
    info_str = '%i atoms\n%i atom types' % (st.natoms, len(st.symbols_unique))
    cell_str = "0.0 {x:.14g} xlo xhi\n0.0 {y:.14g} ylo yhi\n0.0 {z:.14g} zlo zhi\n"
    cell_str += "{tilts} xy xz yz\n"
    cell_str = cell_str.format(x=st.cell[0, 0],
                               y=st.cell[1, 1],
                               z=st.cell[2, 2],
                               tilts=common.str_arr(np.array([
                                   st.cell[1, 0], st.cell[2, 0], st.cell[2, 1]
                               ]),
                                                    eps=1e-13,
                                                    fmt='%.14g',
                                                    delim=' '))
    atoms_str = "Atoms\n\n"
    for iatom in range(st.natoms):
        atoms_str += "{iatom} {ispec} {xyz}".format(
            iatom=iatom + 1,
            ispec=st.order[st.symbols[iatom]],
            xyz=common.str_arr(st.coords[iatom, :], eps=1e-13, fmt='%23.16e') +
            '\n')
    mass_str = "Masses\n\n"
    for idx, sy in enumerate(st.symbols_unique):
        mass_str += "%i %g\n" % (idx + 1, atomic_data.pt[sy]['mass'])
    return head_str + '\n\n' + info_str + '\n\n' + cell_str + \
           '\n' + atoms_str + '\n' + mass_str
예제 #2
0
    def write_input(self, atoms, properties=None, system_changes=None):
        FileIOCalculator.write_input(self, atoms, properties, system_changes)
        struct = crys.atoms2struct(atoms)
        self.cell = common.str_arr(struct.cell)
        self.kpoints = pwscf.kpoints_str_pwin(kpts2mp(atoms, self.kpts))
        if isinstance(self.pp, bytes):
            pseudos = [
                "%s.%s" % (sym, self.pp) for sym in struct.symbols_unique
            ]
        else:
            assert len(self.pp) == struct.ntypat
            pseudos = []
            for sym in struct.symbols_unique:
                for ppi in self.pp:
                    if ppi.startswith(sym):
                        pseudos.append(ppi)
                        break
        assert len(pseudos) == struct.ntypat
        self.atspec = pwscf.atspec_str(symbols=struct.symbols_unique,
                                       masses=struct.mass_unique,
                                       pseudos=pseudos)
        self.atpos = pwscf.atpos_str(symbols=struct.symbols,
                                     coords=struct.coords_frac)
        self.natoms = struct.natoms
        self.ntyp = struct.ntypat

        if self.backup:
            for fn in [self.infile, self.outfile]:
                if os.path.exists(fn):
                    common.backup(fn)
        common.file_write(self.infile, self.fill_infile_templ())
예제 #3
0
    def _fit(self):
        # volume[Bohr^3] etot[Ha] for eos.x
        volume = self.volume * (Ang**3.0 / Bohr**3.0)
        energy = self.energy * (eV / Ha)
        data = np.array([volume, energy]).T
        infn_txt =\
        """
%s
%i
%i
%f,  %f,  %i
%i
%s
        """%(self.name,
             self.natoms,
             self.etype,
             volume[0], volume[-1], self.npoints,
             len(volume),
             common.str_arr(data))
        common.file_write(self.infn, infn_txt)
        out = common.backtick('cd %s && %s' % (self.dir, self.app_basename))
        if self.verbose:
            print(out)
            print((open(os.path.join(self.dir, 'PARAM.OUT')).read()))
        # Remove normalization on natoms. See .../eos/output.f90:
        # fitev: [volume [Bohr^3] / natoms, energy [Ha] / natoms]
        # fitpv: [volume [Bohr^3] / natoms, pressure [GPa]]
        fitev = np.loadtxt(os.path.join(self.dir, 'EVPAI.OUT')) * self.natoms
        # convert energy back to [Ang^3, eV]
        fitev[:, 0] *= (Bohr**3 / Ang**3)
        fitev[:, 1] *= (Ha / eV)
        self.ev = fitev
        fitpv = np.loadtxt(os.path.join(self.dir, 'PVPAI.OUT'))
        fitpv[:, 0] *= (self.natoms * Bohr**3 / Ang**3)
        self.pv = fitpv
예제 #4
0
파일: eos.py 프로젝트: elcorto/pwtools
    def _fit(self):
        # volume[Bohr^3] etot[Ha] for eos.x
        volume = self.volume*(Ang**3.0 / Bohr**3.0)
        energy = self.energy*(eV / Ha)
        data = np.array([volume, energy]).T
        infn_txt =\
        """
%s
%i
%i
%f,  %f,  %i
%i
%s
        """%(self.name, 
             self.natoms, 
             self.etype, 
             volume[0], volume[-1], self.npoints,
             len(volume), 
             common.str_arr(data))
        common.file_write(self.infn, infn_txt)
        out = common.backtick('cd %s && %s' %(self.dir, self.app_basename))
        if self.verbose:
            print out
            print(open(os.path.join(self.dir,'PARAM.OUT')).read())
        # Remove normalization on natoms. See .../eos/output.f90:
        # fitev: [volume [Bohr^3] / natoms, energy [Ha] / natoms]
        # fitpv: [volume [Bohr^3] / natoms, pressure [GPa]]
        fitev = np.loadtxt(os.path.join(self.dir,'EVPAI.OUT')) * self.natoms
        # convert energy back to [Ang^3, eV]
        fitev[:,0] *= (Bohr**3 / Ang**3)
        fitev[:,1] *= (Ha / eV)
        self.ev = fitev
        fitpv = np.loadtxt(os.path.join(self.dir,'PVPAI.OUT'))
        fitpv[:,0] *= (self.natoms * Bohr**3 / Ang**3)
        self.pv = fitpv
예제 #5
0
 def write_input(self, atoms, properties=None, system_changes=None):
     FileIOCalculator.write_input(self, atoms, properties,
                                  system_changes)
     struct = crys.atoms2struct(atoms)
     self.cell = common.str_arr(struct.cell)
     self.kpoints = pwscf.kpoints_str_pwin(kpts2mp(atoms, self.kpts))
     if isinstance(self.pp, types.StringType):
         pseudos = ["%s.%s" %(sym, self.pp) for sym in struct.symbols_unique]
     else: 
         assert len(self.pp) == struct.ntypat
         pseudos = []
         for sym in struct.symbols_unique:
             for ppi in self.pp:
                 if ppi.startswith(sym):
                     pseudos.append(ppi)
                     break
     assert len(pseudos) == struct.ntypat
     self.atspec = pwscf.atspec_str(symbols=struct.symbols_unique,
                                    masses=struct.mass_unique,
                                    pseudos=pseudos)
     self.atpos = pwscf.atpos_str(symbols=struct.symbols,
                                  coords=struct.coords_frac)
     self.natoms = struct.natoms
     self.ntyp = struct.ntypat
     
     if self.backup:
         for fn in [self.infile, self.outfile]:
             if os.path.exists(fn):
                 common.backup(fn)
     common.file_write(self.infile, self.fill_infile_templ())
예제 #6
0
파일: lammps.py 프로젝트: elcorto/pwtools
def struct_str(struct):
    """Convert Structure object to lammps format. 
    
    The returned string can be written to a file and read in a lammps input
    file by ``read_data``.
    
    Parameters
    ----------
    struct : Structure
    
    Returns
    -------
    str : string

    References
    ----------
    ase.calculators.lammpsrun (ASE 3.8).
    """
    # align cell to [[x,0,0],[xy,y,0],[xz, yz, z]] (row format, the transpose
    # is what lammps uses)
    st = struct.copy()
    st.coords = None
    st.cell = None
    st.set_all()
    head_str = "structure written by pwtools {0}".format(time.asctime())        
    info_str = '%i atoms\n%i atom types' %(st.natoms, len(st.symbols_unique))
    cell_str = "0.0 {x:.14g} xlo xhi\n0.0 {y:.14g} ylo yhi\n0.0 {z:.14g} zlo zhi\n"
    cell_str += "{tilts} xy xz yz\n"
    cell_str = cell_str.format(x=st.cell[0,0], 
                               y=st.cell[1,1], 
                               z=st.cell[2,2],
                               tilts=common.str_arr(np.array([st.cell[1,0],
                                                              st.cell[2,0],
                                                              st.cell[2,1]]),
                                                    eps=1e-13, fmt='%.14g',
                                                    delim=' '))
    atoms_str = "Atoms\n\n"
    for iatom in range(st.natoms):
        atoms_str += "{iatom} {ispec} {xyz}".format(
            iatom=iatom+1, 
            ispec=st.order[st.symbols[iatom]],
            xyz=common.str_arr(st.coords[iatom,:], eps=1e-13, fmt='%23.16e') + '\n')
    mass_str = "Masses\n\n"
    for idx,sy in enumerate(st.symbols_unique):
        mass_str += "%i %g\n" %(idx+1, atomic_data.pt[sy]['mass'])
    return head_str + '\n\n' + info_str + '\n\n' + cell_str + \
           '\n' + atoms_str + '\n' + mass_str
예제 #7
0
파일: io.py 프로젝트: elcorto/pwtools
def write_axsf(filename, obj):
    """Write animated XSF file for Structure (only 1 step) or Trajectory.

    Note that forces are converted eV / Ang -> Ha / Ang.
    
    length: Angstrom
    forces: Ha / Angstrom

    Parameters
    ----------
    filename : target file name
    obj : Structure or Trajectory

    References
    ----------
    [XSF] http://www.xcrysden.org/doc/XSF.html
    """
    # Notes
    # -----
    # XSF: The XSF spec [XSF] is a little fuzzy about what PRIMCOORD actually
    #     is (fractional or cartesian Angstrom). Only the latter case results
    #     in a correctly displayed structure in xcrsyden. So we use that.
    #
    # Speed: The only time-consuming step is calling atpos_str*() in the loop
    #     b/c that transforms *every* single float to a string, which
    #     effectively is a double loop over `ccf`. No way to get faster w/ pure
    #     Python.
    #
    traj = crys.struct2traj(obj)
    # ccf = cartesian coords + forces (6 columns)
    if traj.is_set_attr('forces'):
        ccf = np.concatenate((traj.coords, traj.forces*eV/Ha), axis=-1)
    else:
        ccf = traj.coords
    axsf_str = "ANIMSTEPS %i\nCRYSTAL" %traj.nstep
    for istep in range(traj.nstep):
        axsf_str += "\nPRIMVEC %i\n%s" %(istep+1,
                                         common.str_arr(traj.cell[istep,...]))
        axsf_str += "\nPRIMCOORD %i\n%i 1\n%s" %(istep+1,
                                                 traj.natoms,
                                                 pwscf.atpos_str_fast(traj.symbols, 
                                                                      ccf[istep,...]))
    common.file_write(filename, axsf_str)
예제 #8
0
파일: io.py 프로젝트: zari277/pwtools
def write_axsf(filename, obj):
    """Write animated XSF file for Structure (only 1 step) or Trajectory.

    Note that forces are converted eV / Ang -> Ha / Ang.
    
    length: Angstrom
    forces: Ha / Angstrom

    Parameters
    ----------
    filename : target file name
    obj : Structure or Trajectory

    References
    ----------
    [XSF] http://www.xcrysden.org/doc/XSF.html
    """
    # Notes
    # -----
    # XSF: The XSF spec [XSF] is a little fuzzy about what PRIMCOORD actually
    #     is (fractional or cartesian Angstrom). Only the latter case results
    #     in a correctly displayed structure in xcrsyden. So we use that.
    #
    # Speed: The only time-consuming step is calling atpos_str*() in the loop
    #     b/c that transforms *every* single float to a string, which
    #     effectively is a double loop over `ccf`. No way to get faster w/ pure
    #     Python.
    #
    traj = crys.struct2traj(obj)
    # ccf = cartesian coords + forces (6 columns)
    if traj.is_set_attr('forces'):
        ccf = np.concatenate((traj.coords, traj.forces * eV / Ha), axis=-1)
    else:
        ccf = traj.coords
    axsf_str = "ANIMSTEPS %i\nCRYSTAL" % traj.nstep
    for istep in range(traj.nstep):
        axsf_str += "\nPRIMVEC %i\n%s" % (
            istep + 1, common.str_arr(traj.cell[istep, ...]))
        axsf_str += "\nPRIMCOORD %i\n%i 1\n%s" % (
            istep + 1, traj.natoms,
            pwscf.atpos_str_fast(traj.symbols, ccf[istep, ...]))
    common.file_write(filename, axsf_str)
예제 #9
0
파일: pwscf.py 프로젝트: elcorto/pwtools
def atpos_str(symbols, coords, fmt="%.16e", zero_eps=None, eps=EPS, delim=4*' '):
    """Convenience function to make a string for the ATOMIC_POSITIONS section
    of a pw.x input file.
    
    Parameters
    ----------
    symbols : sequence
        strings with atom symbols, (natoms,), must match with the
        rows of coords
    coords : array (natoms, 3) 
        with atomic coords, can also be (natoms, >3) to add constraints on
        atomic forces in PWscf
    eps : float
        Print values as 0.0 where abs(coords[i,j]) < eps. If eps < 0.0, then
        disable this.
    delim : str
        delimiter between columns

    Returns
    -------
    string

    Examples
    --------
    >>> print atpos_str(['Al', 'N'], array([[0,0,0], [0,0,1.]]))
    Al      0.0000000000    0.0000000000    0.0000000000
    N       0.0000000000    0.0000000000    1.0000000000
    """
    if zero_eps is not None:
        warnings.warn("`zero_eps` is deprecated, use `eps` > 0 instead",
                      DeprecationWarning)
    coords = np.asarray(coords)
    assert len(symbols) == coords.shape[0], "len(symbols) != coords.shape[0]"
    txt = '\n'.join("%s%s%s" %(symbols[i], delim, str_arr(row, fmt=fmt, eps=eps,
                                                          delim=delim)) \
        for i,row in enumerate(coords))
    return txt        
예제 #10
0
파일: pwscf.py 프로젝트: zari277/pwtools
def atpos_str(symbols, coords, fmt="%.16e", zero_eps=None, eps=EPS, delim=4*' '):
    """Convenience function to make a string for the ATOMIC_POSITIONS section
    of a pw.x input file.
    
    Parameters
    ----------
    symbols : sequence
        strings with atom symbols, (natoms,), must match with the
        rows of coords
    coords : array (natoms, 3) 
        with atomic coords, can also be (natoms, >3) to add constraints on
        atomic forces in PWscf
    eps : float
        Print values as 0.0 where abs(coords[i,j]) < eps. If eps < 0.0, then
        disable this.
    delim : str
        delimiter between columns

    Returns
    -------
    string

    Examples
    --------
    >>> print atpos_str(['Al', 'N'], array([[0,0,0], [0,0,1.]]))
    Al      0.0000000000    0.0000000000    0.0000000000
    N       0.0000000000    0.0000000000    1.0000000000
    """
    if zero_eps is not None:
        warnings.warn("`zero_eps` is deprecated, use `eps` > 0 instead",
                      DeprecationWarning)
    coords = np.asarray(coords)
    assert len(symbols) == coords.shape[0], "len(symbols) != coords.shape[0]"
    txt = '\n'.join("%s%s%s" %(symbols[i], delim, str_arr(row, fmt=fmt, eps=eps,
                                                          delim=delim)) \
        for i,row in enumerate(coords))
    return txt        
예제 #11
0
파일: 10input.py 프로젝트: elcorto/pwtools
                     scratch='/scratch/schmerler',
                     filename='calc.templ/job.pbs.theo',
                     home='/home/schmerler')

templates = [batch.FileTemplate(basename='pw.in')]

# rs-AlN
st = crys.Structure(coords_frac=np.array([[0.0]*3, [0.5]*3]),
                    symbols=['Al','N'],
                    cryst_const=np.array([2.76]*3 + [60]*3))

params_lst = []
for ecutwfc in np.linspace(30,100,8):
    params_lst.append([sql.SQLEntry(key='ecutwfc', sqlval=ecutwfc),
                       sql.SQLEntry(key='ecutrho', sqlval=4.0*ecutwfc),
                       sql.SQLEntry(key='cell', sqlval=common.str_arr(st.cell)),
                       sql.SQLEntry(key='natoms', sqlval=st.natoms),
                       sql.SQLEntry(key='atpos',
                                    sqlval=pwscf.atpos_str(st.symbols,
                                                           st.coords_frac)),
                      ])

calc = batch.ParameterStudy(machines=theo,
                            templates=templates,
                            params_lst=params_lst, 
                            study_name='convergence_test_cutoff',
                            )
calc.write_input(sleep=0, backup=False, mode='w')

if not os.path.exists('calc'):
    os.symlink('calc_theo', 'calc')
예제 #12
0
#!/usr/bin/python

# Create a PWscf MD "trajectory" where the CELL_PARAMETERS unit changes. This
# is for testing if the parser can handle that. The output file consists only
# of CELL_PARAMETERS blocks, which is enough for PwVCMDOutputFile.get_gell() .
#
# usage
# ------
# ./make-vc-md-cell.py > ../files/pw.vc-md.cell.out 

import numpy as np
from pwtools import common

cell = np.arange(1,10).reshape((3,3))

alat_lst = [2.0, 4.0]
for ialat,alat in enumerate(alat_lst):
    for ii in range(5):
        cell_str = common.str_arr((cell + 0.02*ii + ialat)/alat)
        print "CELL_PARAMETERS (alat= %.5f)\n%s" %(alat, cell_str)
        
예제 #13
0
&input
    asr='crystal',
XXXMASS    
    flfrc='q2r.fc',
    flfrq='XXXFNFREQ'
/
XXXNKS
XXXKS
"""
matdyn_in_fn = 'matdyn.disp.in'
matdyn_freq_fn = 'matdyn.freq.disp'
mass_str = '\n'.join("amass(%i)=%e" %(ii+1,m) for ii,m in \
                      enumerate(st.mass_unique))
rules = {
    'XXXNKS': ks_path.shape[0],
    'XXXKS': common.str_arr(ks_path),
    'XXXMASS': mass_str,
    'XXXFNFREQ': matdyn_freq_fn,
}
txt = common.template_replace(templ_txt, rules, conv=True, mode='txt')
common.file_write(matdyn_in_fn, txt)
common.system("gunzip q2r.fc.gz; matdyn.x < %s; gzip q2r.fc" % matdyn_in_fn)

# parse matdyn output and plot

# define special points path, used in plot_dis() to plot lines at special
# points and make x-labels
sp = kpath.SpecialPointsPath(ks=sp_points,
                             ks_frac=sp_points_frac,
                             symbols=sp_symbols)
예제 #14
0
# test/test_read_matdyn.py .

import numpy as np
from pwtools.common import str_arr

natoms = 2
qpoints = np.array([[0, 0, 0.0], [0, 0, 0.5]])
nqpoints = len(qpoints)
nmodes = 3 * natoms

freqs = np.empty((nqpoints, nmodes))
vecs = np.empty((nqpoints, nmodes, natoms, 3))
num = 0
for iqpoint in range(nqpoints):
    print "     diagonalizing the dynamical matrix ...\n"
    print "  q = %s" % str_arr(qpoints[iqpoint], fmt="%f")
    print "*" * 79
    for imode in range(nmodes):
        freqs[iqpoint, imode] = num
        print "    omega(%i) = %f [THz] = %f [cm-1]" % (imode + 1, num * 0.1, num)
        num += 1
        for iatom in range(natoms):
            vec_str = " ("
            for icoord in range(3):
                vecs[iqpoint, imode, iatom, icoord] = num
                vec_str += "  %f  %f  " % (num, 0.03 * num)
                num += 1
            vec_str += ")"
            print vec_str
    print "*" * 79
예제 #15
0
#!/usr/bin/python

# Create a PWscf MD "trajectory" where the CELL_PARAMETERS unit changes. This
# is for testing if the parser can handle that. The output file consists only
# of CELL_PARAMETERS blocks, which is enough for PwVCMDOutputFile.get_gell() .
#
# usage
# ------
# ./make-vc-md-cell.py > ../files/pw.vc-md.cell.out

import numpy as np
from pwtools import common

if __name__ == '__main__':
    cell = np.arange(1, 10).reshape((3, 3))

    alat_lst = [2.0, 4.0]
    for ialat, alat in enumerate(alat_lst):
        for ii in range(5):
            cell_str = common.str_arr((cell + 0.02 * ii + ialat) / alat)
            print("CELL_PARAMETERS (alat= %.5f)\n%s" % (alat, cell_str))
예제 #16
0
templ_txt = """
&input
    asr='crystal',
XXXMASS    
    flfrc='q2r.fc',
    flfrq='XXXFNFREQ'
/
XXXNKS
XXXKS
"""
matdyn_in_fn = 'matdyn.disp.in'
matdyn_freq_fn = 'matdyn.freq.disp'
mass_str = '\n'.join("amass(%i)=%e" %(ii+1,m) for ii,m in \
                      enumerate(st.mass_unique))
rules = {'XXXNKS': ks_path.shape[0],
         'XXXKS': common.str_arr(ks_path),
         'XXXMASS': mass_str,
         'XXXFNFREQ': matdyn_freq_fn,
         }
txt = common.template_replace(templ_txt,
                              rules,
                              conv=True,
                              mode='txt')
common.file_write(matdyn_in_fn, txt)
common.system("gunzip q2r.fc.gz; matdyn.x < %s; gzip q2r.fc" %matdyn_in_fn)

# parse matdyn output and plot

# define special points path, used in plot_dis() to plot lines at special
# points and make x-labels
sp = kpath.SpecialPointsPath(ks=sp_points, ks_frac=sp_points_frac,
예제 #17
0
파일: cif2any.py 프로젝트: elcorto/pwtools
/
CELL_PARAMETERS angstrom
{cp_ang}

CELL_PARAMETERS bohr
{cp_bohr}

ATOMIC_SPECIES
{atspec}
ATOMIC_POSITIONS crystal
{atpos_frac}
"""
rules = {'bar': bar,
         'nat': struct.natoms,
         'ntyp': struct.ntypat,
         'cp_alat': str_arr(struct.cell / struct.cryst_const[0]),
         'cp_bohr': str_arr(struct.cell),
         'cp_ang': str_arr(struct.cell * Bohr / Angstrom),
         'atspec': atspec,
         'atpos_frac': atpos_frac,
        }
for ii, cd in enumerate(celldm):
    rules['cd%i' %(ii+1,)] = cd
        
print out.format(**rules)

#-------------------------------------------------------------------------------
# ABINIT
#-------------------------------------------------------------------------------
print "\n"
print bar
예제 #18
0
import numpy as np
from pwtools.common import str_arr

if __name__ == '__main__':
    natoms = 2
    qpoints = np.array([[0, 0, 0.], [0, 0, 0.5]])
    nqpoints = len(qpoints)
    nmodes = 3 * natoms

    freqs = np.empty((nqpoints, nmodes))
    vecs = np.empty((nqpoints, nmodes, natoms, 3))
    num = 0
    for iqpoint in range(nqpoints):
        print("     diagonalizing the dynamical matrix ...\n")
        print("  q = %s" % str_arr(qpoints[iqpoint], fmt='%f'))
        print("*" * 79)
        for imode in range(nmodes):
            freqs[iqpoint, imode] = num
            print("    omega(%i) = %f [THz] = %f [cm-1]" %
                  (imode + 1, num * 0.1, num))
            num += 1
            for iatom in range(natoms):
                vec_str = " ("
                for icoord in range(3):
                    vecs[iqpoint, imode, iatom, icoord] = num
                    vec_str += "  %f  %f  " % (num, 0.03 * num)
                    num += 1
                vec_str += ")"
                print(vec_str)
        print("*" * 79)
예제 #19
0
파일: cif2any.py 프로젝트: zari277/pwtools
CELL_PARAMETERS angstrom
{cp_ang}

CELL_PARAMETERS bohr
{cp_bohr}

ATOMIC_SPECIES
{atspec}
ATOMIC_POSITIONS crystal
{atpos_frac}
"""
rules = {
    'bar': bar,
    'nat': struct.natoms,
    'ntyp': struct.ntypat,
    'cp_alat': str_arr(struct.cell / struct.cryst_const[0]),
    'cp_bohr': str_arr(struct.cell),
    'cp_ang': str_arr(struct.cell * Bohr / Angstrom),
    'atspec': atspec,
    'atpos_frac': atpos_frac,
}
for ii, cd in enumerate(celldm):
    rules['cd%i' % (ii + 1, )] = cd

print(out.format(**rules))

#-------------------------------------------------------------------------------
# ABINIT
#-------------------------------------------------------------------------------
print("\n")
print(bar)