GLOBAL Int UMFPACK_numeric
(
    const Int Ap [ ],
    const Int Ai [ ],
    const double Ax [ ],
#ifdef COMPLEX
    const double Az [ ],
#endif
    void *SymbolicHandle,
    void **NumericHandle,
    const double Control [UMFPACK_CONTROL],
    double User_Info [UMFPACK_INFO]
)
{

    /* ---------------------------------------------------------------------- */
    /* local variables */
    /* ---------------------------------------------------------------------- */

    double Info2 [UMFPACK_INFO], alloc_init, relpt, relpt2, droptol,
	front_alloc_init, stats [2] ;
    double *Info ;
    WorkType WorkSpace, *Work ;
    NumericType *Numeric ;
    SymbolicType *Symbolic ;
    Int n_row, n_col, n_inner, newsize, i, status, *inew, npiv, ulen, scale ;
    Unit *mnew ;

    /* ---------------------------------------------------------------------- */
    /* get the amount of time used by the process so far */
    /* ---------------------------------------------------------------------- */

    umfpack_tic (stats) ;

    /* ---------------------------------------------------------------------- */
    /* initialize and check inputs */
    /* ---------------------------------------------------------------------- */

#ifndef NDEBUG
    UMF_dump_start ( ) ;
    init_count = UMF_malloc_count ;
    DEBUGm4 (("\nUMFPACK numeric: U transpose version\n")) ;
#endif

    /* If front_alloc_init negative then allocate that size of front in
     * UMF_start_front.  If alloc_init negative, then allocate that initial
     * size of Numeric->Memory. */

    relpt = GET_CONTROL (UMFPACK_PIVOT_TOLERANCE,
	UMFPACK_DEFAULT_PIVOT_TOLERANCE) ;
    relpt2 = GET_CONTROL (UMFPACK_SYM_PIVOT_TOLERANCE,
	UMFPACK_DEFAULT_SYM_PIVOT_TOLERANCE) ;
    alloc_init = GET_CONTROL (UMFPACK_ALLOC_INIT, UMFPACK_DEFAULT_ALLOC_INIT) ;
    front_alloc_init = GET_CONTROL (UMFPACK_FRONT_ALLOC_INIT,
	UMFPACK_DEFAULT_FRONT_ALLOC_INIT) ;
    scale = GET_CONTROL (UMFPACK_SCALE, UMFPACK_DEFAULT_SCALE) ;
    droptol = GET_CONTROL (UMFPACK_DROPTOL, UMFPACK_DEFAULT_DROPTOL) ;

    relpt   = MAX (0.0, MIN (relpt,  1.0)) ;
    relpt2  = MAX (0.0, MIN (relpt2, 1.0)) ;
    droptol = MAX (0.0, droptol) ;
    front_alloc_init = MIN (1.0, front_alloc_init) ;

    if (scale != UMFPACK_SCALE_NONE && scale != UMFPACK_SCALE_MAX)
    {
	scale = UMFPACK_DEFAULT_SCALE ;
    }

    if (User_Info != (double *) NULL)
    {
	/* return Info in user's array */
	Info = User_Info ;
	/* clear the parts of Info that are set by UMFPACK_numeric */
	for (i = UMFPACK_NUMERIC_SIZE ; i <= UMFPACK_MAX_FRONT_NCOLS ; i++)
	{
	    Info [i] = EMPTY ;
	}
	for (i = UMFPACK_NUMERIC_DEFRAG ; i < UMFPACK_IR_TAKEN ; i++)
	{
	    Info [i] = EMPTY ;
	}
    }
    else
    {
	/* no Info array passed - use local one instead */
	Info = Info2 ;
	for (i = 0 ; i < UMFPACK_INFO ; i++)
	{
	    Info [i] = EMPTY ;
	}
    }

    Symbolic = (SymbolicType *) SymbolicHandle ;
    Numeric = (NumericType *) NULL ;
    if (!UMF_valid_symbolic (Symbolic))
    {
	Info [UMFPACK_STATUS] = UMFPACK_ERROR_invalid_Symbolic_object ;
	return (UMFPACK_ERROR_invalid_Symbolic_object) ;
    }

    /* compute alloc_init automatically for AMD or other symmetric ordering */
    if (/* Symbolic->ordering == UMFPACK_ORDERING_AMD */ alloc_init >= 0
        && Symbolic->amd_lunz > 0)
    {
	alloc_init = (Symbolic->nz + Symbolic->amd_lunz) / Symbolic->lunz_bound;
	alloc_init = MIN (1.0, alloc_init) ;
	alloc_init *= UMF_REALLOC_INCREASE ;
    }

    n_row = Symbolic->n_row ;
    n_col = Symbolic->n_col ;
    n_inner = MIN (n_row, n_col) ;

    /* check for integer overflow in Numeric->Memory minimum size */
    if (INT_OVERFLOW (Symbolic->dnum_mem_init_usage * sizeof (Unit)))
    {
	/* :: int overflow, initial Numeric->Memory size :: */
	/* There's no hope to allocate a Numeric object big enough simply to
	 * hold the initial matrix, so return an out-of-memory condition */
	DEBUGm4 (("out of memory: numeric int overflow\n")) ;
	Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ;
	return (UMFPACK_ERROR_out_of_memory) ;
    }

    Info [UMFPACK_STATUS] = UMFPACK_OK ;
    Info [UMFPACK_NROW] = n_row ;
    Info [UMFPACK_NCOL] = n_col ;
    Info [UMFPACK_SIZE_OF_UNIT] = (double) (sizeof (Unit)) ;

    if (!Ap || !Ai || !Ax || !NumericHandle)
    {
	Info [UMFPACK_STATUS] = UMFPACK_ERROR_argument_missing ;
	return (UMFPACK_ERROR_argument_missing) ;
    }

    Info [UMFPACK_NZ] = Ap [n_col] ;
    *NumericHandle = (void *) NULL ;

    /* ---------------------------------------------------------------------- */
    /* allocate the Work object */
    /* ---------------------------------------------------------------------- */

    /* (1) calls UMF_malloc 15 or 17 times, to obtain temporary workspace of
     * size c+1 Entry's and 2*(n_row+1) + 3*(n_col+1) + (n_col+n_inner+1) +
     * (nn+1) + * 3*(c+1) + 2*(r+1) + max(r,c) + (nfr+1) integers plus 2*nn
     * more integers if diagonal pivoting is to be done.  r is the maximum
     * number of rows in any frontal matrix, c is the maximum number of columns
     * in any frontal matrix, n_inner is min (n_row,n_col), nn is
     * max (n_row,n_col), and nfr is the number of frontal matrices.  For a
     * square matrix, this is c+1 Entry's and about 8n + 3c + 2r + max(r,c) +
     * nfr integers, plus 2n more for diagonal pivoting.
     */

    Work = &WorkSpace ;
    Work->n_row = n_row ;
    Work->n_col = n_col ;
    Work->nfr = Symbolic->nfr ;
    Work->nb = Symbolic->nb ;
    Work->n1 = Symbolic->n1 ;

    if (!work_alloc (Work, Symbolic))
    {
	DEBUGm4 (("out of memory: numeric work\n")) ;
	Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ;
	error (&Numeric, Work) ;
	return (UMFPACK_ERROR_out_of_memory) ;
    }
    ASSERT (UMF_malloc_count == init_count + 16 + 2*Symbolic->prefer_diagonal) ;

    /* ---------------------------------------------------------------------- */
    /* allocate Numeric object */
    /* ---------------------------------------------------------------------- */

    /* (2) calls UMF_malloc 10 or 11 times, for a total space of
     * sizeof (NumericType) bytes, 4*(n_row+1) + 4*(n_row+1) integers, and
     * (n_inner+1) Entry's, plus n_row Entry's if row scaling is to be done.
     * sizeof (NumericType) is a small constant.  Next, it calls UMF_malloc
     * once, for the variable-sized part of the Numeric object
     * (Numeric->Memory).  The size of this object is the larger of
     * (Control [UMFPACK_ALLOC_INIT]) *  (the approximate upper bound computed
     * by UMFPACK_symbolic), and the minimum required to start the numerical
     * factorization.  * This request is reduced if it fails.
     */

    if (!numeric_alloc (&Numeric, Symbolic, alloc_init, scale))
    {
	DEBUGm4 (("out of memory: initial numeric\n")) ;
	Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ;
	error (&Numeric, Work) ;
	return (UMFPACK_ERROR_out_of_memory) ;
    }
    DEBUG0 (("malloc: init_count "ID" UMF_malloc_count "ID"\n",
	init_count, UMF_malloc_count)) ;
    ASSERT (UMF_malloc_count == init_count
	+ (16 + 2*Symbolic->prefer_diagonal)
	+ (11 + (scale != UMFPACK_SCALE_NONE))) ;

    /* set control parameters */
    Numeric->relpt = relpt ;
    Numeric->relpt2 = relpt2 ;
    Numeric->droptol = droptol ;
    Numeric->alloc_init = alloc_init ;
    Numeric->front_alloc_init = front_alloc_init ;
    Numeric->scale = scale ;

    DEBUG0 (("umf relpt %g %g init %g %g inc %g red %g\n",
	relpt, relpt2, alloc_init, front_alloc_init,
	UMF_REALLOC_INCREASE, UMF_REALLOC_REDUCTION)) ;

    /* ---------------------------------------------------------------------- */
    /* scale and factorize */
    /* ---------------------------------------------------------------------- */

    /* (3) During numerical factorization (inside UMF_kernel), the variable-size
     * block of memory is increased in size via a call to UMF_realloc if it is
     * found to be too small.  During factorization, this block holds the
     * pattern and values of L and U at the top end, and the elements
     * (contibution blocks) and the current frontal matrix (Work->F*) at the
     * bottom end.  The peak size of the variable-sized object is estimated in
     * UMFPACK_*symbolic (Info [UMFPACK_VARIABLE_PEAK_ESTIMATE]), although this
     * upper bound can be very loose.  The size of the Symbolic object
     * (which is currently allocated) is in Info [UMFPACK_SYMBOLIC_SIZE], and
     * is between 2*n and 13*n integers.
     */

    DEBUG0 (("Calling umf_kernel\n")) ;
    status = UMF_kernel (Ap, Ai, Ax,
#ifdef COMPLEX
	Az,
#endif
	Numeric, Work, Symbolic) ;

    Info [UMFPACK_STATUS] = status ;
    if (status < UMFPACK_OK)
    {
	/* out of memory, or pattern has changed */
	error (&Numeric, Work) ;
	return (status) ;
    }

    Info [UMFPACK_FORCED_UPDATES] = Work->nforced ;
    Info [UMFPACK_VARIABLE_INIT] = Numeric->init_usage ;
    if (Symbolic->prefer_diagonal)
    {
	Info [UMFPACK_NOFF_DIAG] = Work->noff_diagonal ;
    }

    DEBUG0 (("malloc: init_count "ID" UMF_malloc_count "ID"\n",
	init_count, UMF_malloc_count)) ;

    npiv = Numeric->npiv ;	/* = n_inner for nonsingular matrices */
    ulen = Numeric->ulen ;	/* = 0 for square nonsingular matrices */

    /* ---------------------------------------------------------------------- */
    /* free Work object */
    /* ---------------------------------------------------------------------- */

    /* (4) After numerical factorization all of the objects allocated in step
     * (1) are freed via UMF_free, except that one object of size n_col+1 is
     * kept if there are off-diagonal nonzeros in the last pivot row (can only
     * occur for singular or rectangular matrices).  This is Work->Upattern,
     * which is transfered to Numeric->Upattern if ulen > 0.
     */

    DEBUG0 (("malloc: init_count "ID" UMF_malloc_count "ID"\n",
	init_count, UMF_malloc_count)) ;

    free_work (Work) ;

    DEBUG0 (("malloc: init_count "ID" UMF_malloc_count "ID"\n",
	init_count, UMF_malloc_count)) ;
    DEBUG0 (("Numeric->ulen: "ID" scale: "ID"\n", ulen, scale)) ;
    ASSERT (UMF_malloc_count == init_count + (ulen > 0) +
	(11 + (scale != UMFPACK_SCALE_NONE))) ;

    /* ---------------------------------------------------------------------- */
    /* reduce Lpos, Lilen, Lip, Upos, Uilen and Uip to size npiv+1 */
    /* ---------------------------------------------------------------------- */

    /* (5) Six components of the Numeric object are reduced in size if the
     * matrix is singular or rectangular.   The original size is 3*(n_row+1) +
     * 3*(n_col+1) integers.  The new size is 6*(npiv+1) integers.  For
     * square non-singular matrices, these two sizes are the same.
     */

    if (npiv < n_row)
    {
	/* reduce Lpos, Uilen, and Uip from size n_row+1 to size npiv */
	inew = (Int *) UMF_realloc (Numeric->Lpos, npiv+1, sizeof (Int)) ;
	if (inew)
	{
	    Numeric->Lpos = inew ;
	}
	inew = (Int *) UMF_realloc (Numeric->Uilen, npiv+1, sizeof (Int)) ;
	if (inew)
	{
	    Numeric->Uilen = inew ;
	}
	inew = (Int *) UMF_realloc (Numeric->Uip, npiv+1, sizeof (Int)) ;
	if (inew)
	{
	    Numeric->Uip = inew ;
	}
    }

    if (npiv < n_col)
    {
	/* reduce Upos, Lilen, and Lip from size n_col+1 to size npiv */
	inew = (Int *) UMF_realloc (Numeric->Upos, npiv+1, sizeof (Int)) ;
	if (inew)
	{
	    Numeric->Upos = inew ;
	}
	inew = (Int *) UMF_realloc (Numeric->Lilen, npiv+1, sizeof (Int)) ;
	if (inew)
	{
	    Numeric->Lilen = inew ;
	}
	inew = (Int *) UMF_realloc (Numeric->Lip, npiv+1, sizeof (Int)) ;
	if (inew)
	{
	    Numeric->Lip = inew ;
	}
    }

    /* ---------------------------------------------------------------------- */
    /* reduce Numeric->Upattern from size n_col+1 to size ulen+1 */
    /* ---------------------------------------------------------------------- */

    /* (6) The size of Numeric->Upattern (formerly Work->Upattern) is reduced
     * from size n_col+1 to size ulen + 1.  If ulen is zero, the object does
     * not exist. */

    DEBUG4 (("ulen: "ID" Upattern "ID"\n", ulen, (Int) Numeric->Upattern)) ;
    ASSERT (IMPLIES (ulen == 0, Numeric->Upattern == (Int *) NULL)) ;
    if (ulen > 0 && ulen < n_col)
    {
	inew = (Int *) UMF_realloc (Numeric->Upattern, ulen+1, sizeof (Int)) ;
	if (inew)
	{
	    Numeric->Upattern = inew ;
	}
    }

    /* ---------------------------------------------------------------------- */
    /* reduce Numeric->Memory to hold just the LU factors at the head */
    /* ---------------------------------------------------------------------- */

    /* (7) The variable-sized block (Numeric->Memory) is reduced to hold just L
     * and U, via a call to UMF_realloc, since the frontal matrices are no
     * longer needed.
     */

    newsize = Numeric->ihead ;
    if (newsize < Numeric->size)
    {
	mnew = (Unit *) UMF_realloc (Numeric->Memory, newsize, sizeof (Unit)) ;
	if (mnew)
	{
	    /* realloc succeeded (how can it fail since the size is reduced?) */
	    Numeric->Memory = mnew ;
	    Numeric->size = newsize ;
	}
    }
    Numeric->ihead = Numeric->size ;
    Numeric->itail = Numeric->ihead ;
    Numeric->tail_usage = 0 ;
    Numeric->ibig = EMPTY ;
    /* UMF_mem_alloc_tail_block can no longer be called (no tail marker) */

    /* ---------------------------------------------------------------------- */
    /* report the results and return the Numeric object */
    /* ---------------------------------------------------------------------- */

    UMF_set_stats (
	Info,
	Symbolic,
	(double) Numeric->max_usage,	/* actual peak Numeric->Memory */
	(double) Numeric->size,		/* actual final Numeric->Memory */
	Numeric->flops,			/* actual "true flops" */
	(double) Numeric->lnz + n_inner,		/* actual nz in L */
	(double) Numeric->unz + Numeric->nnzpiv,	/* actual nz in U */
	(double) Numeric->maxfrsize,	/* actual largest front size */
	(double) ulen,			/* actual Numeric->Upattern size */
	(double) npiv,			/* actual # pivots found */
	(double) Numeric->maxnrows,	/* actual largest #rows in front */
	(double) Numeric->maxncols,	/* actual largest #cols in front */
	scale != UMFPACK_SCALE_NONE,
	Symbolic->prefer_diagonal,
	ACTUAL) ;

    Info [UMFPACK_ALLOC_INIT_USED] = Numeric->alloc_init ;
    Info [UMFPACK_NUMERIC_DEFRAG] = Numeric->ngarbage ;
    Info [UMFPACK_NUMERIC_REALLOC] = Numeric->nrealloc ;
    Info [UMFPACK_NUMERIC_COSTLY_REALLOC] = Numeric->ncostly ;
    Info [UMFPACK_COMPRESSED_PATTERN] = Numeric->isize ;
    Info [UMFPACK_LU_ENTRIES] = Numeric->nLentries + Numeric->nUentries +
	    Numeric->npiv ;
    Info [UMFPACK_UDIAG_NZ] = Numeric->nnzpiv ;
    Info [UMFPACK_RSMIN] = Numeric->rsmin ;
    Info [UMFPACK_RSMAX] = Numeric->rsmax ;
    Info [UMFPACK_WAS_SCALED] = Numeric->scale ;

    /* nz in L and U with no dropping of small entries */
    Info [UMFPACK_ALL_LNZ] = Numeric->all_lnz + n_inner ;
    Info [UMFPACK_ALL_UNZ] = Numeric->all_unz + Numeric->nnzpiv ;
    Info [UMFPACK_NZDROPPED] =
	  (Numeric->all_lnz - Numeric->lnz)
	+ (Numeric->all_unz - Numeric->unz) ;

    /* estimate of the reciprocal of the condition number. */
    if (SCALAR_IS_ZERO (Numeric->min_udiag)
     || SCALAR_IS_ZERO (Numeric->max_udiag)
     ||	SCALAR_IS_NAN (Numeric->min_udiag)
     ||	SCALAR_IS_NAN (Numeric->max_udiag))
    {
	/* rcond is zero if there is any zero or NaN on the diagonal */
	Numeric->rcond = 0.0 ;
    }
    else
    {
	/* estimate of the recipricol of the condition number. */
	/* This is NaN if diagonal is zero-free, but has one or more NaN's. */
	Numeric->rcond = Numeric->min_udiag / Numeric->max_udiag ;
    }
    Info [UMFPACK_UMIN]  = Numeric->min_udiag ;
    Info [UMFPACK_UMAX]  = Numeric->max_udiag ;
    Info [UMFPACK_RCOND] = Numeric->rcond ;

    if (Numeric->nnzpiv < n_inner
    || SCALAR_IS_ZERO (Numeric->rcond) || SCALAR_IS_NAN (Numeric->rcond))
    {
	/* there are zeros and/or NaN's on the diagonal of U */
	DEBUG0 (("Warning, matrix is singular in umfpack_numeric\n")) ;
	DEBUG0 (("nnzpiv "ID" n_inner "ID" rcond %g\n", Numeric->nnzpiv,
	    n_inner, Numeric->rcond)) ;
	status = UMFPACK_WARNING_singular_matrix ;
	Info [UMFPACK_STATUS] = status ;
    }

    Numeric->valid = NUMERIC_VALID ;
    *NumericHandle = (void *) Numeric ;

    /* Numeric has 11 to 13 objects */
    ASSERT (UMF_malloc_count == init_count + 11 +
	+ (ulen > 0)			    /* Numeric->Upattern */
	+ (scale != UMFPACK_SCALE_NONE)) ;  /* Numeric->Rs */

    /* ---------------------------------------------------------------------- */
    /* get the time used by UMFPACK_numeric */
    /* ---------------------------------------------------------------------- */

    umfpack_toc (stats) ;
    Info [UMFPACK_NUMERIC_WALLTIME] = stats [0] ;
    Info [UMFPACK_NUMERIC_TIME] = stats [1] ;

    /* return UMFPACK_OK or UMFPACK_WARNING_singular_matrix */
    return (status) ;

}
GLOBAL Int UMFPACK_get_symbolic
(
    Int *p_n_row,
    Int *p_n_col,
    Int *p_n1,			/* number of singletons */
    Int *p_nz,
    Int *p_nfr,
    Int *p_nchains,
    Int P [ ],
    Int Q [ ],
    Int Front_npivcol [ ],
    Int Front_parent [ ],
    Int Front_1strow [ ],
    Int Front_leftmostdesc [ ],
    Int Chain_start [ ],
    Int Chain_maxrows [ ],
    Int Chain_maxcols [ ],
    void *SymbolicHandle
)
{
    SymbolicType *Symbolic ;
    Int k, n_row, n_col, n1, nfr, nchains, *p ;

    /* ---------------------------------------------------------------------- */
    /* check inputs */
    /* ---------------------------------------------------------------------- */

    Symbolic = (SymbolicType *) SymbolicHandle ;
    if (!UMF_valid_symbolic (Symbolic))
    {
        return (UMFPACK_ERROR_invalid_Symbolic_object) ;
    }

    /* ---------------------------------------------------------------------- */
    /* get contents of Symbolic */
    /* ---------------------------------------------------------------------- */

    n_row = Symbolic->n_row ;
    n_col = Symbolic->n_col ;
    n1 = Symbolic->n1 ;
    nfr = Symbolic->nfr ;
    nchains = Symbolic->nchains ;

    if (p_n_row)
    {
        *p_n_row = n_row ;
    }

    if (p_n_col)
    {
        *p_n_col = n_col ;
    }

    if (p_n1)
    {
        *p_n1 = n1 ;
    }

    if (p_nz)
    {
        *p_nz = Symbolic->nz ;
    }

    if (p_nfr)
    {
        *p_nfr = nfr ;
    }

    if (p_nchains)
    {
        *p_nchains = nchains ;
    }

    if (P != (Int *) NULL)
    {
        Int *Rperm_init, *Diagonal_map ;
        Rperm_init = Symbolic->Rperm_init ;
        Diagonal_map = Symbolic->Diagonal_map ;
        if (Diagonal_map != (Int *) NULL)
        {
            ASSERT (n_row == n_col) ;
            /* next pivot rows are found in the diagonal map */
            for (k = 0 ; k < n_row ; k++)
            {
                P [k] = Rperm_init [Diagonal_map [k]] ;
            }
        }
        else
        {
            /* there is no diagonal map.  */
            for (k = 0 ; k < n_row ; k++)
            {
                P [k] = Rperm_init [k] ;
            }
        }
    }

    if (Q != (Int *) NULL)
    {
        p = Symbolic->Cperm_init ;
        for (k = 0 ; k < n_col ; k++)
        {
            Q [k] = p [k] ;
        }
    }

    if (Front_npivcol != (Int *) NULL)
    {
        p = Symbolic->Front_npivcol ;
        for (k = 0 ; k <= nfr ; k++)
        {
            Front_npivcol [k] = p [k] ;
        }
    }

    if (Front_parent != (Int *) NULL)
    {
        p = Symbolic->Front_parent ;
        for (k = 0 ; k <= nfr ; k++)
        {
            Front_parent [k] = p [k] ;
        }
    }

    if (Front_1strow != (Int *) NULL)
    {
        p = Symbolic->Front_1strow ;
        for (k = 0 ; k <= nfr ; k++)
        {
            Front_1strow [k] = p [k] ;
        }
    }

    if (Front_leftmostdesc != (Int *) NULL)
    {
        p = Symbolic->Front_leftmostdesc ;
        for (k = 0 ; k <= nfr ; k++)
        {
            Front_leftmostdesc [k] = p [k] ;
        }
    }

    if (Chain_start != (Int *) NULL)
    {
        p = Symbolic->Chain_start ;
        for (k = 0 ; k <= nchains ; k++)
        {
            Chain_start [k] = p [k] ;
        }
    }

    if (Chain_maxrows != (Int *) NULL)
    {
        p = Symbolic->Chain_maxrows ;
        for (k = 0 ; k < nchains ; k++)
        {
            Chain_maxrows [k] = p [k] ;
        }
        Chain_maxrows [nchains] = 0 ;
    }

    if (Chain_maxcols != (Int *) NULL)
    {
        p = Symbolic->Chain_maxcols ;
        for (k = 0 ; k < nchains ; k++)
        {
            Chain_maxcols [k] = p [k] ;
        }
        Chain_maxcols [nchains] = 0 ;
    }

    return (UMFPACK_OK) ;
}
Beispiel #3
0
GLOBAL Int UMFPACK_save_symbolic
(
    void *SymbolicHandle,
    char *user_filename
)
{
    SymbolicType *Symbolic ;
    char *filename ;
    FILE *f ;

    /* get the Symbolic object */
    Symbolic = (SymbolicType *) SymbolicHandle ;

    /* make sure the Symbolic object is valid */
    if (!UMF_valid_symbolic (Symbolic))
    {
	return (UMFPACK_ERROR_invalid_Symbolic_object) ;
    }

    /* get the filename, or use the default name if filename is NULL */
    if (user_filename == (char *) NULL)
    {
	filename = "symbolic.umf" ;
    }
    else
    {
	filename = user_filename ;
    }
    f = fopen (filename, "wb") ;
    if (!f)
    {
	return (UMFPACK_ERROR_file_IO) ;
    }

    /* write the Symbolic object to the file, in binary */
    WRITE (Symbolic,                     SymbolicType, 1) ;
    WRITE (Symbolic->Cperm_init,         Int, Symbolic->n_col+1) ;
    WRITE (Symbolic->Rperm_init,         Int, Symbolic->n_row+1) ;
    WRITE (Symbolic->Front_npivcol,      Int, Symbolic->nfr+1) ;
    WRITE (Symbolic->Front_parent,       Int, Symbolic->nfr+1) ;
    WRITE (Symbolic->Front_1strow,       Int, Symbolic->nfr+1) ;
    WRITE (Symbolic->Front_leftmostdesc, Int, Symbolic->nfr+1) ;
    WRITE (Symbolic->Chain_start,        Int, Symbolic->nchains+1) ;
    WRITE (Symbolic->Chain_maxrows,      Int, Symbolic->nchains+1) ;
    WRITE (Symbolic->Chain_maxcols,      Int, Symbolic->nchains+1) ;
    WRITE (Symbolic->Cdeg,               Int, Symbolic->n_col+1) ;
    WRITE (Symbolic->Rdeg,               Int, Symbolic->n_row+1) ;
    if (Symbolic->esize > 0)
    {
	/* only when dense rows are present */
	WRITE (Symbolic->Esize, Int, Symbolic->esize) ;
    }
    if (Symbolic->prefer_diagonal)
    {
	/* only when diagonal pivoting is prefered */
	WRITE (Symbolic->Diagonal_map, Int, Symbolic->n_col+1) ;
    }

    /* close the file */
    fclose (f) ;

    return (UMFPACK_OK) ;
}
Beispiel #4
0
GLOBAL Int UMFPACK_report_symbolic
(
    void *SymbolicHandle,
    const double Control [UMFPACK_CONTROL]
)
{
    Int n_row, n_col, nz, nchains, nfr, maxnrows, maxncols, prl,
	k, chain, frontid, frontid1, frontid2, kk, *Chain_start, *W,
	*Chain_maxrows, *Chain_maxcols, *Front_npivcol, *Front_1strow,
	*Front_leftmostdesc, *Front_parent, done, status1, status2 ;
    SymbolicType *Symbolic ;

    prl = GET_CONTROL (UMFPACK_PRL, UMFPACK_DEFAULT_PRL) ;

    if (prl <= 2)
    {
	return (UMFPACK_OK) ;
    }

    PRINTF (("Symbolic object: ")) ;

    Symbolic = (SymbolicType *) SymbolicHandle ;
    if (!UMF_valid_symbolic (Symbolic))
    {
	PRINTF (("ERROR: invalid\n")) ;
	return (UMFPACK_ERROR_invalid_Symbolic_object) ;
    }

    n_row = Symbolic->n_row ;
    n_col = Symbolic->n_col ;

    nz = Symbolic->nz ;

    nchains = Symbolic->nchains ;
    nfr = Symbolic->nfr ;
    maxnrows = Symbolic->maxnrows ;
    maxncols = Symbolic->maxncols ;

    Chain_start = Symbolic->Chain_start ;
    Chain_maxrows = Symbolic->Chain_maxrows ;
    Chain_maxcols = Symbolic->Chain_maxcols ;
    Front_npivcol = Symbolic->Front_npivcol ;
    Front_1strow = Symbolic->Front_1strow ;
    Front_leftmostdesc = Symbolic->Front_leftmostdesc ;
    Front_parent = Symbolic->Front_parent ;

    if (prl >= 4)
    {

	PRINTF (("\n    matrix to be factorized:\n")) ;
	PRINTF (("\tn_row: "ID" n_col: "ID"\n", n_row, n_col)) ;
	PRINTF (("\tnumber of entries: "ID"\n", nz)) ;
	PRINTF (("    block size used for dense matrix kernels:   "ID"\n",
	Symbolic->nb)) ;

	PRINTF (("    strategy used:                              ")) ;
	/* strategy cannot be auto */
	if (Symbolic->strategy == UMFPACK_STRATEGY_SYMMETRIC)
	{
	    PRINTF (("symmetric\n")) ;
            PRINTF (("    ordering used:                              ")) ;
            if (Symbolic->ordering == UMFPACK_ORDERING_AMD)
            {
                PRINTF (("amd on A\n")) ;
            }
            else if (Symbolic->ordering == UMFPACK_ORDERING_GIVEN)
            {
                PRINTF (("user permutation")) ;
            }
            else if (Symbolic->ordering == UMFPACK_ORDERING_USER)
            {
                PRINTF (("user function")) ;
            }
            else if (Symbolic->ordering == UMFPACK_ORDERING_METIS)
            {
                PRINTF (("metis on A")) ;
            }
	}
	else /* if (Symbolic->strategy == UMFPACK_STRATEGY_UNSYMMETRIC) */
	{
	    PRINTF (("unsymmetric\n")) ;
            PRINTF (("    ordering used:                              ")) ;
            if (Symbolic->ordering == UMFPACK_ORDERING_AMD)
            {
                PRINTF (("colamd on A\n")) ;
            }
            else if (Symbolic->ordering == UMFPACK_ORDERING_GIVEN)
            {
                PRINTF (("user permutation")) ;
            }
            else if (Symbolic->ordering == UMFPACK_ORDERING_USER)
            {
                PRINTF (("user function")) ;
            }
            else if (Symbolic->ordering == UMFPACK_ORDERING_METIS)
            {
                PRINTF (("metis on A'A")) ;
            }
	}
	PRINTF (("\n")) ;

	PRINTF (("    performn column etree postorder:            ")) ;
	if (Symbolic->fixQ)
	{
	    PRINTF (("no\n")) ;
	}
	else
	{
	    PRINTF (("yes\n")) ;
	}

	PRINTF (("    prefer diagonal pivoting (attempt P=Q):     ")) ;
	if (Symbolic->prefer_diagonal)
	{
	    PRINTF (("yes\n")) ;
	}
	else
	{
	    PRINTF (("no\n")) ;
	}

	PRINTF (("    variable-size part of Numeric object:\n")) ;
	PRINTF (("\tminimum initial size (Units): %.20g  (MBytes): %.1f\n",
	    Symbolic->dnum_mem_init_usage,
	    MBYTES (Symbolic->dnum_mem_init_usage))) ;
	PRINTF (("\testimated peak size (Units):  %.20g  (MBytes): %.1f\n",
	    Symbolic->num_mem_usage_est,
	    MBYTES (Symbolic->num_mem_usage_est))) ;
	PRINTF (("\testimated final size (Units): %.20g  (MBytes): %.1f\n",
	    Symbolic->num_mem_size_est,
	    MBYTES (Symbolic->num_mem_size_est))) ;
	PRINTF (("    symbolic factorization memory usage (Units):"
	    " %.20g  (MBytes): %.1f\n",
	    Symbolic->peak_sym_usage,
	    MBYTES (Symbolic->peak_sym_usage))) ;
	PRINTF (("    frontal matrices / supercolumns:\n")) ;
	PRINTF (("\tnumber of frontal chains: "ID"\n", nchains)) ;
	PRINTF (("\tnumber of frontal matrices: "ID"\n", nfr)) ;
	PRINTF (("\tlargest frontal matrix row dimension: "ID"\n", maxnrows)) ;
	PRINTF (("\tlargest frontal matrix column dimension: "ID"\n",maxncols));
    }

    k = 0 ;
    done = FALSE ;

    for (chain = 0 ; chain < nchains ; chain++)
    {
	frontid1 = Chain_start [chain] ;
	frontid2 = Chain_start [chain+1] - 1 ;
	PRINTF4 (("\n    Frontal chain: "ID".  Frontal matrices "ID" to "ID"\n",
	    INDEX (chain), INDEX (frontid1), INDEX (frontid2))) ;
	PRINTF4 (("\tLargest frontal matrix in Frontal chain: "ID"-by-"ID"\n",
	    Chain_maxrows [chain], Chain_maxcols [chain])) ;
	for (frontid = frontid1 ; frontid <= frontid2 ; frontid++)
	{
	    kk = Front_npivcol [frontid] ;
	    PRINTF4 (("\tFront: "ID"  pivot cols: "ID" (pivot columns "ID" to "
		ID")\n", INDEX (frontid), kk, INDEX (k), INDEX (k+kk-1))) ;
	    PRINTF4 (("\t    pivot row candidates: "ID" to "ID"\n",
		INDEX (Front_1strow [Front_leftmostdesc [frontid]]),
		INDEX (Front_1strow [frontid+1]-1))) ;
	    PRINTF4 (("\t    leftmost descendant: "ID"\n",
		INDEX (Front_leftmostdesc [frontid]))) ;
	    PRINTF4 (("\t    1st new candidate row : "ID"\n",
		INDEX (Front_1strow [frontid]))) ;
	    PRINTF4 (("\t    parent:")) ;
	    if (Front_parent [frontid] == EMPTY)
	    {
		PRINTF4 ((" (none)\n")) ;
	    }
	    else
	    {
		PRINTF4 ((" "ID"\n", INDEX (Front_parent [frontid]))) ;
	    }
	    done = (frontid == 20 && frontid < nfr-1 && prl == 4) ;
	    if (done)
	    {
		PRINTF4 (("\t...\n")) ;
		break ;
	    }
	    k += kk ;
	}
	if (Front_npivcol [nfr] != 0)
	{
	    PRINTF4 (("\tFront: "ID" placeholder for "ID" empty columns\n",
		INDEX (nfr), Front_npivcol [nfr])) ;
	}
	if (done)
	{
	    break ;
	}
    }

    W = (Int *) UMF_malloc (MAX (n_row, n_col), sizeof (Int)) ;
    if (!W)
    {
	PRINTF (("ERROR: out of memory to check Symbolic object\n\n")) ;
	return (UMFPACK_ERROR_out_of_memory) ;
    }

    PRINTF4 (("\nInitial column permutation, Q1: ")) ;
    status1 = UMF_report_perm (n_col, Symbolic->Cperm_init, W, prl, 0) ;

    PRINTF4 (("\nInitial row permutation, P1: ")) ;
    status2 = UMF_report_perm (n_row, Symbolic->Rperm_init, W, prl, 0) ;

    (void) UMF_free ((void *) W) ;

    if (status1 != UMFPACK_OK || status2 != UMFPACK_OK)
    {
	return (UMFPACK_ERROR_invalid_Symbolic_object) ;
    }

    PRINTF4 (("    Symbolic object:  ")) ;
    PRINTF (("OK\n\n")) ;
    return (UMFPACK_OK) ;
}
GLOBAL Int UMFPACK_report_symbolic
(
    void *SymbolicHandle,
    const double Control [UMFPACK_CONTROL]
)
{
    Int n_row, n_col, nz, nchains, nfr, maxnrows, maxncols, prl,
	k, chain, frontid, frontid1, frontid2, kk, *Chain_start, *W,
	*Chain_maxrows, *Chain_maxcols, *Front_npivcol, *Front_1strow,
	*Front_leftmostdesc, *Front_parent, done, status1, status2 ;
    SymbolicType *Symbolic ;

    prl = GET_CONTROL (UMFPACK_PRL, UMFPACK_DEFAULT_PRL) ;

    if (prl <= 2)
    {
	return (UMFPACK_OK) ;
    }

    PRINTF (("Symbolic object: ")) ;

    Symbolic = (SymbolicType *) SymbolicHandle ;
    if (!UMF_valid_symbolic (Symbolic))
    {
	PRINTF (("ERROR: invalid\n")) ;
	return (UMFPACK_ERROR_invalid_Symbolic_object) ;
    }

    n_row = Symbolic->n_row ;
    n_col = Symbolic->n_col ;

    nz = Symbolic->nz ;

    nchains = Symbolic->nchains ;
    nfr = Symbolic->nfr ;
    maxnrows = Symbolic->maxnrows ;
    maxncols = Symbolic->maxncols ;

    Chain_start = Symbolic->Chain_start ;
    Chain_maxrows = Symbolic->Chain_maxrows ;
    Chain_maxcols = Symbolic->Chain_maxcols ;
    Front_npivcol = Symbolic->Front_npivcol ;
    Front_1strow = Symbolic->Front_1strow ;
    Front_leftmostdesc = Symbolic->Front_leftmostdesc ;
    Front_parent = Symbolic->Front_parent ;

    if (prl >= 4)
    {

	PRINTF (("\n    matrix to be factorized:\n")) ;
	PRINTF (("\tn_row: "ID" n_col: "ID"\n", n_row, n_col)) ;
	PRINTF (("\tnumber of entries: "ID"\n", nz)) ;
	PRINTF (("    block size used for dense matrix kernels:   "ID"\n",
	Symbolic->nb)) ;

	PRINTF (("    strategy used:                              ")) ;
	/* strategy cannot be auto */
	if (Symbolic->strategy == UMFPACK_STRATEGY_SYMMETRIC)
	{
	    PRINTF (("symmetric")) ;
	}
	else /* if (Symbolic->strategy == UMFPACK_STRATEGY_UNSYMMETRIC) */
	{
	    PRINTF (("unsymmetric")) ;
	}
#if 0
	else if (Symbolic->strategy == UMFPACK_STRATEGY_2BY2)