コード例 #1
0
ファイル: submit_pw_post.py プロジェクト: tflovorn/tmd
def _main():
    parser = argparse.ArgumentParser("Run postprocessing to set up Wannier90 calculation",
            formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument("--subdir", type=str, default=None,
            help="Subdirectory under work_base to run calculation")
    parser.add_argument("--global_prefix", type=str, default="MoS2_WS2",
            help="Prefix for calculation")
    args = parser.parse_args()

    gconf = global_config()
    base_path = os.path.expandvars(gconf["work_base"])
    if args.subdir is not None:
        base_path = os.path.join(base_path, args.subdir)

    if "qe_bands" in gconf:
        qe_bands_dir = os.path.expandvars(gconf["qe_bands"])
        qe_bands_path = os.path.join(qe_bands_dir, "bands.x")
    else:
        qe_bands_path = "bands.x"

    calc = "pw_post"
    prefix_groups = get_prefix_groups(base_path, args.global_prefix)

    config = {"machine": "ls5", "cores": 24, "nodes": 1, "queue": "normal",
            "hours": 8, "minutes": 0, "wannier": True, "project": "A-ph9",
            "global_prefix": args.global_prefix, "max_jobs": 24,
            "qe_bands": qe_bands_path}

    submit_dgrid_pw_post(base_path, config, prefix_groups)
コード例 #2
0
def _main():
    parser = ArgumentParser("wfc cleanup")
    parser.add_argument(
        "--subdir",
        type=str,
        default=None,
        help="Subdirectory under work_base where calculation was run")
    parser.add_argument(
        'global_prefix',
        type=str,
        help="System for which wannier/ .save directories will be removed")
    parser.add_argument(
        '--confirm',
        action='store_true',
        help="Must specify --confirm to confirm .save removal is desired")
    args = parser.parse_args()

    if not args.confirm:
        return

    gconf = global_config()
    work = os.path.expandvars(gconf["work_base"])
    if args.subdir is not None:
        work = os.path.join(work, args.subdir)

    prefixes = get_prefixes(work, args.global_prefix)

    for prefix in prefixes:
        save_path = os.path.join(work, prefix, "wannier",
                                 "{}.save".format(prefix))
        shutil.rmtree(save_path)
コード例 #3
0
ファイル: plot_ds.py プロジェクト: tflovorn/tmd
def _main():
    parser = argparse.ArgumentParser(
        description="Plot various quantities as function of displacement")
    parser.add_argument(
        "--subdir",
        type=str,
        default=None,
        help="Subdirectory under work_base where calculation was run")
    parser.add_argument('--global_prefix',
                        type=str,
                        default="MoS2_WS2",
                        help="Calculation global prefix")
    args = parser.parse_args()

    gconf = global_config()
    work = os.path.expandvars(gconf["work_base"])
    if args.subdir is not None:
        work = os.path.join(work, args.subdir)

    prefixes = get_prefixes(work, args.global_prefix)
    ds = ds_from_prefixes(prefixes)

    ds, prefixes = wrap_cell(ds, prefixes)
    dps = sorted_d_group(ds, prefixes)

    write_out_data = {"_ds": []}
    for d, prefix in dps:
        write_out_data["_ds"].append(d)

    energies = get_energies(work, dps)
    energies_rel_meV = energies_relative_to(energies, dps, (0.0, 0.0))

    E_title = "$\\Delta E$ [meV]"
    E_plot_name = "{}_energies".format(args.global_prefix)
    plot_d_vals(E_plot_name, E_title, dps, energies_rel_meV)
    write_out_data["meV_relative_total_energy"] = energies_rel_meV

    soc = True
    Hk_vals = extract_Hk_vals(work, dps, soc)

    for label, this_vals in Hk_vals.items():
        title = label
        plot_name = "{}_{}".format(args.global_prefix, label)
        plot_d_vals(plot_name, title, dps, this_vals)
        write_out_data["eV_{}".format(label)] = this_vals

    na, nb = 16, 16
    num_dos = 1000
    E_below_fermi, E_above_fermi = 3.0, 3.0
    gaps = find_gaps(work, dps, E_below_fermi, E_above_fermi, num_dos, na, nb)

    gap_plot_title = "Gaps [eV]"
    gap_plot_name = "{}_gaps".format(args.global_prefix)
    plot_d_vals(gap_plot_name, gap_plot_title, dps, gaps)
    write_out_data["eV_overall_gap"] = gaps

    with open("{}_plot_ds_data.json".format(args.global_prefix), 'w') as fp:
        json.dump(write_out_data, fp)
コード例 #4
0
def H_klat_Glat(dps, kGs):
    '''Integrate by trapezoid method.
    Lazy way to compute: for each region, compute each Hk at boundaries.
    Avoid point storage scheme and possible high memory use
    at cost of 4x runtime.

    Trapezoid rule in 2D:
    \int_{x1, x2} dx \int_{y1, y2} dy f(x,y) = (1/4)*(x2-x1)(y2-y1)
      * (f(x1, y1) + f(x1, y2) + f(x2, y1) + f(x2, y2))

    To avoid repeated unecessary loads of Hrs, and to avoid keeping all
    Hrs in memory, compute integral values for each (k, G) pair
    simultaneously.
    '''
    gconf = global_config()
    work = os.path.expandvars(gconf["work_base"])
    ds = []
    for d, prefix in dps:
        ds.append(d)

    d_boundary_indices, delta_a, delta_b = trapezoid_d_regions(ds)

    # Calculate integral over each region individually.
    # region_integral_vals is a list (with indices corresponding to regions)
    # whose elements are dicts {(k, G): region_integral_val, ...}
    rint_args = []
    for region_indices in d_boundary_indices:
        rint_args.append([region_indices, delta_a, delta_b, kGs, work, dps])

    with Pool() as p:
        region_integral_vals = p.starmap(region_integral, rint_args)

    # Collect region integrals into totals.
    integral_totals = []
    for kG_i in range(len(kGs)):
        integral_totals.append(None)

    for region_list in region_integral_vals:
        for kG_index, kG_val in enumerate(region_list):
            if integral_totals[kG_index] is None:
                integral_totals[kG_index] = kG_val
            else:
                integral_totals[kG_index] += kG_val

    return integral_totals
コード例 #5
0
ファイル: plotBands.py プロジェクト: tflovorn/tmd
def _main():
    parser = argparse.ArgumentParser(
        description="Plot TMD band structure result",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument(
        "--subdir",
        type=str,
        default=None,
        help="Subdirectory under work_base where calculation was run")
    parser.add_argument("--global_prefix",
                        type=str,
                        default="MoS2_WS2",
                        help="Calculation global prefix")
    parser.add_argument("--prefix",
                        type=str,
                        default=None,
                        help="If specified, plot bands for one prefix only")
    parser.add_argument("--plot_evecs",
                        action='store_true',
                        help="Plot eigenvector components")
    parser.add_argument("--minE",
                        type=float,
                        default=None,
                        help="Minimum energy to plot (not relative to E_F)")
    parser.add_argument("--maxE",
                        type=float,
                        default=None,
                        help="Maximum energy to plot (not relative to E_F)")
    args = parser.parse_args()

    gconf = global_config()
    work = os.path.expandvars(gconf["work_base"])
    if args.subdir is not None:
        work = os.path.join(work, args.subdir)

    if args.prefix is None:
        prefixes = get_prefixes(work, args.global_prefix)

        for prefix in prefixes:
            make_plot(work, prefix, args.plot_evecs, args.minE, args.maxE)
    else:
        make_plot(work, args.prefix, args.plot_evecs, args.minE, args.maxE)
コード例 #6
0
ファイル: moire.py プロジェクト: tflovorn/tmd
def _main():
    parser = argparse.ArgumentParser("Moire band structure")
    parser.add_argument(
        "--subdir",
        type=str,
        default=None,
        help="Subdirectory under work_base where calculation was run")
    parser.add_argument("--global_prefix",
                        type=str,
                        default="MoS2_WS2",
                        help="Prefix for calculation")
    args = parser.parse_args()

    gconf = global_config()
    work = os.path.expandvars(gconf["work_base"])
    if args.subdir is not None:
        work = os.path.join(work, args.subdir)

    prefixes = get_prefixes(work, args.global_prefix)
    ds = ds_from_prefixes(prefixes)
    ds, prefixes = wrap_cell(ds, prefixes)
    dps = sorted_d_group(ds, prefixes)

    scf_0_path = os.path.join(work, prefixes[0], "wannier", "scf.out")
    D = D_from_scf(scf_0_path)
    D_2D = D[0:2, 0:2]

    kpoints = [(0, 0), (1 / 2, 0), (1 / 3, 1 / 3), (0, 0)]
    ks_per_interval = 10
    ktildes = make_kpath(kpoints, ks_per_interval)
    #ktildes = [(1/3, 1/3, 0)]

    epsilon = 1 / 2
    theta = 0.0
    Gcut = 2
    Gcut_cart = False

    Hk_moires = moire_Hamiltonian(dps, ktildes, D_2D, epsilon, theta, Gcut,
                                  Gcut_cart)

    plot_Hk_moire(Hk_moires)
コード例 #7
0
ファイル: optical.py プロジェクト: tflovorn/tmd
def _main():
    parser = argparse.ArgumentParser(
        "Calculate optical matrix elements",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument(
        "--subdir",
        type=str,
        default=None,
        help="Subdirectory under work_base where calculation was run")
    parser.add_argument('global_prefix', type=str, help="Calculation name")
    args = parser.parse_args()

    gconf = global_config()
    work = os.path.expandvars(gconf["work_base"])
    if args.subdir is not None:
        work = os.path.join(work, args.subdir)

    prefixes = get_prefixes(work, args.global_prefix)
    ds = ds_from_prefixes(prefixes)
    ds, prefixes = wrap_cell(ds, prefixes)
    dps = sorted_d_group(ds, prefixes)

    write_optical_data(work, dps)
コード例 #8
0
def _main():
    parser = argparse.ArgumentParser("Analysis of H(k) symmetry")
    parser.add_argument(
        "--subdir",
        type=str,
        default=None,
        help="Subdirectory under work_base where calculation was run")
    parser.add_argument("--global_prefix",
                        type=str,
                        default="MoS2_WS2",
                        help="Prefix for calculation")
    args = parser.parse_args()

    gconf = global_config()
    work = os.path.expandvars(gconf["work_base"])
    if args.subdir is not None:
        work = os.path.join(work, args.subdir)

    prefixes = get_prefixes(work, args.global_prefix)
    ds = ds_from_prefixes(prefixes)

    ds, prefixes = wrap_cell(ds, prefixes)
    dps = sorted_d_group(ds, prefixes)

    ordering = "2H"

    if ordering == "2H":
        d0_prefix = find_d_val(dps, (2 / 3, 1 / 3))
        d1_prefix = find_d_val(dps, (0.0, 0.0))
        d2_prefix = find_d_val(dps, (1 / 3, 2 / 3))
    elif ordering == "2H_top":
        d0_prefix = find_d_val(dps, (0.0, 0.0))
        d1_prefix = find_d_val(dps, (1 / 3, 2 / 3))
        d2_prefix = find_d_val(dps, (2 / 3, 1 / 3))
    else:
        raise ValueError("unrecognized ordering")

    Ks = (("K0", (1 / 3, 1 / 3, 0.0)), ("K1", (-2 / 3, 1 / 3, 0.0)),
          ("K2", (1 / 3, -2 / 3, 0.0)))

    for i_d, prefix in enumerate((d0_prefix, d1_prefix, d2_prefix)):
        Hr = get_Hr(work, prefix)

        # H(R = 0)
        H0 = Hr[(0, 0, 0)][0] / Hr[(0, 0, 0)][1]
        H0_vals = get_H_orbital_vals(H0, work, prefix)

        # H(K)
        Hk_vals = {}
        for K_label, K in Ks:
            HK = Hk_recip(K, Hr)
            Hk_vals[K_label] = get_H_orbital_vals(HK, work, prefix)

        print("i_d = {}, prefix = {}".format(str(i_d), prefix))
        print("H(r = 0, 0, 0)[+,+] = {}".format(str(H0_vals["dp2_M_dp2_Mp"])))
        print("H(r = 0, 0, 0)[-,-] = {}".format(str(H0_vals["dm2_M_dm2_Mp"])))
        print("H(r = 0, 0, 0)[+,-] = {}".format(str(H0_vals["dp2_M_dm2_Mp"])))
        print("H(r = 0, 0, 0)[-,+] = {}".format(str(H0_vals["dm2_M_dp2_Mp"])))
        print("H(r = 0, 0, 0)[z2,z2] = {}".format(str(
            H0_vals["dz2_M_dz2_Mp"])))

        for K_label, K in Ks:
            print("------------")
            print("<d_+2^M|H({})|d_+2^M'> = {}".format(
                K_label, str(Hk_vals[K_label]["dp2_M_dp2_Mp"])))
            print("<d_-2^M|H({})|d_-2^M'> = {}".format(
                K_label, str(Hk_vals[K_label]["dm2_M_dm2_Mp"])))
            print("<d_+2^M|H({})|d_-2^M'> = {}".format(
                K_label, str(Hk_vals[K_label]["dp2_M_dm2_Mp"])))
            print("<d_-2^M|H({})|d_+2^M'> = {}".format(
                K_label, str(Hk_vals[K_label]["dm2_M_dp2_Mp"])))
            print("<d_z2^M|H({})|d_z2^M'> = {}".format(
                K_label, str(Hk_vals[K_label]["dz2_M_dz2_Mp"])))

        print("===================")
コード例 #9
0
ファイル: gap.py プロジェクト: tflovorn/tmd
def _main():
    parser = argparse.ArgumentParser(
        "Calculation of gaps",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument(
        "--subdir",
        type=str,
        default=None,
        help="Subdirectory under work_base where calculation was run")
    parser.add_argument(
        "--threshold",
        type=float,
        default=0.9,
        help="Threshold for deciding if a state is dominated by one layer")
    parser.add_argument(
        "--spin_valence",
        type=str,
        default=None,
        help=
        "Set 'up' or 'down' to choose valence band spin type; closest to E_F is used if not set"
    )
    parser.add_argument(
        "--spin_conduction",
        type=str,
        default=None,
        help=
        "Set 'up' or 'down' to choose conduction band spin type; closest to E_F is used if not set"
    )
    parser.add_argument(
        "--use_QE_evs",
        action='store_true',
        help=
        "Use eigenvalues from QE instead of Wannier H(k); if set, spin_valence and spin_conduction act as if not specified."
    )
    parser.add_argument(
        "--ev_width",
        type=int,
        default=8,
        help="Number of characters per eigenvalue in QE bands.dat")
    parser.add_argument('global_prefix', type=str, help="Calculation name")
    args = parser.parse_args()

    gconf = global_config()
    work = os.path.expandvars(gconf["work_base"])
    if args.subdir is not None:
        work = os.path.join(work, args.subdir)

    prefixes = get_prefixes(work, args.global_prefix)
    ds = ds_from_prefixes(prefixes)
    ds, prefixes = wrap_cell(ds, prefixes)
    dps = sorted_d_group(ds, prefixes)

    K = (1 / 3, 1 / 3, 0.0)
    Gamma = (0.0, 0.0, 0.0)
    do_get_curvature_K, do_get_curvature_Gamma = True, False

    write_gap_data(work, dps, args.threshold, args.spin_valence,
                   args.spin_conduction, args.use_QE_evs, args.ev_width, K,
                   "K", "$K$", do_get_curvature_K)
    write_gap_data(work, dps, args.threshold, args.spin_valence,
                   args.spin_conduction, args.use_QE_evs, args.ev_width, Gamma,
                   "Gamma", "$\\Gamma$", do_get_curvature_Gamma)
コード例 #10
0
def _main():
    parser = argparse.ArgumentParser("Fourier components")
    parser.add_argument(
        "--subdir",
        type=str,
        default=None,
        help="Subdirectory under work_base where calculation was run")
    parser.add_argument("--global_prefix",
                        type=str,
                        default="MoS2_WS2",
                        help="Prefix for calculation")
    args = parser.parse_args()

    gconf = global_config()
    work = os.path.expandvars(gconf["work_base"])
    if args.subdir is not None:
        work = os.path.join(work, args.subdir)

    soc = False
    prefixes = get_prefixes(work, args.global_prefix)
    ds = ds_from_prefixes(prefixes)
    ds, prefixes = wrap_cell(ds, prefixes)
    dps = sorted_d_group(ds, prefixes)

    # Verify all Hr_orders are the same;
    # after this, assume order is the same for all ds.
    verify_Hr_orders_identical(work, prefixes)
    atom_Hr_order = get_atom_order(work, prefixes[0])

    orb_type = ("X2", "pz", "up", "X1p", "pz", "up")
    i_sym, i_orbital, i_spin = orb_type[0], orb_type[1], orb_type[2]
    j_sym, j_orbital, j_spin = orb_type[3], orb_type[4], orb_type[5]
    i_index = orbital_index(atom_Hr_order, i_sym, i_orbital, i_spin, soc)
    j_index = orbital_index(atom_Hr_order, j_sym, j_orbital, j_spin, soc)

    Gs = []
    num_Ga, num_Gb = 5, 5
    for Ga in range(num_Ga):
        for Gb in range(num_Gb):
            G = (Ga, Gb)
            Gs.append(G)

    ks = [(1 / 3, 1 / 3, 0)]
    kGs = list(itertools.product(ks, Gs))

    all_H_vals = H_klat_Glat(dps, kGs)

    Gas, Gbs = [], []
    H_K_re_vals, H_K_im_vals = [], []
    for kG_index, val in enumerate(all_H_vals):
        k, G = kGs[kG_index]
        # Only one k used.
        # TODO - check k?
        H_K_re_vals.append(val[i_index, j_index].real)
        H_K_im_vals.append(val[i_index, j_index].imag)
        Gas.append(float(G[0]))
        Gbs.append(float(G[1]))

    plt.scatter(Gas,
                Gbs,
                c=H_K_re_vals,
                cmap='viridis',
                s=50,
                edgecolors="none")
    plt.colorbar()

    plt.savefig("G_K_re.png", bbox_inches='tight', dpi=500)
    plt.clf()

    plt.scatter(Gas,
                Gbs,
                c=H_K_im_vals,
                cmap='viridis',
                s=50,
                edgecolors="none")
    plt.colorbar()

    plt.savefig("G_K_im.png", bbox_inches='tight', dpi=500)
    plt.clf()
コード例 #11
0
def _main():
    parser = argparse.ArgumentParser(
        "Build and run calculation on grid of d's",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument("--run",
                        action="store_true",
                        help="Run calculation after making inputs")
    parser.add_argument("--subdir",
                        type=str,
                        default=None,
                        help="Subdirectory under work_base to run calculation")
    parser.add_argument("--symA",
                        type=str,
                        default="MoS2",
                        help="Atomic composition of bottom layer")
    parser.add_argument("--symB",
                        type=str,
                        default="WS2",
                        help="Atomic composition of top layer")
    parser.add_argument("--monolayer",
                        action="store_true",
                        help="Use monolayer system instead of bilayer")
    parser.add_argument(
        "--ordering",
        type=str,
        default="2H",
        help="Ordering of atoms: '2H' -> BAB/ABA; '2H_top' -> BAB/BAB")
    parser.add_argument(
        "--c_sep",
        type=float,
        default=None,
        help=
        "Separation between layers (use value from bilayer of symA if not specified)"
    )
    parser.add_argument("--soc",
                        action="store_true",
                        help="Use spin-orbit coupling")
    parser.add_argument("--xc",
                        type=str,
                        default="lda",
                        help="Exchange-correlation functional (lda or pbe)")
    parser.add_argument("--num_d_a",
                        type=int,
                        default=3,
                        help="Number of d's (shifts) along the a-axis")
    parser.add_argument("--num_d_b",
                        type=int,
                        default=3,
                        help="Number of d's (shifts) along the b-axis")
    parser.add_argument("--pp",
                        type=str,
                        default="nc",
                        help="Pseudopotential type ('nc' or 'paw')")
    parser.add_argument(
        "--iprelax",
        action="store_true",
        help="Vary in-plane lattice constant to search for lowest energy")
    parser.add_argument("--bands_only",
                        action="store_true",
                        help="Run only scf and bands calc")
    args = parser.parse_args()

    symA, symB = args.symA, args.symB
    if args.monolayer:
        symB = None

    tmd_base = _base_dir()
    db_path = os.path.join(tmd_base, "c2dm.db")
    gconf = global_config()

    if not args.monolayer:
        c_bulk_values = {"MoS2": 12.296, "MoSe2": 12.939}
        c_bulk = c_bulk_values[symA]
    else:
        c_bulk = None

    dgrid = dgrid_inputs(db_path,
                         symA,
                         symB,
                         c_bulk,
                         args.num_d_a,
                         args.num_d_b,
                         c_sep=args.c_sep,
                         soc=args.soc,
                         xc=args.xc,
                         ordering=args.ordering,
                         iprelax=args.iprelax,
                         pp=args.pp,
                         bands_only=args.bands_only)

    base_path = os.path.expandvars(gconf["work_base"])
    if args.subdir is not None:
        base_path = os.path.join(base_path, args.subdir)

    # Recompiled QE to increase precision in bands.dat output file.
    # (The hard-coded default is 3 decimal places (1 meV) which is too small
    # for gap variation on the scale of 10 meV).
    #
    # Starting with QE 5.4.0,
    # in PP/src/bands.f90 changed:
    # Line 470: 10f8.3 --> 10f13.8
    # Line 476: 10f8.3 --> 10f13.8
    #
    # To compile QE on LS5, need to specify mpich scalapack.
    # With module 'espresso/5.4.0' loaded, compile with:
    # ./configure SCALAPACK_LIBS="-lmkl_scalapack_lp64 -lmkl_blacs_intelmpi_lp64"
    # make pp
    if "qe_bands" in gconf:
        qe_bands_dir = os.path.expandvars(gconf["qe_bands"])
        qe_bands_path = os.path.join(qe_bands_dir, "bands.x")
    else:
        qe_bands_path = "bands.x"

    write_dgrid(base_path, dgrid)

    #config = {"machine": "__local__", "wannier": True}
    #config = {"machine": "__local__", "wannier": True, "__local_mpi_cmd__": "mpirun"}
    if symA is not None and symB is not None:
        global_prefix = "{}_{}".format(symA, symB)
    elif symB is None:
        global_prefix = symA
    elif symA is None:
        global_prefix = symB
    else:
        raise ValueError("symA and symB are None")

    num_nodes = 1
    num_cores = 24 * num_nodes
    config = {
        "machine": "ls5",
        "cores": num_cores,
        "nodes": num_nodes,
        "queue": "normal",
        "hours": 4,
        "minutes": 0,
        "wannier": True,
        "project": "A-ph9",
        "global_prefix": global_prefix,
        "max_jobs": 24,
        "outer_min": -10.0,
        "outer_max": 7.0,
        "inner_min": -8.0,
        "inner_max": 3.0,
        "subdir": args.subdir,
        "iprelax": args.iprelax,
        "bands_only": args.bands_only,
        "qe_bands": qe_bands_path
    }
    prefix_groups = write_dgrid_queuefiles(base_path, dgrid, config)

    if args.run:
        if not args.iprelax and not args.bands_only:
            calc_name = "wan_setup"
        else:
            calc_name = "bands_only"

        submit_dgrid_pw(base_path, config, prefix_groups, calc_name)