Source code for sknano.generators._graphene_generator
# -*- coding: utf-8 -*-
"""
==============================================================================
Graphene structure generator (:mod:`sknano.generators._graphene_generator`)
==============================================================================
.. currentmodule:: sknano.generators._graphene_generator
"""
from __future__ import absolute_import, division, print_function
from six.moves import range
__docformat__ = 'restructuredtext en'
import numpy as np
from sknano.structures import Graphene
from ._base import Atom, Atoms, GeneratorBase
__all__ = ['GrapheneGenerator']
[docs]class GrapheneGenerator(Graphene, GeneratorBase):
"""`N`-layer graphene generator class.
Parameters
----------
length : float
Length of graphene sheet in **nanometers**
width : float
Width of graphene sheet in **nanometers**
edge : {'AC', 'armchair', 'ZZ', 'zigzag'}, optional
**A**\ rm\ **C**\ hair or **Z**\ ig\ **Z**\ ag edge along
the `length` of the sheet.
element1, element2 : {str, int}, optional
Element symbol or atomic number of basis
:class:`~sknano.core.atoms.Atom` 1 and 2
bond : float, optional
bond length between nearest-neighbor atoms in **Angstroms**.
nlayers : int, optional
Number of graphene layers.
layer_spacing : float, optional
Distance between layers in **Angstroms**.
stacking_order : {'AA', 'AB'}, optional
Stacking order of graphene layers
autogen : bool, optional
automatically generate unit cell and full structure
verbose : bool, optional
verbose output
Notes
-----
The `GrapheneGenerator` class and its subclasses generate graphene with
either an armchair or zigzag edge using a 4-atom conventional unit cell.
If you want to generate graphene as an *unrolled nanotube*, see the
:class:`~sknano.generators.UnrolledSWNTGenerator` class.
.. seealso:: :class:`~sknano.generators.UnrolledSWNTGenerator`
Examples
--------
Start an interactive python or ipython session, then import the
`GrapheneGenerator` class.
>>> from sknano.generators import GrapheneGenerator
Now generate a **20 nm x 1 nm** armchair edge graphene nano-ribbon.
>>> ACG = GrapheneGenerator(length=20, width=1, edge='AC')
Save structure data in `xyz` format:
>>> ACG.save_data()
The rendered structure look like:
.. image:: /images/20nmx1nm_AC_edge.png
Now let's generate a **20 nm x 1 nm** zigzag edge graphene nano-ribbon.
>>> ZZG = GrapheneGenerator(length=20, width=1, edge='ZZ')
>>> ZZG.save_data()
The rendered structure looks like:
.. image:: /images/20nmx1nm_ZZ_edge.png
Now generate **25 nm x 5 nm**, `armchair` edge,
5 layer, `AB`-stacked graphene.
>>> ACG_5layers = GrapheneGenerator(length=25, width=5, edge='AC',
... nlayers=5)
>>> ACG_5layers.save_data()
The rendered structure looks like:
.. image:: /images/25nmx5nm_5layer_AC_graphene.png
Now generate single layer, **10 nm x 10 nm** sheet of BN Graphene.
>>> BN_graphene = GrapheneGenerator(length=10, width=10, edge='AC',
... element1='B', element2='N')
>>> BN_graphene.save_data()
The rendered structure looks like:
.. image:: /images/10nmx10nm_single_layer_BN_graphene.png
Now, just because we can, generate a **5 nm x 5 nm** sheet of
Uranium-Einsteinium Graphene.
>>> UEs_graphene = GrapheneGenerator(width=5, length=5, edge='zigzag',
... element1='U', element2='Es')
>>> UEs_graphene.save_data()
The rendered structure looks like:
.. image:: /images/5nmx5nm_single_layer_UEs_graphene.png
"""
def __init__(self, autogen=True, **kwargs):
super(GrapheneGenerator, self).__init__(**kwargs)
if autogen:
self.generate_unit_cell()
self.generate_structure_data()
[docs] def generate_unit_cell(self):
"""Generate the graphene unit cell.
Called automatically if `autogen` is `True`.
"""
bond = self.bond
edge = self.edge
e1 = self.element1
e2 = self.element2
self.unit_cell = Atoms()
# Set up 4 atom basis
# Leave atom 1 at the origin
atom1 = Atom(element=e1)
atom2 = Atom(element=e2)
atom3 = Atom(element=e1)
atom4 = Atom(element=e2)
if edge == 'AC':
# Move atom 2 to 2nd basis position
atom2.x = -np.sqrt(3) / 2 * bond
atom2.y = bond / 2
# Move atom 3 from atom 1 along a1 primitive vector
atom3.x = -np.sqrt(3) / 2 * bond
atom3.y = 3 / 2 * bond
# Move atom 4 from atom 2 along a2 primitive vector
atom4.y = 2 * bond
else:
# Move atom 2 to 2nd basis position
atom2.x = bond
# Move atom 3 from atom 1 along a1 primitive vector
atom3.x = 3 / 2 * bond
atom3.y = np.sqrt(3) / 2 * bond
# Move atom 4 from atom 2 along a2 primitive vector
atom4.x = -bond / 2
atom4.y = np.sqrt(3) / 2 * bond
self.unit_cell.extend([atom1, atom2, atom3, atom4])
#self.Natoms = self.unit_cell.Natoms
[docs] def generate_structure_data(self):
"""Generate the full structure coordinates."""
#self.atoms = Atoms()
self.structure_data.clear()
for nlayer in range(self.nlayers):
layer = Atoms()
for nx in range(self.Nx):
for ny in range(self.Ny):
dr = np.array([nx * self.cell.x,
ny * self.cell.y,
nlayer * self.layer_spacing])
for atom in self.unit_cell:
layer_atom = Atom(element=atom.symbol)
layer_atom.r = atom.r + dr
layer.append(layer_atom)
if self.Natoms_per_layer is None:
self.Natoms_per_layer = layer.Natoms
# translate layer to put its center of mass at the origin
dr = layer.CM
dr.z = 0
layer.translate(dr)
if (nlayer % 2) != 0:
layer.translate(self.layer_shift)
self.atoms.extend(layer)
[docs] def save_data(self, fname=None, outpath=None, structure_format=None,
rotation_angle=-90, rot_axis='x', deg2rad=True,
center_CM=True, **kwargs):
"""Save structure data.
See :meth:`~sknano.generators.GeneratorBase.save_data` method
for documentation.
"""
if fname is None:
dimensions = '{}nmx{}nm'.format(self.length, self.width)
nlayer = '{}layer'.format(self.nlayers)
edge = 'AC' if self.edge in ('AC', 'armchair') else 'ZZ'
atombond = '{}{}'.format(self.element1, self.element2)
fname_wordlist = (dimensions, nlayer, edge, atombond, 'graphene')
fname = '_'.join(fname_wordlist)
if center_CM and self.nlayers > 1:
self.atoms.center_CM()
super(GrapheneGenerator, self).save_data(
fname=fname, outpath=outpath, structure_format=structure_format,
rotation_angle=rotation_angle, rot_axis=rot_axis,
deg2rad=deg2rad, center_CM=False, **kwargs)