Quickstart

Note

In addition to the quickstart guide below, we also have tutorial notebooks under the notebooks directory in the Lightshow GitHub repository.

Welcome to the Lightshow quickstart guide! In the text to follow, we will provide overviews of each type of code and how to use them in the context of Lightshow. We will also provide a bird’s eye example of using the software.

The database

Everything in Lightshow is built around materials databases, specifically the lightshow.database.Database class. This object is a lightweight container for Pymatgen Structure objects, and can be instantiated in a few different ways.

Begin by importing the Database object.

from lightshow import Database

Tip

Almost every object in Lightshow can be json-serialized using the MSONable syntax. For example,

d = database.as_dict()
new_database = Database.from_dict(d)
my_json_rep = database.to_json()

import json
with open("my_database.json", "w") as f:
    json.dump(my_json_rep, f)

Databases from the Materials Project

The database is designed to be constructed via classmethods. The primary classmethod we recommend using is lightshow.database.Database.from_materials_project. It interfaces directly with the mp_api.client.MPRester object to make queries and pull data locally. As of Lightshow 1.0.0, this interfaces directly with the Materials Project v2 API and is a simple passthrough. You should type something like mpr.materials.summary.search? (check its docstring) for the options you can pass directly through to Database.from_materials_project.

  1. Directly pull a list of Materials Project IDs

    database = Database.from_materials_project(
        material_ids=["mp-390"],
        api_key=API_KEY
    )
    
  2. Use the wildcard/patterns syntax to pull larger databases matching certain patterns. For example, to pull all binary and ternary Ti-O structures,

    database = Database.from_materials_project(
         chemsys=["Ti-O", "Ti-O-*"],
         api_key=API_KEY
     )
    

Note

While the Pymatgen API Key can be provided manually during the use of from_materials_project, we highly recommend setting it in the environment variable MP_API_KEY. If api_key in the above arguments is not provided or is set to None, Lightshow will check for this environment variable and use it instead.

Once the database has been built, three properties are accessible:

  1. database.structures is a dictionary of Materials Project IDs (MPIDS) as keys and the Structure as values.

  2. database.metadata is a dictionary of MPIDs as keys and dictionaries containing metadata as values.

  3. database.errors is a dictionary containing any errors logged during the usage of the Database object.

Note

We fully document all “public” functions, classes and methods. Documentation can be easily accessed through the Lightshow API reference (see the sidebar) or by doing e.g. Database.from_materials_project? in a Jupyter Notebook or iPython instance.

Databases from disk

It is also possible to construct the Database from data on disk. This method will not fill the metadata property, though, which might force Lightshow to rely on default parameter values for certain types of input files.

database = Database.from_files(
    root="search/here/for/files",
    filename="CONTCAR"
)

The code above will look recursively in the provided directory for files matching the filename argument, and will attempt to read those into a Structure object via Pymatgen’s Structure.from_file classmethod. The keys to the database.structures property will be the path to the parent directory containing the structure file instead of the MPID.

Input Parameters

Our primary common abstraction is that of the spectroscopy simulation parameters. These control every aspect of the input files to be written and are specific to each type of code. However, while all options are exposed for the user, sensible defaults are also provided, making it straightforward to get started. Currently, we provide support for 5 different codes: FEFF, VASP, EXCITING, OCEAN and Xspectra.

You can begin by importing the simulation code-specific parameter objects,

from lightshow import (
    FEFFParameters,
    VASPParameters,
    OCEANParameters,
    XSpectraParameters,
    EXCITINGParameters
)

which we will go over one-by-one.

FEFF

Note

See here for the FEFF9 documentation.

There are three primary arguments for the FEFFParameters object: the cards, edge and radius. For example,

feff_params = FEFFParameters(
    cards={
        "S02": "0",
        "COREHOLE": "RPA",
        "CONTROL": "1 1 1 1 1 1",
        "XANES": "4 0.04 0.1",
        "SCF": "7.0 0 100 0.2 3",
        "FMS": "9.0 0",
        "EXCHANGE": "0 0.0 0.0 2",
        "RPATH": "-1"
    },
    edge="K",
    radius=10.0
)

cards is a catch-all input which is written directly to the preamble of the feff.inp file. Essentially, any parameter can be provided here, and should be provided as strings (both keys and values). A complete list of allowed “control cards” can be found on page 69 of the FEFF9 documentation. Note that certain cards, while required, are not directly passed using cards above. For example, the POTENTIALS card is automatically written.

edge determines the x-ray absorption edge of the calculation. Particulars are noted on page 89 of the FEFF9 documentation.

Warning

According to the FEFF9 documentation, M-shells or higher are not well tested. Lightshow will provide a warning if the user sets these edges.

radius is a critical parameter that sets the cluster size. For each absorbing atom, a radius of radius Å is taken around that absorbing atom, a supercell is appropriately constructed, and then truncated such that the only atoms contained in the feff.inp file are at most radius Å away from the absorber. Note that in this sense, radius controls much of the computational expense of the FEFF calculation.

The remainder of the feff.inp file is constructed automatically, and to some degree leverages Pymatgen’s FEFF IO module.

