dnlaso.c

来自「InsightToolkit-1.4.0(有大量的优化算法程序)」· C语言 代码 · 共 1,804 行 · 第 1/5 页

C
1,804
字号

/*  THIS IS A SPECIALIZED VERSION OF THE SUBROUTINE BNDEIG TAILORED */
/*  SPECIFICALLY FOR USE BY THE LASO PACKAGE. */

/*  SET PARAMETERS */

    atol = *n * *eps * max(*tmax,-(*tmin));
    artol = atol / sqrt(*eps);
    nval = *nr - *nl + 1;

/*   CHECK FOR SPECIAL CASE OF N = 1 */

    if (*n == 1) {
        eigval[0] = a[0];
        eigvec[0] = 1.;
        return;
    }

/*   SET UP INITIAL EIGENVALUE BOUNDS */

    for (i = 1; i <= nval; ++i) {
        bound[(i << 1)] = *tmin;
        bound[(i << 1) + 1] = *tmax;
    }
    bound[1] = *tmax;
    bound[(nval << 1) + 2] = *tmin;
    if (*nl == 1) {
        bound[1] = *tmin;
    }
    if (*nr == *n) {
        bound[(nval << 1) + 2] = *tmax;
    }

    dlabcm_(n, nband, nl, nr, a, eigval, lde, eigvec, &atol, &artol, bound, atemp, d, vtemp);
} /* dlaeig_ */


/* *********************************************************************** */

/* Subroutine */ void dlager_(n, nband, nstart, a, tmin, tmax)
const integer *n, *nband, *nstart;
doublereal *a, *tmin, *tmax;
{
    /* Local variables */
    static doublereal temp;
    static integer i, k, l;

/*  THIS SUBROUTINE COMPUTES BOUNDS ON THE SPECTRUM OF A BY */
/*  EXAMINING THE GERSCHGORIN CIRCLES. ONLY THE NEWLY CREATED */
/*  CIRCLES ARE EXAMINED */

    for (k = *nstart - 1; k < *n; ++k) {
        temp = 0.;
        for (i = 1; i < *nband; ++i) {
            temp += abs(a[i + k * *nband]);
        }
        l = min(k,*nband-1);
        for (i = 1; i <= l; ++i) {
            temp += abs(a[i + (k-i) * *nband]);
        }
        *tmin = min(*tmin,a[k * *nband] - temp);
        *tmax = max(*tmax,a[k * *nband] + temp);
    }
} /* dlager_ */


/* *********************************************************************** */

/* Subroutine */ void dlaran_(n, x)
const integer *n;
doublereal *x;
{
    /* Initialized data */
    static integer iurand = 0;

    /* Local variables */
    static integer i;

/*  THIS SUBROUTINE SETS THE VECTOR X TO RANDOM NUMBERS */

/*  INITIALIZE SEED */

    for (i = 0; i < *n; ++i) {
        x[i] = urand_(&iurand) - .5;
    }
} /* dlaran_ */


/* ------------------------------------------------------------------ */

/* Subroutine */ void dmvpc_(nblock, bet, maxj, j, s, number, resnrm, orthcf, rv)
const integer *nblock;
const doublereal *bet;
const integer *maxj, *j;
const doublereal *s;
const integer *number;
doublereal *resnrm, *orthcf, *rv;
{
    /* Local variables */
    static integer i, k, m;

/* THIS SUBROUTINE COMPUTES THE NORM AND THE SMALLEST ELEMENT */
/* (IN ABSOLUTE VALUE) OF THE VECTOR BET*SJI, WHERE SJI */
/* IS AN NBLOCK VECTOR OF THE LAST NBLOCK ELEMENTS OF THE ITH */
/* EIGENVECTOR OF T.  THESE QUANTITIES ARE THE RESIDUAL NORM */
/* AND THE ORTHOGONALITY COEFFICIENT RESPECTIVELY FOR THE */
/* CORRESPONDING RITZ PAIR.  THE ORTHOGONALITY COEFFICIENT IS */
/* NORMALIZED TO ACCOUNT FOR THE LOCAL REORTHOGONALIZATION. */

    m = *j - *nblock;
    for (i = 0; i < *number; ++i) {
        rv[0] = ddot_(nblock, &s[m + i * *maxj], &c__1, &bet[0], nblock);
        orthcf[i] = abs(rv[0]);
        for (k = 1; k < *nblock; ++k) {
            rv[k] = ddot_(nblock, &s[m + i * *maxj], &c__1, &bet[k], nblock);
            orthcf[i] = min(orthcf[i], abs(rv[k]));
        }
        resnrm[i] = dnrm2_(nblock, rv, &c__1);
    }
} /* dmvpc_ */


/* ------------------------------------------------------------------ */

