Beispiel #1
0
def get_output_from_qchem(input_qchem,
                          processors=1,
                          use_mpi=False,
                          scratch=None,
                          read_fchk=False,
                          parser=None,
                          parser_parameters=None,
                          force_recalculation=False,
                          fchk_only=False,
                          store_full_output=False,
                          remove_scratch=True,
                          remote=None,
                          strict_policy=False):
    """
    Runs qchem and returns the output in the following format:

    1) If read_fchk is requested:
        [output, parsed_fchk]
    2) If read_fchk is not requested:
        [output]

    Note: if parser is set then output contains a dictionary with the parsed info
          else output contains the q-chem output in plain text

    read_fchk: contains a dictionary with the parsed info inside fchk file.

    :param input_qchem: QcInput object containing the Q-Chem input
    :param processors: number of threads/processors to use in the calculation
    :param use_mpi: If False use OpenMP (threads) else use MPI (processors)
    :param scratch: Full Q-Chem scratch directory path. If None read from $QCSCRATCH
    :param read_fchk: if True, generate and parse the FCHK file containing the electronic structure
    :param parser: function to use to parse the Q-Chem output
    :param parser_parameters: additional parameters that parser function may have
    :param force_recalculation: Force to recalculate even identical calculation has already performed
    :param fchk_only: If true, returns only the electronic structure data parsed from FCHK file
    :param remote: dictionary containing the data for remote calculation (beta)

    :return: output [, fchk_dict]
    """
    from pyqchem.parsers.parser_fchk import parser_fchk

    # check gui > 2 if read_fchk
    if read_fchk:
        if input_qchem.gui is None or input_qchem.gui < 1:
            input_qchem.gui = 2

    if scratch is None:
        scratch = os.getenv('QCSCRATCH')

    work_dir = '{}/qchem{}/'.format(scratch, os.getpid())

    try:
        os.mkdir(work_dir)
    except OSError:
        pass

    # handle custom guess
    if input_qchem.mo_coefficients is not None:
        input_qchem.store_mo_file(work_dir)

    # set scf energy if skip_scfman (to not break)
    # TODO: now SCF energy is set to zero. This works for very little features.
    if input_qchem._skip_scfman:
        input_qchem.store_energy_file(work_dir)

    # check if hessian
    if input_qchem.hessian is not None:
        ndim = len(input_qchem.hessian)

        hessian_triu = np.array(input_qchem.hessian)

        with open(work_dir + '132.0', 'w') as f:
            hessian_triu.tofile(f, sep='')

    input_txt = input_qchem.get_txt()

    # check if parameters is None
    if parser_parameters is None:
        parser_parameters = {}

    # check if full output is stored
    # print('input:', input_qchem)
    output, err = calculation_data[(hash(input_qchem), 'fullout')] if (
        hash(input_qchem), 'fullout') in calculation_data else [None, None]
    # output, err = retrieve_calculation_data(input_qchem, 'fullout') if retrieve_calculation_data(input_qchem, 'fullout') is not None else [None, None]

    if not force_recalculation and not store_full_output:

        data_fchk = retrieve_calculation_data(input_qchem, 'fchk')

        if parser is not None:

            data = retrieve_calculation_data(hash(input_qchem),
                                             parser.__name__)

            if data is not None:
                if read_fchk is False:
                    return data
                elif data_fchk is not None:
                    return data, data_fchk
                else:
                    force_recalculation = True

        else:
            if fchk_only and data_fchk is not None:
                return None, data_fchk

    fchk_filename = 'qchem_temp_{}.fchk'.format(os.getpid())
    temp_filename = 'qchem_temp_{}.inp'.format(os.getpid())

    qchem_input_file = open(os.path.join(work_dir, temp_filename), mode='w')
    qchem_input_file.write(input_txt)
    qchem_input_file.close()

    # Q-Chem calculation
    if output is None or force_recalculation is True:
        if remote is None:
            output, err = local_run(temp_filename,
                                    work_dir,
                                    fchk_filename,
                                    use_mpi=use_mpi,
                                    processors=processors)
        else:
            output, err = remote_run(temp_filename,
                                     work_dir,
                                     fchk_filename,
                                     remote,
                                     use_mpi=use_mpi,
                                     processors=processors)

    if not finish_ok(output):
        raise OutputError(output, err)

    if store_full_output:
        store_calculation_data(input_qchem, 'fullout', [output, err])

    if parser is not None:
        try:
            output = parser(output, **parser_parameters)
        # minimum functionality for error capture
        except:
            raise ParserError(parser.__name__, 'Undefined error')

        store_calculation_data(input_qchem, parser.__name__, output)

    if read_fchk:

        data_fchk = retrieve_calculation_data(input_qchem, 'fchk')
        if data_fchk is not None and not force_recalculation:
            return output, data_fchk

        if not os.path.isfile(os.path.join(work_dir, fchk_filename)):
            warnings.warn(
                'fchk not found! Make sure the input generates it (gui 2)')
            return output, []

        with open(os.path.join(work_dir, fchk_filename)) as f:
            fchk_txt = f.read()
        os.remove(os.path.join(work_dir, fchk_filename))

        data_fchk = parser_fchk(fchk_txt)
        store_calculation_data(input_qchem, 'fchk', data_fchk)

        return output, data_fchk

    if remove_scratch:
        shutil.rmtree(work_dir)

    return output
