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':


(09:46 ~/) psi4 --plugin-name myscf
-- Creating "myscf" with "basic" template. ----------------------
/Users/deprince/software/psi4/install/share/psi4/plugin/basic/__init__.py.template
/Users/deprince/software/psi4/install/share/psi4/plugin/basic/CMakeLists.txt.template
/Users/deprince/software/psi4/install/share/psi4/plugin/basic/doc.rst.template
/Users/deprince/software/psi4/install/share/psi4/plugin/basic/input.dat.template
/Users/deprince/software/psi4/install/share/psi4/plugin/basic/plugin.cc.template
/Users/deprince/software/psi4/install/share/psi4/plugin/basic/pymodule.py.template
==> Created plugin files (in myscf as basic): 
  __init__.py, CMakeLists.txt, doc.rst, input.dat, plugin.cc, pymodule.py
(09:46 ~/) cd myscf/
(09:47 ~/myscf/) ls -lh
total 48
-rw-r--r--  1 deprince  staff   1.1K Apr 28 09:46 CMakeLists.txt
-rw-r--r--  1 deprince  staff   1.2K Apr 28 09:46 __init__.py
-rw-r--r--  1 deprince  staff   2.2K Apr 28 09:46 doc.rst
-rw-r--r--  1 deprince  staff   296B Apr 28 09:46 input.dat
-rw-r--r--  1 deprince  staff   1.7K Apr 28 09:46 plugin.cc
-rw-r--r--  1 deprince  staff   2.2K Apr 28 09:46 pymodule.py

You can see that Psi4 generated several files automatically for you. Your C++ code will reside in plugin.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" PSI_API
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" PSI_API
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. You can use Psi4 to generate a Makefile, which you can then use to compile your plugin with make.


(09:47 ~/myscf/) psi4 --plugin-compile  | /bin/bash
loading initial cache file /Users/deprince/software/psi4/install/share/cmake/psi4/psi4PluginCache.cmake
-- The CXX compiler identification is AppleClang 9.0.0.9000039
-- 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 script:  /Users/deprince/software/psi4/install/bin/psi4
-- Psi4 headers: /Users/deprince/software/psi4/install/include
-- Psi4 library: /Users/deprince/software/psi4/install/lib//psi4/core.so
-- Psi4 components: 
-- Python executable: /opt/local/bin/python3.5
-- Found PythonInterp: /opt/local/bin/python3.5 (found version "3.5.4") 
-- Found PythonLibs: /opt/local/Library/Frameworks/Python.framework/Versions/3.5/lib/libpython3.5m.dylib
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/deprince/myscf
(09:47 ~/myscf/) make
Scanning dependencies of target myscf
[ 50%] Building CXX object CMakeFiles/myscf.dir/plugin.cc.o
/Users/deprince/myscf/plugin.cc:52:20: warning: 'myscf' has C-linkage specified, but returns user-defined type 'SharedWavefunction' (aka 'shared_ptr<psi::Wavefunction>')
      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

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.


(09:47 ~/myscf/) psi4
Attention! This SCF may be density-fitted.

After the program is finished, open output.dat and scroll to the bottom.

 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 stopped on: Saturday, 28 April 2018 09:47AM
    Psi4 wall time for execution: 0:00:00.60

*** 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.