1919
2020! > Implementation of a modified Broyden mixing
2121module tblite_scf_broyden
22- use mctc_env, only : wp
22+ use mctc_env, only : wp, error_type, fatal_error
2323 use tblite_lapack, only : getrf, getrs
2424 implicit none
2525 private
@@ -131,14 +131,21 @@ subroutine diff_1d(self, qvec)
131131 self% idif = self% idif + size (qvec)
132132end subroutine diff_1d
133133
134- subroutine next (self )
134+ subroutine next (self , error )
135135 class(broyden_mixer), intent (inout ) :: self
136+ type (error_type), allocatable , intent (out ) :: error
137+
138+ integer :: info
139+
136140 self% iset = 0
137141 self% idif = 0
138142 self% iget = 0
139143 self% iter = self% iter + 1
140144 call broyden(self% ndim, self% q_in, self% qlast_in, self% dq, self% dqlast, &
141- & self% iter, self% memory, self% damp, self% omega, self% df, self% u, self% a)
145+ & self% iter, self% memory, self% damp, self% omega, self% df, self% u, self% a, info)
146+ if (info /= 0 ) then
147+ call fatal_error(error, " Broyden mixing failed to obtain next iteration" )
148+ end if
142149end subroutine next
143150
144151subroutine get_2d (self , qvec )
@@ -164,7 +171,7 @@ subroutine get_1d(self, qvec)
164171 self% iget = self% iget + size (qvec)
165172end subroutine get_1d
166173
167- subroutine broyden (n , q , qlast , dq , dqlast , iter , memory , alpha , omega , df , u , a )
174+ subroutine broyden (n , q , qlast , dq , dqlast , iter , memory , alpha , omega , df , u , a , info )
168175 integer , intent (in ) :: n
169176 integer , intent (in ) :: iter
170177 integer , intent (in ) :: memory
@@ -177,11 +184,13 @@ subroutine broyden(n, q, qlast, dq, dqlast, iter, memory, alpha, omega, df, u, a
177184 real (wp), intent (inout ) :: a(memory, memory)
178185 real (wp), intent (inout ) :: omega(memory)
179186 real (wp), intent (in ) :: alpha
187+ integer , intent (out ) :: info
180188
181189 real (wp), allocatable :: beta(:,:), c(:, :)
182190 integer :: i, it1
183191 real (wp) :: inv, omega0, minw, maxw, wfac
184192
193+ info = 0
185194 it1 = iter - 1
186195
187196 ! set parameters
@@ -233,7 +242,8 @@ subroutine broyden(n, q, qlast, dq, dqlast, iter, memory, alpha, omega, df, u, a
233242 end do
234243
235244 ! build beta^-1
236- call lineq(beta, c)
245+ call lineq(beta, c, info)
246+ if (info /= 0 ) return
237247
238248 ! Build |u>
239249 u(:, it1) = alpha * df(:, it1) + inv * (q- qlast) ! !!
@@ -251,11 +261,11 @@ subroutine broyden(n, q, qlast, dq, dqlast, iter, memory, alpha, omega, df, u, a
251261
252262end subroutine broyden
253263
254- subroutine lineq (a , c )
264+ subroutine lineq (a , c , info )
255265 real (wp), intent (inout ) :: a(:, :)
256266 real (wp), intent (inout ) :: c(:, :)
267+ integer , intent (out ) :: info
257268
258- integer info
259269 integer , allocatable :: ipiv(:)
260270
261271 allocate (ipiv(size (a, 1 )))
@@ -265,10 +275,6 @@ subroutine lineq(a, c)
265275 ! generate inverse of a matrix given its LU decomposition
266276 call getrs(a, c, ipiv, info, trans= " t" )
267277 endif
268- if (info /= 0 )then
269- error stop " Error in Broyden matrix inversion!"
270- endif
271-
272278end subroutine lineq
273279
274280pure function get_error (self ) result(error)
0 commit comments