예제 #1
0
def get_pseudo_dir(soc, xc, pp):
    if pp == 'nc':
        if soc:
            if xc == 'lda':
                return os.path.join(_base_dir(), "pseudo", "lda_soc")
            else:
                return os.path.join(_base_dir(), "pseudo", "soc")
        else:
            if xc == 'lda':
                return os.path.join(_base_dir(), "pseudo", "lda_no_soc")
            else:
                return os.path.join(_base_dir(), "pseudo", "no_soc")
    elif pp == 'paw':
        if soc and xc == 'lda':
            return os.path.join(_base_dir(), "pseudo", "pslibrary_lda_soc_paw")
        else:
            raise ValueError("paw/non-soc not implemented")
예제 #2
0
    def test_qe_config(self):
        syms = ["WSe2", "WSe2", "WSe2"]
        soc = True
        vacuum_dist = 20.0  # Angstrom
        D = 0.5  # V/nm
        AB_stacking = True
        xc = 'lda'
        pp = 'nc'

        db_path = os.path.join(_base_dir(), "c2dm.db")
        db = ase.db.connect(db_path)
        c_sep = get_c_sep(db, syms[0])

        latvecs, at_syms, cartpos = make_cell(db, syms, c_sep, vacuum_dist,
                                              AB_stacking)
        system = Atoms(symbols=at_syms,
                       positions=cartpos,
                       cell=latvecs,
                       pbc=True)
        system.center(axis=2)

        wann_valence, num_wann = get_wann_valence(
            system.get_chemical_symbols(), soc)
        num_bands = get_num_bands(num_wann)

        qe_config = make_qe_config(system, D, soc, num_bands, xc, pp)
        #with open('test_build_qe_config_new.json', 'w') as fp:
        #    json.dump(qe_config, fp)

        with open('test_build_qe_config.json', 'r') as fp:
            qe_config_expected = json.load(fp)

        check_qe_config(self, qe_config, qe_config_expected, soc, xc, pp)

        prefix = 'test'
        qe_input = build_qe(system, prefix, 'scf', qe_config)
        #with open('test_build_qe_input_new', 'w') as fp:
        #    fp.write(qe_input)

        with open('test_build_qe_input', 'r') as fp:
            qe_input_expected = fp.read()

        check_qe_input(self, qe_input, qe_input_expected, soc, xc, pp)
예제 #3
0
    def test_cell_unshifted(self):
        syms_bilayer = ["WSe2", "WSe2"]
        syms_trilayer = ["WSe2", "WSe2", "WSe2"]
        vacuum_dist = 20.0  # Angstrom
        AB_stacking = True

        db_path = os.path.join(_base_dir(), "c2dm.db")
        db = ase.db.connect(db_path)

        for syms in [syms_bilayer, syms_trilayer]:
            c_sep = get_c_sep(db, syms[0])
            layer_systems = [get_layer_system(db, sym, 'H') for sym in syms]
            a = a_from_2H(layer_systems[0])
            hs = [h_from_2H(layer_system) for layer_system in layer_systems]

            for AB_stacking in [False, True]:
                # layer_shifts = None should be the same as specifying
                # a shift of (0.0, 0.0) for all layers.
                latvecs_None, at_syms_None, cartpos_None = make_cell(
                    db,
                    syms,
                    c_sep,
                    vacuum_dist,
                    AB_stacking=AB_stacking,
                    layer_shifts=None)

                shifts_zero = [(0.0, 0.0)] * len(syms)
                latvecs_zero, at_syms_zero, cartpos_zero = make_cell(
                    db,
                    syms,
                    c_sep,
                    vacuum_dist,
                    AB_stacking=AB_stacking,
                    layer_shifts=shifts_zero)

                self.assertTrue((latvecs_None == latvecs_zero).all())
                self.assertEqual(at_syms_None, at_syms_zero)

                for at_pos_None, at_pos_zero in zip(cartpos_None,
                                                    cartpos_zero):
                    assert ((at_pos_None == at_pos_zero).all())

                self.assertEqual(at_syms_zero, ["Se", "W", "Se"] * len(syms))

                # Should have the correct lattice constant.
                eps = 1e-12
                self.assertTrue(abs(np.linalg.norm(latvecs_None[0]) - a) < eps)
                self.assertTrue(abs(np.linalg.norm(latvecs_None[1]) - a) < eps)

                system = Atoms(symbols=at_syms_zero,
                               positions=cartpos_zero,
                               cell=latvecs_zero,
                               pbc=True)
                system.center(axis=2)

                A = (0.0, 0.0)
                B = (1 / 3, 2 / 3)

                latpos = system.get_scaled_positions()
                for layer_index in range(len(syms)):
                    # Atoms should have the correct in-plane positions.
                    layer_pos = latpos[3 * layer_index:3 * layer_index + 3]
                    if AB_stacking:
                        if layer_index % 2 == 0:
                            self.assertTrue(has_pos_seq(layer_pos, [A, B, A]))
                        else:
                            self.assertTrue(has_pos_seq(layer_pos, [B, A, B]))
                    else:
                        self.assertTrue(has_pos_seq(layer_pos, [A, B, A]))

                    # Atoms should have the correct vertical positions.
                    h = hs[layer_index]
                    layer_cartpos = cartpos_zero[3 *
                                                 layer_index:3 * layer_index +
                                                 3]
                    zs = [layer_cartpos[i][2] for i in range(3)]
                    self.assertTrue(abs(zs[2] - zs[0] - h) < eps)
                    self.assertTrue(abs(zs[2] - zs[1] - h / 2) < eps)

                    if layer_index != 0:
                        z_below = cartpos_zero[3 * layer_index - 1][2]
                        self.assertTrue(abs(zs[0] - z_below - c_sep) < eps)