Beispiel #2
0
    :return:
    """

    # Get xyz file format from Molecule or Geometry (or list)

    if not isinstance(structures, list):
        structures = [structures]

    txt = ''
    for structure in structures:
        txt += '{}\n'.format(structure.get_number_of_atoms())
        txt += '{}\n'.format(
            structure.name if structure.name is not None else '')
        for idp, position in enumerate(structure.get_coordinates()):
            txt += '{:2} {:11.6f} {:11.6f} {:11.6f}\n'.format(
                structure.get_symbols()[idp], position[0], position[1],
                position[2])
    with open(filename, 'w') as f:
        f.write(txt)


if __name__ == '__main__':
    from pyqchem.parsers.parser_fchk import parser_fchk
    txt_fchk = open('qchem_temp_32947.fchk', 'r').read()
    parsed_data = parser_fchk(txt_fchk)
    txt_fchk_new = build_fchk(parsed_data)
    with open('test.fchk', 'w') as f:
        f.write(txt_fchk_new)

    #structure, basis, alpha_coeff, beta_coeff = get_data_from_file_fchk('qchem_temp_32947.fchk')
    #print(basis)
Beispiel #3
0
def get_output_from_qchem(input_qchem,
                          processors=1,
                          use_mpi=False,
                          scratch=None,
                          read_fchk=False,
                          parser=None,
                          parser_parameters=None,
                          force_recalculation=False,
                          fchk_only=False,
                          store_full_output=False,
                          delete_scratch=True,
                          remote=None):
    """
    Runs qchem and returns the output in the following format:

    1) If read_fchk is requested:
        [output, parsed_fchk]
    2) If read_fchk is not requested:
        [output]

    Note: if parser is set then output contains a dictionary with the parsed info
          else output contains the q-chem output in plain text

    read_fchk: contains a dictionary with the parsed info inside fchk file.

    :param input_qchem: QcInput object containing the Q-Chem input
    :param processors: number of threads/processors to use in the calculation
    :param use_mpi: If False use OpenMP (threads) else use MPI (processors)
    :param scratch: Full Q-Chem scratch directory path. If None read from $QCSCRATCH
    :param read_fchk: if True, returns the parsed FCHK file containing the electronic structure
    :param parser: function to use to parse the Q-Chem output
    :param parser_parameters: additional parameters that parser function may have
    :param force_recalculation: Force to recalculate even identical calculation has already performed
    :param fchk_only: If true, returns only the electronic structure data parsed from FCHK file
    :param remote: dictionary containing the data for remote calculation (beta)
    :param store_full_output: store full output in plain text in pkl file
    :param delete_scratch: delete all scratch files when calculation is finished

    :return: output [, fchk_dict]
    """
    from pyqchem.parsers.parser_fchk import parser_fchk
    cache = CacheSystem()

    # Always generate fchk
    if input_qchem.gui is None or input_qchem.gui < 1:
        input_qchem.gui = 2

    if scratch is None:
        scratch = os.getenv('QCSCRATCH')
        if scratch is None:
            warnings.warn('QCSCRATCH environment variable not defined, using workdir')
            scratch = '.'

    work_dir = '{}/pyqchem_{}/'.format(scratch, os.getpid())

    try:
        os.mkdir(work_dir)
    except OSError:
        pass

    # check if parameters is None
    if parser_parameters is None:
        parser_parameters = {}

    # check if full output is stored
    output = cache.retrieve_calculation_data(input_qchem, 'fullout')

    #output, err = cache.calculation_data[(hash(input_qchem), 'fullout')] if (hash(input_qchem), 'fullout') in cache.calculation_data else [None, None]
    data_fchk = cache.retrieve_calculation_data(input_qchem, 'fchk')

    # check if repeated calculation
    if not force_recalculation and not store_full_output:  # store_full_output always force re-parsing
        if parser is not None:
            parsed_data = cache.retrieve_calculation_data(hash(input_qchem), parser.__name__)
            if parsed_data is not None:
                if read_fchk:
                    return parsed_data, data_fchk
                else:
                    return parsed_data
        else:
            if fchk_only and data_fchk is not None:
                return output, data_fchk

    fchk_filename = 'qchem_temp_{}.fchk'.format(os.getpid())
    temp_filename = 'qchem_temp_{}.inp'.format(os.getpid())

    # generate the input in TXT form
    input_txt = input_qchem.get_txt()
    qchem_input_file = open(os.path.join(work_dir, temp_filename), mode='w')
    qchem_input_file.write(input_txt)
    qchem_input_file.close()

    # generate extra files in calculation directory
    generate_additional_files(input_qchem, work_dir)

    # Q-Chem calculation
    if output is None or force_recalculation is True:
        if remote is None:
            output, err = local_run(temp_filename, work_dir, fchk_filename, use_mpi=use_mpi, processors=processors)
        else:
            output, err = remote_run(temp_filename, work_dir, fchk_filename, remote, use_mpi=use_mpi, processors=processors)

        if not finish_ok(output):
            raise OutputError(output, err)

        # parse fchk file & and additional scratch dir files
        if not os.path.isfile(os.path.join(work_dir, fchk_filename)):
            warnings.warn('fchk not found! something may be wrong in calculation')
        else:
            with open(os.path.join(work_dir, fchk_filename)) as f:
                fchk_txt = f.read()

            data_fchk = parser_fchk(fchk_txt)
            data_fchk.update(retrieve_additional_files(input_qchem, data_fchk, work_dir))
            cache.store_calculation_data(input_qchem, 'fchk', data_fchk)

        if store_full_output:
            cache.store_calculation_data(input_qchem, 'fullout', output)

    if parser is not None:

        # Check parser compatibility
        version = get_version_output(output)
        compatibility_list = get_compatibility_list_from_parser(parser)
        if compatibility_list is not None:
            if version not in compatibility_list:
                warnings.warn('Parser "{}" may not be compatible with Q-Chem {}'.format(parser.__name__, version))

        # minimum functionality for parser error capture
        try:
            output = parser(output, **parser_parameters)
        except:
            raise ParserError(parser.__name__, 'Undefined error')

        cache.store_calculation_data(input_qchem, parser.__name__, output)

    if delete_scratch:
        shutil.rmtree(work_dir)

    if read_fchk:
        return output, data_fchk
    else:
        return output