Callback Function Scheme¶

To use OpenRSP, users should also prepare different callback functions needed by OpenRSP. These callback functions will be invoked by OpenRSP during calculations to get integral matrices or expectation values of different one- and two-electron operators, exchange-correlation functionals and nuclear contributions, or to solve the linear response equation. The callback functions are slightly different for C and Fortran users, which will be described separately in this chapter.

It should be noted that the arguments in the following callback functions are over complete. For instance, from the knowledge of perturbations (oper_num_pert, oper_pert_labels and oper_pert_orders), the dimension of integral matrices num_int in the callback function get_one_oper_mat() can be computed.

Last but not least, users should be aware that:

1. OpenRSP always ask for complex expectation values for different one- and two-electron operators, exchange-correlation functionals and nuclear contributions, and these values are presented in memory that the real and imaginary parts of each value are consecutive. This affects:
2. In order to reduce the use of temporary matrices and values, OpenRSP requires that calculated integral matrices and expectation values should be added to the returned argument. OpenRSP will zero the entries of these matrices and expectation values at first. This requirement affects the callback functions of one- and two-electron operators, exchange-correlation functionals and nuclear contributions:

OpenRSP Callback Functions (C version)¶

Examples of C callback functions can be found in these files tests/OpenRSP*Callback.c. The detailed information of these callback functions are given as follows.

void get_pert_concatenation(pert_label, first_cat_comp, num_cat_comps, num_sub_tuples, len_sub_tuples, user_ctx, rank_sub_comps)

User specified function for getting the ranks of components of sub-perturbation tuples (with the same perturbation label) for given components of the corresponding concatenated perturbation tuple, the last argument for the function OpenRSPSetPerturbations().

Parameters: Var rank_sub_comps: pert_label (const QcPertInt) – the perturbation label first_cat_comp (const QInt) – rank of the first component of the concatenated perturbation tuple num_cat_comps (const QInt) – number of components of the concatenated perturbation tuple num_sub_tuples (const QInt) – number of sub-perturbation tuples to construct the concatenated perturbation tuple len_sub_tuples (const QInt*) – length of each sub-perturbation tuple, size is num_sub_tuples; so that the length of the concatenated perturbation is sum(len_sub_tuples) user_ctx (void*) – user-defined callback function context ranks of components of sub-perturbation tuples for the corresponding component of the concatenated perturbation tuple, i.e. num_cat_comps components starting from the one with rank first_cat_comp, size is therefore num_sub_tuples $$\times$$ num_cat_comps, and arranged as [num_cat_comps][num_sub_tuples] QInt* void

NOTE: get_pert_concatenation() will not be invoked in the current release so that users can use a “faked” function for it.

void get_overlap_mat(bra_num_pert, bra_pert_labels, bra_pert_orders, ket_num_pert, ket_pert_labels, ket_pert_orders, oper_num_pert, oper_pert_labels, oper_pert_orders, user_ctx, num_int, val_int)

User-specified callback function to calculate integral matrices of overlap operator as well as its derivatives with respect to different perturbations, the second last argument for the function OpenRSPSetOverlap().

Parameters: Var val_int: bra_num_pert (const QInt) – number of perturbations on the bra center bra_pert_labels (const QcPertInt*) – labels of perturbations on the bra center, size is bra_num_pert bra_pert_orders (const QInt*) – orders of perturbations on the bra center, size is bra_num_pert ket_num_pert (const QInt) – number of perturbations on the ket center ket_pert_labels (const QcPertInt*) – labels of perturbations on the ket center, size is ket_num_pert ket_pert_orders (const QInt*) – orders of perturbations on the ket center, size is ket_num_pert oper_num_pert (const QInt) – number of perturbations on the overlap operator [1] oper_pert_labels (const QcPertInt*) – labels of perturbations on the overlap operator, size is oper_num_pert oper_pert_orders (const QInt*) – orders of perturbations on the overlap operator, size is oper_num_pert [2] user_ctx (void*) – user-defined callback function context num_int (const QInt) – number of the integral matrices, as the product of the sizes of perturbations on the bra, the ket and the overlap operator the integral matrices to be added, size is num_int, and arranged as [oper_pert][bra_pert][ket_pert] QcMat*[] void
 [1] Here perturbations on the overlap operator represent those acting on the whole integral of the overlap operator, i.e. they can act on either the bra center or the ket center by applying the rule of derivatives of a product.
 [2] Only overlap integrals perturbed on the bra and/or the ket, and those perturbed on the whole integral are needed in the calculations. It means that, OpenRSP will only ask for overlap integrals either with perturbations on the bra and/or ket (oper_num_pert=0), or with perturbations on the whole overlap integral (bra_num_pert=0 and ket_num_pert=0).
