Ejemplo n.º 1
0
def surfer(mpid='',
           vacuum=15,
           layers=2,
           mat=None,
           max_index=1,
           write_file=True):
    """
    ASE surface bulder

    Args:
        vacuum: vacuum region
        mat: Structure object
        max_index: maximum miller index
        min_slab_size: minimum slab size

    Returns:
           structures: list of surface Structure objects
    """

    if mat == None:
        with MPRester() as mp:
            mat = mp.get_structure_by_material_id(mpid)
        if mpid == '':
            print('Provide structure')

    sg_mat = SpacegroupAnalyzer(mat)
    mat_cvn = sg_mat.get_conventional_standard_structure()
    mat_cvn.sort()
    indices = get_symmetrically_distinct_miller_indices(mat_cvn, max_index)
    ase_atoms = AseAtomsAdaptor().get_atoms(mat_cvn)

    structures = []
    pos = Poscar(mat_cvn)
    try:
        pos.comment = str('sbulk') + str('@') + str('vac') + str(vacuum) + str(
            '@') + str('layers') + str(layers)
    except:
        pass
    structures.append(pos)
    if write_file == True:
        mat_cvn.to(fmt='poscar',
                   filename=str('POSCAR-') + str('cvn') + str('.vasp'))
    for i in indices:
        ase_slab = surface(ase_atoms, i, layers)
        ase_slab.center(vacuum=vacuum, axis=2)
        slab_pymatgen = AseAtomsAdaptor().get_structure(ase_slab)
        slab_pymatgen.sort()
        surf_name = '_'.join(map(str, i))
        pos = Poscar(slab_pymatgen)
        try:
            pos.comment = str("Surf-") + str(surf_name) + str('@') + str(
                'vac') + str(vacuum) + str('@') + str('layers') + str(layers)
        except:
            pass
        if write_file == True:
            pos.write_file(filename=str('POSCAR-') + str("Surf-") +
                           str(surf_name) + str('.vasp'))
        structures.append(pos)

    return structures
Ejemplo n.º 2
0
def get_ase_slab(pmg_struct, hkl=(1, 1, 1), min_thick=10, min_vac=10):
    """
    takes in the intial structure as pymatgen Structure object
    uses ase to generate the slab
    returns pymatgen Slab object
    
    Args:
	pmg_struct: pymatgen structure object
	hkl: hkl index of surface of slab to be created
	min_thick: minimum thickness of slab in Angstroms
	min_vac: minimum vacuum spacing 
    """
    ase_atoms = AseAtomsAdaptor().get_atoms(pmg_struct)
    pmg_slab_gen = SlabGenerator(pmg_struct, hkl, min_thick, min_vac)
    h = pmg_slab_gen._proj_height
    nlayers = int(math.ceil(pmg_slab_gen.min_slab_size / h))
    ase_slab = surface(ase_atoms, hkl, nlayers)
    ase_slab.center(vacuum=min_vac / 2, axis=2)
    pmg_slab_structure = AseAtomsAdaptor().get_structure(ase_slab)
    return Slab(lattice=pmg_slab_structure.lattice,
                species=pmg_slab_structure.species_and_occu,
                coords=pmg_slab_structure.frac_coords,
                site_properties=pmg_slab_structure.site_properties,
                miller_index=hkl,
                oriented_unit_cell=pmg_slab_structure,
                shift=0.,
                scale_factor=None,
                energy=None)
Ejemplo n.º 3
0
def get_ase_slab(pmg_struct, hkl=(1,1,1), min_thick=10, min_vac=10):
    """
    takes in the intial structure as pymatgen Structure object
    uses ase to generate the slab
    returns pymatgen Slab object
    
    Args:
	pmg_struct: pymatgen structure object
	hkl: hkl index of surface of slab to be created
	min_thick: minimum thickness of slab in Angstroms
	min_vac: minimum vacuum spacing 
    """
    ase_atoms = AseAtomsAdaptor().get_atoms(pmg_struct)
    pmg_slab_gen = SlabGenerator(pmg_struct, hkl, min_thick, min_vac)
    h = pmg_slab_gen._proj_height
    nlayers = int(math.ceil(pmg_slab_gen.min_slab_size / h))
    ase_slab = surface(ase_atoms, hkl, nlayers)
    ase_slab.center(vacuum=min_vac/2, axis=2)
    pmg_slab_structure = AseAtomsAdaptor().get_structure(ase_slab)
    return Slab(lattice=pmg_slab_structure.lattice,
                species=pmg_slab_structure.species_and_occu,
                coords=pmg_slab_structure.frac_coords,
                site_properties=pmg_slab_structure.site_properties,
                miller_index=hkl, oriented_unit_cell=pmg_slab_structure,
                shift=0., scale_factor=None, energy=None)
