GLOBAL Int UMFPACK_report_perm ( Int np, const Int Perm [ ], const double Control [UMFPACK_CONTROL] ) { Int prl, *W, status ; prl = GET_CONTROL (UMFPACK_PRL, UMFPACK_DEFAULT_PRL) ; if (prl <= 2) { return (UMFPACK_OK) ; } W = (Int *) UMF_malloc (MAX (np,1), sizeof (Int)) ; status = UMF_report_perm (np, Perm, W, prl, 1) ; (void) UMF_free ((void *) W) ; return (status) ; }
GLOBAL Int UMFPACK_get_determinant ( double *Mx, #ifdef COMPLEX double *Mz, #endif double *Ex, void *NumericHandle, double User_Info [UMFPACK_INFO] ) { /* ---------------------------------------------------------------------- */ /* local variables */ /* ---------------------------------------------------------------------- */ Entry d_mantissa, d_tmp ; double d_exponent, Info2 [UMFPACK_INFO], one [2] = {1.0, 0.0}, d_sign ; Entry *D ; double *Info, *Rs ; NumericType *Numeric ; Int i, n, itmp, npiv, *Wi, *Rperm, *Cperm, do_scale ; #ifndef NRECIPROCAL Int do_recip ; #endif /* ---------------------------------------------------------------------- */ /* check input parameters */ /* ---------------------------------------------------------------------- */ if (User_Info != (double *) NULL) { /* return Info in user's array */ Info = User_Info ; } else { /* no Info array passed - use local one instead */ Info = Info2 ; for (i = 0 ; i < UMFPACK_INFO ; i++) { Info [i] = EMPTY ; } } Info [UMFPACK_STATUS] = UMFPACK_OK ; Numeric = (NumericType *) NumericHandle ; if (!UMF_valid_numeric (Numeric)) { Info [UMFPACK_STATUS] = UMFPACK_ERROR_invalid_Numeric_object ; return (UMFPACK_ERROR_invalid_Numeric_object) ; } if (Numeric->n_row != Numeric->n_col) { /* only square systems can be handled */ Info [UMFPACK_STATUS] = UMFPACK_ERROR_invalid_system ; return (UMFPACK_ERROR_invalid_system) ; } if (Mx == (double *) NULL) { Info [UMFPACK_STATUS] = UMFPACK_ERROR_argument_missing ; return (UMFPACK_ERROR_argument_missing) ; } n = Numeric->n_row ; /* ---------------------------------------------------------------------- */ /* allocate workspace */ /* ---------------------------------------------------------------------- */ Wi = (Int *) UMF_malloc (n, sizeof (Int)) ; if (!Wi) { DEBUGm4 (("out of memory: get determinant\n")) ; Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ; return (UMFPACK_ERROR_out_of_memory) ; } /* ---------------------------------------------------------------------- */ /* compute the determinant */ /* ---------------------------------------------------------------------- */ Rs = Numeric->Rs ; /* row scale factors */ do_scale = (Rs != (double *) NULL) ; #ifndef NRECIPROCAL do_recip = Numeric->do_recip ; #endif d_mantissa = ((Entry *) one) [0] ; d_exponent = 0.0 ; D = Numeric->D ; /* compute product of diagonal entries of U */ for (i = 0 ; i < n ; i++) { MULT (d_tmp, d_mantissa, D [i]) ; d_mantissa = d_tmp ; if (!rescale_determinant (&d_mantissa, &d_exponent)) { /* the determinant is zero or NaN */ Info [UMFPACK_STATUS] = UMFPACK_WARNING_singular_matrix ; /* no need to compute the determinant of R */ do_scale = FALSE ; break ; } } /* compute product of diagonal entries of R (or its inverse) */ if (do_scale) { for (i = 0 ; i < n ; i++) { #ifndef NRECIPROCAL if (do_recip) { /* compute determinant of R inverse */ SCALE_DIV (d_mantissa, Rs [i]) ; } else #endif { /* compute determinant of R */ SCALE (d_mantissa, Rs [i]) ; } if (!rescale_determinant (&d_mantissa, &d_exponent)) { /* the determinant is zero or NaN. This is very unlikey to * occur here, since the scale factors for a tiny or zero row * are set to 1. */ Info [UMFPACK_STATUS] = UMFPACK_WARNING_singular_matrix ; break ; } } } /* ---------------------------------------------------------------------- */ /* determine if P and Q are odd or even permutations */ /* ---------------------------------------------------------------------- */ npiv = 0 ; Rperm = Numeric->Rperm ; for (i = 0 ; i < n ; i++) { Wi [i] = Rperm [i] ; } for (i = 0 ; i < n ; i++) { while (Wi [i] != i) { itmp = Wi [Wi [i]] ; Wi [Wi [i]] = Wi [i] ; Wi [i] = itmp ; npiv++ ; } } Cperm = Numeric->Cperm ; for (i = 0 ; i < n ; i++) { Wi [i] = Cperm [i] ; } for (i = 0 ; i < n ; i++) { while (Wi [i] != i) { itmp = Wi [Wi [i]] ; Wi [Wi [i]] = Wi [i] ; Wi [i] = itmp ; npiv++ ; } } /* if npiv is odd, the sign is -1. if it is even, the sign is +1 */ d_sign = (npiv % 2) ? -1. : 1. ; /* ---------------------------------------------------------------------- */ /* free workspace */ /* ---------------------------------------------------------------------- */ (void) UMF_free ((void *) Wi) ; /* ---------------------------------------------------------------------- */ /* compute the magnitude and exponent of the determinant */ /* ---------------------------------------------------------------------- */ if (Ex == (double *) NULL) { /* Ex is not provided, so return the entire determinant in d_mantissa */ SCALE (d_mantissa, pow (10.0, d_exponent)) ; } else { Ex [0] = d_exponent ; } Mx [0] = d_sign * REAL_COMPONENT (d_mantissa) ; #ifdef COMPLEX if (SPLIT (Mz)) { Mz [0] = d_sign * IMAG_COMPONENT (d_mantissa) ; } else { Mx [1] = d_sign * IMAG_COMPONENT (d_mantissa) ; } #endif /* determine if the determinant has (or will) overflow or underflow */ if (d_exponent + 1.0 > log10 (DBL_MAX)) { Info [UMFPACK_STATUS] = UMFPACK_WARNING_determinant_overflow ; } else if (d_exponent - 1.0 < log10 (DBL_MIN)) { Info [UMFPACK_STATUS] = UMFPACK_WARNING_determinant_underflow ; } return (UMFPACK_OK) ; }
GLOBAL Int UMFPACK_report_numeric ( void *NumericHandle, const double Control [UMFPACK_CONTROL] ) { Int prl, *W, nn, n_row, n_col, n_inner, num_fixed_size, numeric_size, npiv ; NumericType *Numeric ; prl = GET_CONTROL (UMFPACK_PRL, UMFPACK_DEFAULT_PRL) ; if (prl <= 2) { return (UMFPACK_OK) ; } PRINTF (("Numeric object: ")) ; Numeric = (NumericType *) NumericHandle ; if (!UMF_valid_numeric (Numeric)) { PRINTF (("ERROR: LU factors invalid\n\n")) ; return (UMFPACK_ERROR_invalid_Numeric_object) ; } n_row = Numeric->n_row ; n_col = Numeric->n_col ; nn = MAX (n_row, n_col) ; n_inner = MIN (n_row, n_col) ; npiv = Numeric->npiv ; DEBUG1 (("n_row "ID" n_col "ID" nn "ID" n_inner "ID" npiv "ID"\n", n_row, n_col, nn, n_inner, npiv)) ; /* size of Numeric object, except Numeric->Memory and Numeric->Upattern */ /* see also UMF_set_stats */ num_fixed_size = UNITS (NumericType, 1) /* Numeric structure */ + UNITS (Entry, n_inner+1) /* D */ + UNITS (Int, n_row+1) /* Rperm */ + UNITS (Int, n_col+1) /* Cperm */ + 6 * UNITS (Int, npiv+1) /* Lpos, Uilen, Uip, Upos, Lilen, Lip */ + ((Numeric->scale != UMFPACK_SCALE_NONE) ? UNITS (Entry, n_row) : 0) ; /* Rs */ DEBUG1 (("num fixed size: "ID"\n", num_fixed_size)) ; DEBUG1 (("Numeric->size "ID"\n", Numeric->size)) ; DEBUG1 (("ulen units "ID"\n", UNITS (Int, Numeric->ulen))) ; /* size of Numeric->Memory is Numeric->size */ /* size of Numeric->Upattern is Numeric->ulen */ numeric_size = num_fixed_size + Numeric->size + UNITS (Int, Numeric->ulen) ; DEBUG1 (("numeric total size "ID"\n", numeric_size)) ; if (prl >= 4) { PRINTF (("\n n_row: "ID" n_col: "ID"\n", n_row, n_col)) ; PRINTF ((" relative pivot tolerance used: %g\n", Numeric->relpt)) ; PRINTF ((" relative symmetric pivot tolerance used: %g\n", Numeric->relpt2)) ; PRINTF ((" matrix scaled: ")) ; if (Numeric->scale == UMFPACK_SCALE_NONE) { PRINTF (("no")) ; } else if (Numeric->scale == UMFPACK_SCALE_SUM) { PRINTF (("yes (divided each row by sum abs value in each row)\n")) ; PRINTF ((" minimum sum (abs (rows of A)): %.5e\n", Numeric->rsmin)) ; PRINTF ((" maximum sum (abs (rows of A)): %.5e", Numeric->rsmax)) ; } else if (Numeric->scale == UMFPACK_SCALE_MAX) { PRINTF (("yes (divided each row by max abs value in each row)\n")) ; PRINTF ((" minimum max (abs (rows of A)): %.5e\n", Numeric->rsmin)) ; PRINTF ((" maximum max (abs (rows of A)): %.5e", Numeric->rsmax)) ; } PRINTF (("\n")) ; PRINTF ((" initial allocation parameter used: %g\n", Numeric->alloc_init)) ; PRINTF ((" frontal matrix allocation parameter used: %g\n", Numeric->front_alloc_init)) ; PRINTF ((" final total size of Numeric object (Units): "ID"\n", numeric_size)) ; PRINTF ((" final total size of Numeric object (MBytes): %.1f\n", MBYTES (numeric_size))) ; PRINTF ((" peak size of variable-size part (Units): "ID"\n", Numeric->max_usage)) ; PRINTF ((" peak size of variable-size part (MBytes): %.1f\n", MBYTES (Numeric->max_usage))) ; PRINTF ((" largest actual frontal matrix size: "ID"\n", Numeric->maxfrsize)) ; PRINTF ((" memory defragmentations: "ID"\n", Numeric->ngarbage)) ; PRINTF ((" memory reallocations: "ID"\n", Numeric->nrealloc)) ; PRINTF ((" costly memory reallocations: "ID"\n", Numeric->ncostly)) ; PRINTF ((" entries in compressed pattern (L and U): "ID"\n", Numeric->isize)) ; PRINTF ((" number of nonzeros in L (excl diag): "ID"\n", Numeric->lnz)) ; PRINTF ((" number of entries stored in L (excl diag): "ID"\n", Numeric->nLentries)) ; PRINTF ((" number of nonzeros in U (excl diag): "ID"\n", Numeric->unz)) ; PRINTF ((" number of entries stored in U (excl diag): "ID"\n", Numeric->nUentries)) ; PRINTF ((" factorization floating-point operations: %g\n", Numeric->flops)) ; PRINTF ((" number of nonzeros on diagonal of U: "ID"\n", Numeric->nnzpiv)) ; PRINTF ((" min abs. value on diagonal of U: %.5e\n", Numeric->min_udiag)) ; PRINTF ((" max abs. value on diagonal of U: %.5e\n", Numeric->max_udiag)) ; PRINTF ((" reciprocal condition number estimate: %.2e\n", Numeric->rcond)) ; } W = (Int *) UMF_malloc (nn, sizeof (Int)) ; if (!W) { PRINTF ((" ERROR: out of memory to check Numeric object\n\n")) ; return (UMFPACK_ERROR_out_of_memory) ; } if (Numeric->Rs) { #ifndef NRECIPROCAL if (Numeric->do_recip) { PRINTF4 (("\nScale factors applied via multiplication\n")) ; } else #endif { PRINTF4 (("\nScale factors applied via division\n")) ; } PRINTF4 (("Scale factors, Rs: ")) ; (void) UMF_report_vector (n_row, Numeric->Rs, (double *) NULL, prl, FALSE, TRUE) ; } else { PRINTF4 (("Scale factors, Rs: (not present)\n")) ; } PRINTF4 (("\nP: row ")) ; if (UMF_report_perm (n_row, Numeric->Rperm, W, prl, 0) != UMFPACK_OK) { (void) UMF_free ((void *) W) ; return (UMFPACK_ERROR_invalid_Numeric_object) ; } PRINTF4 (("\nQ: column ")) ; if (UMF_report_perm (n_col, Numeric->Cperm, W, prl, 0) != UMFPACK_OK) { (void) UMF_free ((void *) W) ; return (UMFPACK_ERROR_invalid_Numeric_object) ; } if (!report_L (Numeric, W, prl)) { (void) UMF_free ((void *) W) ; PRINTF ((" ERROR: L factor invalid\n\n")) ; return (UMFPACK_ERROR_invalid_Numeric_object) ; } if (!report_U (Numeric, W, prl)) { (void) UMF_free ((void *) W) ; PRINTF ((" ERROR: U factor invalid\n\n")) ; return (UMFPACK_ERROR_invalid_Numeric_object) ; } /* The diagonal of U is in "merged" (Entry) form, not "split" form. */ PRINTF4 (("\ndiagonal of U: ")) ; (void) UMF_report_vector (n_inner, (double *) Numeric->D, (double *) NULL, prl, FALSE, FALSE) ; (void) UMF_free ((void *) W) ; PRINTF4 ((" Numeric object: ")) ; PRINTF (("OK\n\n")) ; return (UMFPACK_OK) ; }
PRIVATE Int work_alloc ( WorkType *Work, SymbolicType *Symbolic ) { Int n_row, n_col, nn, maxnrows, maxncols, nfr, ok, maxnrc, n1 ; n_row = Work->n_row ; n_col = Work->n_col ; nn = MAX (n_row, n_col) ; nfr = Work->nfr ; n1 = Symbolic->n1 ; ASSERT (n1 <= n_row && n1 <= n_col) ; maxnrows = Symbolic->maxnrows + Symbolic->nb ; maxnrows = MIN (n_row, maxnrows) ; maxncols = Symbolic->maxncols + Symbolic->nb ; maxncols = MIN (n_col, maxncols) ; maxnrc = MAX (maxnrows, maxncols) ; DEBUG0 (("work alloc: maxnrows+nb "ID" maxncols+nb "ID"\n", maxnrows, maxncols)) ; /* 15 allocations, freed in free_work: */ /* accounted for in UMF_set_stats (work_usage) */ Work->Wx = (Entry *) UMF_malloc (maxnrows + 1, sizeof (Entry)) ; Work->Wy = (Entry *) UMF_malloc (maxnrows + 1, sizeof (Entry)) ; Work->Frpos = (Int *) UMF_malloc (n_row + 1, sizeof (Int)) ; Work->Lpattern = (Int *) UMF_malloc (n_row + 1, sizeof (Int)) ; Work->Fcpos = (Int *) UMF_malloc (n_col + 1, sizeof (Int)) ; Work->Wp = (Int *) UMF_malloc (nn + 1, sizeof (Int)) ; Work->Wrp = (Int *) UMF_malloc (MAX (n_col,maxnrows) + 1, sizeof (Int)) ; Work->Frows = (Int *) UMF_malloc (maxnrows + 1, sizeof (Int)) ; Work->Wm = (Int *) UMF_malloc (maxnrows + 1, sizeof (Int)) ; Work->Fcols = (Int *) UMF_malloc (maxncols + 1, sizeof (Int)) ; Work->Wio = (Int *) UMF_malloc (maxncols + 1, sizeof (Int)) ; Work->Woi = (Int *) UMF_malloc (maxncols + 1, sizeof (Int)) ; Work->Woo = (Int *) UMF_malloc (maxnrc + 1, sizeof (Int)); Work->elen = (n_col - n1) + (n_row - n1) + MIN (n_col-n1, n_row-n1) + 1 ; Work->E = (Int *) UMF_malloc (Work->elen, sizeof (Int)) ; Work->Front_new1strow = (Int *) UMF_malloc (nfr + 1, sizeof (Int)) ; ok = (Work->Frpos && Work->Fcpos && Work->Lpattern && Work->Wp && Work->Wrp && Work->Frows && Work->Fcols && Work->Wio && Work->Woi && Work->Woo && Work->Wm && Work->E && Work->Front_new1strow && Work->Wx && Work->Wy) ; /* 2 allocations: accounted for in UMF_set_stats (work_usage) */ if (Symbolic->prefer_diagonal) { Work->Diagonal_map = (Int *) UMF_malloc (nn, sizeof (Int)) ; Work->Diagonal_imap = (Int *) UMF_malloc (nn, sizeof (Int)) ; ok = ok && Work->Diagonal_map && Work->Diagonal_imap ; } else { /* no diagonal map needed for rectangular matrices */ Work->Diagonal_map = (Int *) NULL ; Work->Diagonal_imap = (Int *) NULL ; } /* 1 allocation, may become part of Numeric (if singular or rectangular): */ Work->Upattern = (Int *) UMF_malloc (n_col + 1, sizeof (Int)) ; ok = ok && Work->Upattern ; /* current frontal matrix does not yet exist */ Work->Flublock = (Entry *) NULL ; Work->Flblock = (Entry *) NULL ; Work->Fublock = (Entry *) NULL ; Work->Fcblock = (Entry *) NULL ; DEBUG0 (("work alloc done.\n")) ; return (ok) ; }
PRIVATE Int numeric_alloc ( NumericType **NumericHandle, SymbolicType *Symbolic, double alloc_init, Int scale ) { double nsize, bsize ; Int n_row, n_col, n_inner, min_usage, trying ; NumericType *Numeric ; DEBUG0 (("numeric alloc:\n")) ; n_row = Symbolic->n_row ; n_col = Symbolic->n_col ; n_inner = MIN (n_row, n_col) ; *NumericHandle = (NumericType *) NULL ; /* 1 allocation: accounted for in UMF_set_stats (num_On_size1), * free'd in umfpack_free_numeric */ Numeric = (NumericType *) UMF_malloc (1, sizeof (NumericType)) ; if (!Numeric) { return (FALSE) ; /* out of memory */ } Numeric->valid = 0 ; *NumericHandle = Numeric ; /* 9 allocations: accounted for in UMF_set_stats (num_On_size1), * free'd in umfpack_free_numeric */ Numeric->D = (Entry *) UMF_malloc (n_inner+1, sizeof (Entry)) ; Numeric->Rperm = (Int *) UMF_malloc (n_row+1, sizeof (Int)) ; Numeric->Cperm = (Int *) UMF_malloc (n_col+1, sizeof (Int)) ; Numeric->Lpos = (Int *) UMF_malloc (n_row+1, sizeof (Int)) ; Numeric->Lilen = (Int *) UMF_malloc (n_col+1, sizeof (Int)) ; Numeric->Lip = (Int *) UMF_malloc (n_col+1, sizeof (Int)) ; Numeric->Upos = (Int *) UMF_malloc (n_col+1, sizeof (Int)) ; Numeric->Uilen = (Int *) UMF_malloc (n_row+1, sizeof (Int)) ; Numeric->Uip = (Int *) UMF_malloc (n_row+1, sizeof (Int)) ; /* 1 allocation if scaling: in UMF_set_stats (num_On_size1), * free'd in umfpack_free_numeric */ if (scale != UMFPACK_SCALE_NONE) { DEBUG0 (("Allocating scale factors\n")) ; Numeric->Rs = (double *) UMF_malloc (n_row, sizeof (double)) ; } else { DEBUG0 (("No scale factors allocated (R = I)\n")) ; Numeric->Rs = (double *) NULL ; } Numeric->Memory = (Unit *) NULL ; /* Upattern has already been allocated as part of the Work object. If * the matrix is singular or rectangular, and there are off-diagonal * nonzeros in the last pivot row, then Work->Upattern is not free'd. * Instead it is transfered to Numeric->Upattern. If it exists, * Numeric->Upattern is free'd in umfpack_free_numeric. */ Numeric->Upattern = (Int *) NULL ; /* used for singular matrices only */ if (!Numeric->D || !Numeric->Rperm || !Numeric->Cperm || !Numeric->Upos || !Numeric->Lpos || !Numeric->Lilen || !Numeric->Uilen || !Numeric->Lip || !Numeric->Uip || (scale != UMFPACK_SCALE_NONE && !Numeric->Rs)) { return (FALSE) ; /* out of memory */ } /* ---------------------------------------------------------------------- */ /* allocate initial Numeric->Memory for LU factors and elements */ /* ---------------------------------------------------------------------- */ if (alloc_init < 0) { /* -alloc_init is the exact size to initially allocate */ nsize = -alloc_init ; } else { /* alloc_init is a ratio of the upper bound memory usage */ nsize = (alloc_init * Symbolic->num_mem_usage_est) + 1 ; } min_usage = Symbolic->num_mem_init_usage ; /* Numeric->Memory must be large enough for UMF_kernel_init */ nsize = MAX (min_usage, nsize) ; /* Numeric->Memory cannot be larger in size than Int_MAX / sizeof(Unit) */ /* For ILP32 mode: 2GB (nsize cannot be bigger than 256 Mwords) */ bsize = ((double) Int_MAX) / sizeof (Unit) - 1 ; DEBUG0 (("bsize %g\n", bsize)) ; nsize = MIN (nsize, bsize) ; Numeric->size = (Int) nsize ; DEBUG0 (("Num init %g usage_est %g numsize "ID" minusage "ID"\n", alloc_init, Symbolic->num_mem_usage_est, Numeric->size, min_usage)) ; /* allocates 1 object: */ /* keep trying until successful, or memory request is too small */ trying = TRUE ; while (trying) { Numeric->Memory = (Unit *) UMF_malloc (Numeric->size, sizeof (Unit)) ; if (Numeric->Memory) { DEBUG0 (("Successful Numeric->size: "ID"\n", Numeric->size)) ; return (TRUE) ; } /* too much, reduce the request (but not below the minimum) */ /* and try again */ trying = Numeric->size > min_usage ; Numeric->size = (Int) (UMF_REALLOC_REDUCTION * ((double) Numeric->size)) ; Numeric->size = MAX (min_usage, Numeric->size) ; } return (FALSE) ; /* we failed to allocate Numeric->Memory */ }
GLOBAL Int UMFPACK_transpose ( Int n_row, Int n_col, const Int Ap [ ], /* size n_col+1 */ const Int Ai [ ], /* size nz = Ap [n_col] */ const double Ax [ ], /* size nz, if present */ #ifdef COMPLEX const double Az [ ], /* size nz, if present */ #endif const Int P [ ], /* P [k] = i means original row i is kth row in A(P,Q)*/ /* P is identity if not present */ /* size n_row, if present */ const Int Q [ ], /* Q [k] = j means original col j is kth col in A(P,Q)*/ /* Q is identity if not present */ /* size n_col, if present */ Int Rp [ ], /* size n_row+1 */ Int Ri [ ], /* size nz */ double Rx [ ] /* size nz, if present */ #ifdef COMPLEX , double Rz [ ] /* size nz, if present */ , Int do_conjugate /* if true, then to conjugate transpose */ /* otherwise, do array transpose */ #endif ) { /* ---------------------------------------------------------------------- */ /* local variables */ /* ---------------------------------------------------------------------- */ Int status, *W, nn ; #ifndef NDEBUG init_count = UMF_malloc_count ; UMF_dump_start ( ) ; #endif /* ---------------------------------------------------------------------- */ /* allocate workspace */ /* ---------------------------------------------------------------------- */ nn = MAX (n_row, n_col) ; nn = MAX (nn, 1) ; W = (Int *) UMF_malloc (nn, sizeof (Int)) ; if (!W) { DEBUGm4 (("out of memory: transpose work\n")) ; ASSERT (UMF_malloc_count == init_count) ; return (UMFPACK_ERROR_out_of_memory) ; } ASSERT (UMF_malloc_count == init_count + 1) ; /* ---------------------------------------------------------------------- */ /* C = (A (P,Q))' or (A (P,Q)).' */ /* ---------------------------------------------------------------------- */ status = UMF_transpose (n_row, n_col, Ap, Ai, Ax, P, Q, n_col, Rp, Ri, Rx, W, TRUE #ifdef COMPLEX , Az, Rz, do_conjugate #endif ) ; /* ---------------------------------------------------------------------- */ /* free the workspace */ /* ---------------------------------------------------------------------- */ (void) UMF_free ((void *) W) ; ASSERT (UMF_malloc_count == init_count) ; return (status) ; }
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_load_numeric ( void **NumericHandle, char *user_filename ) { NumericType *Numeric ; char *filename ; FILE *f ; *NumericHandle = (void *) NULL ; /* ---------------------------------------------------------------------- */ /* get the filename, or use the default name if filename is NULL */ /* ---------------------------------------------------------------------- */ if (user_filename == (char *) NULL) { filename = "numeric.umf" ; } else { filename = user_filename ; } f = fopen (filename, "rb") ; if (!f) { return (UMFPACK_ERROR_file_IO) ; } /* ---------------------------------------------------------------------- */ /* read the Numeric header from the file, in binary */ /* ---------------------------------------------------------------------- */ Numeric = (NumericType *) UMF_malloc (1, sizeof (NumericType)) ; if (Numeric == (NumericType *) NULL) { fclose (f) ; return (UMFPACK_ERROR_out_of_memory) ; } if (fread (Numeric, sizeof (NumericType), 1, f) != 1) { (void) UMF_free ((void *) Numeric) ; fclose (f) ; return (UMFPACK_ERROR_file_IO) ; } if (ferror (f)) { (void) UMF_free ((void *) Numeric) ; fclose (f) ; return (UMFPACK_ERROR_file_IO) ; } if (Numeric->valid != NUMERIC_VALID || Numeric->n_row <= 0 || Numeric->n_col <= 0 || Numeric->npiv < 0 || Numeric->ulen < 0 || Numeric->size <= 0) { /* Numeric does not point to a NumericType object */ (void) UMF_free ((void *) Numeric) ; fclose (f) ; return (UMFPACK_ERROR_invalid_Numeric_object) ; } Numeric->D = (Entry *) NULL ; Numeric->Rperm = (Int *) NULL ; Numeric->Cperm = (Int *) NULL ; Numeric->Lpos = (Int *) NULL ; Numeric->Lilen = (Int *) NULL ; Numeric->Lip = (Int *) NULL ; Numeric->Upos = (Int *) NULL ; Numeric->Uilen = (Int *) NULL ; Numeric->Uip = (Int *) NULL ; Numeric->Rs = (double *) NULL ; Numeric->Memory = (Unit *) NULL ; Numeric->Upattern = (Int *) NULL ; /* umfpack_free_numeric can now be safely called if an error occurs */ /* ---------------------------------------------------------------------- */ /* read the rest of the Numeric object */ /* ---------------------------------------------------------------------- */ READ (Numeric->D, Entry, MIN (Numeric->n_row, Numeric->n_col)+1) ; READ (Numeric->Rperm, Int, Numeric->n_row+1) ; READ (Numeric->Cperm, Int, Numeric->n_col+1) ; READ (Numeric->Lpos, Int, Numeric->npiv+1) ; READ (Numeric->Lilen, Int, Numeric->npiv+1) ; READ (Numeric->Lip, Int, Numeric->npiv+1) ; READ (Numeric->Upos, Int, Numeric->npiv+1) ; READ (Numeric->Uilen, Int, Numeric->npiv+1) ; READ (Numeric->Uip, Int, Numeric->npiv+1) ; if (Numeric->scale != UMFPACK_SCALE_NONE) { READ (Numeric->Rs, double, Numeric->n_row) ; }
GLOBAL Int UMFPACK_get_numeric ( Int Lp [ ], Int Lj [ ], double Lx [ ], #ifdef COMPLEX double Lz [ ], #endif Int Up [ ], Int Ui [ ], double Ux [ ], #ifdef COMPLEX double Uz [ ], #endif Int P [ ], Int Q [ ], double Dx [ ], #ifdef COMPLEX double Dz [ ], #endif Int *p_do_recip, double Rs [ ], void *NumericHandle ) { /* ---------------------------------------------------------------------- */ /* local variables */ /* ---------------------------------------------------------------------- */ NumericType *Numeric ; Int getL, getU, *Rperm, *Cperm, k, nn, n_row, n_col, *Wi, *Pattern, n_inner ; double *Rs1 ; Entry *D ; #ifndef NDEBUG init_count = UMF_malloc_count ; #endif Wi = (Int *) NULL ; Pattern = (Int *) NULL ; /* ---------------------------------------------------------------------- */ /* check input parameters */ /* ---------------------------------------------------------------------- */ Numeric = (NumericType *) NumericHandle ; if (!UMF_valid_numeric (Numeric)) { return (UMFPACK_ERROR_invalid_Numeric_object) ; } n_row = Numeric->n_row ; n_col = Numeric->n_col ; nn = MAX (n_row, n_col) ; n_inner = MIN (n_row, n_col) ; /* ---------------------------------------------------------------------- */ /* allocate workspace */ /* ---------------------------------------------------------------------- */ getL = Lp && Lj && Lx ; getU = Up && Ui && Ux ; if (getL || getU) { Wi = (Int *) UMF_malloc (nn, sizeof (Int)) ; Pattern = (Int *) UMF_malloc (nn, sizeof (Int)) ; if (!Wi || !Pattern) { (void) UMF_free ((void *) Wi) ; (void) UMF_free ((void *) Pattern) ; ASSERT (UMF_malloc_count == init_count) ; DEBUGm4 (("out of memory: get numeric\n")) ; return (UMFPACK_ERROR_out_of_memory) ; } ASSERT (UMF_malloc_count == init_count + 2) ; } /* ---------------------------------------------------------------------- */ /* get contents of Numeric */ /* ---------------------------------------------------------------------- */ if (P != (Int *) NULL) { Rperm = Numeric->Rperm ; for (k = 0 ; k < n_row ; k++) { P [k] = Rperm [k] ; } } if (Q != (Int *) NULL) { Cperm = Numeric->Cperm ; for (k = 0 ; k < n_col ; k++) { Q [k] = Cperm [k] ; } } if (getL) { get_L (Lp, Lj, Lx, #ifdef COMPLEX Lz, #endif Numeric, Pattern, Wi) ; } if (getU) { get_U (Up, Ui, Ux, #ifdef COMPLEX Uz, #endif Numeric, Pattern, Wi) ; } if (Dx != (double *) NULL) { D = Numeric->D ; #ifdef COMPLEX if (SPLIT (Dz)) { for (k = 0 ; k < n_inner ; k++) { Dx [k] = REAL_COMPONENT (D [k]) ; Dz [k] = IMAG_COMPONENT (D [k]) ; } } else { for (k = 0 ; k < n_inner ; k++) { Dx [2*k ] = REAL_COMPONENT (D [k]) ; Dx [2*k+1] = IMAG_COMPONENT (D [k]) ; } } #else { D = Numeric->D ; for (k = 0 ; k < n_inner ; k++) { Dx [k] = D [k] ; } } #endif } /* return the flag stating whether the scale factors are to be multiplied, * or divided. If do_recip is TRUE, multiply. Otherwise, divided. * If NRECIPROCAL is defined at compile time, the scale factors are always * to be used by dividing. */ if (p_do_recip != (Int *) NULL) { #ifndef NRECIPROCAL *p_do_recip = Numeric->do_recip ; #else *p_do_recip = FALSE ; #endif } if (Rs != (double *) NULL) { Rs1 = Numeric->Rs ; if (Rs1 == (double *) NULL) { /* R is the identity matrix. */ for (k = 0 ; k < n_row ; k++) { Rs [k] = 1.0 ; } } else { for (k = 0 ; k < n_row ; k++) { Rs [k] = Rs1 [k] ; } } } /* ---------------------------------------------------------------------- */ /* free the workspace */ /* ---------------------------------------------------------------------- */ (void) UMF_free ((void *) Wi) ; (void) UMF_free ((void *) Pattern) ; ASSERT (UMF_malloc_count == init_count) ; return (UMFPACK_OK) ; }