void get_overlap_exp(bra_num_pert, bra_pert_labels, bra_pert_orders, ket_num_pert, ket_pert_labels, ket_pert_orders, oper_num_pert, oper_pert_labels, oper_pert_orders, num_dmat, dens_mat, user_ctx, num_exp, val_exp)

User-specified function for calculating expectation values of the overlap operator and its derivatives, the last argument for the function OpenRSPSetOverlap().

Parameters: Var val_exp: bra_num_pert (const QInt) – number of perturbations on the bra center bra_pert_labels (const QcPertInt*) – labels of perturbations on the bra center, size is bra_num_pert bra_pert_orders (const QInt*) – orders of perturbations on the bra center, size is bra_num_pert ket_num_pert (const QInt) – number of perturbations on the ket center ket_pert_labels (const QcPertInt*) – labels of perturbations on the ket center, size is ket_num_pert ket_pert_orders (const QInt*) – orders of perturbations on the ket center, size is ket_num_pert oper_num_pert (const QInt) – number of perturbations on the overlap operator [3] oper_pert_labels (const QcPertInt*) – labels of perturbations on the overlap operator, size is oper_num_pert oper_pert_orders (const QInt*) – orders of perturbations on the overlap operator, size is oper_num_pert num_dmat (const QInt) – number of atomic orbital (AO) based density matrices dens_mat (QcMat*[]) – the AO based density matrices user_ctx (void*) – user-defined callback function context num_exp (const QInt) – number of the expectation values, as the product of sizes of perturbations on the bra, the ket, the overlap operator and the number of density matrices (num_dmat) the expectation values to be added, size is 2 $$\times$$ num_exp, and arranged as [num_dmat][oper_pert][bra_pert][ket_pert][2] QReal* void
 [3] Similar to the callback function get_overlap_mat(), OpenRSP will only ask for expectation values either with perturbations on the bra and/or ket (oper_num_pert=0), or with perturbations on the whole overlap integral (bra_num_pert=0 and ket_num_pert=0).
void get_one_oper_mat(oper_num_pert, oper_pert_labels, oper_pert_orders, user_ctx, num_int, val_int)

User-specified function for calculating integral matrices of the one-electron operator and its derivatives, the second last argument for the function OpenRSPAddOneOper().

Parameters: Var val_int: oper_num_pert (const QInt) – number of perturbations on the one-electron operator oper_pert_labels (const QcPertInt*) – labels of perturbations on the one-electron operator, size is oper_num_pert oper_pert_orders (const QInt*) – orders of perturbations on the one-electron operator, size is oper_num_pert user_ctx (void*) – user-defined callback function context num_int (const QInt) – number of the integral matrices, as the size of perturbations that are specified by oper_num_pert, oper_pert_labels and oper_pert_orders the integral matrices to be added, size is num_int QcMat*[] void
void get_one_oper_exp(oper_num_pert, oper_pert_labels, oper_pert_orders, num_dmat, dens_mat, user_ctx, num_exp, val_exp)

User-specified callback function to calculate expectation values of one-electron operator as well as its derivatives with respect to different perturbations, the last argument for the function OpenRSPAddOneOper().

Parameters: Var val_exp: oper_num_pert (const QInt) – number of perturbations on the one-electron operator oper_pert_labels (const QcPertInt*) – labels of perturbations on the one-electron operator, size is oper_num_pert oper_pert_orders (const QInt*) – orders of perturbations on the one-electron operator, size is oper_num_pert num_dmat (const QInt) – number of AO based density matrices dens_mat (QcMat*[]) – the AO based density matrices user_ctx (void*) – user-defined callback function context num_exp (const QInt) – number of expectation values, as the product of the size of perturbations on the one-electron operator (specified by oper_num_pert, oper_pert_labels and oper_pert_orders) and the number of density matrices (num_dmat) the expectation values to be added, size is 2 $$\times$$ num_exp, and arranged as [num_dmat][oper_pert][2] QReal* void
void get_two_oper_mat(oper_num_pert, oper_pert_labels, oper_pert_orders, num_dmat, dens_mat, user_ctx, num_int, val_int)

User-specified function for calculating integral matrices of the two-electron operator and its derivatives, the second last argument for the function OpenRSPAddTwoOper().

