示例#1
0
文件: wavefn.py 项目: molmod/hipart
 def __init__(self, filename):
     self.filename = filename
     self.prefix = filename[:-5]
     fchk = FCHKFile(filename,
                     field_labels=[
                         "Charge",
                         "Number of basis functions",
                         "Dipole Moment",
                         "Number of electrons",
                         "Number of alpha electrons",
                         "Number of beta electrons",
                         "Alpha Orbital Energies",
                         "Beta Orbital Energies",
                     ])
     # for usage by the rest of the program
     self.charge = fchk.fields["Charge"]
     self.num_orbitals = fchk.fields["Number of basis functions"]
     self.dipole = fchk.fields["Dipole Moment"]
     self.num_electrons = fchk.fields["Number of electrons"]
     self.num_alpha = fchk.fields["Number of alpha electrons"]
     self.num_beta = fchk.fields["Number of beta electrons"]
     self.restricted = "Beta Orbital Energies" not in fchk.fields
     self.molecule = fchk.molecule
     # for internal usage
     self._hack_fchk = self.restricted and (self.num_alpha != self.num_beta)
     if "mp2" in fchk.lot.lower():
         self._density_type = "mp2"
     elif "mp3" in fchk.lot.lower():
         self._density_type = "mp3"
     elif "mp4" in fchk.lot.lower():
         self._density_type = "mp4"
     else:
         self._density_type = "scf"
示例#2
0
def test_o2_cc_pvtz_cart_num():
    tmpdir, fn_fchk = setup_gaussian("o2_cc_pvtz_cart")
    fchk = FCHKFile(fn_fchk)
    basis = GaussianBasis.from_fchk(fchk)
    assert (basis.num_shells == 20)
    print basis.num_dof
    assert (basis.num_dof == 70)
示例#3
0
def test_orb0_hf_sto3g():
    tmpdir, fn_fchk = setup_gaussian("hf_sto3g")
    fchk = FCHKFile(fn_fchk)
    shutil.rmtree(tmpdir)
    basis = GaussianBasis.from_fchk(fchk)
    weights = fchk.fields["Alpha MO coefficients"][:basis.num_dof]
    points = ref_data_hf_sto3g_orb0[:, :3]
    fns = basis.call_gint_grid(gint1_fns_basis, weights.reshape((1, -1)),
                               points * angstrom, 1)[0]
    assert (abs(fns - ref_data_hf_sto3g_orb0[:, 3]).max() < 1e-10)
示例#4
0
def load_molecule_g98fchk(fn_freq, fn_ener=None, energy=None):
    """Load a molecule from Gaussian98 formatted checkpoint files.

       Arguments:
         | ``fn_freq`` -- The formatted checkpoint file of the frequency job.

       Optional arguments:
         | ``fn_ener`` -- The formatted checkpoint file of a single point
                          computation for the energy. When not given, the energy
                          is taken from the frequency job.
         | ``energy`` -- Override the energy from the formatted checkpoint file
                         with the given value.
    """

    fchk_freq = FCHKFile(fn_freq,
                         ignore_errors=True,
                         field_labels=[
                             "Cartesian Force Constants", "Total Energy",
                             "Multiplicity", "Cartesian Gradient"
                         ])
    if fn_ener is None:
        fchk_ener = fchk_freq
    else:
        fchk_ener = FCHKFile(fn_ener,
                             ignore_errors=True,
                             field_labels=["Total Energy"])
    masses = np.array([g98_masses[n - 1] for n in fchk_freq.molecule.numbers])
    if energy is None:
        energy = fchk_ener.fields["Total Energy"]

    return Molecule(
        fchk_freq.molecule.numbers,
        fchk_freq.molecule.coordinates,
        masses,
        energy,
        np.reshape(np.array(fchk_freq.fields["Cartesian Gradient"]),
                   (len(fchk_freq.molecule.numbers), 3)),
        fchk_freq.get_hessian(),
        fchk_freq.fields["Multiplicity"],
        None,  # gaussian is very poor at computing the rotational symmetry number
        False,
    )