/* Subroutine */ void dnppla_(op, iovect, n, nperm, nop, nmval, val, nmvec,
        vec, nblock, h, hv, p, q, bound, d, delta, small, raritz, eps)
/* Subroutine */ void (*op) (const integer*,const integer*,const doublereal*,doublereal*);
/* Subroutine */ void (*iovect) (const integer*,const integer*,doublereal*,const integer*,const integer*);
const integer *n, *nperm, *nmval;
integer *nop;
doublereal *val;
const integer *nmvec;
doublereal *vec;
const integer *nblock;
doublereal *h, *hv, *p, *q, *bound, *d, *delta;
logical *small, *raritz;
doublereal *eps;
{
    /* System generated locals */
    integer i__1;
    doublereal d__1;

    /* Local variables */
    static doublereal hmin, hmax, temp;
    static doublereal zero=0.;
    static integer i, j, k, l, m;
    static integer jj, kk;

/* THIS SUBROUTINE POST PROCESSES THE EIGENVECTORS.  BLOCK MATRIX */
/* VECTOR PRODUCTS ARE USED TO MINIMIZED THE NUMBER OF CALLS TO OP. */

/* IF RARITZ IS .TRUE.  A FINAL RAYLEIGH-RITZ PROCEDURE IS APPLIED */
/* TO THE EIGENVECTORS. */

    if (! (*raritz)) {
        goto L190;
    }

/* ------------------------------------------------------------------ */

/* THIS CONSTRUCTS H=Q*AQ, WHERE THE COLUMNS OF Q ARE THE */
/* APPROXIMATE EIGENVECTORS.  TEMP = -1 IS USED WHEN SMALL IS */
/* FALSE TO AVOID HAVING TO RESORT THE EIGENVALUES AND EIGENVECTORS */
/* COMPUTED BY DLAEIG. */

    i__1 = *nperm * *nperm;
    dcopy_(&i__1, &zero, &c__0, h, &c__1);
    temp = -1.;
    if (*small) {
        temp = 1.;
    }
    m = *nperm % *nblock;
    if (m == 0) {
        goto L40;
    }
    for (i = 0; i < m; ++i) {
        dcopy_(n, &vec[i * *nmvec], &c__1, &p[i * *n], &c__1);
    }
    (*iovect)(n, &m, p, &m, &c__0);
    (*op)(n, &m, p, q);
    ++(*nop);
    for (i = 0; i < m; ++i) {
        for (j = i; j < *nperm; ++j) {
            jj = j - i;
            h[jj + i * *nperm] = temp * ddot_(n, &vec[j * *nmvec], &c__1, &q[i * *n], &c__1);
        }
    }
    if (*nperm < *nblock) {
        goto L90;
    }
L40:
    m += *nblock;
    for (i = m; *nblock < 0 ? i >= *nperm : i <= *nperm; i += *nblock) {
        for (j = 0; j < *nblock; ++j) {
            l = i - *nblock + j;
            dcopy_(n, &vec[l * *nmvec], &c__1, &p[j * *n], &c__1);
        }
        (*iovect)(n, nblock, p, &i, &c__0);
        (*op)(n, nblock, p, q);
        ++(*nop);
        for (j = 0; j < *nblock; ++j) {
            l = i - *nblock + j;
            for (k = l; k < *nperm; ++k) {
                kk = k - l;
                h[kk + l * *nperm] = temp * ddot_(n, &vec[k * *nmvec], &c__1, &q[j * *n], &c__1);
            }
        }
    }

/* THIS COMPUTES THE SPECTRAL DECOMPOSITION OF H. */

L90:
    hmin = h[0];
    hmax = h[0];
    dlager_(nperm, nperm, &c__1, h, &hmin, &hmax);
    dlaeig_(nperm, nperm, &c__1, nperm, h, val, nperm, hv, bound, p, d, q, eps, &hmin, &hmax);

/* THIS COMPUTES THE RITZ VECTORS--THE COLUMNS OF */
/* Y = QS WHERE S IS THE MATRIX OF EIGENVECTORS OF H. */

    for (i = 0; i < *nperm; ++i) {
        dcopy_(n, &zero, &c__0, &vec[i * *nmvec], &c__1);
    }
    m = *nperm % *nblock;
    if (m == 0) {
        goto L150;
    }
    (*iovect)(n, &m, p, &m, &c__1);
    for (i = 0; i < m; ++i) {
        for (j = 0; j < *nperm; ++j) {
            daxpy_(n, &hv[i + j * *nperm], &p[i * *n], &c__1, &vec[j * *nmvec], &c__1);
        }
    }
    if (*nperm < *nblock) {
        goto L190;
    }
L150:
    m += *nblock;
    for (i = m; *nblock < 0 ? i >= *nperm : i <= *nperm; i += *nblock) {
        (*iovect)(n, nblock, p, &i, &c__1);
        for (j = 0; j < *nblock; ++j) {
            l = i - *nblock + j;
            for (k = 0; k < *nperm; ++k) {
                daxpy_(n, &hv[l + k * *nperm], &p[j * *n], &c__1, &vec[k * *nmvec], &c__1);
            }
        }
    }

/* ------------------------------------------------------------------ */

/* THIS SECTION COMPUTES THE RAYLEIGH QUOTIENTS (IN VAL(*,1)) */
/* AND RESIDUAL NORMS (IN VAL(*,2)) OF THE EIGENVECTORS. */

L190:
    if (! (*small)) {
        *delta = -(*delta);
    }
    m = *nperm % *nblock;
    if (m == 0) {
        goto L220;
    }
    for (i = 0; i < m; ++i) {
        dcopy_(n, &vec[i * *nmvec], &c__1, &p[i * *n], &c__1);
    }
    (*op)(n, &m, p, q);
    ++(*nop);
    for (i = 0; i < m; ++i) {
        val[i] = ddot_(n, &p[i * *n], &c__1, &q[i * *n], &c__1);
        d__1 = -val[i];
        daxpy_(n, &d__1, &p[i * *n], &c__1, &q[i * *n], &c__1);
        val[i + *nmval] = dnrm2_(n, &q[i * *n], &c__1);
    }
    if (*nperm < *nblock) {
        goto L260;
    }
L220:
    ++m;
    for (i = m; *nblock < 0 ? i >= *nperm : i <= *nperm; i += *nblock) {
        for (j = 0; j < *nblock; ++j) {
            l = i - 1 + j;
            dcopy_(n, &vec[l * *nmvec], &c__1, &p[j * *n], &c__1);
        }
        (*op)(n, nblock, p, q);
        ++(*nop);
        for (j = 0; j < *nblock; ++j) {
            l = i - 1 + j;
            val[l] = ddot_(n, &p[j * *n], &c__1, &q[j * *n], &c__1);
            d__1 = -val[l];
            daxpy_(n, &d__1, &p[j * *n], &c__1, &q[j * *n], &c__1);
            val[l + *nmval] = dnrm2_(n, &q[j * *n], &c__1);
        }
    }

/* THIS COMPUTES THE ACCURACY ESTIMATES.  FOR CONSISTENCY WITH DILASO */

L260:
    for (i = 0; i < *nperm; ++i) {
        temp = *delta - val[i];
        if (! (*small)) {
            temp = -temp;
        }
        val[i + *nmval * 3] = 0.;
        if (temp > 0.) {
            val[i + *nmval * 3] = val[i + *nmval] / temp;
        }
        val[i + *nmval * 2] = val[i + *nmval * 3] * val[i + *nmval];
    }

} /* dnppla_ */

