subroutine InitRotCalc() ! Sets up the initial arrays to be used in the orbital rotation. character(len=*), parameter :: this_routine = 'InitRotCalc' integer :: i, j, Const, MinRot, MaxRot call InitSymmArrays() ! Creates an indexing system for each of the cases with symmetry on/off, and mixing all orbitals or separating ! the occuppied from virtual. ! The arrays used in this routine are labelled with a 2 (SymLabelList2_rot and SymLabelCount2), so as to not ! mess up the spawing/FCI calcs. do i = 1, NoOrbs SymLabelList3_rot(i) = SymLabelList2_rot(i) end do ! Set up constraint labels. Constraint l is the dot product of i.j. Const = 0 do i = 1, NoOrbs do j = i, NoOrbs Const = Const + 1 Lab(1, Const) = i Lab(2, Const) = j end do end do ! Just a check that the number of constraints labeled is the same as ! that calculated above. write(stdout, *) 'Total number of constraints = ', TotNoConstraints if (Const /= TotNoConstraints) then call Stop_all(this_routine, 'ERROR in the number of constraints calculated. lmax does not equal TotNoConstraints') end if ! Zero/initialise the arrays ! In the case where symmetry is kept, the starting transformation matrix is just the identity. Starting with a symmetric system ! means the symmetry is never broken. ! When we are breaking the symmetry, the starting transformation matrix is completely random, (and then orthonormalised). ! The ordering of the orbitals in CoeffT1 follow the ordering in SymLabelList2_rot. CoeffT1(:, :) = 0.0_dp if (tRotateOccOnly) then MinRot = 1 MaxRot = NoOcc else if (tRotateVirtOnly) then MinRot = NoOcc + 1 MaxRot = NoOrbs else MinRot = 1 MaxRot = NoOrbs end if do i = 1, NoOrbs CoeffT1(i, i) = 1.0_dp end do ! If the symmetry is kept on, start with the symmetric identity matrix ! of coefficients, and it will be maintained. ! When only the occupied or virtual orbitals are rotated, the non ! rotated orbitals are still included in the transformation matrix, ! but start as the identity, and remain that way throughout. if (lNoSymmetry) then do i = MinRot, MaxRot do j = MinRot, MaxRot CoeffT1(j, i) = genrand_real2_dSFMT() * (1E-02_dp) end do end do end if ! Ensures transformation matrix elements between the occupied and ! virtual orbitals are 0 (should be the case anyway though). if (tSeparateOccVirt) call ZeroOccVirtElements(CoeffT1) ! Orthonormalise starting matrix. call GRAMSCHMIDT_NECI(CoeffT1, NoOrbs) ! A UMATTemp is created (from the UMAT read in from the FCIDUMP) using the rotate orbs indexing system. ! i.e. in UMatTemp(1,1,1,1), the orbital involved is the first in SymLabelList2_rot. ! Doing this now, rather than using UMatInd in each transform2elint routine proved a lot faster. DerivCoeff(:, :) = 0.0_dp UMATTemp01(:, :, :, :) = 0.0_dp if (((.not. tERLocalization) .and. (.not. tReadInCoeff) .and. (.not. tUseMP2VarDenMat) & .and. (.not. tFindCINatOrbs) .and. (.not. tUseHFOrbs))& .or. (tERLocalization .and. tStoreSpinOrbs)) UMATTemp02(:, :, :, :) = 0.0_dp call CopyAcrossUMAT() call TestOrthonormality() ! With UMAT with the correct indexing and the starting coefficient, ! find the partially transformed four index integrals (and hence the ! initial potential energy), and then the initial force. if (tERLocalization .and. (.not. tStoreSpinOrbs)) then call Transform2ElIntsERlocal() else call Transform2ElInts() end if call FindTheForce() if (tPrintInts) then ! This sets the initial values for the integral sums being printed. ! Values printed are then relative to these initial sums, per ! integral. tInitIntValues = .true. call PrintIntegrals() tInitIntValues = .false. end if end subroutine InitRotCalc