📄 s_las1.cc
字号:
iteration = 0; while (iteration <= 30) { for (m = l; m < n; m++) { convergence = FALSE; if (m == last) break; else { test = fabs(d[m]) + fabs(d[m+1]); if (test + fabs(e[m]) == test) convergence = TRUE; } if (convergence) break; } p = d[l]; f = bnd[l]; if (m != l) { if (iteration == 30) { ierr = l; return; } iteration += 1; /*........ form shift ........*/ g = (d[l+1] - p) / (2.0 * e[l]); r = pythag(g, 1.0); g = d[m] - p + e[l] / (g + fsign(r, g)); s = 1.0; c = 1.0; p = 0.0; underflow = FALSE; i = m - 1; while (underflow == FALSE && i >= l) { f = s * e[i]; b = c * e[i]; r = pythag(f, g); e[i+1] = r; if (r == 0.0) underflow = TRUE; else { s = f / r; c = g / r; g = d[i+1] - p; r = (d[i] - g) * s + 2.0 * c * b; p = s * r; d[i+1] = g + p; g = c * r - b; f = bnd[i+1]; bnd[i+1] = s * bnd[i] + c * f; bnd[i] = c * bnd[i] - s * f; i--; } } /* end while (underflow != FALSE && i >= l) */ /*........ recover from underflow .........*/ if (underflow) { d[i+1] -= p; e[m] = 0.0; } else { d[l] -= p; e[l] = g; e[m] = 0.0; } } /* end if (m != l) */ else { /* order the eigenvalues */ exchange = TRUE; if (l != 0) { i = l; while (i >= 1 && exchange == TRUE) { if (p < d[i-1]) { d[i] = d[i-1]; bnd[i] = bnd[i-1]; i--; } else exchange = FALSE; } } if (exchange) i = 0; d[i] = p; bnd[i] = f; iteration = 31; } } /* end while (iteration <= 30) */ } /* end for (l=0; l<n; l++) */ return;}/*********************************************************************** * * * lanczos_step() * * * ***********************************************************************//*********************************************************************** Description ----------- Function embodies a single Lanczos step Arguments --------- (input) n dimension of the eigenproblem for matrix B first start of index through loop last end of index through loop wptr array of pointers pointing to work space alf array to hold diagonal of the tridiagonal matrix T eta orthogonality estimate of Lanczos vectors at step j oldeta orthogonality estimate of Lanczos vectors at step j-1 bet array to hold off-diagonal of T ll number of intitial Lanczos vectors in local orthog. (has value of 0, 1 or 2) enough stop flag Functions used -------------- BLAS ddot, dscal, daxpy, datx, dcopy USER store LAS purge, ortbnd, startv UTILITY imin, imax ***********************************************************************/void s_las1::lanczos_step(long n, long first, long last, double *wptr[], double *alf, double *eta, double *oldeta, double *bet, long *ll, long *enough){ double t, *mid; long i; for (j=first; j<last; j++) { mid = wptr[2]; wptr[2] = wptr[1]; wptr[1] = mid; mid = wptr[3]; wptr[3] = wptr[4]; wptr[4] = mid; store(n, STORQ, j-1, wptr[2]); if (j-1 < MAXLL) store(n, STORP, j-1, wptr[4]); bet[j] = rnm; /* restart if invariant subspace is found */ if (!bet[j]) { rnm = startv(n, wptr); if (ierr) return; if (!rnm) *enough = TRUE; } if (*enough) break; /* take a lanczos step */ t = 1.0 / rnm; datx(n, t, wptr[0], 1, wptr[1], 1); dscal(n, t, wptr[3], 1); opb(n, wptr[3], wptr[0]); daxpy(n, -rnm, wptr[2], 1, wptr[0], 1); alf[j] = ddot(n, wptr[0], 1, wptr[3], 1); daxpy(n, -alf[j], wptr[1], 1, wptr[0], 1); /* orthogonalize against initial lanczos vectors */ if (j <= MAXLL && (fabs(alf[j-1]) > 4.0 * fabs(alf[j]))) *ll = j; for (i=0; i < imin(*ll, j-1); i++) { store(n, RETRP, i, wptr[5]); t = ddot(n, wptr[5], 1, wptr[0], 1); store(n, RETRQ, i, wptr[5]); daxpy(n, -t, wptr[5], 1, wptr[0], 1); eta[i] = eps1; oldeta[i] = eps1; } /* extended local reorthogonalization */ t = ddot(n, wptr[0], 1, wptr[4], 1); daxpy(n, -t, wptr[2], 1, wptr[0], 1); if (bet[j] > 0.0) bet[j] = bet[j] + t; t = ddot(n, wptr[0], 1, wptr[3], 1); daxpy(n, -t, wptr[1], 1, wptr[0], 1); alf[j] = alf[j] + t; dcopy(n, wptr[0], 1, wptr[4], 1); rnm = sqrt(ddot(n, wptr[0], 1, wptr[4], 1)); anorm = bet[j] + fabs(alf[j]) + rnm; tol = reps * anorm; /* update the orthogonality bounds */ ortbnd(alf, eta, oldeta, bet); /* restore the orthogonality state when needed */ purge(n,*ll,wptr[0],wptr[1],wptr[4],wptr[3],wptr[5],eta,oldeta); if (rnm <= tol) rnm = 0.0; } return;}/*********************************************************************** * * * ortbnd() * * * ***********************************************************************//*********************************************************************** Description ----------- Funtion updates the eta recurrence Arguments --------- (input) alf array to hold diagonal of the tridiagonal matrix T eta orthogonality estimate of Lanczos vectors at step j oldeta orthogonality estimate of Lanczos vectors at step j-1 bet array to hold off-diagonal of T n dimension of the eigenproblem for matrix B j dimension of T rnm norm of the next residual vector eps1 roundoff estimate for dot product of two unit vectors (output) eta orthogonality estimate of Lanczos vectors at step j+1 oldeta orthogonality estimate of Lanczos vectors at step j Functions used -------------- BLAS dswap ***********************************************************************/void s_las1::ortbnd(double *alf, double *eta, double *oldeta, double *bet){ long i; if (j < 1) return; if (rnm) { if (j > 1) { oldeta[0] = (bet[1] * eta[1] + (alf[0]-alf[j]) * eta[0] - bet[j] * oldeta[0]) / rnm + eps1; } for (i=1; i<=j-2; i++) oldeta[i] = (bet[i+1] * eta[i+1] + (alf[i]-alf[j]) * eta[i] + bet[i] * eta[i-1] - bet[j] * oldeta[i])/rnm + eps1; } oldeta[j-1] = eps1; dswap(j, oldeta, 1, eta, 1); eta[j] = eps1; return;}/*********************************************************************** * * * purge() * * * ***********************************************************************//*********************************************************************** Description ----------- Function examines the state of orthogonality between the new Lanczos vector and the previous ones to decide whether re-orthogonalization should be performed Arguments --------- (input) n dimension of the eigenproblem for matrix B ll number of intitial Lanczos vectors in local orthog. r residual vector to become next Lanczos vector q current Lanczos vector ra previous Lanczos vector qa previous Lanczos vector wrk temporary vector to hold the previous Lanczos vector eta state of orthogonality between r and prev. Lanczos vectors oldeta state of orthogonality between q and prev. Lanczos vectors j current Lanczos step (output) r residual vector orthogonalized against previous Lanczos vectors q current Lanczos vector orthogonalized against previous ones Functions used -------------- BLAS daxpy, dcopy, idamax, ddot USER store ***********************************************************************/void s_las1::purge(long n, long ll, double *r, double *q, double *ra, double *qa, double *wrk, double *eta, double *oldeta){ double t, tq, tr, reps1; long k, iteration, flag, i; if (j < ll+2) return; k = idamax(j - (ll+1), &eta[ll], 1) + ll; if (fabs(eta[k]) > reps) { reps1 = eps1 / reps; iteration = 0; flag = TRUE; while (iteration < 2 && flag) { if (rnm > tol) { /* bring in a lanczos vector t and orthogonalize both * r and q against it */ tq = 0.0; tr = 0.0; for (i = ll; i < j; i++) { store(n, RETRQ, i, wrk); t = -ddot(n, qa, 1, wrk, 1); tq += fabs(t); daxpy(n, t, wrk, 1, q, 1); t = -ddot(n, ra, 1, wrk, 1); tr += fabs(t); daxpy(n, t, wrk, 1, r, 1); } dcopy(n, q, 1, qa, 1); t = -ddot(n, r, 1, qa, 1); tr += fabs(t); daxpy(n, t, q, 1, r, 1); dcopy(n, r, 1, ra, 1); rnm = sqrt(ddot(n, ra, 1, r, 1)); if (tq <= reps1 && tr <= reps1 * rnm) flag = FALSE; } iteration++; } for (i = ll; i <= j; i++) { eta[i] = eps1; oldeta[i] = eps1; } } return;}/***************************************************************** * Function finds the index of element having max. absolute value* * based on FORTRAN 77 routine from Linpack by J. Dongarra * *****************************************************************/ long s_las1::idamax(long n,double *dx,long incx){ long ix,i,imax; double dtemp, dmax; if (n < 1) return(-1); if (n == 1) return(0); if (incx == 0) return(-1); if (incx < 0) ix = (-n+1) * incx; else ix = 0; imax = ix; dx += ix; dmax = fabs(*dx); for (i=1; i < n; i++) { ix += incx; dx += incx; dtemp = fabs(*dx); if (dtemp > dmax) { dmax = dtemp; imax = ix; } } return(imax);}/*********************************************************************** * * * error_bound() * * * ***********************************************************************//*********************************************************************** Description ----------- Function massages error bounds for very close ritz values by placing a gap between them. The error bounds are then refined to reflect this.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -