********>Bugfix 3: Author: Ross Walker Date: 05/02/2008 Programs: sander Description: Sander QMMM runs where auto diagonalization selection is used but one of the lapack diagonalizers fails to converge can result in a segfault when the diagonalization routine attempts to fall back on the internal diagonalizer as a fail safe. Fix: apply the following patch to amber10/src/sander/qm2_load_params_and_allocate.f amber10/src/sander/qm2_scf.f ------------------------------------------------------------------------------ --- qm2_load_params_and_allocate.f 2008-05-02 11:29:31.000000000 -0700 +++ qm2_load_params_and_allocate.f 2008-05-02 11:21:18.000000000 -0700 @@ -1734,6 +1734,7 @@ integer :: ilaenv_blocksize integer :: diag_iterations integer :: i, ier + integer :: diag_routine_to_test abstol = 2.0d0 * dlamch('S') !tolerance for dspevr @@ -1781,12 +1782,13 @@ allocate (qmmm_scratch%mat_diag_workspace(qm2_struct%norbs,6),stat=ier) REQUIRE(ier==0) + diag_routine_to_test = 1 current_time=0.0d0 do i = 1,diag_iterations !Need to rebuild the fock matrix each time since some diag routines can destroy it. call qm2_time_diag_routines_random(qm2_struct%matsize,qm2_struct%fock_matrix) call wallclock(start_time) - call qm2_full_diagonalize(1,qm2_struct%fock_matrix,qm2_struct%norbs,qm2_struct%eigen_vectors,abstol) + call qm2_full_diagonalize(diag_routine_to_test,qm2_struct%fock_matrix,qm2_struct%norbs,qm2_struct%eigen_vectors,abstol) call wallclock(end_time) current_time = current_time + (end_time-start_time) end do @@ -1795,7 +1797,9 @@ !initially just assume that the internal routine is the fastest. fastest_time = current_time - diag_routine = 1 + diag_routine = diag_routine_to_test !Note reason for this here is if the routine actually failed to converge then + !diag_routine_to_test will have been set back to the internal diagonalizer + !by the diag routine. deallocate (qmmm_scratch%mat_diag_workspace,stat=ier) REQUIRE(ier==0) @@ -1813,12 +1817,13 @@ allocate (qmmm_scratch%mat_diag_workspace(qm2_struct%norbs,4),stat=ier) REQUIRE(ier==0) + diag_routine_to_test = 2 current_time=0.0d0 do i = 1,diag_iterations !Need to rebuild the fock matrix each time since some diag routines can destroy it. call qm2_time_diag_routines_random(qm2_struct%matsize,qm2_struct%fock_matrix) call wallclock(start_time) - call qm2_full_diagonalize(2,qm2_struct%fock_matrix,qm2_struct%norbs,qm2_struct%eigen_vectors,abstol) + call qm2_full_diagonalize(diag_routine_to_test,qm2_struct%fock_matrix,qm2_struct%norbs,qm2_struct%eigen_vectors,abstol) call wallclock(end_time) current_time = current_time + (end_time-start_time) end do @@ -1827,7 +1832,9 @@ !check if this routine is faster than the ones tried so far. if (fastest_time >= current_time) then - diag_routine = 2 + diag_routine = diag_routine_to_test !Note reason for this here is if the routine actually failed to converge then + !diag_routine_to_test will have been set back to the internal diagonalizer + !by the diag routine. fastest_time = current_time end if @@ -1863,12 +1870,13 @@ allocate (qmmm_scratch%lapack_dc_int_scr(qmmm_scratch%lapack_dc_int_scr_aloc), stat=ier) REQUIRE(ier==0) + diag_routine_to_test = 3 current_time=0.0d0 do i = 1,diag_iterations !Need to rebuild the fock matrix each time since some diag routines can destroy it. call qm2_time_diag_routines_random(qm2_struct%matsize,qm2_struct%fock_matrix) call wallclock(start_time) - call qm2_full_diagonalize(3,qm2_struct%fock_matrix,qm2_struct%norbs,qm2_struct%eigen_vectors,abstol) + call qm2_full_diagonalize(diag_routine_to_test,qm2_struct%fock_matrix,qm2_struct%norbs,qm2_struct%eigen_vectors,abstol) call wallclock(end_time) current_time = current_time + (end_time-start_time) end do @@ -1877,7 +1885,9 @@ !check if this routine is faster than the ones tried so far. if (fastest_time >= current_time) then - diag_routine = 3 + diag_routine = diag_routine_to_test !Note reason for this here is if the routine actually failed to converge then + !diag_routine_to_test will have been set back to the internal diagonalizer + !by the diag routine. fastest_time = current_time end if deallocate (qmmm_scratch%lapack_dc_real_scr,stat=ier) @@ -1906,12 +1916,13 @@ allocate (qmmm_scratch%lapack_dc_int_scr(qmmm_scratch%lapack_dc_int_scr_aloc), stat=ier) REQUIRE(ier==0) + diag_routine_to_test = 4 current_time=0.0d0 do i = 1,diag_iterations !Need to rebuild the fock matrix each time since some diag routines can destroy it. call qm2_time_diag_routines_random(qm2_struct%matsize,qm2_struct%fock_matrix) call wallclock(start_time) - call qm2_full_diagonalize(4,qm2_struct%fock_matrix,qm2_struct%norbs,qm2_struct%eigen_vectors,abstol) + call qm2_full_diagonalize(diag_routine_to_test,qm2_struct%fock_matrix,qm2_struct%norbs,qm2_struct%eigen_vectors,abstol) call wallclock(end_time) current_time = current_time + (end_time-start_time) end do @@ -1920,7 +1931,9 @@ !check if this routine is faster than the ones tried so far. if (fastest_time >= current_time) then - diag_routine = 4 + diag_routine = diag_routine_to_test !Note reason for this here is if the routine actually failed to converge then + !diag_routine_to_test will have been set back to the internal diagonalizer + !by the diag routine. fastest_time = current_time end if deallocate (qmmm_scratch%lapack_dc_int_scr,stat=ier) @@ -1955,12 +1968,13 @@ allocate (qmmm_scratch%lapack_dc_real_scr(qmmm_scratch%lapack_dc_real_scr_aloc),stat=ier) REQUIRE(ier==0) + diag_routine_to_test = 5 current_time=0.0d0 do i = 1,diag_iterations !Need to rebuild the fock matrix each time since some diag routines can destroy it. call qm2_time_diag_routines_random(qm2_struct%matsize,qm2_struct%fock_matrix) call wallclock(start_time) - call qm2_full_diagonalize(5,qm2_struct%fock_matrix,qm2_struct%norbs,qm2_struct%eigen_vectors,abstol) + call qm2_full_diagonalize(diag_routine_to_test,qm2_struct%fock_matrix,qm2_struct%norbs,qm2_struct%eigen_vectors,abstol) call wallclock(end_time) current_time = current_time + (end_time-start_time) end do @@ -1969,7 +1983,9 @@ !check if this routine is faster than the ones tried so far. if (fastest_time >= current_time) then - diag_routine = 5 + diag_routine = diag_routine_to_test !Note reason for this here is if the routine actually failed to converge then + !diag_routine_to_test will have been set back to the internal diagonalizer + !by the diag routine. fastest_time = current_time end if deallocate (qmmm_scratch%lapack_dc_real_scr,stat=ier) @@ -2006,12 +2022,13 @@ allocate (qmmm_scratch%lapack_dc_int_scr(qmmm_scratch%lapack_dc_int_scr_aloc),stat=ier) REQUIRE(ier==0) + diag_routine_to_test = 6 current_time=0.0d0 do i = 1,diag_iterations !Need to rebuild the fock matrix each time since some diag routines can destroy it. call qm2_time_diag_routines_random(qm2_struct%matsize,qm2_struct%fock_matrix) call wallclock(start_time) - call qm2_full_diagonalize(6,qm2_struct%fock_matrix,qm2_struct%norbs,qm2_struct%eigen_vectors,abstol) + call qm2_full_diagonalize(diag_routine_to_test,qm2_struct%fock_matrix,qm2_struct%norbs,qm2_struct%eigen_vectors,abstol) call wallclock(end_time) current_time = current_time + (end_time-start_time) end do @@ -2020,7 +2037,9 @@ !check if this routine is faster than the ones tried so far. if (fastest_time >= current_time) then - diag_routine = 6 + diag_routine = diag_routine_to_test !Note reason for this here is if the routine actually failed to converge then + !diag_routine_to_test will have been set back to the internal diagonalizer + !by the diag routine. fastest_time = current_time end if deallocate (qmmm_scratch%lapack_dc_int_scr,stat=ier) @@ -2071,12 +2090,13 @@ REQUIRE(ier==0) end if + diag_routine_to_test = 7 current_time=0.0d0 do i = 1,diag_iterations !Need to rebuild the fock matrix each time since some diag routines can destroy it. call qm2_time_diag_routines_random(qm2_struct%matsize,qm2_struct%fock_matrix) call wallclock(start_time) - call qm2_full_diagonalize(7,qm2_struct%fock_matrix,qm2_struct%norbs,qm2_struct%eigen_vectors,abstol) + call qm2_full_diagonalize(diag_routine_to_test,qm2_struct%fock_matrix,qm2_struct%norbs,qm2_struct%eigen_vectors,abstol) call wallclock(end_time) current_time = current_time + (end_time-start_time) end do @@ -2085,7 +2105,9 @@ !check if this routine is faster than the ones tried so far. if (fastest_time >= current_time) then - diag_routine = 7 + diag_routine = diag_routine_to_test !Note reason for this here is if the routine actually failed to converge then + !diag_routine_to_test will have been set back to the internal diagonalizer + !by the diag routine. fastest_time = current_time end if deallocate (qmmm_scratch%lapack_dc_int_scr,stat=ier) --- qm2_scf.f 2008-05-02 10:39:56.000000000 -0700 +++ qm2_scf.f 2008-05-02 11:27:02.000000000 -0700 @@ -1288,7 +1288,7 @@ qmmm_scratch%lapack_dc_int_scr_aloc, ierr) !Check ierr returned zero. if (ierr /= 0) then - write(6,'("| QMMM: ERROR dspev failed to converge and returned ",i8)') ierr + write(6,'("| QMMM: ERROR dspevd failed to converge and returned ",i8)') ierr write(6,'("| QMMM: Falling back on internal diagonalizer for the remainder of this run.")') diag_routine = 1 deallocate (qmmm_scratch%mat_diag_workspace,stat=ierr) @@ -1316,7 +1316,7 @@ qmmm_scratch%lapack_dc_int_scr, ierr ) !Check ierr returned zero. if (ierr /= 0) then - write(6,'("| QMMM: ERROR dspev failed to converge and returned ",i8)') ierr + write(6,'("| QMMM: ERROR dspevx failed to converge and returned ",i8)') ierr write(6,'("| QMMM: Falling back on internal diagonalizer for the remainder of this run.")') diag_routine = 1 deallocate (qmmm_scratch%mat_diag_workspace,stat=ierr) @@ -1344,7 +1344,7 @@ ierr) !Check ierr returned zero. if (ierr /= 0) then - write(6,'("| QMMM: ERROR dspev failed to converge and returned ",i8)') ierr + write(6,'("| QMMM: ERROR dsyev failed to converge and returned ",i8)') ierr write(6,'("| QMMM: Falling back on internal diagonalizer for the remainder of this run.")') diag_routine = 1 deallocate (qmmm_scratch%mat_diag_workspace,stat=ierr) @@ -1374,7 +1374,7 @@ ierr) !Check ierr returned zero. if (ierr /= 0) then - write(6,'("| QMMM: ERROR dspev failed to converge and returned ",i8)') ierr + write(6,'("| QMMM: ERROR dsyevd failed to converge and returned ",i8)') ierr write(6,'("| QMMM: Falling back on internal diagonalizer for the remainder of this run.")') diag_routine = 1 deallocate (qmmm_scratch%mat_diag_workspace,stat=ierr) @@ -1403,7 +1403,7 @@ (qmmm_scratch%lapack_dc_int_scr_aloc-2*matrix_dimension), ierr) !Check ierr returned zero. if (ierr /= 0) then - write(6,'("| QMMM: ERROR dspev failed to converge and returned ",i8)') ierr + write(6,'("| QMMM: ERROR dsyevr failed to converge and returned ",i8)') ierr write(6,'("| QMMM: Falling back on internal diagonalizer for the remainder of this run.")') diag_routine = 1 deallocate (qmmm_scratch%mat_diag_workspace,stat=ierr) ------------------------------------------------------------------------------ Temporary workarounds: Manually skip the auto diagonalization test and manually select a diagonalizer when running QMMM.