Source code for sknano.scripts.nanogen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
====================================================
Command line script (:mod:`sknano.scripts.nanogen`)
====================================================

CLI to :mod:`sknano.generators` tools.

.. currentmodule:: sknano.scripts.nanogen

This module allows for easy structure generation from the command line.

.. seealso::

   :class:`~sknano.generators.FullereneGenerator`

   :class:`~sknano.generators.GrapheneGenerator`

   :class:`~sknano.generators.BilayerGrapheneGenerator`

   :class:`~sknano.generators.UnrolledSWNTGenerator`

   :class:`~sknano.generators.SWNTGenerator`

   :class:`~sknano.generators.MWNTGenerator`

   :class:`~sknano.generators.LayeredStructureGenerator`

.. code-block:: sh

   > nanogen --help

     usage: nanogen [-h] [--fname FNAME] [--structure-format {data,xyz}]
               [--debug] [--verbose] [--version]
               {fullerene,graphene,bilayer_graphene,unrolled_swnt,swnt,mwnt,layered_structure}
               ...

     optional arguments:
       -h, --help            show this help message and exit
       --fname FNAME         structure file name
       --structure-format {data,xyz}
                             structure file format (default: xyz)
       --debug               debug output
       --verbose             verbose output
       --version             show nanogen's version number and exit

     sub-commands:
       {fullerene,graphene,bilayer_graphene,unrolled_swnt,swnt,mwnt,layered_structure}

.. autofunction:: nanogen

Examples
--------

The following command generates a graphene sheet with a 10 Å long
armchair edge and 1 Å long zigzag edge and saves the data in the
LAMMPS data format.::

    > nanogen --structure-format data graphene 10 1

This command will generate a :math:`(20, 0)` SWNT, 5 unit cells
long and saves the data in `xyz` format.::

    > nanogen swnt --Ch 20 0 --nz 5

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

import argparse
import importlib
import sys

from sknano.core.refdata import aCC, element_data
# from sknano.core.structures import get_chiral_indices_from_str
from .parser import add_default_arguments

_r_CC_vdw = element_data['C']['VanDerWaalsRadius']

__all__ = ['nanogen', 'nanogen_parser']