Parameters: Var val_int: oper_num_pert (const QInt) – number of perturbations on the two-electron operator oper_pert_labels (const QcPertInt*) – labels of perturbations on the two-electron operator, size is oper_num_pert oper_pert_orders (const QInt*) – orders of perturbations on the two-electron operator, size is oper_num_pert num_dmat (const QInt) – number of AO based density matrices dens_mat (QcMat*[]) – the AO based density matrices ($$\boldsymbol{D}$$) for calculating $$\boldsymbol{G}^{\texttt{perturbations}}(\boldsymbol{D})$$, where $$\texttt{perturbations}$$ are specified by oper_num_pert, oper_pert_labels and oper_pert_orders. user_ctx (void*) – user-defined callback function context num_int (const QInt) – number of the integral matrices, as the product of the size of perturbations on the two-electron operator (specified by oper_num_pert, oper_pert_labels and oper_pert_orders) and the number of AO based density matrices (num_dmat) the integral matrices to be added, size is num_int, and arranged as [num_dmat][oper_pert] QcMat*[] void
void get_two_oper_exp(oper_num_pert, oper_pert_labels, oper_pert_orders, dmat_len_tuple, num_LHS_dmat, LHS_dens_mat, num_RHS_dmat, RHS_dens_mat, user_ctx, num_exp, val_exp)

User-specified callback function to calculate expectation values of two-electron operator as well as its derivatives with respect to different perturbations, the last argument for the function OpenRSPAddTwoOper().

Parameters: Var val_exp: oper_num_pert (const QInt) – number of perturbations on the two-electron operator oper_pert_labels (const QcPertInt*) – labels of perturbations on the two-electron operator, size is oper_num_pert oper_pert_orders (const QInt*) – orders of perturbations on the two-electron operator, size is oper_num_pert dmat_len_tuple (const QInt) – length of different perturbation tuples of the left-hand-side (LHS) and right-hand-side (RHS) AO based density matrices passed; for instance, if the LHS density matrices passed are ($$\boldsymbol{D}$$, $$\boldsymbol{D}^{a}$$, $$\boldsymbol{D}^{b}$$, $$\boldsymbol{D}^{ab}$$), and the RHS density matrices passed are ($$\boldsymbol{D}^{b}$$, $$\boldsymbol{D}^{c}$$, $$\boldsymbol{D}^{bc}$$, $$\boldsymbol{D}^{d}$$), then dmat_len_tuple equals to 4, and that means we want to calculate $$\mathrm{Tr}[\boldsymbol{G}^{\texttt{perturbations}}(\boldsymbol{D})\boldsymbol{D}^{b}]$$, $$\mathrm{Tr}[\boldsymbol{G}^{\texttt{perturbations}}(\boldsymbol{D}^{a})\boldsymbol{D}^{c}]$$, $$\mathrm{Tr}[\boldsymbol{G}^{\texttt{perturbations}}(\boldsymbol{D}^{b})\boldsymbol{D}^{bc}]$$, and $$\mathrm{Tr}[\boldsymbol{G}^{\texttt{perturbations}}(\boldsymbol{D}^{ab})\boldsymbol{D}^{d}]$$, where $$\texttt{perturbations}$$ are specified by oper_num_pert, oper_pert_labels and oper_pert_orders. num_LHS_dmat (const QInt*) – number of LHS AO based density matrices passed for each LHS density matrix perturbation tuple, size is dmat_len_tuple; sticking with the above example, num_LHS_dmat will be {1, N_a, N_b, N_ab} where N_a, N_b and N_ab are respectively the numbers of density matrices for the density matrix perturbation tuples a, b and ab LHS_dens_mat (QcMat*[]) – the LHS AO based density matrices ($$\boldsymbol{D}_{\text{LHS}}$$) for calculating $$\mathrm{Tr}[\boldsymbol{G}^{\texttt{perturbations}}(\boldsymbol{D}_{\text{LHS}})\boldsymbol{D}_{\text{RHS}}]$$, size is the sum of num_LHS_dmat num_RHS_dmat (const QInt*) – number of RHS AO based density matrices passed for each RHS density matrix perturbation tuple, size is dmat_len_tuple; sticking with the above example, num_RHS_dmat will be {N_b, N_c, N_bc, N_d} where N_b, N_c N_bc and N_d are respectively the numbers of density matrices for the density matrix perturbation tuples b, c, bc and d RHS_dens_mat (QcMat*[]) – the RHS AO based density matrices ($$\boldsymbol{D}_{\text{RHS}}$$) for calculating $$\mathrm{Tr}[\boldsymbol{G}^{\texttt{perturbations}}(\boldsymbol{D}_{\text{LHS}})\boldsymbol{D}_{\text{RHS}}]$$, size is the sum of num_RHS_dmat user_ctx (void*) – user-defined callback function context num_exp (const QInt) – number of expectation values, as the product of the size of perturbations on the two-electron operator (specified by oper_num_pert, oper_pert_labels and oper_pert_orders) and the number of pairs of LHS and RHS density matrices, and the number of pairs of LHS and RHS density matrices can be computed as the dot product of num_LHS_dmat and num_RHS_dmat the expectation values to be added, size is 2 $$\times$$ num_exp, and arranged as [dmat_len_tuple][num_LHS_dmat][num_RHS_dmat][oper_pert][2] QReal* void
void get_xc_fun_mat(xc_len_tuple, xc_pert_tuple, num_freq_configs, pert_freq_category, dmat_num_tuple, dmat_idx_tuple, num_dmat, dens_mat, user_ctx, num_int, val_int)

