Esempio n. 1
0
 def __init__(self, file):
     if not isinstance(file, str):
         file_name = file.name
         file.close()
     else:
         file_name = file
     if not CRYSTOUT.acceptable(file_name):
         raise FileNotFoundError(
             "{} is not a valid CRYSTAL output file".format(file_name))
     result = CRYSTOUT(file_name)
     self.info = result.info
Esempio n. 2
0
def test_failed_elastic():
    """Failed elastic constants calculation"""
    test_file = os.path.join(DATA_DIR, 'failed_elastic.out')

    with pytest.raises(CRYSTOUT_Error) as ex:
        CRYSTOUT(test_file)
        assert 'Inadequate elastic calculation' in ex.msg
Esempio n. 3
0
def test_elastic():
    """Elastic constants calculation"""
    test_file = os.path.join(DATA_DIR, '1674.out')
    parser = CRYSTOUT(test_file)
    info = parser.info
    assert info['prog'] == '17 1.0.2'  # CRYSTAL version
    assert info['finished'] == 2  # finished without errors
    assert info['energy'] == -6.2238169993737E+02 * Ha  # energy in eV
    assert info['k'] == '8x8x8'  # Monkhorst-Pack net
    assert info['elastic']['K_V'] == 33.87
    test_file = os.path.join(DATA_DIR, '2324.out')
    parser = CRYSTOUT(test_file)
    info = parser.info
    assert info['elastic']['elastic_moduli'][0] == [
        659.2238, -404.2543, -249.8055, 0.0, 0.0, 0.0
    ]
Esempio n. 4
0
def test_freqcalc():
    """Phonon dispersion"""
    test_file = os.path.join(DATA_DIR, 'qua_hf_2d_f.out')
    parser = CRYSTOUT(test_file)
    info = parser.info
    assert info['prog'] == '06 1.0'  # CRYSTAL version
    assert info['finished'] == 2  # finished without errors
    assert info['energy'] == -1.3167028008915E+03 * Ha  # energy in eV
    assert info['k'] == '3x3x3'  # Monkhorst-Pack net
    assert info['phonons']['td']['et'] == [0.144398520226]  # Et in eV/cell
    test_file = os.path.join(DATA_DIR, 'raman.out')
    parser = CRYSTOUT(test_file)
    info = parser.info
    assert info['prog'] == '14 1.0.1'  # CRYSTAL version
    assert info['energy'] == -7473.993352557831
    assert info['phonons']['zpe'] == 0.09020363263183974
    assert info['phonons']['td']['t'][0] == 298.15
Esempio n. 5
0
def test_incomplete():
    """Incomplete OUT file, single-point calculation"""
    test_file = os.path.join(DATA_DIR, 'incomplete.out')
    parser = CRYSTOUT(test_file)
    info = parser.info
    assert info['finished'] == 1  # not finished
    assert info['energy'] is None  # energy in eV
    assert info['k'] == '12x12x12'  # Monkhorst-Pack net
    assert not info['ncycles']
Esempio n. 6
0
def test_spin():
    """Spin calculation"""
    test_file = os.path.join(DATA_DIR, 'test37.out')
    parser = CRYSTOUT(test_file)
    info = parser.info
    assert info['prog'] == '17 1.0.1'  # CRYSTAL version
    assert info['finished'] == 2  # finished without errors
    assert info['energy'] == -3.0283685769288E+03 * Ha  # energy in eV
    assert info['k'] == '4x4x1'  # Monkhorst-Pack net
    assert info['spin']
Esempio n. 7
0
def test_elastic_bug_2():
    """Elastic constants calculation (one more)"""
    test_file = os.path.join(DATA_DIR, '2324.out')
    parser = CRYSTOUT(test_file)
    info = parser.info
    assert info['prog'] == '17 1.0.2'  # CRYSTAL version
    assert info['finished'] == 2  # finished without errors
    assert info['energy'] == -6.3910338752478E+03 * Ha  # energy in eV
    assert info['k'] == '8x8x8'  # Monkhorst-Pack net
    assert info['elastic']['K_V'] == -122.44