VASP

The added complexity of the VASP input files necessitates slightly more complicated syntax on the side of Lightshow. During any VASP run, there are four objects that are required in the working directory before running the VASP executable: INCAR, KPONTS, POTCAR and POSCAR, representing the general input file parameters, k-points parameters, pseudopotential files, and structure files, respectively.

Note

The VASP documentation can be found here.

The general VASPParameter object structure looks something like this:

vasp_parameters = VASPParameters(
    incar=...,
    edge="K",
    potcar_directory=None
)

where for now we have suppressed some sensible defaults which are discussed later. The primary information required to instantiate the lightshow.parameters.vasp.VASPParameters object are the incar, edge, and potcar_directory arguments.

INCAR sets the parameters for the INCAR input file. It can either take a Python dictionary, or lightshow.parameters.vasp.Incar object. The only parameter that can be overwritten is incar["NBANDS"]. If this INCAR parameter is None, Lightshow will attempt to use a default method to estimate a good number of bands for the VASP calculation. This is discussed more in Customize the number of bands below. We provide sensible defaults for the INCAR files in lightshow.parameters.vasp.

edge sets the x-ray absorption edge. See FEFF.

Pseudopotentials

potcar_directory points Lightshow to a directory containing VASP pseudopotential files. The handling of these files can be confusing, hence we outline how Lightshow handles them here in detail.

Warning

VASP POTCAR (potential) files are under the VASP license and thus are not included in Lightshow. In order to use VASP and the potential files, you must have a VASP license. See the VASP Website for more details.

The lightshow.parameters.vasp.PotcarConstructor handles creating the POTCAR file when writing the input files. The default parameters of this object can be overwritten through various other arguments in lightshow.parameters.vasp.VASPParameters, but the defaults are recommended.

Tip

If potcar_directory is None, Lightshow will attempt to read this from an environment variable VASP_POTCAR_DIRECTORY.

The directory that potcar_directory points to should contain files of the form of the values in lightshow.parameters.vasp.VASP_POTCAR_DEFAULT_ELEMENT_MAPPING. Specific values for these mappings, which map element types to specific potential files in the directory provided, can be overwritten by setting potcar_element_mapping. These provided values will only override the keys provided.

OCEAN

Note

See here for the OCEAN documentation.

There are three required primary arguments for the OCEANParameters object: the cards and edge. For example, the general OCEANParameter object structure looks something like this:

ocean_params = OCEANParameters(
    cards={
        'dft': 'qe',
        'ecut': '-1',
        'opf.program': 'hamann',
        'para_prefix': 'mpirun -np 24'
    }
    edge="K",
)

cards is a catch-all input which is written directly to the preamble of the ocean.in file. Essentially, any parameter can be provided here, and should be provided as strings (both keys and values). Here, we provided a minimal default parameters to run OCEAN the latest versions in which an installation of the pesudo potential database is required. The users are not resticted to this version of OCEAN, but they need to take care of the associated files, such as pseudo potentials, by themselves. dft parameter determines the code to run the DFT calcualtion. It can be either qe (for Quantum Espresso) or abinit. We set qe as the default, but again this is not restricted and users can switch to abinit if they prefer. Similar case also applies to other parameters, such as para_prefix, which is highly dependent on the users’ computing resources.

edge sets the x-ray absorption edge. See FEFF. If the input value for edge is not supported by OCEAN, LightShow will raise an ValueError.

EXCITING

Note

See here for the EXCITING documentation.

There are three required primary arguments for the EXCITINGParameters object: the cards, species_directory and edge. For example, the general EXCITINGParameter object structure looks something like this:

exciting_params = EXCITINGParameters(
    cards={
            "structure": {"speciespath": "./", "autormt": "true"},
            "groundstate": {
                "xctype": "GGA_PBE",
                "nempty": "200",
                "rgkmax": "9.0",
                "do": "fromscratch",
                "gmaxvr": "25",
                "lmaxmat": "10",
                "lmaxvr": "10",
                "lmaxapw": "10",
            },
            "xs": {
                "xstype": "BSE",
                "vkloff": "0.05 0.03 0.13",
                "nempty": "150",
                "gqmax": 4.0,
                "broad": "0.0327069",
                "tevout": "true",
                "tappinfo": "true",
                "energywindow": {"intv": "178.2 180.5", "points": "1000"},
                "screening": {"screentype": "full", "nempty": "150"},
                "BSE": {
                    "xas": "true",
                    "bsetype": "singlet",
                    "nstlxas": "1 20",
                    "distribute": "true",
                    "eecs": "1000",
                },
                "qpointset": {"qpoint": {"text()": "0.0 0.0 0.0"}},
            },

    },
    species_directory = 'this/is/not/a/directory'
    edge="K",
)

cards is a catch-all input which is written directly to the preamble of the input.xml file. Essentially, any parameter can be provided here, and should be provided as strings (both keys and values). Note that certain cards, while required, are not directly passed using cards above. An example is the species_directory discussed below.