示例#5
0
def test_orb0_o2_cc_pvtz_pure():
    tmpdir, fn_fchk = setup_gaussian("o2_cc_pvtz_pure")
    fchk = FCHKFile(fn_fchk)
    shutil.rmtree(tmpdir)
    basis = GaussianBasis.from_fchk(fchk)
    weights = fchk.fields["Alpha MO coefficients"][:basis.num_dof]
    weights = weights[basis.g03_permutation]
    points = ref_data_o2_cc_pvtz_pure_orb0[:, :3]
    fns = basis.call_gint_grid(gint1_fns_basis, weights.reshape((1, -1)),
                               points * angstrom, 1)[0]
    assert (abs(fns - ref_data_o2_cc_pvtz_pure_orb0[:, 3]).max() < 1e-10)
示例#6
0
 def get_mol(self, state, root):
     if self.name == "opt":
         # load the initial geometry
         mol = Molecule.from_file("init/%s.xyz" % state.name)
     else:
         # load the optimized geometry
         fn_fchk = "%s/%s__opt/gaussian.fchk" % (root, state.name)
         mol = FCHKFile(fn_fchk, field_labels=[]).molecule
     with open("init/%s.fragments" % state.name) as f:
         mol.charge_mult = f.readline().split()
         mol.tags = f.readline().split()
     return mol
示例#7
0
def test_orb0_h_sto3g():
    tmpdir, fn_fchk = setup_gaussian("h_sto3g")
    fchk = FCHKFile(fn_fchk)
    shutil.rmtree(tmpdir)
    basis = GaussianBasis.from_fchk(fchk)
    # real test for the output
    weights = fchk.fields["Alpha MO coefficients"][:basis.num_dof]
    points = ref_data_h_sto3g_orb0[:, :3]
    fns = basis.call_gint_grid(gint1_fns_basis, weights.reshape((1, -1)),
                               points * angstrom, 1)[0]
    assert (abs(fns - ref_data_h_sto3g_orb0[:, 3]).max() < 1e-10)
    # test error mechanism
    basis.shell_types[0] = 102
    assert_raises(ValueError, basis.call_gint_grid, gint1_fns_basis,
                  weights.reshape((1, -1)), points * angstrom, 1)
    basis.shell_types[0] = -763
    assert_raises(ValueError, basis.call_gint_grid, gint1_fns_basis,
                  weights.reshape((1, -1)), points * angstrom, 1)
示例#8
0
def test_pot_o2_cc_pvtz_pure():
    tmpdir, fn_fchk = setup_gaussian("o2_cc_pvtz_pure")
    fchk = FCHKFile(fn_fchk)
    shutil.rmtree(tmpdir)
    basis = GaussianBasis.from_fchk(fchk)
    dmat = fchk.fields["Total SCF Density"]
    reorder_dmat(dmat, basis.g03_permutation)
    points = ref_data_o2_cc_pvtz_pure_pot[:, :3] * angstrom
    ref_potential = ref_data_o2_cc_pvtz_pure_pot[:, 3]
    nuc_potential = 0.0
    for i in xrange(fchk.molecule.size):
        center = fchk.molecule.coordinates[i]
        Z = fchk.molecule.numbers[i]
        radius = numpy.sqrt(((points - center)**2).sum(axis=1))
        nuc_potential += Z / radius
    ref_potential -= nuc_potential
    potential = -basis.call_gint_grid(gint2_nai_dmat, dmat, points)
    assert (abs(potential - ref_potential).max() < 1e-6)
示例#9
0
def test_pot_h_sto3g():
    tmpdir, fn_fchk = setup_gaussian("h_sto3g")
    fchk = FCHKFile(fn_fchk)
    shutil.rmtree(tmpdir)
    basis = GaussianBasis.from_fchk(fchk)
    # real test for the output
    dmat = fchk.fields["Total SCF Density"]
    points = ref_data_h_sto3g_pot[:, :3] * angstrom
    radius = numpy.sqrt((points**2).sum(axis=1))
    ref_data_h_sto3g_pot[:, 3] -= 1 / radius
    potential = -basis.call_gint_grid(gint2_nai_dmat, dmat, points)
    assert (abs(potential - ref_data_h_sto3g_pot[:, 3]).max() < 1e-8)
    # test error mechanism
    basis.shell_types[0] = 102
    assert_raises(ValueError, basis.call_gint_grid, gint2_nai_dmat, dmat,
                  points * angstrom)
    basis.shell_types[0] = -763
    assert_raises(ValueError, basis.call_gint_grid, gint2_nai_dmat, dmat,
                  points * angstrom)