Ejemplo n.º 4
0
def surfer(vacuum=15, layers=2, mat=None, max_index=1, write_file=True):
    """
    ASE surface bulder

    Args:
        vacuum: vacuum region
        mat: Structure object
        max_index: maximum miller index
        min_slab_size: minimum slab size

    Returns:
           structures: list of surface Structure objects
    """

    if mat == None:
        print("Provide structure")

    sg_mat = SpacegroupAnalyzer(mat)
    mat_cvn = sg_mat.get_conventional_standard_structure()
    mat_cvn.sort()
    indices = get_symmetrically_distinct_miller_indices(mat_cvn, max_index)
    ase_atoms = AseAtomsAdaptor().get_atoms(mat_cvn)

    structures = []
    pos = Poscar(mat_cvn)
    try:
        pos.comment = (str("sbulk") + str("@") + str("vac") + str(vacuum) +
                       str("@") + str("layers") + str(layers))
    except:
        pass
    structures.append(pos)
    if write_file == True:
        mat_cvn.to(fmt="poscar",
                   filename=str("POSCAR-") + str("cvn") + str(".vasp"))
    for i in indices:
        ase_slab = surface(ase_atoms, i, layers)
        ase_slab.center(vacuum=vacuum, axis=2)
        slab_pymatgen = AseAtomsAdaptor().get_structure(ase_slab)
        slab_pymatgen.sort()
        surf_name = "_".join(map(str, i))
        pos = Poscar(slab_pymatgen)
        try:
            pos.comment = (str("Surf-") + str(surf_name) + str("@") +
                           str("vac") + str(vacuum) + str("@") +
                           str("layers") + str(layers))
        except:
            pass
        if write_file == True:
            pos.write_file(filename=str("POSCAR-") + str("Surf-") +
                           str(surf_name) + str(".vasp"))
        structures.append(pos)

    return structures
Ejemplo n.º 5
0
  def build_tilt_sym_frac(self, bp=[-1,1,12], v=[1,1,0], c_space=None):
    bpxv = [(bp[1]*v[2]-v[1]*bp[2]),(bp[2]*v[0]-bp[0]*v[2]),(bp[0]*v[1]- v[0]*bp[1])]
    grain_a = BodyCenteredCubic(directions = [bpxv, bp, v],
                              size = (1,1,1), symbol='Fe', pbc=(1,1,1),
                              latticeconstant = 2.85)
    n_grain_unit = len(grain_a)
    n = 2
# Slightly different from slabmaker since in the fracture
# Simulations we want the grainboundary plane to be normal to y.
    while(grain_a.get_cell()[1,1] < 120.0):
      grain_a = BodyCenteredCubic(directions = [bpxv, bp, v],
                           size = (1,n,2), symbol='Fe', pbc=(1,1,1),
                           latticeconstant = 2.85)
      n += 1
    print '\t {0} repeats in z direction'.format(n)
    grain_b = grain_a.copy()
    grain_c = grain_a.copy()
    print '\t', '{0} {1} {2}'.format(v[0],v[1],v[2])
    print '\t', '{0} {1} {2}'.format(bpxv[0],bpxv[1],bpxv[2])
    print '\t', '{0} {1} {2}'.format(bp[0], bp[1], bp[2])
    if c_space==None:
      s1 = surface('Fe', (map(int, bp)), n)
      c_space = s1.get_cell()[2,2]/float(n) #-s1.positions[:,2].max()
      s2 = surface('Fe', (map(int, v)), 1)
      x_space = s2.get_cell()[0,0] #-s1.positions[:,2].max()
      s3 = surface('Fe', (map(int, bpxv)), 1)
      y_space = s3.get_cell()[1,1] #-s1.positions[:,2].max()
    print '\t Interplanar spacing: ', x_space.round(2), y_space.round(2), c_space.round(2), 'A'
	# Reflect grain b in z-axis (across mirror plane):
    print grain_a.get_cell()[1,1]-grain_a.positions[:,1].max()
    grain_b.positions[:,1]  = -1.0*grain_b.positions[:,1]
    grain_c.extend(grain_b)
    grain_c.set_cell([grain_c.get_cell()[0,0], 2*grain_c.get_cell()[1,1], grain_c.get_cell()[2,2]])
    grain_c.positions[:,1] += abs(grain_c.positions[:,1].min())
    pos = [grain.position for grain in grain_c]
    pos = sorted(pos, key= lambda x: x[2])
    dups = get_duplicate_atoms(grain_c)
 #  now center fracture cell with plenty of vacuum
    grain_c.center(vacuum=10.0,axis=1)
    return grain_c
