SAPT calculation input file from Gaussian .log file

Hello,
I am a newcomer to PSI4 and learning my way around SAPT-0 calculations using PSI4. I wonder if there is a way to read the geometry of a non-covalent complex of 2 molecules from a geometry optimization output carried out using Gaussian 16.
I have done SAPT0 calculation in which I copied the coordinates by hand and ran the calculation. However, I have more than 100 such calculations and was wondering if there is a way to get psi4 to read Gaussian .log file to extract coordinates.

Thank you,

molname

#! SAPT 0

setting available memory to 48 GB

memory 48 GB

molecule part1{
0 1

}
molecule part2{
0 1

}

set {
basis jun-cc-pVDZ
scf_type DF
freeze_core True
}
energy(‘sapt0’)

There is no build-in way. Common practise is to write a short bash/python/awk/etc. script to do such specific tasks.

The cclib library may help though I never used it.

If you a dimer you can use the auto_fragments() function as shown here: psi4/input.dat at master · psi4/psi4 · GitHub
to simplify the psi4 input.

Ok, thank you. I will try that and/or play around with newzmat or obabel to see if that could help.

Sorry for the late reply. You’ve probably already found a solution, but AaronTools is a Python module that can read Gaussian output files and write Psi4 input files (I am an AaronTools developer). Psi4 input files are very flexible, and AaronTools cannot take full advantage of that. However, it can make SAPT input files with defined monomers. Here’s a quick example I set up for a benzene dimer:

from AaronTools.geometry import Geometry
from AaronTools.theory import Theory, SAPTMethod, SinglePointJob

sapt_theory = Theory(
    method=SAPTMethod("sapt0"),
    basis="jun-cc-pVDZ",
    job_type="energy",
    charge=[0, 0, 0], # net charge, and the charge on both monomers
    multiplicity=[1, 1, 1], # overall multiplicity, and multiplicity of both monomers
    memory=8,
    processors=4,
    settings={
        "scf_type": "DF",
        "freeze_core": "true",
    },
)

# read the benzene structure
# make a copy of it and shift the Z coordinates by 3.5 A for the 2nd monomer
# alternatively, we could read a different file
monomer1 = Geometry("benzene.xyz")
monomer2 = monomer1.copy()
monomer2.coord_shift([0, 0, 3.5])

# create a new geometry by combining both monomers
# need to define components for SAPT
combined_structure = Geometry(
    [*monomer1.atoms, *monomer2.atoms],
    components=[monomer1, monomer2],
)

combined_structure.write(
    outfile="benzene_dimer.in",
    style="psi4",
    theory=sapt_theory,
)

This read the benzene structure from an XYZ file, but reading a structure from Gaussian output works the same way - just use “some.log” instead of benzene.xyz. Here’s the resulting Psi4 input file:

#
set_num_threads(4)
memory 8 GB
basis {
    assign    jun-cc-pVDZ
}

molecule {
     0 1
    --
     0 1
     C       -1.97696       -2.32718        0.00126
     C       -2.36814       -1.29554        0.85518
     C       -1.67136       -0.08735        0.85440
     C       -0.58210        0.08919        0.00026
     C       -0.19077       -0.94241       -0.85309
     C       -0.88848       -2.15056       -0.85289
     H       -3.22679       -1.43483        1.52790
     H       -1.98002        0.72606        1.52699
     H        0.66766       -0.80358       -1.52636
     H       -0.57992       -2.96360       -1.52585
     H       -0.03766        1.03348       -0.00013
     H       -2.52191       -3.27117        0.00170
    --
     0 1
     C       -1.97696       -2.32718        3.50126
     C       -2.36814       -1.29554        4.35518
     C       -1.67136       -0.08735        4.35440
     C       -0.58210        0.08919        3.50026
     C       -0.19077       -0.94241        2.64691
     C       -0.88848       -2.15056        2.64711
     H       -3.22679       -1.43483        5.02790
     H       -1.98002        0.72606        5.02699
     H        0.66766       -0.80358        1.97364
     H       -0.57992       -2.96360        1.97415
     H       -0.03766        1.03348        3.49987
     H       -2.52191       -3.27117        3.50170
}

set {
    scf_type                DF
    freeze_core             true
}

nrg = energy('sapt0')

You can also create an input file using auto_fragments() with a few adjustments. You don’t need to use a SAPTMethod, specify charge and multiplicity for each monomer, or specify the components when creating the combined geometry. You also will have to add a keyword to include auto_fragments() before the energy computation:

sapt_theory = Theory(
    method="sapt0",
    basis="jun-cc-pVDZ",
    job_type="energy",
    charge=0,
    multiplicity=1,
    memory=8,
    processors=4,
    settings={
        "scf_type": "DF",
        "freeze_core": "true",
    },
    before_job=["activate(auto_fragments())"],
)

AaronTools can also read Psi4 output, including the SAPT results:

from AaronTools.fileIO import FileReader

# read in the output file
# just_geom=False means read data, not just structures
fr = FileReader("benzene_dimer.out", just_geom=False)

# print some of the SAPT results (in Hartrees)
# every energy in the "SAPT Results" section is read
# the keys are just whatever is in the first column
# (e.g. "Ind20,r" and "Total sSAPT0" are also valid keys)
for key in ["Electrostatics", "Exchange", "Induction", "Dispersion"]:
    print(key, fr[key])

There’s an installation guide on the AaronTools wiki. Running “python -m pip install AaronTools” should work. The wiki also has some other examples for using our Theory, Geometry, and FileReader objects.

2 Likes

One more thing - if the Gaussian output file is the structure of the dimer, you can define the monomers (components) after reading in the structure:

combined_structure = Geometry("dimer.log")
combined_structure.components = [
    Geometry(combined_structure.find("1-12")),
    Geometry(combined_structure.find("13-24")),
]

Here, I just used the atom indices to identify the monomers. We have a function for detecting the monomers like auto_fragments, but I don’t think it’s on the PyPI version of AaronTools yet. That would look like:

combined_structure.components = [
    Geometry(monomer) for monomer in combined_structure.get_monomers()
]