예제 #4
0
    def test_cell_shifted(self):
        syms_bilayer = ["WSe2", "WSe2"]
        syms_trilayer = ["WSe2", "WSe2", "WSe2"]
        vacuum_dist = 20.0  # Angstrom
        AB_stacking = True

        db_path = os.path.join(_base_dir(), "c2dm.db")
        db = ase.db.connect(db_path)

        for syms in [syms_bilayer, syms_trilayer]:
            c_sep = get_c_sep(db, syms[0])

            shifts_zero = [(0.0, 0.0)] * len(syms)
            num_shifts_l2 = 3
            all_shifts_nonzero = make_layer_shifts(len(syms), num_shifts_l2)

            for AB_stacking in [False, True]:
                for layer_shifts in all_shifts_nonzero:
                    latvecs_zero, at_syms_zero, cartpos_zero = make_cell(
                        db,
                        syms,
                        c_sep,
                        vacuum_dist,
                        AB_stacking=AB_stacking,
                        layer_shifts=shifts_zero)
                    latvecs_shift, at_syms_shift, cartpos_shift = make_cell(
                        db,
                        syms,
                        c_sep,
                        vacuum_dist,
                        AB_stacking=AB_stacking,
                        layer_shifts=layer_shifts)

                    self.assertTrue((latvecs_zero == latvecs_shift).all())
                    self.assertEqual(at_syms_zero, at_syms_shift)

                    system_zero = Atoms(symbols=at_syms_zero,
                                        positions=cartpos_zero,
                                        cell=latvecs_zero,
                                        pbc=True)
                    system_zero.center(axis=2)

                    system_shift = Atoms(symbols=at_syms_shift,
                                         positions=cartpos_shift,
                                         cell=latvecs_shift,
                                         pbc=True)
                    system_shift.center(axis=2)

                    latpos_zero = system_zero.get_scaled_positions()
                    latpos_shift = system_shift.get_scaled_positions()
                    for layer_index in range(len(syms)):
                        # Atoms should have the correct in-plane positions.
                        layer_pos_zero = latpos_zero[3 * layer_index:3 *
                                                     layer_index + 3]
                        layer_pos_shift = latpos_shift[3 * layer_index:3 *
                                                       layer_index + 3]

                        self.assertTrue(
                            has_pos_shift(layer_pos_zero, layer_pos_shift,
                                          layer_shifts[layer_index]))

                        # Atoms should have the correct vertical positions.
                        eps = 1e-12
                        for i in range(3):
                            self.assertTrue(
                                abs(layer_pos_zero[i][2] -
                                    layer_pos_shift[i][2]) < eps)