示例#10
0
    def from_file(cls, filename):
        """Construct a molecule object read from the given file.

           The file format is inferred from the extensions. Currently supported
           formats are: ``*.cml``, ``*.fchk``, ``*.pdb``, ``*.sdf``, ``*.xyz``

           If a file contains more than one molecule, only the first one is
           read.

           Argument:
            | ``filename``  --  the name of the file containing the molecule

           Example usage::

             >>> mol = Molecule.from_file("foo.xyz")
        """
        # TODO: many different API's to load files. brrr...
        if filename.endswith(".cml"):
            from molmod.io import load_cml
            return load_cml(filename)[0]
        elif filename.endswith(".fchk"):
            from molmod.io import FCHKFile
            fchk = FCHKFile(filename, field_labels=[])
            return fchk.molecule
        elif filename.endswith(".pdb"):
            from molmod.io import load_pdb
            return load_pdb(filename)
        elif filename.endswith(".sdf"):
            from molmod.io import SDFReader
            return next(SDFReader(filename))
        elif filename.endswith(".xyz"):
            from molmod.io import XYZReader
            xyz_reader = XYZReader(filename)
            title, coordinates = next(xyz_reader)
            return Molecule(xyz_reader.numbers,
                            coordinates,
                            title,
                            symbols=xyz_reader.symbols)
        else:
            raise ValueError("Could not determine file format for %s." %
                             filename)
示例#11
0
def test_dens_h_sto3g():
    tmpdir, fn_fchk = setup_gaussian("h_sto3g")
    fchk = FCHKFile(fn_fchk)
    shutil.rmtree(tmpdir)
    basis = GaussianBasis.from_fchk(fchk)
    weights = fchk.fields["Alpha MO coefficients"][:basis.num_dof]
    weights = weights[basis.g03_permutation]
    points = ref_data_h_sto3g_orb0[:, :3]
    orb0 = basis.call_gint_grid(gint1_fns_basis, weights.reshape((1, -1)),
                                points * angstrom, 1)[0]
    num_dmat = (basis.num_dof * (basis.num_dof + 1)) / 2
    dmat = fchk.fields["Total SCF Density"][:num_dmat]
    density = basis.call_gint_grid(gint1_fn_dmat, dmat, points * angstrom)
    assert (abs(orb0**2 - density).max() < 1e-10)
    # test error mechanism
    basis.shell_types[0] = 102
    assert_raises(ValueError, basis.call_gint_grid, gint1_fn_dmat, dmat,
                  points * angstrom, 1)
    basis.shell_types[0] = -763
    assert_raises(ValueError, basis.call_gint_grid, gint1_fn_dmat, dmat,
                  points * angstrom, 1)
示例#12
0
def test_dens_o2_cc_pvtz_pure():
    tmpdir, fn_fchk = setup_gaussian("o2_cc_pvtz_pure")
    fchk = FCHKFile(fn_fchk)
    shutil.rmtree(tmpdir)
    basis = GaussianBasis.from_fchk(fchk)
    num_dmat = (basis.num_dof * (basis.num_dof + 1)) / 2

    points = ref_data_o2_cc_pvtz_pure_orb0[:, :3]

    dmat = fchk.fields["Total SCF Density"][:num_dmat]
    reorder_dmat(dmat, basis.g03_permutation)
    density = basis.call_gint_grid(gint1_fn_dmat, dmat, points * angstrom)

    num_alpha = fchk.fields["Number of alpha electrons"]
    weights = fchk.fields["Alpha MO coefficients"][:num_alpha * basis.num_dof]
    weights = weights.reshape((num_alpha, basis.num_dof))
    weights = weights[:, basis.g03_permutation]
    orbitals = basis.call_gint_grid(gint1_fns_basis, weights,
                                    points * angstrom, num_alpha)
    assert (orbitals.shape == (num_alpha, len(points)))
    expected_density = 2 * (orbitals**2).sum(axis=0)

    assert (abs(density - expected_density).max() < 1e-6)
