Source code for sknano.generators.unrolled_swnt_generator

# -*- coding: utf-8 -*-
"""
===============================================================================
Unrolled SWNT generator (:mod:`sknano.generators.unrolled_swnt_generator`)
===============================================================================

.. currentmodule:: sknano.generators.unrolled_swnt_generator

.. todo::

   Add methods to perform fractional translation and cartesian translation
   before structure generation.

.. todo::

   Handle different units in output coordinates.

"""
from __future__ import absolute_import, division, print_function, \
    unicode_literals
__docformat__ = 'restructuredtext en'

import copy

# import numpy as np

from sknano.core import pluralize
from sknano.core.atoms import StructureAtom as Atom, StructureAtoms as Atoms
from sknano.core.crystallography import SuperCell
from sknano.core.math import Vector
from sknano.core.structures import UnrolledSWNT
from .base import NanoStructureGenerator

__all__ = ['UnrolledSWNTGenerator']


[docs]class UnrolledSWNTGenerator(NanoStructureGenerator, UnrolledSWNT): """Class for generating unrolled nanotube structures. .. versionadded:: 0.2.23 Parameters ---------- n, m : int Chiral indices defining the nanotube chiral vector :math:`\\mathbf{C}_{h} = n\\mathbf{a}_{1} + m\\mathbf{a}_{2} = (n, m)`. nx, ny, nz : int, optional Number of repeat unit cells in the :math:`x, y, z` dimensions basis : {:class:`python:list`}, optional List of :class:`python:str`\ s of element symbols or atomic number of the two atom basis (default: ['C', 'C']) .. versionadded:: 0.3.10 element1, element2 : {str, int}, optional Element symbol or atomic number of basis :class:`~sknano.core.Atom` 1 and 2 .. deprecated:: 0.3.10 Use `basis` instead bond : float, optional :math:`\\mathrm{a}_{\\mathrm{CC}} =` distance between nearest neighbor atoms. Must be in units of **Angstroms**. Lx, Ly, Lz : float, optional Length of bundle in :math:`x, y, z` dimensions in **Angstroms**. Overrides the :math:`n_x, n_y, n_z` cell values. .. versionchanged:: 0.4.0 Changed units from nanometers to **Angstroms** fix_Lz : bool, optional Generate the nanotube with length as close to the specified :math:`L_z` as possible. If `True`, then non integer :math:`n_z` cells are permitted. autogen : bool, optional if `True`, automatically call :meth:`~UnrolledSWNTGenerator.generate`. verbose : bool, optional if `True`, show verbose output Notes ----- The `UnrolledSWNTGenerator` class generates graphene using the nanotube unit cell defined by the chiral vector :math:`\\mathbf{C}_{h} = n\\mathbf{a}_{1} + m\\mathbf{a}_{2} = (n, m)`. If you want to generate graphene with an armchair or zigzag edge using `length` and `width` parameters, see the :class:`~sknano.generators.GrapheneGenerator` class. .. seealso:: :class:`~sknano.generators.GrapheneGenerator` Examples -------- First, load the :class:`~sknano.generators.UnrolledSWNTGenerator` class. >>> from sknano.generators import UnrolledSWNTGenerator Now let's generate an unrolled :math:`\\mathbf{C}_{\\mathrm{h}} = (10, 5)` SWCNT unit cell. >>> unrolled_swnt = UnrolledSWNTGenerator(10, 5) >>> unrolled_swnt.save() The rendered structure looks like: .. image:: /images/unrolled_1005_1cellx1cell-2.png """
[docs] def generate(self, finalize=True): """Generate structure data.""" self.structure.clear() layer0 = Atoms() scaling_matrix = self.scaling_matrix supercell = SuperCell(self.unit_cell, scaling_matrix) for atom in supercell: layer0.append(Atom(**atom.todict())) layer0.center_centroid() lattice_shift = Vector(p0=supercell.basis.centroid, p=layer0.centroid) lattice_shift.z = self.nlayers * lattice_shift.z self.lattice_shift = Vector(lattice_shift) for nlayer in range(self.nlayers): layer = copy.deepcopy(layer0) layer.translate(Vector([0, nlayer * self.layer_spacing, 0])) [setattr(atom, 'mol', nlayer + 1) for atom in layer] if (nlayer % 2) != 0: layer.translate(self.layer_shift) layer.rotate(angle=self.layer_rotation_angles[nlayer], axis='z') self.atoms.extend(layer) self.layers.append(layer) if finalize: self.finalize()
@classmethod
[docs] def generate_fname(cls, n=None, m=None, nx=None, nz=None, fix_Lx=False, fix_Lz=False, **kwargs): fname = '{}{}'.format('{}'.format(n).zfill(2), '{}'.format(m).zfill(2)) nx_fmtstr = '{:.2f}' if fix_Lx else '{:.0f}' nx = ''.join((nx_fmtstr.format(nx), pluralize('cell', nx))) nz_fmtstr = '{:.2f}' if fix_Lz else '{:.0f}' nz = ''.join((nz_fmtstr.format(nz), pluralize('cell', nz))) cells = 'x'.join((nx, nz)) return '_'.join(('unrolled', fname, cells))
[docs] def save(self, fname=None, outpath=None, structure_format=None, center_centroid=True, **kwargs): """Save structure data. See :meth:`~sknano.generators.GeneratorBase.save` method for documentation. """ if fname is None: fname = self.generate_fname(n=self.n, m=self.m, nx=self.nx, nz=self.nz, fix_Lx=self.fix_Lx, fix_Lz=self.fix_Lz) if center_centroid: self.atoms.center_centroid() super().save(fname=fname, outpath=outpath, structure_format=structure_format, center_centroid=False, **kwargs)