Beispiel #1
0
    def _run_g16(cfg):

        # Run Gaussian 16. We capture stdout and if error log the last 10 lines that
        # should include the error description from Gaussian
        process = None
        try:
            process = Popen(GAUSSIAN_16, stdin=PIPE, stdout=PIPE, universal_newlines=True)
            stdout, stderr = process.communicate(cfg)
            process.wait()
        except:
            if process is not None:
                process.kill()

            raise QiskitChemistryError('{} run has failed'.format(GAUSSIAN_16_DESC))

        if process.returncode != 0:
            errmsg = ""
            if stdout is not None:
                lines = stdout.splitlines()
                start = 0
                if len(lines) > 10:
                    start = len(lines) - 10
                for i in range(start, len(lines)):
                    logger.error(lines[i])
                    errmsg += lines[i] + "\n"
            raise QiskitChemistryError('{} process return code {}\n{}'.format(GAUSSIAN_16_DESC, process.returncode, errmsg))
        else:
            if logger.isEnabledFor(logging.DEBUG):
                alltext = ""
                if stdout is not None:
                    lines = stdout.splitlines()
                    for line in lines:
                        alltext += line + "\n"
                logger.debug("Gaussian output:\n{}".format(alltext))
Beispiel #2
0
def _register_chemistry_operator(cls):
    # Verify that the pluggable is not already registered
    if cls in [
            input.cls for input in _REGISTERED_CHEMISTRY_OPERATORS.values()
    ]:
        raise QiskitChemistryError(
            'Could not register class {} is already registered'.format(cls))

    # Verify that it has a minimal valid configuration.
    try:
        chemistry_operator_name = cls.CONFIGURATION['name']
    except (LookupError, TypeError):
        raise QiskitChemistryError(
            'Could not register chemistry operator: invalid configuration')

    if chemistry_operator_name in _REGISTERED_CHEMISTRY_OPERATORS:
        raise QiskitChemistryError(
            'Could not register class {}. Name {} {} is already registered'.
            format(
                cls, chemistry_operator_name,
                _REGISTERED_CHEMISTRY_OPERATORS[chemistry_operator_name].cls))

    # Append the pluggable to the `registered_classes` dict.
    _REGISTERED_CHEMISTRY_OPERATORS[
        chemistry_operator_name] = RegisteredChemOp(
            chemistry_operator_name, cls, copy.deepcopy(cls.CONFIGURATION))
    return chemistry_operator_name
Beispiel #3
0
def _check_molecule_format(val):
    """If it seems to be zmatrix rather than xyz format we convert before returning"""
    atoms = [x.strip() for x in val.split(';')]
    if atoms is None or len(atoms) < 1:  # pylint: disable=len-as-condition
        raise QiskitChemistryError('Molecule format error: ' + val)

    # An xyz format has 4 parts in each atom, if not then do zmatrix convert
    # Allows dummy atoms, using symbol 'X' in zmatrix format for coord computation to xyz
    parts = [x.strip() for x in atoms[0].split(' ')]
    if len(parts) != 4:
        try:
            zmat = []
            for atom in atoms:
                parts = [x.strip() for x in atom.split(' ')]
                z = [parts[0]]
                for i in range(1, len(parts), 2):
                    z.append(int(parts[i]))
                    z.append(float(parts[i + 1]))
                zmat.append(z)
            xyz = z2xyz(zmat)
            new_val = ""
            for atm in xyz:
                if atm[0].upper() == 'X':
                    continue
                if new_val:
                    new_val += "; "
                new_val += "{} {} {} {}".format(atm[0], atm[1], atm[2], atm[3])
            return new_val
        except Exception as exc:
            raise QiskitChemistryError('Failed to convert atom string: ' +
                                       val) from exc

    return val