[docs]def nanogen_parser(): """:mod:`~sknano.scripts.nanogen` script \ :class:`~python:argparse.ArgumentParser`.""" parser = argparse.ArgumentParser() parser.add_argument('--fname', help='structure file name') parser.add_argument('--structure-format', default='xyz', choices=('data', 'xyz'), help='structure file format (default: %(default)s)') parser = add_default_arguments(parser) subparsers = parser.add_subparsers(title='sub-commands') fullerene_parser = subparsers.add_parser('fullerene') fullerene_parser.add_argument('N', type=int, help='The N in C_N') fullerene_parser.set_defaults(generator_class='FullereneGenerator') nanostructure_parent_parser = argparse.ArgumentParser(add_help=False) nanostructure_parent_parser.add_argument( '--basis', type=str, nargs=2, metavar=('ELEMENT1', 'ELEMENT2'), default=['C', 'C'], help='2 element symbols or atomic numbers of the ' 'two atom basis (default: %(default)s)') nanostructure_parent_parser.add_argument( '--bond', type=float, default=aCC, help='Bond length between ' 'nearest-neighbor atoms. Must be in units of Angstroms. ' '(default: %(default)s)') graphene_parent_parser = argparse.ArgumentParser(add_help=False) graphene_parent_parser.add_argument('--layer-spacing', type=float, default=2*_r_CC_vdw, help='distance between ' 'graphene layers in **Angstroms**. ' '(default: %(default)s)') graphene_parent_parser.add_argument('--layer-rotation-increment', type=float, default=None, help='Layer rotation angles of ' 'each layer in **degrees** ' '(default: %(default)s)') graphene_parent_parser.add_argument('--layer-rotation-angles', type=list, default=None, help='Layer rotation angles of ' 'each layer in **degrees** ' '(default: %(default)s)') graphene_parent_parser.add_argument('--stacking-order', default='AB', choices=('AA', 'AB'), help='Stacking order of graphene ' 'layers (default: %(default)s)') graphene_parser = \ subparsers.add_parser('graphene', parents=[nanostructure_parent_parser, graphene_parent_parser]) graphene_parser.add_argument('--nlayers', type=int, default=1, help='Number of graphene layers. ' '(default: %(default)s)') graphene_subparsers = \ graphene_parser.add_subparsers(title='graphene sub-commands') primitive_cell_graphene_parser = \ graphene_subparsers.add_parser('from_primitive_cell') primitive_cell_graphene_parser.add_argument( '--edge-length', type=float, default=10, help='graphene edge length in **Angstroms**') primitive_cell_graphene_parser.set_defaults( generator_class='PrimitiveCellGrapheneGenerator') conventional_cell_graphene_parser = \ graphene_subparsers.add_parser('from_conventional_cell') conventional_cell_graphene_parser.add_argument( '--armchair-edge-length', type=float, default=10, help='length of graphene armchair edge in **Angstroms**') conventional_cell_graphene_parser.add_argument( '--zigzag-edge-length', type=float, default=10, help='length of graphene zigzag edge in **Angstroms**') conventional_cell_graphene_parser.set_defaults( generator_class='ConventionalCellGrapheneGenerator') # graphene_parser.set_defaults(generator_class='GrapheneGenerator') bilayer_graphene_parser = \ subparsers.add_parser('bilayer_graphene', parents=[nanostructure_parent_parser, graphene_parent_parser]) bilayer_graphene_parser.set_defaults( generator_class='BilayerGrapheneGenerator') swnt_parent_parser = argparse.ArgumentParser(add_help=False) swnt_parent_parser.add_argument('--Ch', type=int, nargs=2, metavar=('n', 'm'), default=(5, 0), help='Chiral indices (`n`, `m`) ' '(default: %(default)s)') swnt_parent_parser_group = \ swnt_parent_parser.add_mutually_exclusive_group() swnt_parent_parser_group.add_argument('--nz', type=int, default=1, help='Number of repeat unit cells ' 'along `z` axis ' '(default: %(default)s)') swnt_parent_parser_group.add_argument('--Lz', type=float, default=None, help='Length of nanotube along `z` ' 'axis in **Angstroms**. ' '(default: %(default)s)') swnt_parent_parser.add_argument( '--fix-Lz', action='store_true', help='Generate the nanotube with ' 'length as close to the specified `Lz` as possible. If `True`, then ' 'non integer `nz` cells are permitted. (default: %(default)s)') unrolled_swnt_parser = \ subparsers.add_parser('unrolled_swnt', parents=[nanostructure_parent_parser, swnt_parent_parser]) unrolled_swnt_parser_group = \ unrolled_swnt_parser.add_mutually_exclusive_group() unrolled_swnt_parser_group.add_argument( '--nx', type=int, default=1, help='Number of repeat unit cells along `x` axis ' '(default: %(default)s)') unrolled_swnt_parser_group.add_argument( '--Lx', type=float, default=None, help='Length of unrolled nanotube along `x` axis in **Angstroms**. ' '(default: %(default)s)') unrolled_swnt_parser.add_argument( '--fix-Lx', action='store_true', help='Generate the nanotube with ' 'length as close to the specified `Lx` as possible. If `True`, then ' 'non integer `nx` cells are permitted. (default: %(default)s)') unrolled_swnt_parser.set_defaults(generator_class='UnrolledSWNTGenerator') mwnt_parent_parser = argparse.ArgumentParser(add_help=False) mwnt_parent_parser.add_argument('--Ch', default=None, metavar=('n', 'm'), type=int, nargs=2, action='append', help='Use this command multiple times to ' 'generate a list of (`n`, `m`) ' 'chiralities for each `SWNT` wall in ' '`MWNT` (default: %(default)s)') mwnt_parent_parser.add_argument('--Nwalls', type=int, default=3, help='Number of `SWNT` walls in `MWNT` ' '(default: %(default)s)') mwnt_parent_parser.add_argument('--Lz', type=float, default=None, help='Length of nanotube along `z` axis ' 'in **Angstroms**. ' '(default: %(default)s)') mwnt_parent_parser.add_argument('--min-wall-diameter', type=float, default=None, help='Minimum `MWNT` wall diameter, in ' 'units of **Angstroms** ' '(default: %(default)s)') mwnt_parent_parser.add_argument('--max-wall-diameter', type=float, default=None, help='Maximum `MWNT` wall diameter, in ' 'units of **Angstroms** ' '(default: %(default)s)') mwnt_parent_parser.add_argument('--max-walls', type=int, default=None, help='Maximum number of `MWNT` walls ' '(default: %(default)s)') bundle_parent_parser = argparse.ArgumentParser(add_help=False) bundle_parent_parser.add_argument('--nx', type=int, default=1, help='Number of repeat unit cells ' 'along `x` axis (default: %(default)s)') bundle_parent_parser.add_argument('--ny', type=int, default=1, help='Number of repeat unit cells ' 'along `y` axis (default: %(default)s)') bundle_parent_parser.add_argument('--vdw-radius', type=float, default=_r_CC_vdw, help='van der Waals ' 'radius of nanotube atoms ' '(default: %(default)s)') bundle_parent_parser.add_argument('--bundle-packing', choices=('hcp', 'ccp'), default=None, help='Packing arrangement of nanotube ' 'bundles. (default: %(default)s)') bundle_parent_parser.add_argument('--bundle-geometry', choices=('hexagon', 'square', 'rectangle', 'triangle'), default=None, help='Force a specific geometry on the ' 'nanotube bundle boundaries ' '(default: %(default)s)') swnt_parser = \ subparsers.add_parser('swnt', parents=[nanostructure_parent_parser, swnt_parent_parser, bundle_parent_parser]) swnt_parser.set_defaults(generator_class='SWNTGenerator') mwnt_parser = \ subparsers.add_parser('mwnt', parents=[nanostructure_parent_parser, mwnt_parent_parser, bundle_parent_parser]) mwnt_parser.set_defaults(generator_class='MWNTGenerator') layered_structure_parser = subparsers.add_parser('layered_structure') layered_structure_parser.add_argument('cfgfile') layered_structure_parser.set_defaults( generator_class='LayeredStructureGenerator') return parser
[docs]def nanogen(generator_class=None, fname=None, structure_format='xyz', **kwargs): """Function for the nanogen script. Parameters ---------- generator_class : str nano-structure generator class fname : str, optional structure file name structure_format : str, optional output file format """ generator = getattr(importlib.import_module('sknano.generators'), generator_class) generator(**kwargs).save(fname=fname, structure_format=structure_format)
def main(): args = nanogen_parser().parse_args() if hasattr(args, 'generator_class'): nanogen(**vars(args)) else: nanogen_parser().print_help() if __name__ == '__main__': sys.exit(main())