Ejemplo n.º 6
0
def get_ase_surf(s=[], miller=(0, 0, 1), layers=1):
    strt = center_struct(s)
    ase_atoms = AseAtomsAdaptor().get_atoms(strt)
    ase_slab = surface(ase_atoms, miller, layers)
    ase_slab.center(axis=2)
    tmp = AseAtomsAdaptor().get_structure(ase_slab)
    range_z = rangexyz(strt)
    # print ('rz',abs(strt.lattice.matrix[2][2]),range_z)
    if abs(strt.lattice.matrix[2][2] - range_z) <= 6.0:
        ase_slab.center(axis=2, vacuum=12.0)
    else:
        ase_slab.center(axis=2)
    slab_pymatgen = AseAtomsAdaptor().get_structure(ase_slab)
    slab_pymatgen.sort()
    print("Surface")
    print(Poscar(slab_pymatgen))
    return slab_pymatgen
Ejemplo n.º 7
0
import sys
from ase.lattice.surface import surface
from ase.io import read
from ase.visualize import view
# facet = sys.argv[1]
try:
    layers = int(sys.argv[2])
except:
    layers = 1

try:
    vacuum = float(sys.argv[3])
except:
    vacuum = 9

# facet = [int(i) for i in facet]
facet = [1, 1, 1]

atoms = read(sys.argv[1])  #Bulk traj file (no vacuum)
atoms = surface(atoms, facet, layers, vacuum)
atoms.set_pbc(True)
view(atoms)
Ejemplo n.º 8
0

a = 3.6

bulk = FaceCenteredCubic('Fe',
                         directions=[[1, 0, 0], [0, 1, 0], [0, 0, 1]],
                         latticeconstant=a)

#bulk = Atoms('Fe4', scaled_positions=[ (0.5,0.5,0), (0.5, 0, 0.5), (0, 0.5, 0.5), (0,0,0)],
#            magmoms=[5,5,-5,-5], cell=[a,a,a], pbc=(1,1,1))
a = bulk.copy()

bulk = bulk * (1, 2, 1)
bulk.set_initial_magnetic_moments([5, 5, 5, 5, -5, -5, -5, -5])

s1 = surface(bulk, (1, 2, 1), 6)
s1 = s1 * (1, 2, 1)

mask = [atom.position[2] < 0.5 or atom.position[2] > 10.0 for atom in s1]
constraint = FixAtoms(mask=mask)
s1.set_constraint(constraint)

atoms = s1

view(s1)

os.system('mkdir result')

# pts = ibz_points['cubic']
pts = get_special_points('cubic', a.cell)
print pts
Ejemplo n.º 9
0
#!/usr/bin/python

import ase
from ase import Atoms
from ase.lattice.surface import surface
from ase.io import *

ice = read("0000_Ih_bulk.POSCAR")

sf = surface(ice, (0, 0, 1), 1)
sf.center(vacuum=0, axis=2)

write("Ih_SF_001.POSCAR", sf)
Ejemplo n.º 10
0
from ase.lattice.surface import surface
from ase.io import write
# Au(211) with 9 layers
s1 = surface('Au', (2, 1, 1), 9)
s1.center(vacuum=10, axis=2)
write('images/Au-211.png',
      s1.repeat((3,3,1)),
      rotation='-30z,90x', # change the orientation for viewing
      show_unit_cell=2)
Ejemplo n.º 11
0
a = 3.5574

fcc = FaceCenteredCubic('Fe',
                        directions=[[1, 0, 0], [0, 1, 0], [0, 0, 1]],
                        latticeconstant=a,
                        pbc=True)

fcc.set_calculator(calc)

