def parse_bands(self, bands):
        """Parse bands from fort.25 file"""
        if not bands:
            raise ValueError("Sorry, didn't find bands info in fort.25")

        from aiida.plugins import DataFactory
        # to get BandsData node first we need to get k-points path and set KpointsData
        shrink = self.node.inputs.parameters.dict.band['shrink']
        path = bands["path"]
        k_number = bands["n_k"]
        # for path construction we're getting geometry from fort.9
        with self.node.inputs.wavefunction.open() as f:
            fort9_name = f.name
        geometry_parser = Fort9(fort9_name)
        cell = geometry_parser.get_cell(scale=True)
        path_description = construct_kpoints_path(cell, path, shrink, k_number)
        structure = DataFactory('structure')(ase=geometry_parser.get_ase())
        # and now find k-points along the path
        k_points = get_explicit_kpoints_path(
            structure, path_description)['explicit_kpoints']
        # ...and finally populate bands data
        bands_data = DataFactory('array.bands')()
        bands_data.set_kpointsdata(k_points)
        bands_data.set_bands(bands["bands_up"])
        # TODO: Deal with bands_down?
        bands_down_data = None
        if bands["bands_down"] is not None:
            bands_down_data = DataFactory('array.bands')()
            bands_down_data.set_kpointsdata(k_points)
            bands_down_data.set_bands(bands["bands_down"])
        return bands_data, bands_down_data
Beispiel #2
0
def test_pass():
    parser = Fort9(file_name)
    cell, positions, numbers = parser.get_cell()
    assert cell.shape == (3, 3)
    assert positions.shape == (2, 3)
    assert sorted(numbers.tolist()) == [8, 12]
    assert parser.get_ao_number() == 18
Beispiel #3
0
    def _set_default_parameters(self, parameters):
        """Set defaults to calculation parameters"""
        parameters_dict = parameters.get_dict()
        from aiida_crystal_dft.io.f9 import Fort9
        with self.inputs.wavefunction.open() as f:
            file_name = f.name
        wf = Fort9(file_name)
        if 'band' in parameters_dict:

            # automatic generation of k-point path
            if 'bands' not in parameters_dict['band']:
                self.logger.info(
                    'Proceeding with automatic generation of k-points path')
                structure = wf.get_structure()
                shrink, points, path = get_shrink_kpoints_path(structure)
                parameters_dict['band']['shrink'] = shrink
                parameters_dict['band']['bands'] = path

            # automatic generation of first and last band
            if 'first' not in parameters_dict['band']:
                parameters_dict['band']['first'] = 1
            if 'last' not in parameters_dict['band']:
                parameters_dict['band']['last'] = wf.get_ao_number()

        if 'dos' in parameters_dict:
            # automatic generation of projections in case no projections are given
            # TODO: explicit asking for automatic projections
            if ('projections_atoms' not in parameters_dict['dos']
                    and 'projections_orbitals' not in parameters_dict['dos']):
                self.logger.info(
                    'Proceeding with automatic generation of dos atomic projections'
                )
                parameters_dict['dos'][
                    'projections_atoms'] = get_dos_projections_atoms(
                        wf.get_atomic_numbers())

            # automatic generation of first and last band
            if 'first' not in parameters_dict['dos']:
                parameters_dict['dos']['first'] = 1
            if 'last' not in parameters_dict['dos']:
                parameters_dict['dos']['last'] = wf.get_ao_number()
        return get_data_class('dict')(dict=parameters_dict)