Beispiel #4
0
    def __init__(self,
                 fcidump_input: str,
                 atoms: Optional[List[str]] = None) -> None:
        """
        Args:
            fcidump_input: Path to the FCIDump file.
            atoms: Allows to specify the atom list of the molecule. If it is provided, the created
                QMolecule instance will permit frozen core Hamiltonians. This list must consist of
                valid atom symbols.

        Raises:
            QiskitChemistryError: If ``fcidump_input`` is not a string or if ``atoms`` is not a list
                of valid atomic symbols as specified in ``QMolecule``.
        """
        super().__init__()

        if not isinstance(fcidump_input, str):
            raise QiskitChemistryError(
                "The fcidump_input must be str, not '{}'".format(
                    fcidump_input))
        self._fcidump_input = fcidump_input

        if atoms and not isinstance(atoms, list) \
                and not all(sym in QMolecule.symbols for sym in atoms):
            raise QiskitChemistryError(
                "The atoms must be a list of valid atomic symbols, not '{}'".
                format(atoms))
        self.atoms = atoms
Beispiel #5
0
    def _run_psi4(input_file, output_file):

        # Run psi4.
        process = None
        try:
            process = subprocess.Popen([PSI4, input_file, output_file],
                                       stdout=subprocess.PIPE,
                                       universal_newlines=True)
            stdout, _ = process.communicate()
            process.wait()
        except Exception:
            if process is not None:
                process.kill()

            raise QiskitChemistryError('{} run has failed'.format(PSI4))

        if process.returncode != 0:
            errmsg = ""
            if stdout is not None:
                lines = stdout.splitlines()
                for i, _ in enumerate(lines):
                    logger.error(lines[i])
                    errmsg += lines[i] + "\n"
            raise QiskitChemistryError('{} process return code {}\n{}'.format(
                PSI4, process.returncode, errmsg))
    def save_to_file(self, file_name):
        if file_name is None:
            raise QiskitChemistryError('Missing file path')

        file_name = file_name.strip()
        if len(file_name) == 0:
            raise QiskitChemistryError('Missing file path')

        prev_filename = self.get_filename()
        sections = copy.deepcopy(self.get_sections())
        if prev_filename is not None:
            prev_dirname = os.path.dirname(os.path.realpath(prev_filename))
            dirname = os.path.dirname(os.path.realpath(file_name))
            if prev_dirname != dirname:
                InputParser._from_relative_to_abs_paths(sections, prev_filename)

        contents = ''
        lastIndex = len(sections) - 1
        for i, (section_name, section) in enumerate(sections.items()):
            contents += '{}{}'.format(InputParser._START_SECTION, section_name)
            if self.section_is_text(section_name):
                value = section if isinstance(section, str) else json.dumps(section, sort_keys=True, indent=4)
                contents += '\n{}'.format(value)
            else:
                for k, v in section.items():
                    contents += '\n   {}{}{}'.format(k, InputParser._PROPVALUE_SEPARATOR, str(v))

            contents += '\n{}'.format(InputParser._END_SECTION)
            if i < lastIndex:
                contents += '\n\n'

        with open(file_name, 'w') as f:
            print(contents, file=f)
Beispiel #7
0
def _register_driver(cls):
    # Verify that the driver is not already registered.
    if cls in [driver.cls for driver in _REGISTERED_DRIVERS.values()]:
        raise QiskitChemistryError('Could not register class {} is already registered'.format(cls))

    # Verify that it has a minimal valid configuration.
    try:
        driver_name = cls.CONFIGURATION['name']
    except (LookupError, TypeError):
        raise QiskitChemistryError('Could not register driver: invalid configuration')

    # Verify that the driver is valid
    check_driver_valid = getattr(cls, 'check_driver_valid', None)
    if check_driver_valid is not None:
        try:
            check_driver_valid()
        except Exception as e:
            logger.debug(str(e))
            raise QiskitChemistryError('Could not register class {}. Name {} is not valid'.format(cls, driver_name)) from e

    if driver_name in _REGISTERED_DRIVERS:
        raise QiskitChemistryError('Could not register class {}. Name {} {} is already registered'.format(cls,
                                                                                                          driver_name,
                                                                                                          _REGISTERED_DRIVERS[driver_name].cls))

    # Append the driver to the `registered_classes` dict.
    _REGISTERED_DRIVERS[driver_name] = RegisteredDriver(driver_name, cls, copy.deepcopy(cls.CONFIGURATION))
    return driver_name