species_directory lets the user to specify where the species files are located. The species files, which are in xml format, contain the lapw and lo information for each element. Usually, one can find these files in the exciting souce code under the species directory. The detailed description of the species files can be found here <http://exciting.wikidot.com/ref:species>. If species_directory is not set, a warning will show up indicating the users should copy the corresponding species files to the working directory, e.g. where the input.xml file is generated.

edge sets the x-ray absorption edge. See FEFF.

XSpectra

Note

See here for the XSpectra documentation.

The required primary arguments for the XSpectraParameters object are the cards and edge. For example, the general XSpectraParameter object structure looks something like this:

xspectra_params = XSpectraParameters(
     cards={'QE': {'control': {'restart_mode': 'from_scratch'},
                   'electrons': {'conv_thr': 1e-08, 'mixing_beta': 0.4},
                   'system': {'degauss': 0.002, 'ecutrho': 320, 'ecutwfc': 40,
                              'nspin': 1, 'occupations': 'smearing', 'smearing': 'gauss'}
           },
            'XS': {'cut_occ': {'cut_desmooth': 0.3},
                   'input_xspectra': {'outdir': '../',
                   'prefix': 'pwscf',
                   'xcheck_conv': 200,
                   'xerror': 0.01,
                   'xniter': 5000,
                   'xcoordcrys': '.false.'},
                   'kpts': {'kpts': '2 2 2', 'shift': '0 0 0'},
                   'plot': {'cut_occ_states': '.true.',
                   'terminator': '.true.',
                   'xemax': 70,
                   'xemin': -15.0,
                   'xnepoint': 400}
           }
     }
     edge="K",
)

cards is a catch-all input which is written directly to the preamble of the necessary input files for xspectra such as es..in, gs.in, xanes.in. Notice three are actually two parts of the calculations for run the xspectra calculation: 1) Quantum Espresso SCF calculation (es.in) and 2) XSpectra calcualtion (xanes.in). cards['QE'] governs the parameters for Quantum Espresso calcalcutions. And cards['XS'] governs the parameters for XANES calculations. Essentially, any parameter can be provided here for Quantum Espresso calculations using cards['QE'], and should be provided as strings (both keys and values). But the keys for cards['XS'] are relatively fixed. If you introduce new keys, they will be ignored. Some parameters, such as, cards['kpts']['kpts'] will be overwritten during the writing process.

edge sets the x-ray absorption edge. See FEFF.

Neutral Pseudopotentials

Currently, the code can handle three cases when dealing with neutral pseudo potentials.

  1. psp_directory is not given or psp_cutoff_table is not given The code will use placeholders like Ti.upf and O.upf to put into the input files. In this case, the users need to take care of the pseudo potential files by themselves, such as the correct pseudo potential filename and locations, and the correpsonding cutoff energy.

  2. psp_directory is given and the corresponding pseudo potentials are inside the psp_directory

    Warning

    psp_cutoff_table should _always_ be provided in this case. The cutoff table should have silimar structures as the on for SSSP pseudo potential database, which looks like:

    cutoff_table = {
        'Ag': {
            'filename': 'Ag.upf',
            'cutoff_wfc': 50.0,
            'cutoff_rho': 200.0
        },
    }
    

    It can also contain some other keys, but the element name, cutoff_wfc, cutoff_rho should always be in the keys. Lightshow will find the corresponding pseudo potential files and copy it to the working directory. It will also set the correct pseudo potential filename and recommended cutoff energy automatically.

  3. psp_directory is given and the corresponding pseudo potentials are not include the psp_directory

    Warning

    psp_cutoff_table should _always_ be provided in this case. The structure is the same as the one discussed above.

    In this case, we offer a method (lightshow.parameters.xspectra.XSpectraParameters.packPsps) to condense all the pseudo potential files into a single json file. The code will recover all the necessary pseudo potential files from the json file without copying the pseudo potential file from the psp_directory folder to the working directory. The performance of using the json file to recover pseudo potential files is better, especially for high throughput calcualtions. If user want to use this feature, they need to delete all the pseudo potential files in the psp_directory, e.g. only psp_cutoff_table and psp_json should be present in the psp_directory.

Core-hole Pseudopotentials

Lightshow will copy the corresponding core-hole pseudo potential as well as the core wave function in chpsp_directory to the working directory. The naming of the potential and wave function is strict: element.fch.upf and Core_element.wfc. The users need to generate these two files by themselves.

Advanced

Customize k-points

Due to the number of computational spectroscopy packages that require it, Lightshow offers a common way of defining the structure of the k-points grid as a function of the structure itself.

The abstraction is derived from the base class lightshow.common.kpoints._BaseKpointsMethod. Such a class requires a __call__ dunder method that takes as input the Pymatgen Structure and returns a tuple containing the k-points density along the x, y and z axes.

Customize the number of bands

A similar abstraction to the methods used for determining the k-points grids is used for determining the number of bands required for a calculation. Instead of __call__ returning a tuple, it returns an integer for the number of conduction bands to use in the calculation. Such objects inherit from lightshow.common.nbands._BaseNbandsMethod.

Note

As with everything else in Lightshow, we provide sensible defaults to the user when using any of the parameter objects.