//============================================================================= int Amesos_Umfpack::PerformNumericFactorization( ) { // MS // no overhead time in this method ResetTimer(0); RcondValidOnAllProcs_ = false ; if (MyPID_ == 0) { std::vector<double> Control(UMFPACK_CONTROL); std::vector<double> Info(UMFPACK_INFO); umfpack_di_defaults( &Control[0] ) ; if (Numeric) umfpack_di_free_numeric (&Numeric) ; int status = umfpack_di_numeric (&Ap[0], &Ai[0], &Aval[0], Symbolic, &Numeric, &Control[0], &Info[0]) ; Rcond_ = Info[UMFPACK_RCOND]; #if NOT_DEF std::cout << " Rcond_ = " << Rcond_ << std::endl ; int lnz1 = 1000 ; int unz1 = 1000 ; int n = 4; int * Lp = (int *) malloc ((n+1) * sizeof (int)) ; int * Lj = (int *) malloc (lnz1 * sizeof (int)) ; double * Lx = (double *) malloc (lnz1 * sizeof (double)) ; int * Up = (int *) malloc ((n+1) * sizeof (int)) ; int * Ui = (int *) malloc (unz1 * sizeof (int)) ; double * Ux = (double *) malloc (unz1 * sizeof (double)) ; int * P = (int *) malloc (n * sizeof (int)) ; int * Q = (int *) malloc (n * sizeof (int)) ; double * Dx = (double *) NULL ; /* D vector not requested */ double * Rs = (double *) malloc (n * sizeof (double)) ; if (!Lp || !Lj || !Lx || !Up || !Ui || !Ux || !P || !Q || !Rs) { assert( false ) ; } int do_recip; status = umfpack_di_get_numeric (Lp, Lj, Lx, Up, Ui, Ux, P, Q, Dx, &do_recip, Rs, Numeric) ; if (status < 0) { assert( false ) ; } printf ("\nL (lower triangular factor of C): ") ; (void) umfpack_di_report_matrix (n, n, Lp, Lj, Lx, 0, &Control[0]) ; printf ("\nU (upper triangular factor of C): ") ; (void) umfpack_di_report_matrix (n, n, Up, Ui, Ux, 1, &Control[0]) ; printf ("\nP: ") ; (void) umfpack_di_report_perm (n, P, &Control[0]) ; printf ("\nQ: ") ; (void) umfpack_di_report_perm (n, Q, &Control[0]) ; printf ("\nScale factors: row i of A is to be ") ; #endif assert( status == 0 ) ; } NumFactTime_ = AddTime("Total numeric factorization time", NumFactTime_, 0); return 0; }
/*! \fn solve a singular linear system with UmfPack methods * * \param [in/out] [systemData] * * * solve even singular system * (note that due to initialization A is given in its transposed form A^T) * * A * x = b * <=> P * R * A * Q * Q * x = P * R * b | P * R * A * Q = L * U * <=> L * U * Q * x = P * R * b * * note that P and Q are orthogonal permutation matrices, so P^(-1) = P^T and Q^(-1) = Q^T * * (1) L * y = P * R * b <=> P^T * L * y = R * b (L is always regular so this can be solved by umfpack) * * (2) U * z = y (U is singular, this cannot be solved by umfpack) * * (3) Q * x = z <=> x = Q^T * z * * * author: kbalzereit, wbraun */ int solveSingularSystem(LINEAR_SYSTEM_DATA* systemData) { DATA_UMFPACK* solverData = (DATA_UMFPACK*) systemData->solverData; double *Ux, *Rs, r_ii, *b, sum, *y, *z; int *Up, *Ui, *Q, do_recip, rank = 0, current_rank, current_unz, i, j, k, l, success = 0, status, stop = 0; int unz = solverData->info[UMFPACK_UNZ]; Up = (int*) malloc((solverData->n_row + 1) * sizeof(int)); Ui = (int*) malloc(unz * sizeof(int)); Ux = (double*) malloc(unz * sizeof(double)); Q = (int*) malloc(solverData->n_col * sizeof(int)); Rs = (double*) malloc(solverData->n_row * sizeof(double)); b = (double*) malloc(solverData->n_col * sizeof(double)); y = (double*) malloc(solverData->n_col * sizeof(double)); z = (double*) malloc(solverData->n_col * sizeof(double)); infoStreamPrint(LOG_LS_V, 0, "Solve singular system"); status = umfpack_di_get_numeric((int*) NULL, (int*) NULL, (double*) NULL, Up, Ui, Ux, (int*) NULL, Q, (double*) NULL, &do_recip, Rs, solverData->numeric); switch (status) { case UMFPACK_WARNING_singular_matrix: case UMFPACK_ERROR_out_of_memory: case UMFPACK_ERROR_argument_missing: case UMFPACK_ERROR_invalid_system: case UMFPACK_ERROR_invalid_Numeric_object: infoStreamPrint(LOG_LS_V, 0, "error: %d", status); } /* calculate R*b */ if (do_recip == 0) { for (i = 0; i < solverData->n_row; i++) { b[i] = systemData->b[i] / Rs[i]; } } else { for (i = 0; i < solverData->n_row; i++) { b[i] = systemData->b[i] * Rs[i]; } } /* solve L * y = P * R * b <=> P^T * L * y = R * b */ status = umfpack_di_solve(UMFPACK_Pt_L, solverData->Ap, solverData->Ai, solverData->Ax, y, b, solverData->numeric, solverData->control, solverData->info); switch (status) { case UMFPACK_WARNING_singular_matrix: case UMFPACK_ERROR_out_of_memory: case UMFPACK_ERROR_argument_missing: case UMFPACK_ERROR_invalid_system: case UMFPACK_ERROR_invalid_Numeric_object: infoStreamPrint(LOG_LS_V, 0, "error: %d", status); } /* rank is at most as high as the maximum in Ui */ for (i = 0; i < unz; i++) { if (rank < Ui[i]) rank = Ui[i]; } /* if rank is already smaller than n set last component of result zero */ for (i = rank + 1; i < solverData->n_col; i++) { if (y[i] < 1e-12) { z[i] = 0.0; } else { infoStreamPrint(LOG_LS_V, 0, "error: system is not solvable*"); /* free all used memory */ free(Up); free(Ui); free(Ux); free(Q); free(Rs); free(b); free(y); free(z); return -1; } } current_rank = rank; current_unz = unz; while ((stop == 0) && (current_rank > 1)) { /* check if last two rows of U are the same */ if ((Ux[current_unz] == Ux[current_unz - 1]) && (Ui[current_unz] == Ui[current_unz - 1]) && (Up[current_rank] - Up[current_rank - 1] > 1)) { /* if diagonal entry on second to last row is nonzero, remaining matrix is regular */ if (Ui[Up[current_rank] - 1] == current_rank - 1) { stop = 1; } /* last two rows are the same -> under-determined system, calculate one value and set the other one zero */ else { z[current_rank] = y[current_rank] / Ux[current_unz]; /* reduce system */ for (i = Up[current_rank]; i < current_unz; i++) { y[Ui[i]] -= z[current_rank] * Ux[i]; } current_unz = Up[current_rank] - 1; current_rank--; /* now last row has only zero entries */ if (y[current_rank] < 1e-12) { z[current_rank] = 0.0; } else { infoStreamPrint(LOG_LS_V, 0, "error: system is not solvable"); /* free all used memory */ free(Up); free(Ui); free(Ux); free(Q); free(Rs); free(b); free(y); free(z); return -1; } current_rank--; } } else { stop = 1; } } /* remaining system is regular so solve system by back substitution */ z[current_rank] = Ux[current_unz] * y[current_rank]; for (i = current_rank - 1; i >= 0; i--) { /* get diagonal element r_ii, j shows where the element is in vector Ux, Ui */ j = Up[i]; while (Ui[j] != i) { j++; } r_ii = Ux[j]; sum = 0.0; for (k = i + 1; k < current_rank; k++) { for (l = Up[k]; l < Up[k + 1]; l++) { if (Ui[l] == Ui[i]) { sum += Ux[i] * z[k]; } } } z[i] = (y[i] - sum) / r_ii; } /* x = Q^T * z */ for (i = 0; i < solverData->n_col; i++) { systemData->x[Q[i]] = z[i]; } /* free all used memory */ free(Up); free(Ui); free(Ux); free(Q); free(Rs); free(b); free(y); free(z); return success; }
int sci_umf_luget(char* fname, void* pvApiCtx) { /* * LU_ptr is (a pointer to) a factorization of A, we have: * -1 * P R A Q = L U * * A is n_row x n_col * L is n_row x n * U is n x n_col n = min(n_row, n_col) */ SciErr sciErr; void* Numeric = NULL; int lnz = 0, unz = 0, n_row = 0, n_col = 0, n = 0, nz_udiag = 0, i = 0, stat = 0, do_recip = 0, it_flag = 0; int *L_mnel = NULL, *L_icol = NULL, *L_ptrow = NULL, *U_mnel = NULL, *U_icol = NULL, *U_ptrow = NULL, *V_irow = NULL, *V_ptcol = NULL; double *L_R = NULL, *L_I = NULL, *U_R = NULL, *U_I = NULL, *V_R = NULL, *V_I = NULL, *Rs = NULL; int *p = NULL, *q = NULL, pl_miss = 0, error_flag = 0 ; int* piAddr1 = NULL; int iType1 = 0; /* Check numbers of input/output arguments */ CheckInputArgument(pvApiCtx, 1, 1); CheckOutputArgument(pvApiCtx, 1, 5); /* get the pointer to the LU factors */ sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr1); if (sciErr.iErr) { printError(&sciErr, 0); return 1; } /* Check if the first argument is a pointer */ sciErr = getVarType(pvApiCtx, piAddr1, &iType1); if (sciErr.iErr || iType1 != sci_pointer) { printError(&sciErr, 0); Scierror(999, _("%s: Wrong type for input argument #%d: A pointer expected.\n"), fname, 1); return 1; } sciErr = getPointer(pvApiCtx, piAddr1, &Numeric); if (sciErr.iErr) { printError(&sciErr, 0); return 1; } /* Check if the pointer is a valid ref to ... */ if ( IsAdrInList(Numeric, ListNumeric, &it_flag) ) { if (it_flag == 0 ) { umfpack_di_get_lunz(&lnz, &unz, &n_row, &n_col, &nz_udiag, Numeric); } else { umfpack_zi_get_lunz(&lnz, &unz, &n_row, &n_col, &nz_udiag, Numeric); } } else { Scierror(999, _("%s: Wrong value for input argument #%d: Must be a valid reference to (umf) LU factors.\n"), fname, 1); return 1; } if (n_row <= n_col) { n = n_row; } else { n = n_col; } L_mnel = (int*)MALLOC(n_row * sizeof(int)); L_icol = (int*)MALLOC(lnz * sizeof(int)); L_ptrow = (int*)MALLOC((n_row + 1) * sizeof(int)); L_R = (double*)MALLOC( lnz * sizeof(double)); U_mnel = (int*)MALLOC(n * sizeof(int)); U_icol = (int*)MALLOC(unz * sizeof(int)); U_ptrow = (int*)MALLOC((n + 1) * sizeof(int)); U_R = (double*)MALLOC( unz * sizeof(double)); V_irow = (int*)MALLOC(unz * sizeof(int)); V_ptcol = (int*)MALLOC((n_col + 1) * sizeof(int)); V_R = (double*)MALLOC( unz * sizeof(double)); p = (int*)MALLOC(n_row * sizeof(int)); q = (int*)MALLOC(n_col * sizeof(int)); Rs = (double*)MALLOC(n_row * sizeof(double)); if ( it_flag == 1 ) { L_I = (double*)MALLOC(lnz * sizeof(double)); U_I = (double*)MALLOC(unz * sizeof(double)); V_I = (double*)MALLOC(unz * sizeof(double)); } else { L_I = U_I = V_I = NULL; } if ( !(L_mnel && L_icol && L_R && L_ptrow && p && U_mnel && U_icol && U_R && U_ptrow && q && V_irow && V_R && V_ptcol && Rs) || (it_flag && !(L_I && U_I && V_I)) ) { error_flag = 1; goto the_end; } if ( it_flag == 0 ) { stat = umfpack_di_get_numeric(L_ptrow, L_icol, L_R, V_ptcol, V_irow, V_R, p, q, (double *)NULL, &do_recip, Rs, Numeric); } else { stat = umfpack_zi_get_numeric(L_ptrow, L_icol, L_R, L_I, V_ptcol, V_irow, V_R, V_I, p, q, (double *)NULL, (double *)NULL, &do_recip, Rs, Numeric); } if ( stat != UMFPACK_OK ) { error_flag = 2; goto the_end; }; if ( do_recip ) { for ( i = 0 ; i < n_row ; i++ ) { Rs[i] = 1.0 / Rs[i]; } } if ( it_flag == 0 ) { stat = umfpack_di_transpose(n, n_col, V_ptcol, V_irow, V_R, (int *) NULL, (int*) NULL, U_ptrow, U_icol, U_R); } else { stat = umfpack_zi_transpose(n, n_col, V_ptcol, V_irow, V_R, V_I, (int *) NULL, (int*) NULL, U_ptrow, U_icol, U_R, U_I, 0); } if ( stat != UMFPACK_OK ) { error_flag = 2; goto the_end; }; for ( i = 0 ; i < n_row ; i++ ) { L_mnel[i] = L_ptrow[i + 1] - L_ptrow[i]; } for ( i = 0 ; i < n ; i++ ) { U_mnel[i] = U_ptrow[i + 1] - U_ptrow[i]; } for ( i = 0 ; i < lnz ; i++ ) { L_icol[i]++; } for ( i = 0 ; i < unz ; i++ ) { U_icol[i]++; } for ( i = 0 ; i < n_row ; i++ ) { p[i]++; } for ( i = 0 ; i < n_col ; i++ ) { q[i]++; } /* output L */ if (it_flag) // complex { sciErr = createComplexSparseMatrix(pvApiCtx, 2, n_row, n, lnz, L_mnel, L_icol, L_R, L_I); } else { sciErr = createSparseMatrix(pvApiCtx, 2, n_row, n, lnz, L_mnel, L_icol, L_R); } if (sciErr.iErr) { printError(&sciErr, 0); FREE(L_mnel); FREE(U_mnel); return 1; } /* output U */ if (it_flag) // complex { sciErr = createComplexSparseMatrix(pvApiCtx, 3, n, n_col, unz, U_mnel, U_icol, U_R, U_I); } else { sciErr = createSparseMatrix(pvApiCtx, 3, n, n_col, unz, U_mnel, U_icol, U_R); } if (sciErr.iErr) { printError(&sciErr, 0); FREE(L_mnel); FREE(U_mnel); return 1; } /* output p */ sciErr = createMatrixOfDoubleAsInteger(pvApiCtx, 4, n_row, 1, p); if (sciErr.iErr) { printError(&sciErr, 0); FREE(L_mnel); FREE(U_mnel); return 1; } /* output q */ sciErr = createMatrixOfDoubleAsInteger(pvApiCtx, 5, n_col, 1, q); if (sciErr.iErr) { printError(&sciErr, 0); FREE(L_mnel); FREE(U_mnel); return 1; } /* output res */ sciErr = createMatrixOfDouble(pvApiCtx, 6, n_row, 1, Rs); if (sciErr.iErr) { printError(&sciErr, 0); FREE(L_mnel); FREE(U_mnel); return 1; } the_end: FREE(L_mnel); FREE(L_icol); FREE(L_R); FREE(L_ptrow); FREE(p); FREE(U_mnel); FREE(U_icol); FREE(U_R); FREE(U_ptrow); FREE(q); FREE(V_irow); FREE(V_R); FREE(V_ptcol); FREE(Rs); if ( it_flag == 1 ) { FREE(L_I); FREE(V_I); FREE(U_I); } switch (error_flag) { case 0: /* no error */ AssignOutputVariable(pvApiCtx, 1) = 2; AssignOutputVariable(pvApiCtx, 2) = 3; AssignOutputVariable(pvApiCtx, 3) = 4; AssignOutputVariable(pvApiCtx, 4) = 5; AssignOutputVariable(pvApiCtx, 5) = 6; ReturnArguments(pvApiCtx); return 0; case 1: /* enough memory (with malloc) */ Scierror(999, _("%s: No more memory.\n"), fname); break; case 2: /* a problem with one umfpack routine */ Scierror(999, "%s: %s\n", fname, UmfErrorMes(stat)); break; } return 1; }