예제 #5
0
def _main():
    parser = argparse.ArgumentParser(
        "Build and run calculation over various TMD stacks",
        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("--stacking",
                        type=str,
                        default="AB",
                        help="Stacking mode: 'AB' (2H) or 'AA' (1H)")
    parser.add_argument("--D",
                        type=float,
                        default=None,
                        help="Displacement field (default: no field)")
    parser.add_argument("--xc",
                        type=str,
                        default="lda",
                        help="Exchange-correlation functional (lda or pbe)")
    parser.add_argument("--pp",
                        type=str,
                        default="nc",
                        help="Pseudopotential type ('nc' or 'paw')")
    args = parser.parse_args()

    soc = True
    all_syms = get_all_syms()
    AB_stacking = get_stacking(args.stacking)

    vacuum_dist = 20.0  # Angstrom

    db_path = os.path.join(_base_dir(), "c2dm.db")
    db = ase.db.connect(db_path)

    prefixes = []
    for syms in all_syms:
        p = set_up_calculation(db, args.subdir, syms, AB_stacking, soc,
                               vacuum_dist, args.D, args.xc, args.pp)
        prefixes.append(p)

    global_prefix = "alignment"
    machine = "stampede2"
    num_nodes = 2
    num_cores = num_nodes * mpi_procs_per_node(machine)
    queue_config = {
        "machine": machine,
        "nodes": num_nodes,
        "cores": num_cores,
        "queue": "normal",
        "hours": 12,
        "minutes": 0,
        "wannier": True,
        "project": "A-ph9",
        "global_prefix": global_prefix,
        "max_jobs": 6,
        "outer_min": -10.0,
        "outer_max": 5.0,
        "inner_min": -8.0,
        "inner_max": 3.0,
        "subdir": args.subdir,
        "qe_bands": _global_config()['qe_bands']
    }

    _write_queuefiles(_get_base_path(args.subdir), prefixes, queue_config)
예제 #6
0
def _main():
    parser = argparse.ArgumentParser(
        "Build and run calculation over displacement field values",
        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(
        "--syms",
        type=str,
        default="WSe2;WSe2;WSe2",
        help=
        "Semicolon-separated list of atomic composition of layers. Format example: WSe2;MoSe2;MoS2"
    )
    parser.add_argument("--stacking",
                        type=str,
                        default="AB",
                        help="Stacking mode: 'AB' (2H) or 'AA' (1H)")
    parser.add_argument("--minD",
                        type=float,
                        default=0.01,
                        help="Minimum displacement field in V/nm")
    parser.add_argument("--maxD",
                        type=float,
                        default=0.5,
                        help="Maximum displacement field in V/nm")
    parser.add_argument(
        "--numD",
        type=int,
        default=10,
        help=
        "Number of displacement field steps. Set to 0 to not use displacement field."
    )
    parser.add_argument(
        "--shifts_l2",
        type=int,
        default=None,
        help=
        "Number of interlayer shifts to include for second layer: if specified, include\
                  calculations with second layer shifts tiling the unit cell.")
    parser.add_argument(
        "--interlayer_relax",
        action="store_true",
        help="Relax in the out-of-plane direction before performing scf")
    parser.add_argument("--no_soc",
                        action="store_true",
                        help="Turn off spin-orbit coupling")
    parser.add_argument("--xc",
                        type=str,
                        default="lda",
                        help="Exchange-correlation functional (lda or pbe)")
    parser.add_argument("--pp",
                        type=str,
                        default="nc",
                        help="Pseudopotential type ('nc' or 'paw')")
    args = parser.parse_args()

    syms = _extract_syms(args.syms)
    global_prefix = "_".join(syms)

    print("Generating inputs for {} system {}.".format(num_layers_label(syms),
                                                       syms))

    soc = not args.no_soc

    db_path = os.path.join(_base_dir(), "c2dm.db")
    db = ase.db.connect(db_path)

    # Choose separation between layers as if the system was a bulk system
    # where all layers are the same as the first layer here.
    # TODO -- is there a better strategy for this?
    c_sep = get_c_sep(db, syms[0])

    vacuum_dist = 20.0  # Angstrom

    if args.stacking == 'AB':
        AB_stacking = True
    elif args.stacking == 'AA':
        AB_stacking = False
    else:
        raise ValueError("unrecognized value for argument 'stacking'")

    if args.numD == 0:
        Ds = [None]
    else:
        Ds = np.linspace(args.minD, args.maxD, args.numD)

    if args.shifts_l2 is None:
        all_layer_shifts = [None]
    else:
        num_layers = len(syms)
        all_layer_shifts = make_layer_shifts(num_layers, args.shifts_l2)

    prefixes = []
    for layer_shifts in all_layer_shifts:
        prefixes.extend(
            make_system_at_shift(global_prefix, args.subdir, db, syms, c_sep,
                                 vacuum_dist, AB_stacking, soc,
                                 args.interlayer_relax, args.xc, args.pp, Ds,
                                 layer_shifts))

    machine = "stampede2"
    num_nodes = 1
    num_cores = num_nodes * mpi_procs_per_node(machine)
    queue_config = {
        "machine": machine,
        "cores": num_cores,
        "nodes": num_nodes,
        "queue": "normal",
        "hours": 12,
        "minutes": 0,
        "wannier": True,
        "project": "A-ph9",
        "global_prefix": global_prefix,
        "max_jobs": 1,
        "relax": args.interlayer_relax,
        "outer_min": -10.0,
        "outer_max": 6.0,
        "inner_min": -8.0,
        "inner_max": 3.0,
        "subdir": args.subdir,
        "qe_bands": _global_config()['qe_bands']
    }

    print(
        "Generating queuefiles for machine {} on {} nodes and {} jobs with max runtime {} hours."
        .format(machine, num_nodes, queue_config["max_jobs"],
                queue_config["hours"]))

    base_path = _get_base_path(args.subdir)
    prefix_groups = _write_queuefiles(base_path, prefixes, queue_config)

    if args.run:
        calc_name = "wan_setup"
        submit_pw(base_path, queue_config, prefix_groups, calc_name)