Esempio n. 8
0
def test_optgeom():
    """Geometry optimization"""
    test_file = os.path.join(DATA_DIR, 'optgeom.out')
    parser = CRYSTOUT(test_file)
    info = parser.info
    assert info['prog'] == '14 1.0.2'  # CRYSTAL version
    assert info['finished'] == 2  # finished without errors
    assert info['energy'] == -1.400469343370E+03 * Ha  # energy in eV
    assert info['k'] == '3x3x3'  # Monkhorst-Pack net
    assert len(info['ncycles']) == 11  # number of optimization steps
    assert len(
        info['structures']) == 12  # structures before and after each opt step
Esempio n. 9
0
def test_single_dft():
    """Single-point calculation; DFT; ECP basis"""
    test_file = os.path.join(DATA_DIR, 'test39_dft.out')
    parser = CRYSTOUT(test_file)
    info = parser.info
    assert info['finished'] == 2  # finished without errors
    assert info['energy'] == -4.8538264773648E+02 * Ha  # energy in eV
    assert info['k'] == '6x6x6'  # Monkhorst-Pack net
    assert info['H'] == "LDA/PZ_LDA"
    assert info['ncycles'][0] == 9
    assert info['electrons']['basis_set']['ecp']['Ge'][0][1] == (0.82751,
                                                                 -1.26859, -1)
    assert info['electrons']['basis_set']['bs']['Ge'][0][1] == (1.834, 0.4939,
                                                                0.006414)
Esempio n. 10
0
def test_single_hf():
    """Single-point calculation; HF; standard AE basis"""
    test_file = os.path.join(DATA_DIR, 'test08.out')
    parser = CRYSTOUT(test_file)
    info = parser.info
    pprint(info)
    assert info['prog'] == '17 1.0.1'  # CRYSTAL version
    assert info['finished'] == 2  # finished without errors
    assert info['energy'] == -5.7132081224317E+02 * Ha  # energy in eV
    assert info['k'] == '8x8x8'  # Monkhorst-Pack mesh
    assert info['H'] == 'Hartree-Fock'
    assert info['ncycles'][0] == 6
    assert not info['electrons']['basis_set']['ecp']
    assert info['electrons']['basis_set']['bs']['Si']
Esempio n. 11
0
def test_band_gap():
    """Elastic constants calculation"""
    test_file = os.path.join(DATA_DIR, '1674.out')
    parser = CRYSTOUT(test_file)
    info = parser.info
    assert info['prog'] == '17 1.0.2'  # CRYSTAL version
    assert info['conduction'][0] == {
        'state': 'INSULATING',
        'top_valence': 14,
        'bottom_virtual': 15,
        'band_gap': 6.2079,
        'band_gap_type': 'INDIRECT'
    }
    test_file = os.path.join(DATA_DIR, 'mgo_sto3g.out')
    parser = CRYSTOUT(test_file)
    info = parser.info
    assert info['prog'] == '14 1.0.1'  # CRYSTAL version
    assert info['conduction'][0] == {
        'state': 'INSULATING',
        'top_valence': 10,
        'bottom_virtual': 11,
        'band_gap': 19.72174073396588,
        'band_gap_type': 'DIRECT'
    }