n = fcc.get_number_of_atoms()
p = fcc.get_potential_energy() / n
v = fcc.get_volume() / n

print n, p, v

slab1 = surface(fcc, (1, 1, 1), 3)
slab1 = slab1 * (1, 1, 1)

slab1.set_calculator(calc)

n = slab1.get_number_of_atoms()
p = slab1.get_potential_energy() / n
v = slab1.get_volume() / n

print n, p, v

slab2 = fcc111('Fe', size=(4, 4, 20), a=a, orthogonal=False)
slab2.set_pbc([True, True, True])

view(slab2)
Ejemplo n.º 12
0
from ase.io import read, write
from ase.visualize import view
from ase.lattice.surface import surface

cut = (1, 0, 0)

atoms = read('POSCAR_SiO2')

surf = surface(atoms, cut, 3, 10)

write('POSCAR_orig', surf)

view(atoms)
Ejemplo n.º 13
0
def save( filename, arg ):
    f = open(filename, 'a+t')
    f.write('{0} \n'.format(arg))
    f.close()

a = 3.5349

bulk = FaceCenteredCubic('Fe', directions=[[1,0,0],[0,1,0],[0,0,1]], latticeconstant=a)

#bulk = Atoms('Fe4', scaled_positions=[ (0.5,0.5,0), (0.5, 0, 0.5), (0, 0.5, 0.5), (0,0,0)],
#            magmoms=[5,5,-5,-5], cell=[a,a,a], pbc=(1,1,1))

bulk = bulk*(1,2,1)
bulk.set_initial_magnetic_moments([5,5,5,5,-5,-5,-5,-5])

s1 = surface(bulk, (1,2,1), 3)
s1 = s1*(1,2,1)

# view(s1)

s2 = s1.copy()
s2.translate(s2.get_cell()[2])

cell = s1.get_cell()
# cell[1] = cell[1]*8./7.
cell[1] = cell[1]*24./23.
s2.set_cell(cell, scale_atoms=True)

s1 = s1+s2

#s2.set_cell([0,1,0], scale_atoms=True)
Ejemplo n.º 14
0
#!/usr/bin/env python
from ase.db import connect
from jasp import *
from ase.lattice.surface import surface, add_adsorbate
from ase.constraints import FixAtoms
from ase import Atoms, Atom
from ase.io import write, read


catadb = connect("~/datas/catadb/catadb.db")
bulk = catadb.get_atoms(name='pto-fm3m-relax')
atoms = surface(bulk, (1, 1, 1), 4, vacuum=10.0)
for atom in atoms:
   if atom.symbol=='Pt':
     atom.symbol='O'
   elif atom.symbol=='O':
     atom.symbol='Pt'

constraint = FixAtoms(mask=[atom.z < 17.5 for atom in atoms])
atoms.set_constraint(constraint)

with jasp('surfaces/pto-100-224-relax',
          xc='PBE',
          kpts=[5, 5, 1],
	  lreal='auto',
          encut=450,
          ibrion=2,
          nsw=500,
          ediff=1e-5,
          atoms=atoms) as calc:
    print atoms.get_potential_energy()