/* ------------------------------------------------------------------ */

/* Subroutine */ void dortqr_(nz, n, nblock, z, b)
const integer *nz, *n, *nblock;
doublereal *z, *b;
{
    /* System generated locals */
    doublereal d__1;

    /* Local variables */
    static doublereal temp;
    static integer i, k;
    static doublereal sigma;
    static integer length;
    static doublereal tau;

/* THIS SUBROUTINE COMPUTES THE QR FACTORIZATION OF THE N X NBLOCK */
/* MATRIX Z.  Q IS FORMED IN PLACE AND RETURNED IN Z.  R IS */
/* RETURNED IN B. */

/* THIS SECTION REDUCES Z TO TRIANGULAR FORM. */

    for (i = 0; i < *nblock; ++i) {

/* THIS FORMS THE ITH REFLECTION. */

        length = *n - i;
        d__1 = dnrm2_(&length, &z[i + i * *nz], &c__1);
        sigma = d_sign(&d__1, &z[i + i * *nz]);
        b[i + i * *nblock] = -sigma;
        z[i + i * *nz] += sigma;
        tau = sigma * z[i + i * *nz];

/* THIS APPLIES THE ROTATION TO THE REST OF THE COLUMNS. */

        for (k = i+1; k < *nblock; ++k) {
            if (tau != 0.) {
                temp = -ddot_(&length, &z[i + i * *nz], &c__1, &z[i + k * *nz], &c__1) / tau;
                daxpy_(&length, &temp, &z[i + i * *nz], &c__1, &z[i + k * *nz], &c__1);
            }
            b[i + k * *nblock] = z[i + k * *nz];
            z[i + k * *nz] = 0.;
        }
    }

/* THIS ACCUMULATES THE REFLECTIONS IN REVERSE ORDER. */

    for (i = *nblock-1; i >= 0; --i) {

/* THIS RECREATES THE ITH = NBLOCK-M+1)TH REFLECTIO

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?