示例#13
0
    N3 = coordinates.size
    jacobian = numpy.zeros((N3, len(ics)), float)
    for j, ic in enumerate(ics):
        # Let the ic object fill in each column of the Jacobian.
        ic.fill_jacobian_column(jacobian[:, j], coordinates)
    return jacobian


# This if block is only executed when this file is ran as a program, and not
# when it is loaded as a module.
if __name__ == "__main__":
    # Load the formatted checkpoint file with the frequency computation. This
    # file also contains the atomic numbers and the coordinates of the atoms,
    # and therefore one can access the dopamine molecule object through
    # fchk.molecule.
    fchk = FCHKFile("dopamine.fchk")
    # Set the default graph for the construction of the internal coordinates:
    fchk.molecule.set_default_graph()
    # Setup a list of internal coordinates
    ics = setup_ics(fchk.molecule.graph)
    # Compute the Jacobian.
    J = compute_jacobian(ics, fchk.molecule.coordinates)
    # Compute the pseudo-inverse, using a loose threshold for the singular
    # values to filter out equivalent internal coordinates.
    Jinv = numpy.linalg.pinv(J, 1e-5)
    # Get the Hessian in Cartesian coordinates.
    H = fchk.get_hessian()
    # Transform to internal coordinates.
    K = numpy.dot(Jinv, numpy.dot(H, Jinv.transpose()))
    # Make a nice printout of K.
    print("The Hessian in internal coordinates in kcal/mol/angstrom**2")
示例#14
0
 def load_ener(fn_fchk):
     fchk = FCHKFile(fn_fchk, field_labels=["Total Energy"])
     return fchk.fields["Total Energy"]
示例#15
0
def load_molecule_g03fchk(fn_freq, fn_ener=None, fn_vdw=None, energy=None, fn_punch=None):
    """Load a molecule from Gaussian03 formatted checkpoint files.

       Arguments:
         | ``fn_freq`` -- the formatted checkpoint file of the frequency job

       Optional arguments:
         | ``fn_ener`` -- the formatted checkpoint file of a single point
                          computation for the energy. When not given, the energy
                          is taken from the frequency job.
         | ``fn_vdw`` -- An orca output file containing a Van der Waals
                         correction for the energy.
         | ``energy`` -- Override the energy from the formatted checkpoint file
                         with the given value.
         | ``punch`` -- A Gaussian derivatives punch file. When given, the
                        gradient and the Hessian are read from this file
                        instead.
    """

    fchk_freq = FCHKFile(fn_freq, ignore_errors=True, field_labels=[
        "Cartesian Force Constants", "Real atomic weights", "Total Energy",
        "Multiplicity", "Cartesian Gradient", "MicOpt",
    ])
    if fn_ener is None:
        fchk_ener = fchk_freq
    else:
        fchk_ener = FCHKFile(fn_ener, ignore_errors=True, field_labels=[
            "Total Energy"
        ])
    if energy is None:
        energy = fchk_ener.fields["Total Energy"]
    vdw = 0
    if fn_vdw is not None:
        from tamkin.io.dispersion import load_dftd_orca
        vdw = load_dftd_orca(fn_vdw)

    natom = fchk_freq.molecule.size
    if fchk_freq.molecule.size == 1 and \
       "Cartesian Force Constants" not in fchk_freq.fields:
        gradient = np.zeros((1,3), float)
        hessian = np.zeros((3,3), float)
    elif fn_punch is None:
        gradient = fchk_freq.fields["Cartesian Gradient"].copy()
        gradient.shape = (natom, 3)
        hessian = fchk_freq.get_hessian()
    else:
        gradient = np.zeros((natom, 3), float)
        hessian = np.zeros((3*natom, 3*natom), float)
        iterator = iter_floats_file(fn_punch)
        for i in xrange(natom):
            for j in xrange(3):
                gradient[i,j] = iterator.next()
        for i in xrange(3*natom):
            for j in xrange(i+1):
                v = iterator.next()
                hessian[i,j] = v
                hessian[j,i] = v

    if "MicOpt" in fchk_freq.fields:
        fixed = (fchk_freq.fields["MicOpt"] == -2).nonzero()[0]
        if len(fixed) == 0:
            fixed = None
    else:
        fixed = None

    return Molecule(
        fchk_freq.molecule.numbers,
        fchk_freq.molecule.coordinates,
        fchk_freq.fields["Real atomic weights"]*amu,
        energy+vdw,
        gradient,
        hessian,
        fchk_freq.fields["Multiplicity"],
        None, # gaussian is very poor at computing the rotational symmetry number
        False,
        title=fchk_freq.title,
        fixed=fixed,
    )
