PluginPlay Primer
The guts of NWChemEx uses the PluginPlay framework. Additional functionality is added to the PluginPlay by writing plugins called “modules”. Generally speaking each module can compute one or more properties. For example a module which runs a Hartree-Fock calculation will likely compute the total electronic energy, the canonical molecular orbitals, and the Fock matrix. Associated with each property is an API called the “property type”. The property types define the hooks that NWChemEx uses to call plugins. To interface your code with NWChemEx you need to wrap it in a module, register the properties your module can compute, and register the module with NWChemEx. NWChemEx will handle everything else.
Writing a module
NWChemEx and the PluginPlay are able to work with modules written in either C++ or in Python.
C++
If you want to write your module in C++ you will need to create a library with
your module. Your library will need to link to the SimDE repo (which
will automatically also expose your library to PluginPlay and Chemist). For sake of
argument we’ll assume your module computes overlap integrals of Gaussian basis
functions using a deep neural network. Given how the module works we decide to
call it DeepOverlap
(module names are case-sensitive) and we decide to call
the library DeepIntegrals
.
DeepIntegrals
needs a very simple header file, deep_integrals.hpp
:
#pragma once // Header guard; avoids multiple inclusions
#include <pluginplay/pluginplay.hpp> // Makes PluginPlay visible to your module
namespace deep_integrals {
DECLARE_MODULE(DeepOverlap);
// if your library provides more than one module, other DECLARE_MODULE
// statements would show up here
// This is the hook NWChemEx uses to enter your library
void load_modules(pluginplay::ModuleManager& mm);
} // namespace deep_integrals
Overlap integrals are of type simde::EOverlap
The definition of DeepOverlap
will look something like:
#include "path/to/deep_integrals.hpp"
#include <simde/simde.hpp>
// Typedef of the Overlap property type for readability
using pt = simde::EOverlap;
namespace deep_integrals {
MODULE_CTOR(DeepOverlap) {
// Register that your module satisfies the Overlap property type
satisfies_property_type<pt>();
}
MODULE_RUN(DeepOverlap) {
// This is boilerplate for unwrapping the inputs provided to the module
const auto& [bra, ket] = pt::unwrap_inputs(inputs);
// Step 1: Translate the AO basis sets for the bra and ket to your
// library's native format
// Step 2: Compute the overlap integral tensor
// Step 3: Convert the overlap integral tensor from your library's format
// to NWChemEx's tensor format
auto S = get_overlap_integral_in_NWX_format();
// This is boilerplate for wrapping and returning the results
auto rv = results();
return pt::wrap_results(rv, S);
}
} // namespace your_library_namespace
Finally we need to define the load_modules
function, which we do in its own
source file:
#include "path/to/deep_integrals.hpp"
namespace deep_integrals {
void load_modules(pluginplay::ModuleManager& mm) {
mm.add_module<DeepOverlap>("Deep Overlap");
}
} // namespace deep_integrals
Python
TODO: Write me!!!!