Esempio n. 12
0
def download_basis_library():

    library = {}

    while True:
        if not known_page_names:
            break
        page = known_page_names.pop(0)

        r = requests.get('http://www.crystal.unito.it/Basis_Sets/%s.html' %
                         page)
        if r.status_code != 200:
            logging.warning("NO PAGE FOR %s" % page)
            continue

        soup = BeautifulSoup(r.content, 'html.parser')

        for a in soup.find_all('a'):
            anchor = a.get('href', '')
            if anchor.startswith('http') and anchor.endswith(
                    '.html') and '#' not in anchor:
                logging.warning("PAGE %s HAS AN EXTERNAL LINK: %s" %
                                (page, anchor))
                known_page_names.append(anchor.split('/')[-1][:-5])

        for basis in soup.find_all('pre'):
            title = basis.findPrevious('p').text.strip()
            if not title:
                title = basis.findPrevious('font').text.strip()

            parts = [
                item for item in linebreak.split(basis.text) if len(item) > 2
            ]
            page = page.split(
                '_'
            )[0]  # PS such as http://www.crystal.unito.it/Basis_Sets/oxygen_baranek.html

            # Correct mis-formats in the BS library at the CRYSTAL website
            if page == 'sulphur' and '10.1002/jcc.23153' in parts[1]:
                # "1 0" -> "1.0"
                parts[0] = parts[0].replace(
                    "\r\n0 3 1 0.0 1 0\r\n 0.5207010100 1.00000000000000",
                    "\r\n0 3 1 0.0 1.0\r\n 0.5207010100 1.00000000000000")

            elif page == 'sulphur' and '10.1002/jcc.26013' in parts[1]:
                # "1 0" -> "1.0"
                parts[0] = parts[0].replace(
                    "\r\n0 3 1 0.0 1 0\r\n  0.4107010100     1.0000000000000",
                    "\r\n0 3 1 0.0 1.0\r\n  0.4107010100     1.0000000000000")

            elif page == 'titanium' and 'Mahmoud' in parts[1]:
                # remove "Ti"
                parts[0] = parts[0].replace("Ti\r\n22 9\r\n", "22 9\r\n")

            elif page == 'bismuth' and 'weihrich' in title:
                # remove comment
                parts[0] = parts[0].replace(
                    "ECP modified from Hay and Wadt, JCP 82, 284 (1985)", "")

            elif page == 'mercury' and 'weihrich' in title:
                # remove comments
                parts[0] = parts[0].replace(
                    "ECP modified from Hay and Wadt, JCP 82, 1985", "")

            elif page == 'thallium' and 'Bachhuber' in title:
                # fix INPUT
                parts[0] = parts[0].replace("13. 6 5 6 6 6 0 0",
                                            "13. 6 5 6 6 6 0")

            elif page == 'oxygen' and 'corno' in title:
                # remove comments
                parts[0] = parts[0].replace("same as gatti_1994", "").replace(
                    "gatti_1994 modified", "")

            elif page == 'plutonium' and '_NO_G_' in title:
                # fix Pu ECP format
                parts[0] = parts[0].replace("294 11", "294 9")

            elif page == 'polonium' and 'TZVP_rev2' in title:
                # fix Po
                parts[0] = parts[0].replace("282 12", "284 12")

            # NB. sometimes the comments get included afterwards

            expected_element = chemical_symbols[ref_page_names.index(page)]

            parsed = CRYSTOUT.parse_bs_input(parts[0], as_d12=False)
            gbasis = dict(data=parts[0].strip(),
                          meta=" ".join(parts[1:]).replace("\n", " ").replace(
                              "\r", "").strip(),
                          title=title)
            element = list(parsed['bs'].keys())[0]
            assert expected_element == element, "%s is on the page of %s" % (
                element, expected_element)

            library.setdefault(element, []).append(gbasis)

    return library