示例#16
0
def test_h_sto3g_num():
    tmpdir, fn_fchk = setup_gaussian("h_sto3g")
    fchk = FCHKFile(fn_fchk)
    basis = GaussianBasis.from_fchk(fchk)
    assert (basis.num_shells == 1)
    assert (basis.num_dof == 1)
示例#17
0
def get_pf(dn, temps):
    '''Construct a partition function from a molecule directory.

       **Arguments:**

       dn
            A molecule directory name

       temps
            A list of temperatures at which the properties of the molecule must be
            evaluated.
    '''
    print '  Loading partition function from', dn

    # A1) load the molecule
    molecule = load_molecule_g03fchk('%s/freq/gaussian.fchk' % dn)

    # A2) if present, load a more accurate energy
    fn_sp = '%s/sp/gaussian.fchk' % dn
    if os.path.isfile(fn_sp):
        from molmod.io import FCHKFile
        sp_energy = FCHKFile(fn_sp).fields['Total Energy']
        molecule = molecule.copy_with(energy=sp_energy)

    # A3) if present add a grimme correction
    fn_dftd3 = '%s/dftd3/dftd3.out' % dn
    if os.path.isfile(fn_dftd3):
        print '    Loading DFT-D3 corrections'
        disp_energy = load_dftd3(fn_dftd3)
        molecule = molecule.copy_with(energy=molecule.energy + disp_energy)

    # B) Load all rotors and keep directories of each rotor (dns_rotor).
    rotors = []
    dns_rotor = []

    # B1) load all rotors computed with Gaussian
    for dn_rotor in glob('%s/rotor_g_*' % dn):
        print '    Loading rotor', dn_rotor
        dns_rotor.append(dn_rotor)
        fn_log = '%s/gaussian.log' % dn_rotor
        # Load the config file
        rotor_cfg = load_cfg(os.path.join(dn_rotor, 'rotor.cfg'))
        # Load the rotational scan data from the Gaussian log file.
        rotor_scan = load_rotscan_g03log(fn_log,
                                         get_atom_indexes(rotor_cfg, 'top'))
        # Construct a Rotor object (solves Schrodinger equation etc.)
        rotor = Rotor(rotor_scan,
                      molecule,
                      suffix=os.path.basename(dn_rotor)[6:],
                      rotsym=rotor_cfg.get('rotsym', 1),
                      even=rotor_cfg.get('even', False),
                      num_levels=rotor_cfg.get('num_levels', 50),
                      dofmax=rotor_cfg.get('dofmax', 5),
                      v_threshold=v_threshold)
        rotors.append(rotor)

    # B2) load all free rotors
    for dn_rotor in glob('%s/rotor_f_*' % dn):
        print '    Loading rotor', dn_rotor
        dns_rotor.append(dn_rotor)
        fn_cfg = '%s/rotor.cfg' % dn_rotor
        # Load the config file
        rotor_cfg = load_cfg(fn_cfg)
        # Construct a Rotor object (solves Schrodinger equation etc.)
        rotor_scan = RotScan(get_atom_indexes(rotor_cfg, 'dihed'), molecule,
                             get_atom_indexes(rotor_cfg, 'top'))
        rotor = Rotor(rotor_scan,
                      molecule,
                      suffix=os.path.basename(dn_rotor)[6:],
                      rotsym=rotor_cfg.get('rotsym', 1),
                      num_levels=rotor_cfg.get('num_levels', 50),
                      dofmax=rotor_cfg.get('dofmax', 5),
                      v_threshold=v_threshold)
        rotors.append(rotor)

    # B3) load all custom rotors
    for dn_rotor in glob('%s/rotor_c_*' % dn):
        print '    Loading rotor', dn_rotor
        dns_rotor.append(dn_rotor)
        fn_dat = '%s/rotor.dat' % dn_rotor
        # Load the potential data
        potential = np.loadtxt(fn_dat).T
        # Load the config file
        rotor_cfg = load_cfg(os.path.join(dn_rotor, 'rotor.cfg'))
        # Construct a Rotor object (solves Schrodinger equation etc.)
        rotor_scan = RotScan(get_atom_indexes(rotor_cfg, 'dihed'), molecule,
                             get_atom_indexes(rotor_cfg, 'top'), potential)
        rotor = Rotor(rotor_scan,
                      molecule,
                      suffix=os.path.basename(dn_rotor)[6:],
                      rotsym=rotor_cfg.get('rotsym', 1),
                      even=rotor_cfg.get('even', False),
                      num_levels=rotor_cfg.get('num_levels', 50),
                      dofmax=rotor_cfg.get('dofmax', 5),
                      v_threshold=v_threshold)
        rotors.append(rotor)

    # C) Perform a normal mode analysis
    if molecule.fixed is None:
        print '    Performing NMA with fixed external degrees of freedom'
        nma = NMA(molecule,
                  ConstrainExt(gradient_threshold=gradient_threshold))
    else:
        print '    Performing NMA with fixed atoms: %s' % molecule.fixed
        nma = NMA(molecule, PHVA(molecule.fixed))

    # D) Define the partition function
    mol_cfg = load_cfg('%s/molecule.cfg' % dn)
    pf_contributions = [
        Vibrations(freq_scaling=mol_cfg.get('freq_scaling', 1.0),
                   zp_scaling=mol_cfg.get('zp_scaling', 1.0))
    ]
    if molecule.fixed is None:
        pf_contributions.append(ExtTrans())
        pf_contributions.append(ExtRot(mol_cfg.get('symnum', None)))
    pf_contributions.extend(rotors)
    pf = PartFun(nma, pf_contributions)
    # Store the atomic numbers as an attribute of the partition function (used
    # to check that no atoms get lost in a reaction.
    pf.numbers = molecule.numbers

    # E) Make plots of the rotor
    for dn_rotor, rotor in zip(dns_rotor, rotors):
        rotor.plot_levels('%s/levels.png' % dn_rotor, 300)

    # F) Write a partf.txt file
    pf.write_to_file('%s/partf.txt' % dn)

    # G) Write a thermo analysis if temperatures are provided
    if len(temps) > 0:
        ta = ThermoAnalysis(pf, temps)
        ta.write_to_file('%s/thermo.csv' % dn)

    return pf
