Example #1
0
void
cgssvx(superlu_options_t *options, SuperMatrix *A, int *perm_c, int *perm_r,
       int *etree, char *equed, float *R, float *C,
       SuperMatrix *L, SuperMatrix *U, void *work, int lwork,
       SuperMatrix *B, SuperMatrix *X, float *recip_pivot_growth,
       float *rcond, float *ferr, float *berr,
       mem_usage_t *mem_usage, SuperLUStat_t *stat, int *info )
{


    DNformat  *Bstore, *Xstore;
    complex    *Bmat, *Xmat;
    int       ldb, ldx, nrhs;
    SuperMatrix *AA;/* A in SLU_NC format used by the factorization routine.*/
    SuperMatrix AC; /* Matrix postmultiplied by Pc */
    int       colequ, equil, nofact, notran, rowequ, permc_spec;
    trans_t   trant;
    char      norm[1];
    int       i, j, info1;
    float    amax, anorm, bignum, smlnum, colcnd, rowcnd, rcmax, rcmin;
    int       relax, panel_size;
    float    diag_pivot_thresh;
    double    t0;      /* temporary time */
    double    *utime;

    /* External functions */
    extern float clangs(char *, SuperMatrix *);

    Bstore = B->Store;
    Xstore = X->Store;
    Bmat   = Bstore->nzval;
    Xmat   = Xstore->nzval;
    ldb    = Bstore->lda;
    ldx    = Xstore->lda;
    nrhs   = B->ncol;

    *info = 0;
    nofact = (options->Fact != FACTORED);
    equil = (options->Equil == YES);
    notran = (options->Trans == NOTRANS);
    if ( nofact ) {
        *(unsigned char *)equed = 'N';
        rowequ = FALSE;
        colequ = FALSE;
    } else {
        rowequ = lsame_(equed, "R") || lsame_(equed, "B");
        colequ = lsame_(equed, "C") || lsame_(equed, "B");
        smlnum = slamch_("Safe minimum");
        bignum = 1. / smlnum;
    }

#if 0
printf("dgssvx: Fact=%4d, Trans=%4d, equed=%c\n",
       options->Fact, options->Trans, *equed);
#endif

    /* Test the input parameters */
    if (!nofact && options->Fact != DOFACT && options->Fact != SamePattern &&
        options->Fact != SamePattern_SameRowPerm &&
        !notran && options->Trans != TRANS && options->Trans != CONJ &&
        !equil && options->Equil != NO)
        *info = -1;
    else if ( A->nrow != A->ncol || A->nrow < 0 ||
              (A->Stype != SLU_NC && A->Stype != SLU_NR) ||
              A->Dtype != SLU_C || A->Mtype != SLU_GE )
        *info = -2;
    else if (options->Fact == FACTORED &&
             !(rowequ || colequ || lsame_(equed, "N")))
        *info = -6;
    else {
        if (rowequ) {
            rcmin = bignum;
            rcmax = 0.;
            for (j = 0; j < A->nrow; ++j) {
                rcmin = SUPERLU_MIN(rcmin, R[j]);
                rcmax = SUPERLU_MAX(rcmax, R[j]);
            }
            if (rcmin <= 0.) *info = -7;
            else if ( A->nrow > 0)
                rowcnd = SUPERLU_MAX(rcmin,smlnum) / SUPERLU_MIN(rcmax,bignum);
            else rowcnd = 1.;
        }
        if (colequ && *info == 0) {
            rcmin = bignum;
            rcmax = 0.;
            for (j = 0; j < A->nrow; ++j) {
                rcmin = SUPERLU_MIN(rcmin, C[j]);
                rcmax = SUPERLU_MAX(rcmax, C[j]);
            }
            if (rcmin <= 0.) *info = -8;
            else if (A->nrow > 0)
                colcnd = SUPERLU_MAX(rcmin,smlnum) / SUPERLU_MIN(rcmax,bignum);
            else colcnd = 1.;
        }
        if (*info == 0) {
            if ( lwork < -1 ) *info = -12;
            else if ( B->ncol < 0 || Bstore->lda < SUPERLU_MAX(0, A->nrow) ||
                      B->Stype != SLU_DN || B->Dtype != SLU_C ||
                      B->Mtype != SLU_GE )
                *info = -13;
            else if ( X->ncol < 0 || Xstore->lda < SUPERLU_MAX(0, A->nrow) ||
                      (B->ncol != 0 && B->ncol != X->ncol) ||
                      X->Stype != SLU_DN ||
                      X->Dtype != SLU_C || X->Mtype != SLU_GE )
                *info = -14;
        }
    }
    if (*info != 0) {
        i = -(*info);
        xerbla_("cgssvx", &i);
        return;
    }

    /* Initialization for factor parameters */
    panel_size = sp_ienv(1);
    relax      = sp_ienv(2);
    diag_pivot_thresh = options->DiagPivotThresh;

    utime = stat->utime;

    /* Convert A to SLU_NC format when necessary. */
    if ( A->Stype == SLU_NR ) {
        NRformat *Astore = A->Store;
        AA = (SuperMatrix *) SUPERLU_MALLOC( sizeof(SuperMatrix) );
        cCreate_CompCol_Matrix(AA, A->ncol, A->nrow, Astore->nnz,
                               Astore->nzval, Astore->colind, Astore->rowptr,
                               SLU_NC, A->Dtype, A->Mtype);
        if ( notran ) { /* Reverse the transpose argument. */
            trant = TRANS;
            notran = 0;
        } else {
            trant = NOTRANS;
            notran = 1;
        }
    } else { /* A->Stype == SLU_NC */
        trant = options->Trans;
        AA = A;
    }

    if ( nofact && equil ) {
        t0 = SuperLU_timer_();
        /* Compute row and column scalings to equilibrate the matrix A. */
        cgsequ(AA, R, C, &rowcnd, &colcnd, &amax, &info1);

        if ( info1 == 0 ) {
            /* Equilibrate matrix A. */
            claqgs(AA, R, C, rowcnd, colcnd, amax, equed);
            rowequ = lsame_(equed, "R") || lsame_(equed, "B");
            colequ = lsame_(equed, "C") || lsame_(equed, "B");
        }
        utime[EQUIL] = SuperLU_timer_() - t0;
    }


    if ( nofact ) {

        t0 = SuperLU_timer_();
        /*
         * Gnet column permutation vector perm_c[], according to permc_spec:
         *   permc_spec = NATURAL:  natural ordering
         *   permc_spec = MMD_AT_PLUS_A: minimum degree on structure of A'+A
         *   permc_spec = MMD_ATA:  minimum degree on structure of A'*A
         *   permc_spec = COLAMD:   approximate minimum degree column ordering
         *   permc_spec = MY_PERMC: the ordering already supplied in perm_c[]
         */
        permc_spec = options->ColPerm;
        if ( permc_spec != MY_PERMC && options->Fact == DOFACT )
            get_perm_c(permc_spec, AA, perm_c);
        utime[COLPERM] = SuperLU_timer_() - t0;

        t0 = SuperLU_timer_();
        sp_preorder(options, AA, perm_c, etree, &AC);
        utime[ETREE] = SuperLU_timer_() - t0;

/*      printf("Factor PA = LU ... relax %d\tw %d\tmaxsuper %d\trowblk %d\n",
               relax, panel_size, sp_ienv(3), sp_ienv(4));
        fflush(stdout); */

        /* Compute the LU factorization of A*Pc. */
        t0 = SuperLU_timer_();
        cgstrf(options, &AC, relax, panel_size, etree,
                work, lwork, perm_c, perm_r, L, U, stat, info);
        utime[FACT] = SuperLU_timer_() - t0;

        if ( lwork == -1 ) {
            mem_usage->total_needed = *info - A->ncol;
            return;
        }
    }

    if ( options->PivotGrowth ) {
        if ( *info > 0 ) {
            if ( *info <= A->ncol ) {
                /* Compute the reciprocal pivot growth factor of the leading
                   rank-deficient *info columns of A. */
                *recip_pivot_growth = cPivotGrowth(*info, AA, perm_c, L, U);
            }
            return;
        }

        /* Compute the reciprocal pivot growth factor *recip_pivot_growth. */
        *recip_pivot_growth = cPivotGrowth(A->ncol, AA, perm_c, L, U);
    }

    if ( options->ConditionNumber ) {
        /* Estimate the reciprocal of the condition number of A. */
        t0 = SuperLU_timer_();
        if ( notran ) {
            *(unsigned char *)norm = '1';
        } else {
            *(unsigned char *)norm = 'I';
        }
        anorm = clangs(norm, AA);
        cgscon(norm, L, U, anorm, rcond, stat, info);
        utime[RCOND] = SuperLU_timer_() - t0;
    }

    if ( nrhs > 0 ) {
        /* Scale the right hand side if equilibration was performed. */
        if ( notran ) {
            if ( rowequ ) {
                for (j = 0; j < nrhs; ++j)
                    for (i = 0; i < A->nrow; ++i)
                        cs_mult(&Bmat[i+j*ldb], &Bmat[i+j*ldb], R[i]);
            }
        } else if ( colequ ) {
            for (j = 0; j < nrhs; ++j)
                for (i = 0; i < A->nrow; ++i)
                    cs_mult(&Bmat[i+j*ldb], &Bmat[i+j*ldb], C[i]);
        }

        /* Compute the solution matrix X. */
        for (j = 0; j < nrhs; j++)  /* Save a copy of the right hand sides */
            for (i = 0; i < B->nrow; i++)
                Xmat[i + j*ldx] = Bmat[i + j*ldb];

        t0 = SuperLU_timer_();
        cgstrs (trant, L, U, perm_c, perm_r, X, stat, info);
        utime[SOLVE] = SuperLU_timer_() - t0;

        /* Use iterative refinement to improve the computed solution and compute
           error bounds and backward error estimates for it. */
        t0 = SuperLU_timer_();
        if ( options->IterRefine != NOREFINE ) {
            cgsrfs(trant, AA, L, U, perm_c, perm_r, equed, R, C, B,
                   X, ferr, berr, stat, info);
        } else {
            for (j = 0; j < nrhs; ++j) ferr[j] = berr[j] = 1.0;
        }
        utime[REFINE] = SuperLU_timer_() - t0;

        /* Transform the solution matrix X to a solution of the original system. */
        if ( notran ) {
            if ( colequ ) {
                for (j = 0; j < nrhs; ++j)
                    for (i = 0; i < A->nrow; ++i)
                        cs_mult(&Xmat[i+j*ldx], &Xmat[i+j*ldx], C[i]);
            }
        } else if ( rowequ ) {
            for (j = 0; j < nrhs; ++j)
                for (i = 0; i < A->nrow; ++i)
                    cs_mult(&Xmat[i+j*ldx], &Xmat[i+j*ldx], R[i]);
        }
    } /* end if nrhs > 0 */

    if ( options->ConditionNumber ) {
        /* Set INFO = A->ncol+1 if the matrix is singular to working precision. */
        if ( *rcond < slamch_("E") ) *info = A->ncol + 1;
    }

    if ( nofact ) {
        cQuerySpace(L, U, mem_usage);
        Destroy_CompCol_Permuted(&AC);
    }
    if ( A->Stype == SLU_NR ) {
        Destroy_SuperMatrix_Store(AA);
        SUPERLU_FREE(AA);
    }

}
Example #2
0
int main(int argc, char *argv[])
{
    SuperMatrix A;
    NCformat *Astore;
    complex   *a;
    int      *asub, *xa;
    int      *perm_c; /* column permutation vector */
    int      *perm_r; /* row permutations from partial pivoting */
    SuperMatrix L;      /* factor L */
    SCformat *Lstore;
    SuperMatrix U;      /* factor U */
    NCformat *Ustore;
    SuperMatrix B;
    int      nrhs, ldx, info, m, n, nnz;
    complex   *xact, *rhs;
    mem_usage_t   mem_usage;
    superlu_options_t options;
    SuperLUStat_t stat;
    FILE      *fp = stdin;
    
#if ( DEBUGlevel>=1 )
    CHECK_MALLOC("Enter main()");
#endif

    /* Set the default input options:
	options.Fact = DOFACT;
        options.Equil = YES;
    	options.ColPerm = COLAMD;
	options.DiagPivotThresh = 1.0;
    	options.Trans = NOTRANS;
    	options.IterRefine = NOREFINE;
    	options.SymmetricMode = NO;
    	options.PivotGrowth = NO;
    	options.ConditionNumber = NO;
    	options.PrintStat = YES;
     */
    set_default_options(&options);

    /* Read the matrix in Harwell-Boeing format. */
    creadhb(fp, &m, &n, &nnz, &a, &asub, &xa);

    cCreate_CompCol_Matrix(&A, m, n, nnz, a, asub, xa, SLU_NC, SLU_C, SLU_GE);
    Astore = A.Store;
    printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, Astore->nnz);
    
    nrhs   = 1;
    if ( !(rhs = complexMalloc(m * nrhs)) ) ABORT("Malloc fails for rhs[].");
    cCreate_Dense_Matrix(&B, m, nrhs, rhs, m, SLU_DN, SLU_C, SLU_GE);
    xact = complexMalloc(n * nrhs);
    ldx = n;
    cGenXtrue(n, nrhs, xact, ldx);
    cFillRHS(options.Trans, nrhs, xact, ldx, &A, &B);

    if ( !(perm_c = intMalloc(n)) ) ABORT("Malloc fails for perm_c[].");
    if ( !(perm_r = intMalloc(m)) ) ABORT("Malloc fails for perm_r[].");

    /* Initialize the statistics variables. */
    StatInit(&stat);
    
    cgssv(&options, &A, perm_c, perm_r, &L, &U, &B, &stat, &info);
    
    if ( info == 0 ) {

	/* This is how you could access the solution matrix. */
        complex *sol = (complex*) ((DNformat*) B.Store)->nzval; 

	 /* Compute the infinity norm of the error. */
	cinf_norm_error(nrhs, &B, xact);

	Lstore = (SCformat *) L.Store;
	Ustore = (NCformat *) U.Store;
    	printf("No of nonzeros in factor L = %d\n", Lstore->nnz);
    	printf("No of nonzeros in factor U = %d\n", Ustore->nnz);
    	printf("No of nonzeros in L+U = %d\n", Lstore->nnz + Ustore->nnz - n);
    	printf("FILL ratio = %.1f\n", (float)(Lstore->nnz + Ustore->nnz - n)/nnz);
	
	cQuerySpace(&L, &U, &mem_usage);
	printf("L\\U MB %.3f\ttotal MB needed %.3f\n",
	       mem_usage.for_lu/1e6, mem_usage.total_needed/1e6);
	
    } else {
	printf("cgssv() error returns INFO= %d\n", info);
	if ( info <= n ) { /* factorization completes */
	    cQuerySpace(&L, &U, &mem_usage);
	    printf("L\\U MB %.3f\ttotal MB needed %.3f\n",
		   mem_usage.for_lu/1e6, mem_usage.total_needed/1e6);
	}
    }

    if ( options.PrintStat ) StatPrint(&stat);
    StatFree(&stat);

    SUPERLU_FREE (rhs);
    SUPERLU_FREE (xact);
    SUPERLU_FREE (perm_r);
    SUPERLU_FREE (perm_c);
    Destroy_CompCol_Matrix(&A);
    Destroy_SuperMatrix_Store(&B);
    Destroy_SuperNode_Matrix(&L);
    Destroy_CompCol_Matrix(&U);

#if ( DEBUGlevel>=1 )
    CHECK_MALLOC("Exit main()");
#endif
}