Beispiel #4
0
def run_properties_direct(wf_path, input_dict):
    """
    This procedure runs properties
    outside of AiiDA graph and scheduler
    """
    assert wf_path.endswith('fort.9')
    assert 'band' in input_dict and 'dos' in input_dict
    assert 'first' not in input_dict['dos'] and 'first' not in input_dict[
        'band']
    assert 'last' not in input_dict['dos'] and 'last' not in input_dict['band']
    print('Working with %s' % wf_path)

    work_folder = os.path.join(
        config.get('local', 'data_dir'), '_'.join([
            'props',
            datetime.now().strftime('%Y%m%d_%H%M%S'),
            ''.join([random.choice(string.ascii_lowercase) for _ in range(4)])
        ]))
    os.makedirs(work_folder, exist_ok=False)
    shutil.copy(wf_path, work_folder)
    shutil.copy(os.path.join(os.path.dirname(wf_path), 'fort.34'),
                work_folder)  # save structure

    wf = Fort9(os.path.join(work_folder, 'fort.9'))

    # automatic generation of k-point path
    #structure = wf.get_structure()
    # NB fort.9 may produce slightly different structure, so use fort.34
    f34 = f34_input.read(os.path.join(os.path.dirname(wf_path), 'fort.34'))
    structure = f34.to_aiida()

    shrink, _, kpath = get_shrink_kpoints_path(structure)
    last_state = wf.get_ao_number()
    input_dict['band']['shrink'] = shrink
    input_dict['band']['bands'] = kpath

    # automatic generation of first and last state
    input_dict['band']['first'] = 1
    input_dict['band']['last'] = last_state
    input_dict['dos']['first'] = 1
    input_dict['dos']['last'] = last_state

    d3_content = str(D3(input_dict))
    inp = open(os.path.join(work_folder, 'INPUT'), "w")
    inp.write(d3_content)
    inp.close()

    start_time = time.time()
    p = subprocess.Popen(
        exec_cmd %
        (work_folder, EXEC_PATH, os.path.join(work_folder, 'OUTPUT')),
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        shell=True)
    try:
        p.wait(timeout=EXEC_TIMEOUT)
    except subprocess.TimeoutExpired:
        kill(p.pid)
        print("Killed as too time-consuming")

    print("Done in %1.2f sc" % (time.time() - start_time))

    if p.returncode != 0:
        return None, 'PROPERTIES failed, see %s' % work_folder

    if not os.path.exists(os.path.join(work_folder, 'BAND.DAT')) \
        or not os.path.exists(os.path.join(work_folder, 'DOSS.DAT')) \
        or not os.path.exists(os.path.join(work_folder, 'fort.25')):
        return None, 'No PROPERTIES outputs'

    edata = Fort25(os.path.join(work_folder, 'fort.25')).parse()

    assert sum(edata['DOSS']['e']) == 0  # all zeros, FIXME?
    print('>N DOSS: %s' % len(edata['DOSS']['dos'][0]))

    path = edata['BAND']['path']
    k_number = edata['BAND']['n_k']

    #cell = wf.get_cell(scale=True) # for path construction we're getting geometry from fort.9
    # NB fort.9 may produce slightly different structure, so use fort.34
    cell = f34.abc, f34.positions, f34.atomic_numbers

    path_description = construct_kpoints_path(cell, path, shrink, k_number)
    # find k-points along the path
    k_points = get_explicit_kpoints_path(structure,
                                         path_description)['explicit_kpoints']

    # pass through the internal AiiDA repr, FIXME?
    bands_data = DataFactory('array.bands')()
    bands_data.set_kpointsdata(k_points)
    bands_data.set_bands(edata['BAND']['bands'])

    edata['BAND']['bands'] = bands_data.get_bands()
    k_points = bands_data.get_kpoints().tolist()
    print('>N KPOINTS: %s' % len(k_points))
    print('>N BANDS: %s' % len(edata['BAND']['bands'][0]))

    edata['BAND']['bands'] -= edata['DOSS']['e_fermi']
    edata['BAND']['bands'] *= Hartree
    edata['DOSS']['dos'] -= edata['DOSS']['e_fermi']
    edata['DOSS']['dos'] *= Hartree
    # get rid of the negative DOS artifacts
    edata['DOSS']['dos'][edata['DOSS']['dos'] < 0] = 0

    e_min, e_max = np.amin(edata['BAND']['bands']), np.amax(
        edata['BAND']['bands'])
    dos_energies = np.linspace(e_min, e_max, num=len(edata['DOSS']['dos'][0]))
    stripes = edata['BAND']['bands'].transpose().copy()

    if is_conductor(stripes):
        indirect_gap, direct_gap = None, None
    else:
        indirect_gap, direct_gap = get_band_gap_info(stripes)

    # save only the range of the interest
    E_MIN, E_MAX = -15, 20
    stripes = stripes[(stripes[:, 0] > E_MIN) & (stripes[:, 0] < E_MAX)]
    dos = []
    for n, i in enumerate(dos_energies):  # FIXME use numpy advanced slicing
        if E_MIN < i < E_MAX:
            dos.append(edata['DOSS']['dos'][0][n])
    dos_energies = dos_energies[(dos_energies > E_MIN)
                                & (dos_energies < E_MAX)]

    return {
        # - gaps
        'direct_gap': direct_gap,
        'indirect_gap': indirect_gap,
        # - dos values
        'dos': np.round(np.array(dos), 3).tolist(),
        'levels': np.round(dos_energies, 3).tolist(),
        # - bands values
        'k_points': k_points,
        'stripes': np.round(stripes, 3).tolist(),
        # - auxiliary
        'work_folder': work_folder,
        'units': 'eV'
    }, None
Beispiel #5
0
def test_tof98():
    name = os.path.join(TEST_DIR, "output_files", "optimise", "fort.9")
    parser = Fort9(name)
    print(parser._data)
Beispiel #6
0
def test_issue_30():
    name = os.path.join(TEST_DIR, "input_files", "issue_30", "fort.9")
    parser = Fort9(name)
    assert parser.get_ao_number() == 71
Beispiel #7
0
def test_fail():
    with pytest.raises(ValueError):
        Fort9("invalid_file_name.9")