Beispiel #8
0
    def _augment_config(self, fname, cfg):
        cfgaug = ""
        with io.StringIO() as outf:
            with io.StringIO(cfg) as inf:
                # Add our Route line at the end of any existing ones
                line = ""
                added = False
                while not added:
                    line = inf.readline()
                    if not line:
                        break
                    if line.startswith('#'):
                        outf.write(line)
                        while not added:
                            line = inf.readline()
                            if not line:
                                raise QiskitChemistryError('Unexpected end of Gaussian input')
                            if len(line.strip()) == 0:
                                outf.write('# Window=Full Int=NoRaff Symm=(NoInt,None) output=(matrix,i4labels,mo2el) tran=full\n')
                                added = True
                            outf.write(line)
                    else:
                        outf.write(line)

                # Now add our filename after the title and molecule but before any additional data. We located
                # the end of the # section by looking for a blank line after the first #. Allows comment lines
                # to be inter-mixed with Route lines if that's ever done. From here we need to see two sections
                # more, the title and molecule so we can add the filename.
                added = False
                section_count = 0
                blank = True
                while not added:
                    line = inf.readline()
                    if not line:
                        raise QiskitChemistryError('Unexpected end of Gaussian input')
                    if len(line.strip()) == 0:
                        blank = True
                        if section_count == 2:
                            break
                    else:
                        if blank:
                            section_count += 1
                            blank = False
                    outf.write(line)

                outf.write(line)
                outf.write(fname)
                outf.write('\n\n')

                # Whatever is left in the original config we just append without further inspection
                while True:
                    line = inf.readline()
                    if not line:
                        break
                    outf.write(line)

                cfgaug = outf.getvalue()

        return cfgaug
Beispiel #9
0
    def check_driver_valid():
        err_msg = 'PyQuante2 is not installed. See https://github.com/rpmuller/pyquante2'
        try:
            spec = importlib.util.find_spec('pyquante2')
            if spec is not None:
                return
        except Exception as e:
            logger.debug('PyQuante2 check error {}'.format(str(e)))
            raise QiskitChemistryError(err_msg) from e

        raise QiskitChemistryError(err_msg)
Beispiel #10
0
    def check_driver_valid():
        err_msg = "PySCF is not installed. See https://sunqm.github.io/pyscf/install.html"
        try:
            spec = importlib.util.find_spec('pyscf')
            if spec is not None:
                return
        except Exception as e:
            logger.debug('PySCF check error {}'.format(str(e)))
            raise QiskitChemistryError(err_msg) from e

        raise QiskitChemistryError(err_msg)
Beispiel #11
0
    def _check_valid():
        err_msg = 'PyQuante2 is not installed. See https://github.com/rpmuller/pyquante2'
        try:
            spec = importlib.util.find_spec('pyquante2')
            if spec is not None:
                return
        except Exception as ex:  # pylint: disable=broad-except
            logger.debug('PyQuante2 check error %s', str(ex))
            raise QiskitChemistryError(err_msg) from ex

        raise QiskitChemistryError(err_msg)