Ejemplo n.º 15
0
def smart_surf(strt=None, parameters=None, layers=3, tol=0.5):
    """
    Function to get all surface energies

    Args:
        strt: Structure object
        parameters: parameters with LAMMPS inputs
        layers: starting number of layers
        tol: surface energy tolerance for convergence
    Returns:
          surf_list: list of surface energies
          surf_header_list: list of surface names

    """
    parameters["control_file"] = input_nobox  #'/users/knc6/inelast_nobox.mod'
    sg_mat = SpacegroupAnalyzer(strt)
    mat_cvn = sg_mat.get_conventional_standard_structure()
    mat_cvn.sort()
    layers = 3
    indices = get_symmetrically_distinct_miller_indices(mat_cvn, 1)
    ase_atoms = AseAtomsAdaptor().get_atoms(mat_cvn)
    for i in indices:
        ase_slab = surface(ase_atoms, i, layers)
        ase_slab.center(vacuum=15, axis=2)
        if len(ase_slab) < 50:
            layers = 3
    surf_arr = []
    surf_done = True
    try:
        surf = surfer(mat=strt, layers=layers)
        surf_list = [100000 for y in range(len(surf) - 1)]
        print("in smart_surf :surf,surf_list=", surf, surf_list)
    except:
        print("Failed at s1", os.getcwd())
        pass
    while surf_done:
        layers = layers + 1
        indices = get_symmetrically_distinct_miller_indices(mat_cvn, 1)
        ase_atoms = AseAtomsAdaptor().get_atoms(mat_cvn)
        for i in indices:
            ase_slab = surface(ase_atoms, i, layers)
            ase_slab.center(vacuum=15, axis=2)
            # if len(ase_slab) > 100:
            #   surf_done=True
            # if (ase_slab.get_cell()[2][2]) > 40:
            #   surf_done=True

        try:
            surf = surfer(mat=strt, layers=layers)
        except:

            print("Failed at s2", os.getcwd())
            pass
        if surf not in surf_arr:
            surf_arr.append(surf)
            try:
                surf_list2, surf_header_list = surf_energy(
                    surf=surf, parameters=parameters
                )
                print("in smart_surf :surf2,surf_list2=", surf_list2, surf_header_list)
                diff = matrix(surf_list) - matrix(surf_list2)
                print(
                    "in smart_surf :surf3,surf_list3=",
                    matrix(surf_list),
                    matrix(surf_list2),
                )
                diff_arr = np.array(diff).flatten()
            except:
                print("Failed for s_3", os.getcwd())
                pass
            if len(ase_slab) > 50:
                surf_done = True
                break
                # print ("layersssssssssssssssssssssssss",layers,surf_done)
                break
            if any(diff_arr) > tol:
                # for el in diff_arr:
                #    if abs(el)>tol :
                #        print ("in smart_surf :abs el=",abs(el))
                surf_done = True
                surf_list = surf_list2
            else:
                surf_done = False
    return surf_list, surf_header_list
Ejemplo n.º 16
0
# creates: s1.png s2.png s3.png s4.png general_surface.pdf
from ase.lattice.surface import surface
s1 = surface('Au', (2, 1, 1), 9)
s1.center(vacuum=10, axis=2)

from ase.lattice import bulk
Mobulk = bulk('Mo', 'bcc', a=3.16, cubic=True)
s2 = surface(Mobulk, (3, 2, 1), 9)
s2.center(vacuum=10, axis=2)

a = 4.0
from ase import Atoms
Pt3Rh = Atoms('Pt3Rh',
              scaled_positions=[(0, 0, 0),
                                (0.5, 0.5, 0),
                                (0.5, 0, 0.5),
                                (0, 0.5, 0.5)],
              cell=[a, a, a],
              pbc=True)
s3 = surface(Pt3Rh, (2, 1, 1), 9)
s3.center(vacuum=10, axis=2)

Pt3Rh.set_chemical_symbols('PtRhPt2')
s4 = surface(Pt3Rh , (2, 1, 1), 9)
s4.center(vacuum=10, axis=2)

