Programming Projects: Getting Started


Creating a Psi4 plugin


First, you must download and install Psi4. See the Psi4 GitHub page and psicode.org for detailed instructions.


Once you have downloaded and installed Psi4, create a new plugin directory. I'm going to call my plugin 'myscf':


> psi4 --plugin-name myscf
-- Creating "myscf" with "basic" template. ----------------------
==> Created plugin files (in myscf as basic): 
  __init__.py, CMakeLists.txt, doc.rst, input.dat, plugin.cc, pymodule.py
> cd myscf
> ls -lh
total 48
-rw-r--r--  1 deprince  staff   1.5K Dec 19 20:11 CMakeLists.txt
-rw-r--r--  1 deprince  staff   1.3K Dec 19 20:11 __init__.py
-rw-r--r--  1 deprince  staff   2.2K Dec 19 20:11 doc.rst
-rw-r--r--  1 deprince  staff   296B Dec 19 20:11 input.dat
-rw-r--r--  1 deprince  staff   1.7K Dec 19 20:11 plugin.cc
-rw-r--r--  1 deprince  staff   2.2K Dec 19 20:11 pymodule.py

You can see that Psi4 generated several files automatically for you. Your C++ code will reside in myscf.cc, and you can interface with other modules in Psi4 through the driver in pymodule.py.

The closest thing to a 'main()' function will reside in plugin.cc. Take a look:


extern "C"
SharedWavefunction myscf(SharedWavefunction ref_wfn, Options& options)
{
    int print = options.get_int("PRINT");

    /* Your code goes here */

    // Typically you would build a new wavefunction and populate it with data
    return ref_wfn;
}

Like the comment says, you're code belongs in the myscf(SharedWavefunction ref_wfn, Options& options) function. The name of this function matches whatever you called your plugin. Let's add a print statement using Psi4's printer class 'outfile':


    /* Your code goes here */
    outfile->Printf("Hello from my first psi4 plugin!\n");

Next, check out the 'read_options' function:


extern "C"
int read_options(std::string name, Options& options)
{
    if (name == "MYSCF"|| options.read_globals()) {
        /*- The amount of information printed to the output file -*/
        options.add_int("PRINT", 1);
    }

    return true;
}

This function is where you will define any input options that are specific to your plugin. Note that you can still use any other valid Psi4 options, so you may not need to introduce any new ones.

Now, let's compile and run the plugin. If you look in input.dat, you should see a call to energy('myscf') was automatically placed there when you created the plugin. So, to run your plugin, you need only excecute psi4 using this input file.


> cmake .
-- The CXX compiler identification is AppleClang 8.0.0.8000042
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Psi4 include directory: /Users/deprince/software/psi4/install/include
-- Psi4 executable: /Users/deprince/software/psi4/install/bin/psi4
-- Psi4 core library: /Users/deprince/software/psi4/install/lib/psi4/core.so
-- Python executable: /Users/deprince/software/psi4-conda/bin/python
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/deprince/chem/plugins/myscf
> make
Scanning dependencies of target myscf
[ 50%] Building CXX object CMakeFiles/myscf.dir/plugin.cc.o
/Users/deprince/chem/plugins/myscf/plugin.cc:49:20: warning: 'myscf' has
      C-linkage specified, but returns user-defined type 'SharedWavefunction'
      (aka 'shared_ptr\ltpsi::Wavefunction\gt') which is incompatible with C
      [-Wreturn-type-c-linkage]
SharedWavefunction myscf(SharedWavefunction ref_wfn, Options& options)
                   ^
1 warning generated.
[100%] Linking CXX shared module myscf.so
[100%] Built target myscf
> psi4
Attention! This SCF may be density-fitted.
> vi output.dat


Scroll down to the bottom of output.dat.

 Number of primitives:             15
      Number of atomic orbitals:         7
      Number of basis functions:         7

      Number of irreps:                  4
      Integral cutoff                 0.00e+00
      Number of functions per irrep: [   4    0    1    2 ]

 OEINTS: Overlap, kinetic, potential, dipole, and quadrupole integrals
         stored in file 35.

      Computing two-electron integrals...done
      Computed 138 non-zero two-electron integrals.
        Stored in file 33.


Reading options from the MYSCF block
Calling plugin myscf.so.


Hello from my first psi4 plugin!

*** Psi4 exiting successfully. Buy a developer a beer!

What you should see is some text indicating that Psi4 has generated one- and two-electron integrals and written them to disk, followed by the super-exciting output from your plugin, myscf.so.