Beispiel #12
0
    def _process_z2symmetry_reduction(self, qubit_op, aux_ops):

        z2_symmetries = Z2Symmetries.find_Z2_symmetries(qubit_op)
        if z2_symmetries.is_empty():
            logger.debug('No Z2 symmetries found')
            z2_qubit_op = qubit_op
            z2_aux_ops = aux_ops
            z2_symmetries = Z2Symmetries([], [], [], None)
        else:
            logger.debug('%s Z2 symmetries found: %s', len(z2_symmetries.symmetries),
                         ','.join([symm.to_label() for symm in z2_symmetries.symmetries]))

            # Check auxiliary operators commute with main operator's symmetry
            logger.debug('Checking operators commute with symmetry:')
            symmetry_ops = []
            for symmetry in z2_symmetries.symmetries:
                symmetry_ops.append(WeightedPauliOperator(paulis=[[1.0, symmetry]]))
            commutes = Hamiltonian._check_commutes(symmetry_ops, qubit_op)
            if not commutes:
                raise QiskitChemistryError('Z2 symmetry failure main operator must commute '
                                           'with symmetries found from it')
            for i, aux_op in enumerate(aux_ops):
                commutes = Hamiltonian._check_commutes(symmetry_ops, aux_op)
                if not commutes:
                    aux_ops[i] = None  # Discard since no meaningful measurement can be done

            if self._z2symmetry_reduction == 'auto':
                hf_state = HartreeFock(num_orbitals=self._molecule_info[self.INFO_NUM_ORBITALS],
                                       qubit_mapping=self._qubit_mapping,
                                       two_qubit_reduction=self._two_qubit_reduction,
                                       num_particles=self._molecule_info[self.INFO_NUM_PARTICLES])
                z2_symmetries = Hamiltonian._pick_sector(z2_symmetries, hf_state.bitstr)
            else:
                if len(self._z2symmetry_reduction) != len(z2_symmetries.symmetries):
                    raise QiskitChemistryError('z2symmetry_reduction tapering values list has '
                                               'invalid length {} should be {}'.
                                               format(len(self._z2symmetry_reduction),
                                                      len(z2_symmetries.symmetries)))
                valid = np.all(np.isin(self._z2symmetry_reduction, [-1, 1]))
                if not valid:
                    raise QiskitChemistryError('z2symmetry_reduction tapering values list must '
                                               'contain -1\'s and/or 1\'s only was {}'.
                                               format(self._z2symmetry_reduction,))
                z2_symmetries.tapering_values = self._z2symmetry_reduction

            logger.debug('Apply symmetry with tapering values %s', z2_symmetries.tapering_values)
            chop_to = 0.00000001  # Use same threshold as qubit mapping to chop tapered operator
            z2_qubit_op = z2_symmetries.taper(qubit_op).chop(chop_to)
            z2_aux_ops = []
            for aux_op in aux_ops:
                z2_aux_ops.append(z2_symmetries.taper(aux_op).chop(chop_to) if aux_op is not None
                                  else None)

        return z2_qubit_op, z2_aux_ops, z2_symmetries
Beispiel #13
0
    def check_driver_valid():
        err_msg = "PySCF is not installed. Use 'pip install pyscf'"
        try:
            spec = importlib.util.find_spec('pyscf')
            if spec is not None:
                return
        except Exception as e:
            logger.debug('PySCF check error {}'.format(str(e)))
            raise QiskitChemistryError(err_msg) from e

        raise QiskitChemistryError(err_msg)
Beispiel #14
0
    def check_driver_valid():
        err_msg = "PySCF is not installed. See https://sunqm.github.io/pyscf/install.html"
        try:
            spec = importlib.util.find_spec('pyscf')
            if spec is not None:
                return
        except Exception as ex:  # pylint: disable=broad-except
            logger.debug('PySCF check error %s', str(ex))
            raise QiskitChemistryError(err_msg) from ex

        raise QiskitChemistryError(err_msg)
Beispiel #15
0
    def export_dictionary(self, file_name):
        if file_name is None:
            raise QiskitChemistryError('Missing file path')

        file_name = file_name.strip()
        if len(file_name) == 0:
            raise QiskitChemistryError('Missing file path')

        value = json.loads(json.dumps(self.to_dictionary()))
        value = pprint.pformat(value, indent=4)
        with open(file_name, 'w') as f:
            print(value, file=f)
def run_g16(cfg: str) -> str:
    """
    Runs Gaussian 16. We capture stdout and if error log the last 10 lines that
    should include the error description from Gaussian.

    Args:
        cfg: configuration

    Returns:
        Text log output

    Raises:
        QiskitChemistryError: Failed run or log not captured.

    """
    process = None
    try:
        process = Popen(_GAUSSIAN_16,
                        stdin=PIPE,
                        stdout=PIPE,
                        universal_newlines=True)
        stdout, _ = process.communicate(cfg)
        process.wait()
    except Exception as ex:
        if process is not None:
            process.kill()

        raise QiskitChemistryError(
            '{} run has failed'.format(_GAUSSIAN_16_DESC)) from ex

    if process.returncode != 0:
        errmsg = ""
        if stdout is not None:
            lines = stdout.splitlines()
            start = 0
            if len(lines) > 10:
                start = len(lines) - 10
            for i in range(start, len(lines)):
                logger.error(lines[i])
                errmsg += lines[i] + "\n"
        raise QiskitChemistryError('{} process return code {}\n{}'.format(
            _GAUSSIAN_16_DESC, process.returncode, errmsg))

    all_text = ""
    if stdout is not None:
        lines = stdout.splitlines()
        for line in lines:
            all_text += line + "\n"

    logger.debug("Gaussian output:\n%s", all_text)

    return all_text
