-
Notifications
You must be signed in to change notification settings - Fork 478
LibDIIS
Psi has a DIIS class that is capable of extrapolating quantities stored in any format. Here's an example of a simultaneous extrapolation of quantities stored as both Matrix and dpdbuf4 objects. The first step is to create an extrapolation object. Here we just use defaults, but much of the behavior can be controlled. For example, how to store the vectors on disk/in core, how to decide which ones to remove from the subspace when it's full, and what the largest subspace size is can all be controlled by passing extra arguments to the constructor. See the Doxygen documentation for DiisManager::DiisManager for details.
DIISManager _diisManager = DIISManager(_maxDiis, "DCFT DIIS vectors");
Then, the amount of storage needed for each vector and error vector needs to be determined:
dpdbuf4 Laa, Lab, Lbb;
dpd_buf4_init(&Laa, PSIF_LIBTRANS_DPD, 0, ID("[O,O]"), ID("[V,V]"),
ID("[O,O]"), ID("[V,V]"), 0, "Lambda <OO|VV>");
dpd_buf4_init(&Lab, PSIF_LIBTRANS_DPD, 0, ID("[O,o]"), ID("[V,v]"),
ID("[O,o]"), ID("[V,v]"), 0, "Lambda <Oo|Vv>");
dpd_buf4_init(&Lbb, PSIF_LIBTRANS_DPD, 0, ID("[o,o]"), ID("[v,v]"),
ID("[o,o]"), ID("[v,v]"), 0, "Lambda <oo|vv>");
_diisManager.set_error_vector_size(5, DIISEntry::Matrix, &_aScfError,
DIISEntry::Matrix, &_bScfError,
DIISEntry::DPDBuf4, &Laa,
DIISEntry::DPDBuf4, &Lab,
DIISEntry::DPDBuf4, &Lbb);
_diisManager.set_vector_size(5, DIISEntry::Matrix, &_Fa,
DIISEntry::Matrix, &_Fb,
DIISEntry::DPDBuf4, &Laa,
DIISEntry::DPDBuf4, &Lab,
DIISEntry::DPDBuf4, &Lbb);
dpd_buf4_close(&Laa);
dpd_buf4_close(&Lab);
dpd_buf4_close(&Lbb);
Note that DPD entities must be initialized before the calls to set_error_vector_size and set_vector_size. The set_size functions are needed because the error vectors might have different dimensions to the vectors to be extrapolated. These functions should only be called once, and their purpose is to determine the size of each quantity involved. For set_error_vector_size, the first argument is the number of components of the composite error vector, followed by a list of the (type of each component, pointer to each component). See the Doxygen documentation for DIISEntry::InputType for a list of allowed types. N.B. for double* components, the type should be Pointer, and the dimension of the array should be passed in, instead of the pointer itself; this is because there is no way of determining the size of an array in standard C++. After setting up the error vector, you should do the same for the vector to be extrapolated. The error vector must be set up before the vector, as shown above. Once this setup is complete, just add the new quantities each iteration:
_diisManager.add_entry(10, &_aScfError, &_bScfError, &Raa, &Rab, &Rbb,
&_Fa, &_Fb, &Laa, &Lab, &Lbb);
In add_entry, the first argument is the sum of the number of components of the error vector and vectors. Then you just list the error vector components and vector components to be extrapolated in the same order as they were passed to set_error_vector_size and set_vector_size above. The types do not need to be specified in this function call, because they were stored in the set_size routines. The extrapolation can be performed as follows
_diisManager.extrapolate(5, &_Fa, &_Fb, &Laa, &Lab, &Lbb);
where the first argument is just the number of components of the vector to be extrapolated, and the rest are the components themselves, in the order passed to set_vector_size.