# Running Psi 3 from MPQC

Psi 3 is a suite of ab initio codes related to the original Psi package started in Prof.

Fritz Schaefer's group at UC Berkeley. Current version of MPQC works with stable versions of Psi 3 starting with 3.2.0. From now on we will refer to Psi 3 as simply Psi. Psi is written primarily in C and executes in serial mode only. The interface between Psi and MPQC is intended mainly for Psi users who wish to exploit MPQC's geometry optimization and frequency analyses capabilities with Psi energies and gradients.

The following sections explain how to use Psi from MPQC:

- How the MPQC-Psi interface works
- Environmental Variables
- Preparing an input file
- Psi Execution Environment
- PsiWavefunction specializations
- More examples

## How the MPQC-Psi interface works

The current version of the interface is rather slim. It is only possible to import energies and gradients computed with Psi into MPQC, i.e. wave functions cannot be imported. All MPQC-Psi interaction happens via text files and system calls. MPQC generates input file for Psi, calls appropriate Psi modules, and then parses the output files for energies and gradients.

## Environmental Variables

Several environmental variables are used to control MPQC-Psi interaction:

`PSIBIN`
  By default, MPQC will try to find Psi binaries under `/usr/local/psi/bin`. Use `PSIBIN` environmental variable to point to the right location.

The rest of the Psi environment is job specific and specified in the input file.

## Preparing an input file

As noted above, MPQC parses the input file, and as such the input file has to be in the MPQC OO input format. All features of usual MPQC input files are there (`mpqc` section, `mole` MolecularEnergy object, etc.). In addition the following rules apply:

- instead of using MPQC Wavefunction objects (CLHF, MBPT2, etc.), the Psi specific Wavefunction types (i.e. specializations of PsiWavefunction) have to be used. Presently the following specializations are supported: PsiCLHF, PsiHSOSHF, PsiUHF, PsiCCSD, PsiCCSD_T . The first three are directly analogous to MPQC Wavefunction types CLHF, HSOSHF, and UHF. The latter two do not have MPQC analogs yet. See appropriate class documentation on how to specify them properly.
- each Psi-specific Wavefunction object has to have a member object `psienv` of type PsiExEnv. PsiExEnv contains job specific information, such as the directory in which Psi input, output, and checkpoint files will be kept, filename prefix, scratch directories, etc. It makes sense to define one such object and simply refer to it from all PsiWavefunction objects. See PsiExEnv class documentation for more info.

## Psi Execution Environment

Each PsiWavefunction-derived class has to have a member object called `psienv` of type PsiExEnv. The following keywords are used by its KeyVal constructor:

`cwd`
  The directory where to keep Psi input, checkpoint, stdout, stderr, and other files. Default is `/tmp`.
`fileprefix`
  The file prefix to use for Psi checkpoint, scratch, and some ASCII files. Equivalent to keyword `name` in Psi `psi:files:default` section. Defaults to `psi`.
`stdout`
  The file into which to redirect standard output of Psi modules. Defaults to `psi.stdout`.
`stderr`
  The file into which to redirect standard error of Psi modules. Defaults to `psi.stderr`.
`nscratch`
  The number of locations over which to stripe Psi binary files. Equivalent to keyword `nvolume` in Psi `psi:files:default` section. Default is 1.
`scratch`
  The locations over which to stripe Psi binary files. Equivalent to keyword `volumex` in Psi `psi:files:default` section. There's no default.

Here's an example:

      psienv<PsiExEnv>: (
        cwd = ./
        fileprefix = psi.test
        nscratch = 2
        scratch = [ "/scratch1/" "/scratch2/" ]
      )

## PsiWavefunction specializations

Class PsiWavefunction is derived from class Wavefunction, hence its KeyVal constructor uses all keywords that Wavefunction's KeyVal constructor uses (`basis`, `molecule`, etc.). In addition, PsiWavefunction's KeyVal constructor looks for the following keywords in the input file:

`psienv`
  The PsiExEnv object that provides job specific Psi environment. There's no default.
`docc`
  An optional array of integers that specifies the number of doubly-occupied orbitals in each irrep.
`socc`
  An optional array of integers that specifies the number of singly-occupied orbitals in each irrep.
`frozen_docc`
  An optional array of integers that specifies the number of doubly-occupied orbitals in each irrep frozen in correlated computations.
`frozen_uocc`
  An optional array of integers that specifies the number of unoccupied orbitals in each irrep frozen in correlated computations.
`total_charge`
  The total charge of the system. This keyword is queried only if neither `docc` nor `socc` are given.
`multiplicity`
  The spin multiplicity of the system (2*M_S+1). This keyword is queried only if neither `docc` nor `socc` are given.
`memory`
  The number of bytes of memory Psi modules associated with this PsiWavefunction are allowed to use. Default is 2000000 (2 million bytes, approximately 2 MB).

