module huti_bicgstab_2
use huti_aux
implicit none
#include "huti_fdefs.h"
#define X xvec
#define B rhsvec
#define RTLD work(:,1)
#define RTLD_ind 1
#define U work(:,2)
#define U_ind 2
#define T1V work(:,3)
#define T1V_ind 3
#define V work(:,4)
#define V_ind 4
#define S work(:,5)
#define S_ind 5
#define W work(:,6)
#define W_ind 6
#define T work(:,7)
#define T_ind 7
#define R work(:,8)
#define R_ind 8
contains
subroutine huti_sbicgstab_2solv ( ndim, wrkdim, xvec, rhsvec, &
ipar, dpar, work, matvecsubr, pcondlsubr, &
pcondrsubr, dotprodfun, normfun, stopcfun )
use huti_interfaces
implicit none
procedure( mv_iface_s ), pointer :: matvecsubr
procedure( pc_iface_s ), pointer :: pcondlsubr
procedure( pc_iface_s ), pointer :: pcondrsubr
procedure( dotp_iface_s ), pointer :: dotprodfun
procedure( norm_iface_s ), pointer :: normfun
procedure( stopc_iface_s ), pointer :: stopcfun
integer :: ndim, wrkdim
real, dimension(ndim) :: xvec, rhsvec
integer, dimension(HUTI_IPAR_DFLTSIZE) :: ipar
double precision, dimension(HUTI_DPAR_DFLTSIZE) :: dpar
real, dimension(ndim,wrkdim) :: work
real :: rho, oldrho, alpha, beta, omega1, omega2
real :: tau, delta, myy
integer :: iter_count
real :: residual, rhsnorm, precrhsnorm
iter_count = 1
HUTI_EXTOP_MATTYPE = HUTI_MAT_NOTTRPSED
if ( HUTI_STOPC .eq. HUTI_TRESID_SCALED_BYB .or. &
HUTI_STOPC .eq. HUTI_PRESID_SCALED_BYB ) then
rhsnorm = normfun( HUTI_NDIM, B, 1 )
end if
if ( HUTI_STOPC .eq. HUTI_PRESID_SCALED_BYPRECB ) then
call pcondlsubr( T1V, B, ipar )
precrhsnorm = normfun( HUTI_NDIM, T1V, 1 )
end if
if ( HUTI_INITIALX .eq. HUTI_RANDOMX ) then
call huti_srandvec ( X, ipar )
else if ( HUTI_INITIALX .ne. HUTI_USERSUPPLIEDX ) then
X = 1
end if
call pcondrsubr( U, X, ipar )
call matvecsubr( U, R, ipar )
U = B - R
call pcondlsubr( R, U, ipar )
RTLD = R
U = 0
oldrho = 1; omega2 = 1; alpha = 0
300 continue
oldrho = -omega2 * oldrho
rho = dotprodfun( HUTI_NDIM, RTLD, 1, R, 1 )
if ( rho .eq. 0 ) then
HUTI_INFO = HUTI_BICGSTAB_2_RHO
go to 1000
end if
beta = ( rho * alpha ) / oldrho
oldrho = rho
U = R - beta * U
call pcondrsubr( V, U, ipar )
call matvecsubr( V, T1V, ipar )
call pcondlsubr( V, T1V, ipar )
alpha = oldrho / dotprodfun( HUTI_NDIM, RTLD, 1, V, 1 )
R = R - alpha * V
call pcondrsubr( S, R, ipar )
call matvecsubr( S, T1V, ipar )
call pcondlsubr( S, T1V, ipar )
X = X + alpha * U
rho = dotprodfun( HUTI_NDIM, RTLD, 1, S, 1 )
if ( rho .eq. 0 ) then
HUTI_INFO = HUTI_BICGSTAB_2_RHO
go to 1000
end if
beta = ( rho * alpha ) / oldrho
oldrho = rho
V = S - beta * V
call pcondrsubr( W, V, ipar )
call matvecsubr( W, T1V, ipar )
call pcondlsubr( W, T1V, ipar )
alpha = oldrho / dotprodfun( HUTI_NDIM, RTLD, 1, W, 1 )
U = R - beta * U
R = R - alpha * V
S = S - alpha * W
call pcondrsubr( T, S, ipar )
call matvecsubr( T, T1V, ipar )
call pcondlsubr( T, T1V, ipar )
omega1 = dotprodfun( HUTI_NDIM, R, 1, S, 1 )
myy = dotprodfun( HUTI_NDIM, S, 1, S, 1 )
delta = dotprodfun( HUTI_NDIM, S, 1, T, 1 )
tau = dotprodfun( HUTI_NDIM, T, 1, T, 1 )
omega2 = dotprodfun( HUTI_NDIM, R, 1, T, 1 )
tau = tau - ( delta * delta ) / myy
omega2 = ( omega2 - ( delta * omega1 ) / myy ) / tau
omega1 = ( omega1 - delta * omega2 ) / myy
X = X + omega1 * R + omega2 * S + alpha * U
R = R - omega1 * S - omega2 * T
select case (HUTI_STOPC)
case (HUTI_TRUERESIDUAL)
call pcondrsubr( S, X, ipar )
call matvecsubr( S, T1V, ipar )
T1V = T1V - B
call pcondlsubr( S, T1V, ipar )
residual = normfun( HUTI_NDIM, S, 1 )
case (HUTI_TRESID_SCALED_BYB)
call pcondrsubr( S, X, ipar )
call matvecsubr( S, T1V, ipar )
T1V = T1V - B
call pcondlsubr( S, T1V, ipar )
residual = normfun( HUTI_NDIM, S, 1 ) / rhsnorm
case (HUTI_PSEUDORESIDUAL)
residual = normfun( HUTI_NDIM, R, 1 )
case (HUTI_PRESID_SCALED_BYB)
residual = normfun( HUTI_NDIM, R, 1 ) / rhsnorm
case (HUTI_PRESID_SCALED_BYPRECB)
residual = normfun( HUTI_NDIM, R, 1 ) / precrhsnorm
case (HUTI_XDIFF_NORM)
T1V = omega1 * R + omega2 * S + alpha * U
residual = normfun( HUTI_NDIM, T1V, 1 )
case (HUTI_USUPPLIED_STOPC)
residual = stopcfun( X, B, R, ipar, dpar )
case default
call pcondrsubr( S, X, ipar )
call matvecsubr( S, T1V, ipar )
T1V = T1V - B
call pcondlsubr( S, T1V, ipar )
residual = normfun( HUTI_NDIM, S, 1 )
end select
if ( HUTI_DBUGLVL .ne. HUTI_NO_DEBUG ) then
if ( mod(iter_count, HUTI_DBUGLVL) .eq. 0 ) then
write (*, '(I8, E11.4)') iter_count, residual
end if
end if
if ( residual .lt. HUTI_TOLERANCE ) then
HUTI_INFO = HUTI_CONVERGENCE
go to 1000
end if
IF( residual /= residual .OR. residual > HUTI_MAXTOLERANCE ) THEN
HUTI_INFO = HUTI_DIVERGENCE
GOTO 1000
END IF
U = U - omega1 * V - omega2 * W
iter_count = iter_count + 1
if ( iter_count .gt. HUTI_MAXIT ) then
HUTI_INFO = HUTI_MAXITER
go to 1000
end if
go to 300
1000 continue
if ( HUTI_DBUGLVL .ne. HUTI_NO_DEBUG ) then
write (*, '(I8, E11.4)') iter_count, residual
end if
HUTI_ITERS = iter_count
return
end subroutine huti_sbicgstab_2solv
subroutine huti_dbicgstab_2solv ( ndim, wrkdim, xvec, rhsvec, &
ipar, dpar, work, matvecsubr, pcondlsubr, &
pcondrsubr, dotprodfun, normfun, stopcfun )
use huti_interfaces
implicit none
procedure( mv_iface_d ), pointer :: matvecsubr
procedure( pc_iface_d ), pointer :: pcondlsubr
procedure( pc_iface_d ), pointer :: pcondrsubr
procedure( dotp_iface_d ), pointer :: dotprodfun
procedure( norm_iface_d ), pointer :: normfun
procedure( stopc_iface_d ), pointer :: stopcfun
integer :: ndim, wrkdim
double precision, dimension(ndim) :: xvec, rhsvec
integer, dimension(HUTI_IPAR_DFLTSIZE) :: ipar
double precision, dimension(HUTI_DPAR_DFLTSIZE) :: dpar
double precision, dimension(ndim,wrkdim) :: work
double precision :: rho, oldrho, alpha, beta, omega1, omega2
double precision :: tau, delta, myy
integer :: iter_count
double precision :: residual, rhsnorm, precrhsnorm
iter_count = 1
HUTI_EXTOP_MATTYPE = HUTI_MAT_NOTTRPSED
if ( HUTI_STOPC .eq. HUTI_TRESID_SCALED_BYB .or. &
HUTI_STOPC .eq. HUTI_PRESID_SCALED_BYB ) then
rhsnorm = normfun( HUTI_NDIM, B, 1 )
end if
if ( HUTI_STOPC .eq. HUTI_PRESID_SCALED_BYPRECB ) then
call pcondlsubr( T1V, B, ipar )
precrhsnorm = normfun( HUTI_NDIM, T1V, 1 )
end if
if ( HUTI_INITIALX .eq. HUTI_RANDOMX ) then
call huti_drandvec ( X, ipar )
else if ( HUTI_INITIALX .ne. HUTI_USERSUPPLIEDX ) then
X = 1
end if
call pcondrsubr( U, X, ipar )
call matvecsubr( U, R, ipar )
U = B - R
call pcondlsubr( R, U, ipar )
RTLD = R
U = 0
oldrho = 1; omega2 = 1; alpha = 0
300 continue
oldrho = -omega2 * oldrho
rho = dotprodfun( HUTI_NDIM, RTLD, 1, R, 1 )
if ( rho .eq. 0 ) then
HUTI_INFO = HUTI_BICGSTAB_2_RHO
go to 1000
end if
beta = ( rho * alpha ) / oldrho
oldrho = rho
U = R - beta * U
call pcondrsubr( V, U, ipar )
call matvecsubr( V, T1V, ipar )
call pcondlsubr( V, T1V, ipar )
alpha = oldrho / dotprodfun( HUTI_NDIM, RTLD, 1, V, 1 )
R = R - alpha * V
call pcondrsubr( S, R, ipar )
call matvecsubr( S, T1V, ipar )
call pcondlsubr( S, T1V, ipar )
X = X + alpha * U
rho = dotprodfun( HUTI_NDIM, RTLD, 1, S, 1 )
if ( rho .eq. 0 ) then
HUTI_INFO = HUTI_BICGSTAB_2_RHO
go to 1000
end if
beta = ( rho * alpha ) / oldrho
oldrho = rho
V = S - beta * V
call pcondrsubr( W, V, ipar )
call matvecsubr( W, T1V, ipar )
call pcondlsubr( W, T1V, ipar )
alpha = oldrho / dotprodfun( HUTI_NDIM, RTLD, 1, W, 1 )
U = R - beta * U
R = R - alpha * V
S = S - alpha * W
call pcondrsubr( T, S, ipar )
call matvecsubr( T, T1V, ipar )
call pcondlsubr( T, T1V, ipar )
omega1 = dotprodfun( HUTI_NDIM, R, 1, S, 1 )
myy = dotprodfun( HUTI_NDIM, S, 1, S, 1 )
delta = dotprodfun( HUTI_NDIM, S, 1, T, 1 )
tau = dotprodfun( HUTI_NDIM, T, 1, T, 1 )
omega2 = dotprodfun( HUTI_NDIM, R, 1, T, 1 )
tau = tau - ( delta * delta ) / myy
omega2 = ( omega2 - ( delta * omega1 ) / myy ) / tau
omega1 = ( omega1 - delta * omega2 ) / myy
X = X + omega1 * R + omega2 * S + alpha * U
R = R - omega1 * S - omega2 * T
select case (HUTI_STOPC)
case (HUTI_TRUERESIDUAL)
call pcondrsubr( S, X, ipar )
call matvecsubr( S, T1V, ipar )
T1V = T1V - B
call pcondlsubr( S, T1V, ipar )
residual = normfun( HUTI_NDIM, S, 1 )
case (HUTI_TRESID_SCALED_BYB)
call pcondrsubr( S, X, ipar )
call matvecsubr( S, T1V, ipar )
T1V = T1V - B
call pcondlsubr( S, T1V, ipar )
residual = normfun( HUTI_NDIM, S, 1 ) / rhsnorm
case (HUTI_PSEUDORESIDUAL)
residual = normfun( HUTI_NDIM, R, 1 )
case (HUTI_PRESID_SCALED_BYB)
residual = normfun( HUTI_NDIM, R, 1 ) / rhsnorm
case (HUTI_PRESID_SCALED_BYPRECB)
residual = normfun( HUTI_NDIM, R, 1 ) / precrhsnorm
case (HUTI_XDIFF_NORM)
T1V = omega1 * R + omega2 * S + alpha * U
residual = normfun( HUTI_NDIM, T1V, 1 )
case (HUTI_USUPPLIED_STOPC)
residual = stopcfun( X, B, R, ipar, dpar )
case default
call pcondrsubr( S, X, ipar )
call matvecsubr( S, T1V, ipar )
T1V = T1V - B
call pcondlsubr( S, T1V, ipar )
residual = normfun( HUTI_NDIM, S, 1 )
end select
if ( HUTI_DBUGLVL .ne. HUTI_NO_DEBUG ) then
if ( mod(iter_count, HUTI_DBUGLVL) .eq. 0 ) then
write (*, '(I8, E11.4)') iter_count, residual
end if
end if
if ( residual .lt. HUTI_TOLERANCE ) then
HUTI_INFO = HUTI_CONVERGENCE
go to 1000
end if
IF( residual /= residual .OR. residual > HUTI_MAXTOLERANCE ) THEN
HUTI_INFO = HUTI_DIVERGENCE
GOTO 1000
END IF
U = U - omega1 * V - omega2 * W
iter_count = iter_count + 1
if ( iter_count .gt. HUTI_MAXIT ) then
HUTI_INFO = HUTI_MAXITER
go to 1000
end if
go to 300
1000 continue
if ( HUTI_DBUGLVL .ne. HUTI_NO_DEBUG ) then
write (*, '(I8, E11.4)') iter_count, residual
end if
HUTI_ITERS = iter_count
return
end subroutine huti_dbicgstab_2solv
subroutine huti_cbicgstab_2solv ( ndim, wrkdim, xvec, rhsvec, &
ipar, dpar, work, matvecsubr, pcondlsubr, &
pcondrsubr, dotprodfun, normfun, stopcfun )
use huti_interfaces
implicit none
procedure( mv_iface_c ), pointer :: matvecsubr
procedure( pc_iface_c ), pointer :: pcondlsubr
procedure( pc_iface_c ), pointer :: pcondrsubr
procedure( dotp_iface_c ), pointer :: dotprodfun
procedure( norm_iface_c ), pointer :: normfun
procedure( stopc_iface_c ), pointer :: stopcfun
integer :: ndim, wrkdim
complex, dimension(ndim) :: xvec, rhsvec
integer, dimension(HUTI_IPAR_DFLTSIZE) :: ipar
double precision, dimension(HUTI_DPAR_DFLTSIZE) :: dpar
complex, dimension(ndim,wrkdim) :: work
complex :: rho, oldrho, alpha, beta, omega1, omega2
complex :: tau, delta, myy
integer :: iter_count
real :: residual, rhsnorm, precrhsnorm
iter_count = 1
HUTI_EXTOP_MATTYPE = HUTI_MAT_NOTTRPSED
if ( HUTI_STOPC .eq. HUTI_TRESID_SCALED_BYB .or. &
HUTI_STOPC .eq. HUTI_PRESID_SCALED_BYB ) then
rhsnorm = normfun( HUTI_NDIM, B, 1 )
end if
if ( HUTI_STOPC .eq. HUTI_PRESID_SCALED_BYPRECB ) then
call pcondlsubr( T1V, B, ipar )
precrhsnorm = normfun( HUTI_NDIM, T1V, 1 )
end if
if ( HUTI_INITIALX .eq. HUTI_RANDOMX ) then
call huti_crandvec ( X, ipar )
else if ( HUTI_INITIALX .ne. HUTI_USERSUPPLIEDX ) then
X = 1
end if
call pcondrsubr( U, X, ipar )
call matvecsubr( U, R, ipar )
U = B - R
call pcondlsubr( R, U, ipar )
RTLD = R
U = 0
oldrho = 1; omega2 = 1; alpha = 0
300 continue
oldrho = -omega2 * oldrho
rho = dotprodfun( HUTI_NDIM, RTLD, 1, R, 1 )
if ( rho .eq. 0 ) then
HUTI_INFO = HUTI_BICGSTAB_2_RHO
go to 1000
end if
beta = ( rho * alpha ) / oldrho
oldrho = rho
U = R - beta * U
call pcondrsubr( V, U, ipar )
call matvecsubr( V, T1V, ipar )
call pcondlsubr( V, T1V, ipar )
alpha = oldrho / dotprodfun( HUTI_NDIM, RTLD, 1, V, 1 )
R = R - alpha * V
call pcondrsubr( S, R, ipar )
call matvecsubr( S, T1V, ipar )
call pcondlsubr( S, T1V, ipar )
X = X + alpha * U
rho = dotprodfun( HUTI_NDIM, RTLD, 1, S, 1 )
if ( rho .eq. 0 ) then
HUTI_INFO = HUTI_BICGSTAB_2_RHO
go to 1000
end if
beta = ( rho * alpha ) / oldrho
oldrho = rho
V = S - beta * V
call pcondrsubr( W, V, ipar )
call matvecsubr( W, T1V, ipar )
call pcondlsubr( W, T1V, ipar )
alpha = oldrho / dotprodfun( HUTI_NDIM, RTLD, 1, W, 1 )
U = R - beta * U
R = R - alpha * V
S = S - alpha * W
call pcondrsubr( T, S, ipar )
call matvecsubr( T, T1V, ipar )
call pcondlsubr( T, T1V, ipar )
omega1 = dotprodfun( HUTI_NDIM, R, 1, S, 1 )
myy = dotprodfun( HUTI_NDIM, S, 1, S, 1 )
delta = dotprodfun( HUTI_NDIM, S, 1, T, 1 )
tau = dotprodfun( HUTI_NDIM, T, 1, T, 1 )
omega2 = dotprodfun( HUTI_NDIM, R, 1, T, 1 )
tau = tau - ( delta * delta ) / myy
omega2 = ( omega2 - ( delta * omega1 ) / myy ) / tau
omega1 = ( omega1 - delta * omega2 ) / myy
X = X + omega1 * R + omega2 * S + alpha * U
R = R - omega1 * S - omega2 * T
select case (HUTI_STOPC)
case (HUTI_TRUERESIDUAL)
call pcondrsubr( S, X, ipar )
call matvecsubr( S, T1V, ipar )
T1V = T1V - B
call pcondlsubr( S, T1V, ipar )
residual = normfun( HUTI_NDIM, S, 1 )
case (HUTI_TRESID_SCALED_BYB)
call pcondrsubr( S, X, ipar )
call matvecsubr( S, T1V, ipar )
T1V = T1V - B
call pcondlsubr( S, T1V, ipar )
residual = normfun( HUTI_NDIM, S, 1 ) / rhsnorm
case (HUTI_PSEUDORESIDUAL)
residual = normfun( HUTI_NDIM, R, 1 )
case (HUTI_PRESID_SCALED_BYB)
residual = normfun( HUTI_NDIM, R, 1 ) / rhsnorm
case (HUTI_PRESID_SCALED_BYPRECB)
residual = normfun( HUTI_NDIM, R, 1 ) / precrhsnorm
case (HUTI_XDIFF_NORM)
T1V = omega1 * R + omega2 * S + alpha * U
residual = normfun( HUTI_NDIM, T1V, 1 )
case (HUTI_USUPPLIED_STOPC)
residual = stopcfun( X, B, R, ipar, dpar )
case default
call pcondrsubr( S, X, ipar )
call matvecsubr( S, T1V, ipar )
T1V = T1V - B
call pcondlsubr( S, T1V, ipar )
residual = normfun( HUTI_NDIM, S, 1 )
end select
if ( HUTI_DBUGLVL .ne. HUTI_NO_DEBUG ) then
if ( mod(iter_count, HUTI_DBUGLVL) .eq. 0 ) then
write (*, '(I8, E11.4)') iter_count, residual
end if
end if
if ( residual .lt. HUTI_TOLERANCE ) then
HUTI_INFO = HUTI_CONVERGENCE
go to 1000
end if
IF( residual /= residual .OR. residual > HUTI_MAXTOLERANCE ) THEN
HUTI_INFO = HUTI_DIVERGENCE
GOTO 1000
END IF
U = U - omega1 * V - omega2 * W
iter_count = iter_count + 1
if ( iter_count .gt. HUTI_MAXIT ) then
HUTI_INFO = HUTI_MAXITER
go to 1000
end if
go to 300
1000 continue
if ( HUTI_DBUGLVL .ne. HUTI_NO_DEBUG ) then
write (*, '(I8, E11.4)') iter_count, residual
end if
HUTI_ITERS = iter_count
return
end subroutine huti_cbicgstab_2solv
subroutine huti_zbicgstab_2solv ( ndim, wrkdim, xvec, rhsvec, &
ipar, dpar, work, matvecsubr, pcondlsubr, &
pcondrsubr, dotprodfun, normfun, stopcfun )
use huti_interfaces
implicit none
procedure( mv_iface_z ), pointer :: matvecsubr
procedure( pc_iface_z ), pointer :: pcondlsubr
procedure( pc_iface_z ), pointer :: pcondrsubr
procedure( dotp_iface_z ), pointer :: dotprodfun
procedure( norm_iface_z ), pointer :: normfun
procedure( stopc_iface_z ), pointer :: stopcfun
integer :: ndim, wrkdim
double complex, dimension(ndim) :: xvec, rhsvec
integer, dimension(HUTI_IPAR_DFLTSIZE) :: ipar
double precision, dimension(HUTI_DPAR_DFLTSIZE) :: dpar
double complex, dimension(ndim,wrkdim) :: work
double complex :: rho, oldrho, alpha, beta, omega1, omega2
double complex :: tau, delta, myy
integer :: iter_count
double precision :: residual, rhsnorm, precrhsnorm
iter_count = 1
HUTI_EXTOP_MATTYPE = HUTI_MAT_NOTTRPSED
if ( HUTI_STOPC .eq. HUTI_TRESID_SCALED_BYB .or. &
HUTI_STOPC .eq. HUTI_PRESID_SCALED_BYB ) then
rhsnorm = normfun( HUTI_NDIM, B, 1 )
end if
if ( HUTI_STOPC .eq. HUTI_PRESID_SCALED_BYPRECB ) then
call pcondlsubr( T1V, B, ipar )
precrhsnorm = normfun( HUTI_NDIM, T1V, 1 )
end if
if ( HUTI_INITIALX .eq. HUTI_RANDOMX ) then
call huti_zrandvec ( X, ipar )
else if ( HUTI_INITIALX .ne. HUTI_USERSUPPLIEDX ) then
X = 1
end if
call pcondrsubr( U, X, ipar )
call matvecsubr( U, R, ipar )
U = B - R
call pcondlsubr( R, U, ipar )
RTLD = R
U = 0
oldrho = 1; omega2 = 1; alpha = 0
300 continue
oldrho = -omega2 * oldrho
rho = dotprodfun( HUTI_NDIM, RTLD, 1, R, 1 )
if ( rho .eq. 0 ) then
HUTI_INFO = HUTI_BICGSTAB_2_RHO
go to 1000
end if
beta = ( rho * alpha ) / oldrho
oldrho = rho
U = R - beta * U
call pcondrsubr( V, U, ipar )
call matvecsubr( V, T1V, ipar )
call pcondlsubr( V, T1V, ipar )
alpha = oldrho / dotprodfun( HUTI_NDIM, RTLD, 1, V, 1 )
R = R - alpha * V
call pcondrsubr( S, R, ipar )
call matvecsubr( S, T1V, ipar )
call pcondlsubr( S, T1V, ipar )
X = X + alpha * U
rho = dotprodfun( HUTI_NDIM, RTLD, 1, S, 1 )
if ( rho .eq. 0 ) then
HUTI_INFO = HUTI_BICGSTAB_2_RHO
go to 1000
end if
beta = ( rho * alpha ) / oldrho
oldrho = rho
V = S - beta * V
call pcondrsubr( W, V, ipar )
call matvecsubr( W, T1V, ipar )
call pcondlsubr( W, T1V, ipar )
alpha = oldrho / dotprodfun( HUTI_NDIM, RTLD, 1, W, 1 )
U = R - beta * U
R = R - alpha * V
S = S - alpha * W
call pcondrsubr( T, S, ipar )
call matvecsubr( T, T1V, ipar )
call pcondlsubr( T, T1V, ipar )
omega1 = dotprodfun( HUTI_NDIM, R, 1, S, 1 )
myy = dotprodfun( HUTI_NDIM, S, 1, S, 1 )
delta = dotprodfun( HUTI_NDIM, S, 1, T, 1 )
tau = dotprodfun( HUTI_NDIM, T, 1, T, 1 )
omega2 = dotprodfun( HUTI_NDIM, R, 1, T, 1 )
tau = tau - ( delta * delta ) / myy
omega2 = ( omega2 - ( delta * omega1 ) / myy ) / tau
omega1 = ( omega1 - delta * omega2 ) / myy
X = X + omega1 * R + omega2 * S + alpha * U
R = R - omega1 * S - omega2 * T
select case (HUTI_STOPC)
case (HUTI_TRUERESIDUAL)
call pcondrsubr( S, X, ipar )
call matvecsubr( S, T1V, ipar )
T1V = T1V - B
call pcondlsubr( S, T1V, ipar )
residual = normfun( HUTI_NDIM, S, 1 )
case (HUTI_TRESID_SCALED_BYB)
call pcondrsubr( S, X, ipar )
call matvecsubr( S, T1V, ipar )
T1V = T1V - B
call pcondlsubr( S, T1V, ipar )
residual = normfun( HUTI_NDIM, S, 1 ) / rhsnorm
case (HUTI_PSEUDORESIDUAL)
residual = normfun( HUTI_NDIM, R, 1 )
case (HUTI_PRESID_SCALED_BYB)
residual = normfun( HUTI_NDIM, R, 1 ) / rhsnorm
case (HUTI_PRESID_SCALED_BYPRECB)
residual = normfun( HUTI_NDIM, R, 1 ) / precrhsnorm
case (HUTI_XDIFF_NORM)
T1V = omega1 * R + omega2 * S + alpha * U
residual = normfun( HUTI_NDIM, T1V, 1 )
case (HUTI_USUPPLIED_STOPC)
residual = stopcfun( X, B, R, ipar, dpar )
case default
call pcondrsubr( S, X, ipar )
call matvecsubr( S, T1V, ipar )
T1V = T1V - B
call pcondlsubr( S, T1V, ipar )
residual = normfun( HUTI_NDIM, S, 1 )
end select
if ( HUTI_DBUGLVL .ne. HUTI_NO_DEBUG ) then
if ( mod(iter_count, HUTI_DBUGLVL) .eq. 0 ) then
write (*, '(I8, E11.4)') iter_count, residual
end if
end if
if ( residual .lt. HUTI_TOLERANCE ) then
HUTI_INFO = HUTI_CONVERGENCE
go to 1000
end if
IF( residual /= residual .OR. residual > HUTI_MAXTOLERANCE ) THEN
HUTI_INFO = HUTI_DIVERGENCE
GOTO 1000
END IF
U = U - omega1 * V - omega2 * W
iter_count = iter_count + 1
if ( iter_count .gt. HUTI_MAXIT ) then
HUTI_INFO = HUTI_MAXITER
go to 1000
end if
go to 300
1000 continue
if ( HUTI_DBUGLVL .ne. HUTI_NO_DEBUG ) then
write (*, '(I8, E11.4)') iter_count, residual
end if
HUTI_ITERS = iter_count
return
end subroutine huti_zbicgstab_2solv
end module huti_bicgstab_2