! This file is an example of the kind of manipulations that you can do with providers ! !!!!!!!!!!!!!!!!!!!!!!!!!! Main providers useful for the program !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!! type name BEGIN_PROVIDER [ double precision, trace_mo_one_e_ints] implicit none BEGIN_DOC ! trace_mo_one_e_ints = Trace of the one-electron integrals on the MO basis ! ! = sum_i mo_one_e_integrals(i,i) END_DOC integer :: i trace_mo_one_e_ints = 0.d0 do i = 1, mo_num trace_mo_one_e_ints += mo_one_e_integrals(i,i) enddo END_PROVIDER BEGIN_PROVIDER [ double precision, trace_ao_one_e_ints] implicit none BEGIN_DOC ! trace_ao_one_e_ints = Trace of the one-electron integrals on the AO basis taking into account the non orthogonality ! ! Be aware that the trace of an operator in a non orthonormal basis is Tr(A S^{-1}) = \sum_{m,n}(A_mn S^{-1}_mn) ! ! WARNING: it is equal to the trace on the MO basis if and only if the AO basis and MO basis ! have the same number of functions END_DOC integer :: i,j double precision, allocatable :: inv_overlap_times_integrals(:,:) ! = h S^{-1} allocate(inv_overlap_times_integrals(ao_num,ao_num)) ! routine that computes the product of two matrices, you can check it with ! irpman get_AB_prod call get_AB_prod(ao_one_e_integrals,ao_num,ao_num,s_inv,ao_num,inv_overlap_times_integrals) ! Tr(inv_overlap_times_integrals) = Tr(h S^{-1}) trace_ao_one_e_ints = 0.d0 do i = 1, ao_num trace_ao_one_e_ints += inv_overlap_times_integrals(i,i) enddo ! ! testing the formula Tr(A S^{-1}) = \sum_{m,n}(A_mn S^{-1}_mn) double precision :: test test = 0.d0 do i = 1, ao_num do j = 1, ao_num test += ao_one_e_integrals(j,i) * s_inv(i,j) enddo enddo if(dabs(accu - trace_ao_one_e_ints).gt.1.d-12)then print*,'Warning ! ' print*,'Something is wrong because Tr(AB) \ne sum_{mn}A_mn B_nm' endif END_PROVIDER BEGIN_PROVIDER [ double precision, trace_ao_one_e_ints_from_mo] implicit none BEGIN_DOC ! trace_ao_one_e_ints_from_mo = Trace of the one-electron integrals on the AO basis after projection on the MO basis ! ! = Tr([SC h {SC}^+] S^{-1}) ! ! = Be aware that the trace of an operator in a non orthonormal basis is = Tr(A S^{-1}) where S is the metric ! Must be equal to the trace_mo_one_e_ints END_DOC integer :: i double precision, allocatable :: inv_overlap_times_integrals(:,:) allocate(inv_overlap_times_integrals(ao_num,ao_num)) ! Using the provider ao_one_e_integrals_from_mo = [SC h {SC}^+] call get_AB_prod(ao_one_e_integrals_from_mo,ao_num,ao_num,s_inv,ao_num,inv_overlap_times_integrals) ! inv_overlap_times_integrals = [SC h {SC}^+] S^{-1} trace_ao_one_e_ints_from_mo = 0.d0 ! Computing the trace do i = 1, ao_num trace_ao_one_e_ints_from_mo += inv_overlap_times_integrals(i,i) enddo END_PROVIDER !!!!!!!!!!!!!!!!!!!!!!!!!!! Additional providers to check some stuffs !!!!!!!!!!!!!!!!!!!!!!!!! BEGIN_PROVIDER [ double precision, ao_one_e_int_no_ov_from_mo, (ao_num, ao_num) ] BEGIN_DOC ! ao_one_e_int_no_ov_from_mo = C mo_one_e_integrals C^T ! ! WARNING : NON EQUAL TO ao_one_e_integrals due to the non orthogonality END_DOC call mo_to_ao_no_overlap(mo_one_e_integrals,mo_num,ao_one_e_int_no_ov_from_mo,ao_num) END_PROVIDER BEGIN_PROVIDER [ double precision, ao_one_e_int_no_ov_from_mo_ov_ov, (ao_num, ao_num)] BEGIN_DOC ! ao_one_e_int_no_ov_from_mo_ov_ov = S ao_one_e_int_no_ov_from_mo S = SC mo_one_e_integrals (SC)^T ! ! EQUAL TO ao_one_e_integrals ONLY IF ao_num = mo_num END_DOC double precision, allocatable :: tmp(:,:) allocate(tmp(ao_num, ao_num)) call get_AB_prod(ao_overlap,ao_num,ao_num,ao_one_e_int_no_ov_from_mo,ao_num,tmp) call get_AB_prod(tmp,ao_num,ao_num,ao_overlap,ao_num,ao_one_e_int_no_ov_from_mo_ov_ov) END_PROVIDER BEGIN_PROVIDER [ double precision, c_t_s_c, (mo_num, mo_num)] implicit none BEGIN_DOC ! C^T S C = should be the identity END_DOC call get_AB_prod(mo_coef_transp,mo_num,ao_num,S_mo_coef,mo_num,c_t_s_c) END_PROVIDER