multishifter

Logo

casm powered utility to create gamma surfaces, UBER curves, and twisted bilayers along crystal planes.

View the Project on GitHub goirijo/multishifter

\( $$\newcommand{\AA}{\unicode{x212B}} \AA$$ \)

Tutorial VII: Fourier interpolation

In this tutorial we’ll use multishift fourier to get analytical expressions for the calculated values of the shift tutorial.

Collecting data

The input format for the data is the same as the record.json that gets generated when you run cleave, shift, or chain. In the shift tutorial, we learned how to enumerate shifted structures, and looked at the symmetry for the basal plane of \(\mathrm{Mg}\) on a \(12\times 12\) grid. After this step, the structures (remember that knowing the symmetry, you only need to calculate a subset of them!), get put through DFT caclulations. You can download the results of calculations done with VASP here.

We now have 144 energy values for our \(\gamma\)-surface, one for each of the \(12\times 12\) gridpoints. We’re going to smoothen these out to an arbitrary resolution with multishift fourier. In order to do this, we need to modify the report.json file that got generated during the shift command. Each generated structure has it’s own entry in the file under the “ids” key. Each entry has a series of values, which we will supplement with the energy values, using “dft_energy” as a key. Below is a truncated version of the original report.json:

{
    "cleavages": [ "..." ],
    "equivalents": [[ "..." ]],
    "grid": [
        12,
        12
    ],
    "ids": {
        "0:0:0.000000": {
            "cleavage": 0.0,
            "directory": "shift__0.0",
            "equivalent_structures": [
                "0:0:0.000000"
            ],
            "grid_point": [
                0,
                0
            ],
            "orbit": 0,
            "shift": [
                0.0,
                0.0
            ]
        },
        "..." : {"..."},
        "9:9:0.000000": {
            "cleavage": 0.0,
            "directory": "shift__9.9",
            "equivalent_structures": [
                "6:9:0.000000",
                "9:6:0.000000",
                "9:9:0.000000"
            ],
            "grid_point": [
                9,
                9
            ],
            "orbit": 27,
            "shift": [
                3.591212709318049,
                2.0733876166740566
            ]
        }
    },
    "shift_units": [[ "..." ]]
}

After you insert the energy entries, it will look like this (note the new “dft_energy” entry):

{
    "cleavages": [ "..." ],
    "equivalents": [[ "..." ]],
    "grid": [
        12,
        12
    ],
    "ids": {
        "0:0:0.000000": {
            "cleavage": 0.0,
            "directory": "shift__0.0",
            "equivalent_structures": [
                "0:0:0.000000"
            ],
            "grid_point": [
                0,
                0
            ],
            "orbit": 0,
            "shift": [
                0.0,
                0.0
            ],
            "dft_energy": -12.771096
        },
        "..." : {"..."},
        "9:9:0.000000": {
            "cleavage": 0.0,
            "directory": "shift__9.9",
            "equivalent_structures": [
                "6:9:0.000000",
                "9:6:0.000000",
                "9:9:0.000000"
            ],
            "grid_point": [
                9,
                9
            ],
            "orbit": 27,
            "shift": [
                3.591212709318049,
                2.0733876166740566
            ],
            "dft_energy": -12.724973
        }
    },
    "shift_units": [[ "..." ]]
}

Fill the all the values in a copy of your report.json, and name the file modified_record.json. The structure of report.json should make this straightforward, as is being done with this script. You can also download the complete modified record here.

Interpolate your data

We’re ready to do our interpolation now:

multishift fourier --data modified_record.json --key "dft_energy"

You’ll see a large function being printed to the screen. This is the analytical expression of the \(\gamma\)-surface, which you can plot directly in python. For interpolations of only real values, the “Imaginary functions” values should always be exactly zero. A simple surface plot of the analytical expression is shown below.

Cleavage slices

If you’ve run the chain command, then the record.json file will have entries for the same shift at different cleavage values. The interpolation can only work for one value per grid point, so you must select a “slice” of the data, where all the grid points have consistend cleavage values. This is done with the --cleavage-slice flag:

multishift fourier --data modified_record.json --key "dft_energy" --cleavage-slice 0.0

The command above will take all the data with cleavage values equal to 0.0.

Basis crushing

You can “crush” the basis functions whose coefficients fall below a certain threshold By providing a magnitude to the --crush flag Any basis function whose coefficient magninude is small enough will be dropped from the formula.