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) ; }
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) ; }
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)