Beispiel #17
0
    def export_dictionary(self, file_name):
        """ export data to python dictionary, saving to file """
        if file_name is None:
            raise QiskitChemistryError('Missing file path')

        file_name = file_name.strip()
        if not file_name:
            raise QiskitChemistryError('Missing file path')

        value = json.loads(json.dumps(self.to_dictionary()))
        value = pprint.pformat(value, indent=4)
        with open(file_name, 'w') as file:
            print(value, file=file)
    def _validate_operator_problem(self):
        operator_name = self.get_section_property(InputParser.OPERATOR, JSONSchema.NAME)
        if operator_name is None:
            return

        problem_name = self.get_section_property(JSONSchema.PROBLEM, JSONSchema.NAME)
        if problem_name is None:
            problem_name = self.get_property_default_value(JSONSchema.PROBLEM, JSONSchema.NAME)

        if problem_name is None:
            raise QiskitChemistryError("No algorithm 'problem' section found on input.")

        problems = InputParser.get_operator_problems(operator_name)
        if problem_name not in problems:
            raise QiskitChemistryError("Problem: {} not in the list of problems: {} for operator: {}.".format(problem_name, problems, operator_name))
Beispiel #19
0
    def process_substitutions(self, substitutions=None):
        """ change property values by their corresponding substitutions """
        if substitutions is not None and not isinstance(substitutions, dict):
            raise QiskitChemistryError(
                'Invalid substitution parameter: {}'.format(substitutions))

        if not self.is_substitution_allowed():
            return {}

        result = {}
        for key, value in self._substitutions.items():
            key_items = key.split('.')
            if len(key_items) != 3:
                raise QiskitChemistryError(
                    'Invalid substitution key: {}'.format(key))

            name = self.get_property_default_value(key_items[0],
                                                   JSONSchema.NAME)
            name = self.get_section_property(key_items[0], JSONSchema.NAME,
                                             name)
            if name != key_items[1]:
                continue

            value_set = False
            value_items = value.split('.')
            if len(value_items) == 3:
                name = self.get_section_property(value_items[0],
                                                 JSONSchema.NAME)
                if name == value_items[1]:
                    v = self.get_property_default_value(
                        value_items[0], value_items[2])
                    v = self.get_section_property(value_items[0],
                                                  value_items[2], v)
                    if v is not None:
                        self.set_section_property(key_items[0], key_items[2],
                                                  v)
                        result[key] = v
                        value_set = True

            if value_set or substitutions is None:
                continue

            if value in substitutions:
                self.set_section_property(key_items[0], key_items[2],
                                          substitutions[value])
                result[key] = substitutions[value]

        return result
Beispiel #20
0
    def init_from_input(cls, section):
        """
        Initialize via section dictionary.

        Args:
            section (dict): section dictionary

        Returns:
            PySCFDriver: Driver object
        Raises:
            QiskitChemistryError: Invalid or missing section
        """
        if section is None or not isinstance(section, dict):
            raise QiskitChemistryError('Invalid or missing section {}'.format(section))

        params = section
        kwargs = {}
        for k, v in params.items():
            if k == 'unit':
                v = UnitsType(v)
            elif k == 'hf_method':
                v = HFMethodType(v)
            elif k == 'init_guess':
                v = InitialGuess(v)

            kwargs[k] = v

        logger.debug('init_from_input: %s', kwargs)
        return cls(**kwargs)
Beispiel #21
0
    def __init__(self,
                 atom,
                 unit=UnitsType.ANGSTROM,
                 charge=0,
                 spin=0,
                 basis='sto3g',
                 max_memory=None):
        """
        Initializer
        Args:
            atom (str or list): atom list or string separated by semicolons or line breaks
            unit (UnitsType): angstrom or bohr
            charge (int): charge
            spin (int): spin
            basis (str): basis set
            max_memory (int): maximum memory
        """
        if not isinstance(atom, list) and not isinstance(atom, str):
            raise QiskitChemistryError(
                "Invalid atom input for PYSCF Driver '{}'".format(atom))

        if isinstance(atom, list):
            atom = ';'.join(atom)
        else:
            atom = atom.replace('\n', ';')

        unit = unit.value
        self.validate(locals())
        super().__init__()
        self._atom = atom
        self._unit = unit
        self._charge = charge
        self._spin = spin
        self._basis = basis
        self._max_memory = max_memory