示例#18
0
文件: wavefn.py 项目: molmod/hipart
    def __init__(self, filename, options):
        if len(options) == 1:
            density_type = options[0]
        elif len(options) == 0:
            density_type = None
        else:
            raise ValueError(
                "Only one option is supported for the FCHKWaveFunction")
        self.filename = filename
        self.options = options
        self.prefix = filename[:-5]
        fchk = FCHKFile(filename)
        # for use by the rest of the program
        self.charge = fchk.fields["Charge"]
        self.num_orbitals = fchk.fields["Number of basis functions"]
        self.dipole = fchk.fields["Dipole Moment"]
        self.num_electrons = fchk.fields["Number of electrons"]
        self.num_alpha = fchk.fields["Number of alpha electrons"]
        self.num_beta = fchk.fields["Number of beta electrons"]
        self.restricted = "Beta Orbital Energies" not in fchk.fields
        self.molecule = fchk.molecule
        self.nuclear_charges = fchk.fields["Nuclear charges"]
        # for internal usage
        if density_type is None:
            if "mp2" in fchk.lot.lower():
                density_type = "mp2"
            elif "mp3" in fchk.lot.lower():
                density_type = "mp3"
            elif "mp4" in fchk.lot.lower():
                density_type = "mp4"
            else:
                density_type = "scf"
        # electronic structure data
        self.basis = GaussianBasis.from_fchk(fchk)
        # orbitals
        self.alpha_orbital_energies = None
        self.beta_orbital_energies = None
        self.natural_orbitals = None
        self.alpha_orbitals = None
        self.beta_orbitals = None
        self.alpha_occupations = None
        self.beta_occupations = None
        self.natural_occupations = None
        if density_type == "scf":
            # Load orbital stuff only for scf computations.
            self.alpha_orbital_energies = fchk.fields["Alpha Orbital Energies"]
            self.beta_orbital_energies = fchk.fields.get(
                "Beta Orbital Energies", self.alpha_orbital_energies)
            self.alpha_orbitals = fchk.fields["Alpha MO coefficients"].reshape(
                (-1, self.basis.num_dof))
            self.alpha_orbitals = self.alpha_orbitals[:, self.basis.
                                                      g03_permutation]
            self.beta_orbitals = fchk.fields.get("Beta MO coefficients")
            if self.beta_orbitals is None:
                self.beta_orbitals = self.alpha_orbitals
            else:
                self.beta_orbitals = self.beta_orbitals.reshape(
                    (-1, self.basis.num_dof))[:, self.basis.g03_permutation]
            self.alpha_occupations = numpy.zeros(self.num_orbitals, float)
            self.alpha_occupations[:self.num_alpha] = 1.0
            if self.beta_orbitals is None:
                self.beta_occupations = self.alpha_occupations
            else:
                self.beta_occupations = numpy.zeros(self.num_orbitals, float)
                self.beta_occupations[:self.num_beta] = 1.0
            if self.restricted:
                self.natural_orbitals = self.alpha_orbitals
                self.natural_occupations = self.alpha_occupations + self.beta_occupations
                self.num_natural = max(self.num_alpha, self.num_beta)

        # density matrices
        hack_fchk = self.restricted and (
            self.num_alpha != self.num_beta) and density_type == "scf"
        if hack_fchk:
            # construct density matrices manually because the fchk file
            # contains the wrong one. we only do this for scf computations.
            n = self.basis.num_dof
            size = (n * (n + 1)) / 2
            self.density_matrix = numpy.zeros(size, float)
            add_orbitals_to_dmat(self.alpha_orbitals[:self.num_alpha],
                                 self.density_matrix)
            add_orbitals_to_dmat(self.beta_orbitals[:self.num_beta],
                                 self.density_matrix)
            self.spin_density_matrix = numpy.zeros(size, float)
            num_min = min(self.num_alpha, self.num_beta)
            num_max = max(self.num_alpha, self.num_beta)
            add_orbitals_to_dmat(self.alpha_orbitals[num_min:num_max],
                                 self.spin_density_matrix)
        else:
            self.density_matrix = None
            self.spin_density_matrix = None
            # load the density matrices
            for key in fchk.fields:
                if key.startswith("Total") and key.endswith("Density"):
                    if key[6:-8].lower() != density_type:
                        continue
                    assert self.density_matrix is None
                    dmat = fchk.fields[key]
                    reorder_dmat(dmat, self.basis.g03_permutation)
                    self.density_matrix = dmat
                elif key.startswith("Spin") and key.endswith("Density"):
                    if key[5:-8].lower() != density_type:
                        continue
                    assert self.spin_density_matrix is None
                    dmat = fchk.fields[key]
                    reorder_dmat(dmat, self.basis.g03_permutation)
                    self.spin_density_matrix = dmat
            if self.density_matrix is None:
                raise ValueError(
                    "Could not find the '%s' density matrix in the fchk file."
                    % self._density_type)