Esempio n. 13
0
def check_status():
    parser = argparse.ArgumentParser(
        description="Submit task to yascheduler daemon")
    parser.add_argument('-j',
                        '--jobs',
                        required=False,
                        default=None,
                        nargs='*')
    parser.add_argument('-v',
                        '--view',
                        required=False,
                        default=None,
                        nargs='?',
                        type=bool,
                        const=True)
    parser.add_argument('-o',
                        '--convergence',
                        required=False,
                        default=None,
                        nargs='?',
                        type=bool,
                        const=True,
                        help='needs -v option')
    parser.add_argument('-i',
                        '--info',
                        required=False,
                        default=None,
                        nargs='?',
                        type=bool,
                        const=True)
    parser.add_argument('-k',
                        '--kill',
                        required=False,
                        default=None,
                        nargs='?',
                        type=bool,
                        const=True)

    args = parser.parse_args()
    config = ConfigParser()
    config.read(CONFIG_FILE)
    yac = Yascheduler(config)
    statuses = {
        yac.STATUS_TO_DO: "QUEUED",
        yac.STATUS_RUNNING: "RUNNING",
        yac.STATUS_DONE: "FINISHED"
    }
    local_parsing_ready, local_calc_snippet = False, False

    if args.jobs:
        tasks = yac.queue_get_tasks(jobs=args.jobs)
    else:
        tasks = yac.queue_get_tasks(status=(yac.STATUS_RUNNING,
                                            yac.STATUS_TO_DO))

    if args.view or args.kill:
        if not tasks:
            print('NO MATCHING TASKS FOUND')
            return
        ssh_custom_key = {}
        for filename in os.listdir(config.get('local', 'data_dir')):
            if not filename.startswith('yakey') or not os.path.isfile(
                    os.path.join(config.get('local', 'data_dir'), filename)):
                continue
            key_path = os.path.join(config.get('local', 'data_dir'), filename)
            pmk_key = RSAKey.from_private_key_file(key_path)
            print('LOADED KEY %s' % key_path)
            ssh_custom_key = {'pkey': pmk_key}
            break

    if args.convergence:
        try:
            from pycrystal import CRYSTOUT
            from numpy import nan
            local_parsing_ready = True
        except:
            pass

    if args.view:
        yac.cursor.execute(
            'SELECT task_id, label, metadata, ip FROM yascheduler_tasks WHERE status=%s AND task_id IN (%s);'
            % (yac.STATUS_RUNNING, ', '.join(
                [str(task['task_id']) for task in tasks])))
        for row in yac.cursor.fetchall():
            print("." * 50 + "ID%s %s at %s@%s:%s" %
                  (row[0], row[1], config.get('remote', 'user'), row[3],
                   row[2]['remote_folder']))
            ssh_conn = SSH_Connection(host=row[3],
                                      user=config.get('remote', 'user'),
                                      connect_kwargs=ssh_custom_key)
            try:
                result = ssh_conn.run('tail -n15 %s/OUTPUT' %
                                      row[2]['remote_folder'],
                                      hide=True)
            except UnexpectedExit:
                print('OUTDATED TASK, SKIPPING')
            else:
                print(result.stdout)

            if local_parsing_ready:
                local_calc_snippet = os.path.join(
                    config.get('local', 'data_dir'), 'local_calc_snippet.tmp')
                try:
                    ssh_conn.get(row[2]['remote_folder'] + '/OUTPUT',
                                 local_calc_snippet)
                except IOError as err:
                    continue
                calc = CRYSTOUT(local_calc_snippet)
                output_lines = ''
                if calc.info['convergence']:
                    output_lines += str(calc.info['convergence']) + "\n"
                if calc.info['optgeom']:
                    for n in range(len(calc.info['optgeom'])):
                        try:
                            ncycles = calc.info['ncycles'][n]
                        except IndexError:
                            ncycles = "^"
                        output_lines += "{:8f}".format(calc.info['optgeom'][n][0] or nan) + "  " + \
                                        "{:8f}".format(calc.info['optgeom'][n][1] or nan) + "  " + \
                                        "{:8f}".format(calc.info['optgeom'][n][2] or nan) + "  " + \
                                        "{:8f}".format(calc.info['optgeom'][n][3] or nan) + "  " + \
                                        "E={:12f}".format(calc.info['optgeom'][n][4] or nan) + " eV" + "  " + \
                                        "(%s)" % ncycles + "\n"
                print(output_lines)

    elif args.kill:
        if not args.jobs:
            print('NO JOBS GIVEN')
            return
        yac.cursor.execute(
            'SELECT ip FROM yascheduler_tasks WHERE status=%s AND task_id IN (%s);'
            % (yac.STATUS_RUNNING, ', '.join(
                [str(task['task_id']) for task in tasks])))
        for row in yac.cursor.fetchall():
            ssh_conn = SSH_Connection(host=row[0],
                                      user=config.get('remote', 'user'),
                                      connect_kwargs=ssh_custom_key)
            try:
                result = ssh_conn.run('pkill %s' % yac.RUNNING_MARKER,
                                      hide=True)
            except:
                pass

    elif args.info:
        for task in tasks:
            print('task_id={}\tstatus={}\tlabel={}\tip={}'.format(
                task['task_id'], statuses[task['status']], task['label'],
                task['ip'] or '-'))

    else:
        for task in tasks:
            print('{}   {}'.format(task['task_id'], statuses[task['status']]))

    yac.connection.close()

    if local_calc_snippet and os.path.exists(local_calc_snippet):
        os.unlink(local_calc_snippet)
Esempio n. 14
0

class Mock(Calculator):
    def __init__(self, *args, **kwargs):
        Calculator.__init__(self)

    def get_property(self, *args, **kwargs):
        return 42


for root, dirs, files in os.walk(sys.argv[1]):
    # NB beware of the broken links (clean e.g. find . -type l -exec rm -f {} \;)

    for filename in files:
        target = root + os.sep + filename
        if not CRYSTOUT.acceptable(target):
            continue

        logging.info("*"*25 + root + os.sep + filename + "*"*25)
        skipped = False

        # Parsing with ejp
        tic = time.time()
        with open(target) as fp:
            try:
                ejp_result = Ejpcry.read_file(fp, log_warnings=False)
            except Exception as err:
                logging.error("EJP FAILED TO PARSE: %s" % str(err))
                skipped = True
        ejp_perf = round(time.time() - tic, 3)