User-specified function for calculating integral matrices of the XC functional and its derivatives, the second last argument for the function OpenRSPAddXCFun().

Parameters: Var val_int: xc_len_tuple (const QInt) – length of the perturbation tuple on the XC functional xc_pert_tuple (const QcPertInt*) – perturbation tuple on the XC functional, size is xc_len_tuple num_freq_configs (const QInt) – the number of different frequency configurations to be considered for the perturbation tuple specified by xc_pert_tuple pert_freq_category (const QInt*) – category of perturbation frequencies, size is [num_freq_configs][xc_len_tuple]. Take $$\mathcal{E}^{gfff}$$ as an example, suppose we have four different frequency configurations: “0.0,0.0,0.0,0.0” ($$3N\times 10$$ unique elements), “0.0,-0.2,0.1,0.1” ($$3N\times 18$$ unique elements), “0.0,-0,3,0.1,0.2” ($$3N\times 27$$ unique elements) and “0.0,-0.1,0.1,0.0” ($$3N\times 27$$ unique elements), the pert_freq_category argument would then be (1,1,1,1, 1,2,3,3, 1,2,3,4, 1,2,3,1). dmat_num_tuple (const QInt) – the number of different perturbation tuples of the AO based density matrices passed; for instance, the complete density matrix perturbation tuples (canonically ordered) for a property $$\mathcal{E}^{abc}$$ (i.e. the perturbation tuple xc_pert_tuple is abc) are ($$\boldsymbol{D}$$, $$\boldsymbol{D}^{a}$$, $$\boldsymbol{D}^{b}$$, $$\boldsymbol{D}^{ab}$$, $$\boldsymbol{D}^{c}$$, $$\boldsymbol{D}^{ac}$$, $$\boldsymbol{D}^{bc}$$), and with the $$(0,2)$$ rule, the relevant density matrix perturbation tuples become ($$\boldsymbol{D}$$, $$\boldsymbol{D}^{b}$$, $$\boldsymbol{D}^{c}$$, $$\boldsymbol{D}^{bc}$$) that gives the dmat_num_tuple as 4 dmat_idx_tuple (const QInt*) – indices of the density matrix perturbation tuples passed (canonically ordered), size is dmat_num_tuple; sticking with the above example, the density matrix perturbation tuples passed are ($$\boldsymbol{D}$$, $$\boldsymbol{D}^{b}$$, $$\boldsymbol{D}^{c}$$, $$\boldsymbol{D}^{bc}$$) and their associated indices dmat_idx_tuple is {1, 3, 5, 7} because these numbers correspond to the positions of the “$$(k,n)$$-surviving” perturbation tuples in the canonically ordered complete density matrix perturbation tuples num_dmat (const QInt) – number of collected AO based density matrices for the passed density matrix perturbation tuples (specified by dmat_idx_tuple) and all frequency configurations, that is num_freq_configs $$\times\sum_{\text{i}}N_{\text{i}}$$, where $$N_{\text{i}}$$ is the number of density matrices for the density matrix perturbation tuple dmat_idx_tuple[i] for a frequency configuration dens_mat (QcMat*[]) – the collected AO based density matrices, size is num_dmat, and arranged as [num_freq_configs][dmat_idx_tuple] user_ctx (void*) – user-defined callback function context num_int (const QInt) – number of the integral matrices, equals to the product of the size of perturbations on the XC functional (specified by the perturbation tuple xc_pert_tuple) and the number of different frequency configurations num_freq_configs the integral matrices to be added, size is num_int, and arranged as [num_freq_configs][xc_pert_tuple] QcMat*[] void
void get_xc_fun_exp(xc_len_tuple, xc_pert_tuple, num_freq_configs, pert_freq_category, dmat_num_tuple, dmat_idx_tuple, num_dmat, dens_mat, user_ctx, num_exp, val_exp)