from ase.io import write
for atoms, name in [(s1, 's1'), (s2, 's2'), (s3, 's3'), (s4, 's4')]:
    write(name + '.pov', atoms,
          rotation='-90x',
          show_unit_cell=2,
Ejemplo n.º 17
0
#!/usr/bin/python

import ase
from ase import Atoms
from ase.lattice.surface import surface
from ase.io import *


ice = read("0000_Ic_SC_6x4x4.POSCAR")

sf = surface(ice, (-3,8,2), 20)
sf.center(vacuum=10, axis=2)

write("test.POSCAR", sf)
Ejemplo n.º 18
0
from ase.lattice.surface import surface
from ase.io import write
# Au(211) with 9 layers
s1 = surface('Au', (2, 1, 1), 9)
s1.center(vacuum=10, axis=2)
write('images/Au-211.png',
      s1.repeat((3, 3, 1)),
      rotation='-30z,90x',  # change the orientation for viewing
      show_unit_cell=2)
from ase.constraints import FixAtoms
from ase import Atoms, Atom
from ase.io import write, read


bulk = read('bulk/pt-relax/CONTCAR')


fix_layers = [1, 2, 3, 4, 5, 6]
relax_layers = [1, 2, 3, 4, 5, 6]
energies=[]
vac = 10.0
for fl in fix_layers:
	for rl in relax_layers:
		tl = fl + rl
		ssur = surface(bulk, (1, 1, 1), tl, vacuum=vac)
		# fix bottom atoms
		constraint = FixAtoms(mask=[atom.position[2] < ((ssur.cell[2][2] - vac*2)*fl/tl+vac+0.5)
                            for atom in ssur])
		ssur.set_constraint(constraint)
		# add adsorbate CO
		co = Atoms('CO')
		co[0].z = ssur[tl-1].z + 1.6
		co[1].z = co[0].z + 1.14
		ssur = ssur + co
		write('images/pt-111-co-ontop-{0}-{1}.png'.format(fl, rl), ssur, show_unit_cell=2)
		with jasp('surfaces/pt-111-114-co-ontop/relax-{0}-{1}'.format(fl, rl),
                   xc='PBE',
                   kpts=[7, 7, 1],
                   encut=450,
                   ibrion=2,
Ejemplo n.º 20
0
from ase.io import write, read
from ase.visualize import view
from multiprocessing import Pool
import numpy as np

def sortz(atoms):
  tags = atoms.positions[:,2]
  deco = sorted([(tag, i) for i, tag in enumerate(tags)])
  indices = [i for tag, i in deco]
  return atoms[indices]

bulk = read('~/vasp/bulk/ceo2-relax-u/CONTCAR')
#bulk[0].z = bulk[0].z + bulk.cell[2][2]
#bulk.positions[:,2] -= min(bulk.positions[:,2])
#view(bulk)
atoms = surface(bulk, (1, 1, 1), 3, vacuum=0.0)
atoms = sortz(atoms)
atoms_2o = atoms.copy()
atoms_o = atoms.copy()
atoms_ce = atoms.copy()


atoms_2o.cell[2][2] += 10.0
constraint = FixAtoms(mask=[atom.position[2] < 3.3
                            for atom in atoms_2o])
atoms_2o.set_constraint(constraint)
atoms_2o.write('ceo2-111-2o.in')

for i in range(-4, 0):
  atoms_o[i].z -= atoms_o.cell[2][2] + (atoms_o[-8].z - atoms_o[-9].z)
Ejemplo n.º 21
0
          sigma=0.05,  # very small smearing factor for a molecule
          ispin=2,
          isif=3,
          ibrion=2,
          nsw=200,
          nelm=100,
          lreal='auto',
          atoms=bulk) as calc:
    print('energy = {0} eV'.format(bulk.get_potential_energy()))
    print(bulk.get_forces())
    print calc


bulk = read('bulk/' + sysname + '/CONTCAR')

surf = surface(bulk, (1, 1, 1), 5, vacuum = 10)
#print(s3.positions[3])
t1 = np.array([0,0,surf.positions[0][2]])
surf.positions = surf.positions - t1

#view(s3, repeat=(1, 1, 1))
#write('surface_ceo2.png', bulk, show_unit_cell=2)

constraint = FixAtoms(mask=[atom.tag >= 3 for atom in surf])
surf.set_constraint(constraint)

with jasp('surfaces/' + sysname + '-slab-relaxed',
          xc='PBE',  # the exchange-correlation functional
          encut=400,    # planewave cutoff
          kpts=(3, 3, 1),
          ismear=0,    # Methfessel-Paxton smearing
Ejemplo n.º 22
0
# creates: s1.png s2.png s3.png s4.png general_surface.pdf
from ase.lattice.surface import surface
s1 = surface('Au', (2, 1, 1), 9)
s1.center(vacuum=10, axis=2)

from ase.lattice import bulk
Mobulk = bulk('Mo', 'bcc', a=3.16, cubic=True)
s2 = surface(Mobulk, (3, 2, 1), 9)
s2.center(vacuum=10, axis=2)

a = 4.0
from ase import Atoms
Pt3Rh = Atoms('Pt3Rh',
              scaled_positions=[(0, 0, 0), (0.5, 0.5, 0), (0.5, 0, 0.5),
                                (0, 0.5, 0.5)],
              cell=[a, a, a],
              pbc=True)
s3 = surface(Pt3Rh, (2, 1, 1), 9)
s3.center(vacuum=10, axis=2)

Pt3Rh.set_chemical_symbols('PtRhPt2')
s4 = surface(Pt3Rh, (2, 1, 1), 9)
s4.center(vacuum=10, axis=2)

from ase.io import write
for atoms, name in [(s1, 's1'), (s2, 's2'), (s3, 's3'), (s4, 's4')]:
    write(name + '.pov',
          atoms,
          rotation='-90x',
          show_unit_cell=2,
          transparent=False,