Note that keywords `docc`, `socc`, `frozen_docc`, `frozen_uocc`, `total_charge`, and `multiplicity` are used by appropriate specializations of PsiWavefunctions, i.e. PsiCLHF only checks for `docc`, etc.

PsiWavefunction specializations PsiCCSD and PsiCCSD_T also look for keyword `reference` which specifies the reference wave function (an object of type PsiSCF). All classes for correlated Psi wave functions will require such an object.

Here are a few examples of PsiWavefunctions:

      %
      % ROHF DZ on F atom
      %
      mole<PsiHSOSHF>: (
        docc = [ 2 0 0 0 0 1 1 0 ] socc = [ 0 0 0 0 0 0 0 1]
        memory = 10000000

        % Psi Environment data
        psienv<PsiExEnv>: (
          cwd = ./
          fileprefix = f.dz.test
          stdout = f.dz.test.stdout
          stderr = f.dz.test.stderr
          nscratch = 1
          scratch = [ "/scratch/mpqc/" ]
        )

        % MolecularEnergy input
        molecule<Molecule>: (
            {atoms geometry} = {
              F  [   0.0  0.0   0.0 ]
             }
          )

        % Basis input
        basis<GaussianBasisSet>: (
            molecule = $..:molecule
            name = "DZ (Dunning)"
          )

      )

      %
      % RHF CCSD/cc-pVDZ on water
      %
      mole<PsiCCSD>: (
        frozen_docc = [1 0 0 0]
        memory = 40000000

        % Psi Environment data
        psienv<PsiExEnv>: (
          cwd = ./
          fileprefix = h2o.ccpvdz.ccsd.test
          nscratch = 1
          scratch = [ "/tmp/" ]
        )

        % MolecularEnergy input
        molecule<Molecule>: (
            {atoms geometry} = {
              H  [  -1.5  0.0  -0.3 ]
              H  [   1.5  0.0  -0.3 ]
              O  [   0.0  0.0   1.0 ]
             }
          )

        % Basis input
        basis<GaussianBasisSet>: (
            molecule = $..:molecule
            name = "cc-pVDZ"
          )

        reference<PsiCLHF>: (
          psienv = $..:psienv
          molecule = $..:molecule
          basis = $..:basis
          total_charge = 0
          multiplicity = 1
        )
      )

## More examples

This section contains some examples of complete inputs that specify an MPQC/Psi computations.

Here's an optimization + subsequent frequency analysis on water molecule at the RHF CCSD 6-311G** level:

    % Emacs should use -*- KeyVal -*- mode
    % this file was automatically generated
    % label: water test series
    % molecule specification
    molecule<Molecule>: (
      symmetry = C2V
      unit = angstrom
      { atoms geometry } = {
         O     [     0.000000000000     0.000000000000     0.369372944000 ]
         H     [     0.783975899000     0.000000000000    -0.184686472000 ]
         H     [    -0.783975899000     0.000000000000    -0.184686472000 ]
      }
    )
    % basis set specification
    basis<GaussianBasisSet>: (
      name = "6-311G**"
      molecule = $:molecule
    )
    % Psi environment specification
    psienv<PsiExEnv>: (
          cwd = ./
          fileprefix = mpqcpsi
          stdout = mpqcpsi.stdout
          stderr = mpqcpsi.stderr
          nscratch = 1
          scratch = [ "/scratch/evaleev/" ]
    )

    mpqc: (
      checkpoint = no
      savestate = no
      restart = no
      coor<SymmMolecularCoor>: (
        molecule = $:molecule
        generator<IntCoorGen>: (
          molecule = $:molecule
        )
      )
      % molecular coordinates for optimization  do_energy = yes
      do_gradient = no
      % method for computing the molecule's energy
      mole<PsiCCSD>: (
        molecule = $:molecule
        basis = $:basis
        coor = $..:coor
        psienv = $:psienv
        memory = 32000000
        reference<PsiCLHF>: (
          psienv = $:psienv
          molecule = $:molecule
          total_charge = 0
          multiplicity = 1
          basis = $:basis
          memory = 32000000
        )
        hessian<FinDispMolecularHessian>: (
          point_group<PointGroup>: symmetry = C2V
          checkpoint = no
          restart = no
        )
      )
      optimize = yes
      % optimizer object for the molecular geometry
      opt<QNewtonOpt>: (
        max_iterations = 20
        function = $..:mole
        update<BFGSUpdate>: ()
        convergence<MolEnergyConvergence>: (
          cartesian = yes
          energy = $..:..:mole
        )
      )
    % vibrational frequency input
      freq<MolecularFrequencies>: (
        point_group<PointGroup>: symmetry = C2V
        molecule = $:molecule
      )
    )