User-specified function for calculating expectation values of the XC functional and its derivatives, the last argument for the function OpenRSPAddXCFun().

Parameters: Var val_exp: xc_len_tuple (const QInt) – length of the perturbation tuple on the XC functional xc_pert_tuple (const QcPertInt*) – perturbation tuple on the XC functional, size is xc_len_tuple num_freq_configs (const QInt) – the number of different frequency configurations to be considered for the perturbation tuple specified by xc_pert_tuple pert_freq_category (const QInt*) – category of perturbation frequencies, size is [num_freq_configs][xc_len_tuple]. dmat_num_tuple (const QInt) – the number of different perturbation tuples of the AO based density matrices passed dmat_idx_tuple (const QInt*) – indices of the density matrix perturbation tuples passed (canonically ordered), size is dmat_num_tuple num_dmat (const QInt) – number of collected AO based density matrices for the passed density matrix perturbation tuples (specified by dmat_idx_tuple) and all frequency configurations, that is num_freq_configs $$\times\sum_{\text{i}}N_{\text{i}}$$, where $$N_{\text{i}}$$ is the number of density matrices for the density matrix perturbation tuple dmat_idx_tuple[i] for a frequency configuration dens_mat (QcMat*[]) – the collected AO based density matrices, size is num_dmat, and arranged as [num_freq_configs][dmat_idx_tuple] user_ctx (void*) – user-defined callback function context num_exp (const QInt) – number of the expectation values, equals to the product of the size of perturbations on the XC functional (specified by the perturbation tuple xc_pert_tuple) and the number of different frequency configurations num_freq_configs the expectation values to be added, size is 2 $$\times$$ num_exp, and arranged as [num_freq_configs][xc_pert_tuple][2] QReal* void
void get_zero_oper_contrib(oper_num_pert, oper_pert_labels, oper_pert_orders, user_ctx, size_pert, val_oper)

User-specified callback function to calculate contributions from the zero-electron operator, the last argument for the function OpenRSPAddZeroOper().

Parameters: Var val_oper: oper_num_pert (const QInt) – number of perturbations on the zero-electron operator oper_pert_labels (const QcPertInt*) – labels of perturbations on the zero-electron operator, size is oper_num_pert oper_pert_orders (const QInt*) – orders of perturbations on the zero-electron operator, size is oper_num_pert user_ctx (void*) – user-defined callback function context size_pert (const QInt) – size of the perturbations on the zero-electron operator contributions from the zero-electron operator to be added, arranged as [size_pert][2] QReal* void
void get_linear_rsp_solution(num_pert, num_comps, num_freq_sums, freq_sums, RHS_mat, user_ctx, rsp_param)

User-specified callback function of linear response equation solver, the last argument for the function OpenRSPSetLinearRSPSolver().

Parameters: Var rsp_param: num_pert (const QInt) – number of different perturbations on the right hand side of the linear response equation num_comps (const QInt*) – number of components of each perturbation, size is num_pert num_freq_sums (const QInt*) – for each perturbation, number of complex frequency sums on the left hand side of the linear response equation, size is num_pert freq_sums (const QReal*) – the complex frequency sums on the left hand side of the linear response equation, size is twice of the sum of num_freq_sums, the real and imaginary parts of each frequency sum are consecutive in memory RHS_mat (QcMat*[]) – RHS matrices, size is the dot product of num_comps and num_freq_sums, and index of num_freq_sums runs faster in memory user_ctx (void*) – user-defined callback function context solved response parameters, size is the dot product of num_comps and num_freq_sums, and index of num_freq_sums runs faster in memory QcMat*[] void

OpenRSP Callback Subroutines (Fortran version)¶

The callback subroutines of Fortran codes take almost the exact arguments as the callback functions of C codes. One difference is the type convention between C and Fortran, which has been discussed in Secion Functions of OpenRSP API (Fortran version). Moreover, the pointers of basic types (integer and real numbers) in the C codes should be converted to corresponding array in Fortran. The array of QcMat pointers should be converted to an array of type(QcMat) in Fortran. Last, the user-defined callback function/subroutine context should be replaced by type(C_PTR).

We will develop Fortran unit testing in next release. For the time being, interested users can refer to LSDalton for examples of Fortran callback subroutines.