First, I wanted to thank the developers for all of their hard work on Psi4, it’s really quite amazing.

While I know it is possible to extract integrals from PSI4, I was wondering if it’s modularity extended to the possibility of injecting or transforming them as well. For example, say I had a second prototype code performing integrals in a non-standard (non-gaussian) atomic basis set, but wanted to perform a full CI or MCSCF calculation of that molecule in that basis set within PSI4 so I didn’t have to write my own solver. In principle, all I should need to do is redefine the integrals, and have PSI4 run through the standard chain of calculations without recalculating them from scratch. Is there any sort of functionality built for this type of approach, and if not is there a particular part of the code that would represent a path of least resistance to hacking it in? Thank you for you time!

If you are doing all integrals (kinetic, potential, ERI) this should be relatively straightforward for C1 symmetry. We should just be able to replace the on-disk files with your integrals for most algorithms.

So a few questions first:

Are you replacing all integrals, or just say the ERI’s?

Would SCF/MP2 with ~200 basis functions be sufficient as a first pass (very easy to do)?

Are you concerned with spatial symmetry?

We have been toying with the idea of using several integral packages inside Psi4 with a single standard interface. However, I’m not sure exactly how this would work for non-gaussian integrals.

@bennybp and I have been designing Pulsar so that this can be done and there are a number of gotchas involved. Since Psi4 did not consider it from the beginning I am skeptical that it will be as simple as swap one type out for another in Psi4. If your type is very Gaussian like it may be doable with some effort, but I doubt you are going to put plane waves in without rewriting most of Psi4; it simply isn’t encapsulated enough. As a place to start I would look at the wrapper around ERD’s two electron integrals in libmints and see if you can squeeze your integrals into the same API.

Thank you for your responses. In response to dgasmith’s questions, I would indeed be doing all the integrals, kinetic, potential, overlap, ERI and I believe C1 symmetry would be fine in fact. Certainly SCF/MP2 with 200 basis functions would be a good first place to start and more than I currently have available.

I actually have two parallel interests for modifying the integrals. The first being injecting non-Gaussian integrals, such as localized numerical atomic orbitals and proceeding with a correlated calculation. The second is a non-standard transformation of Gaussian integrals. For the second case, an imagined work flow would be to get the Gaussian integrals from PSI4, transform them, then feed them back in before PSI4 started doing the SCF calculations and beyond.

I suspected that one way to do this might be to try to get PSI4 to use a disk based integral algorithm, stop the computation once the integrals are computed, change the integrals on the disk and restart, but perhaps there is a more elegant/easier way? This hack could also cause some pain related to matching the number of basis functions etc, and certainly property calculations would be meaningless if I didn’t change those integrals as well.

What is Pulsar if I might ask? The integrals are in some ways Gaussian-like, as they are relatively localized in space and real-valued.

Using files may be an option, although others can probably say more about that.

If you want to place your integral code directly into Psi4, that might be a little tougher. The place I would start to look is src/lib/libmints/integral.cc. The functionality there is called by the other parts of the code to obtain objects used to calculate integrals. You would replace the code in ao_overlap, ao_kinetic, etc, with instantiations of your own classes (which have to derive from the appropriate base class). I have done this with ERI before, and it wasn’t too hard.

Building the project in that case is a little tricky, but not too bad if you want to hack something together just to try it.

Pulsar is a project we are developing that is built from the ground-up to be able to do things like this very easily. It’s still under heavy development, and isn’t (yet) ready for what you would like. But the hope is to have functionality that allows for exactly what you describe.

Modifying the integral files would be the easiest course to follow in connection with conventional integral methods (non-DF). The integrals for conventional methods are computed in MintsHelper::integrals() (src/lib/libmints/mintshelper.cc:215). One-electron integrals should be reasonably easier to adjust. The two-electron integrals are stored in our IWL format.

For a small simple case I was thinking of the Psi4Numpy project. If you can generate a dense form of integrals on disk you can simply read them in to the majority of these coding examples.