Beispiel #22
0
    def _update_operator_problem(self):
        problem_name = self.get_section_property(JSONSchema.PROBLEM,
                                                 JSONSchema.NAME)
        if problem_name is None:
            problem_name = self.get_property_default_value(
                JSONSchema.PROBLEM, JSONSchema.NAME)

        if problem_name is None:
            raise QiskitChemistryError(
                "No algorithm 'problem' section found on input.")

        operator_name = self.get_section_property(InputParser.OPERATOR,
                                                  JSONSchema.NAME)
        if operator_name is not None and problem_name in InputParser.get_operator_problems(
                operator_name):
            return

        for operator_name in local_chemistry_operators():
            if problem_name in self.get_operator_problems(operator_name):
                # set to the first input to solve the problem
                self.set_section_property(InputParser.OPERATOR,
                                          JSONSchema.NAME, operator_name)
                return

        # no input solve this problem, remove section
        self.delete_section(InputParser.OPERATOR)
Beispiel #23
0
    def _process_line(self, section, line):
        stripLine = line.strip()
        if len(stripLine) == 0:
            if section is not None:
                section['data'].append(line)

            return section

        if stripLine.lower().startswith(InputParser._END_SECTION):
            if section is not None:
                self._sections[section[
                    JSONSchema.NAME]] = self._process_section(section)
            return None

        if stripLine.startswith(InputParser._START_SECTION):
            if section is not None:
                raise QiskitChemistryError(
                    'New section "{0}" starting before the end of previuos section "{1}"'
                    .format(line, section[JSONSchema.NAME]))

            return OrderedDict([(JSONSchema.NAME, stripLine[1:].lower()),
                                ('data', [])])

        if section is None:
            return section

        section['data'].append(line)

        return section
Beispiel #24
0
    def __init__(self,
                 atoms,
                 units=UnitsType.ANGSTROM,
                 charge=0,
                 multiplicity=1,
                 basis=BasisType.BSTO3G):
        """
        Initializer
        Args:
            atoms (str or list): atoms list or string separated by semicolons or line breaks
            units (UnitsType): angstrom or bohr
            charge (int): charge
            multiplicity (int): spin multiplicity
            basis (BasisType): sto3g or 6-31g or 6-31g**
        """
        if not isinstance(atoms, list) and not isinstance(atoms, str):
            raise QiskitChemistryError(
                "Invalid atom input for PYQUANTE Driver '{}'".format(atoms))

        if isinstance(atoms, list):
            atoms = ';'.join(atoms)
        else:
            atoms = atoms.replace('\n', ';')

        units = units.value
        basis = basis.value

        self.validate(locals())
        super().__init__()
        self._atoms = atoms
        self._units = units
        self._charge = charge
        self._multiplicity = multiplicity
        self._basis = basis
Beispiel #25
0
    def init_from_input(cls, section):
        """
        Initialize via section dictionary.

        Args:
            params (dict): section dictionary

        Returns:
            Driver: Driver object
        """
        if section is None or not isinstance(section, dict):
            raise QiskitChemistryError(
                'Invalid or missing section {}'.format(section))

        params = section
        kwargs = {}
        for k, v in params.items():
            if k == PyQuanteDriver.KEY_UNITS:
                v = UnitsType(v)
            elif k == PyQuanteDriver.KEY_BASIS:
                v = BasisType(v)

            kwargs[k] = v

        logger.debug('init_from_input: {}'.format(kwargs))
        return cls(**kwargs)
def _parse_atom(val):
    if val is None or len(val) < 1:
        raise QiskitChemistryError('Molecule atom format error: empty')

    parts = re.split(r'\s+', val)
    if len(parts) != 4:
        raise QiskitChemistryError('Molecule atom format error: ' + val)

    parts[0] = parts[0].lower().capitalize()
    if not parts[0].isdigit():
        if parts[0] in QMolecule.symbols:
            parts[0] = QMolecule.symbols.index(parts[0])
        else:
            raise QiskitChemistryError('Molecule atom symbol error: ' + parts[0])

    return int(float(parts[0])), float(parts[1]), float(parts[2]), float(parts[3])
Beispiel #27
0
def compute_integrals(atoms,
                      units,
                      charge,
                      multiplicity,
                      basis,
                      hf_method='rhf',
                      tol=1e-8,
                      maxiters=100):
    """ Compute integrals """
    # Get config from input parameters
    # Molecule is in this format xyz as below or in Z-matrix e.g "H; O 1 1.08; H 2 1.08 1 107.5":
    # atoms=H .0 .0 .0; H .0 .0 0.2
    # units=Angstrom
    # charge=0
    # multiplicity=1
    # where we support symbol for atom as well as number

    units = _check_units(units)
    mol = _parse_molecule(atoms, units, charge, multiplicity)
    hf_method = hf_method.lower()

    try:
        q_mol = _calculate_integrals(mol, basis, hf_method, tol, maxiters)
    except Exception as exc:
        raise QiskitChemistryError(
            'Failed electronic structure computation') from exc

    return q_mol
Beispiel #28
0
def _check_units(units):
    if units.lower() in ["angstrom", "ang", "a"]:
        units = 'Angstrom'
    elif units.lower() in ["bohr", "b"]:
        units = 'Bohr'
    else:
        raise QiskitChemistryError('Molecule units format error: ' + units)
    return units
def _parse_molecule(val, units, charge, multiplicity):
    val = _check_molecule_format(val)

    parts = [x.strip() for x in val.split(';')]
    if parts is None or len(parts) < 1:
        raise QiskitChemistryError('Molecule format error: ' + val)
    geom = []
    for n in range(len(parts)):
        part = parts[n]
        geom.append(_parse_atom(part))

    if len(geom) < 1:
        raise QiskitChemistryError('Molecule format error: ' + val)

    try:
        return molecule(geom, units=units, charge=charge, multiplicity=multiplicity)
    except Exception as exc:
        raise QiskitChemistryError('Failed to create molecule') from exc
Beispiel #30
0
def _calculate_integrals(molecule, basis='sto3g', calc_type='rhf'):
    """Function to calculate the one and two electron terms. Perform a Hartree-Fock calculation in
        the given basis.
    Args:
        molecule : A pyquante2 molecular object.
        basis : The basis set for the electronic structure computation
        calc_type: rhf, uhf, rohf
    Returns:
        ehf : Hartree-Fock energy
        enuke: Nuclear repulsion energy
        norbs : Number of orbitals
        mohij : One electron terms of the Hamiltonian.
        mohijkl : Two electron terms of the Hamiltonian.
        orbs: Molecular orbital coefficients
        orbs_energy: Orbital energies
    """
    bfs = basisset(molecule, basis)
    integrals = onee_integrals(bfs, molecule)
    hij = integrals.T + integrals.V
    hijkl_compressed = twoe_integrals(bfs)

    # convert overlap integrals to molecular basis
    # calculate the Hartree-Fock solution of the molecule

    if calc_type == 'rhf':
        solver = rhf(molecule, bfs)
    elif calc_type == 'rohf':
        solver = rohf(molecule, bfs)
    elif calc_type == 'uhf':
        solver = uhf(molecule, bfs)
    else:
        raise QiskitChemistryError('Invalid calc_type: {}'.format(calc_type))
    logger.debug('Solver name {}'.format(solver.name))
    ehf = solver.converge()
    if hasattr(solver, 'orbs'):
        orbs = solver.orbs
    else:
        orbs = solver.orbsa
    norbs = len(orbs)
    if hasattr(solver, 'orbe'):
        orbs_energy = solver.orbe
    else:
        orbs_energy = solver.orbea
    enuke = molecule.nuclear_repulsion()
    # Get ints in molecular orbital basis
    mohij = simx(hij, orbs)
    mohijkl_compressed = transformintegrals(hijkl_compressed, orbs)
    mohijkl = np.zeros((norbs, norbs, norbs, norbs))
    for i in range(norbs):
        for j in range(norbs):
            for k in range(norbs):
                for l in range(norbs):
                    mohijkl[i, j, k,
                            l] = mohijkl_compressed[ijkl2intindex(i, j, k, l)]

    return ehf[0], enuke, norbs, mohij, mohijkl, orbs, orbs_energy