/* * *************************************************************************** * Routine: Slu_solve * * Purpose: Use sparse LU factors to back/forward solve a linear system. * * Author: Michael Holst and Stephen Bond * *************************************************************************** */ VPUBLIC int Slu_solve(Slu *thee, int key, double *b, double *x) { int status; int n = thee->n, m = thee->m, skey = thee->skey; int *Ap = thee->ia, *Ai = thee->ja; double *Ax = thee->a; void *Numeric = thee->work; VASSERT( thee != VNULL ); VASSERT( thee->statLU ); /* solve the system with the existing factors */ if( (key == 0 && skey == 1) || (key == 1 && skey == 0) ) { status = umfpack_di_solve(UMFPACK_A, Ap, Ai, Ax, x, b, Numeric, VNULL, VNULL); } else { status = umfpack_di_solve(UMFPACK_At, Ap, Ai, Ax, x, b, Numeric, VNULL, VNULL); } /* return: 1=success, 0=failure */ if ( UMFPACK_OK == status ) { return 1; } else { return 0; } }
bool SparseMatrix::solveUMF (Vector& B, Real* rcond) { if (!factored) this->optimiseSLU(); #ifdef HAS_UMFPACK double info[UMFPACK_INFO]; Vector X(B.size()); if (!umfSymbolic) { umfpack_di_symbolic(nrow, ncol, IA.data(), JA.data(), A.data(), &umfSymbolic, nullptr, info); if (info[UMFPACK_STATUS] != UMFPACK_OK) return false; } void* numeric; umfpack_di_numeric(IA.data(), JA.data(), A.data(), umfSymbolic, &numeric, nullptr, info); if (info[UMFPACK_STATUS] != UMFPACK_OK) return false; if (rcond) *rcond = info[UMFPACK_RCOND]; umfpack_di_solve(UMFPACK_A, IA.data(), JA.data(), A.data(), &X[0], &B[0], numeric, nullptr, info); if (info[UMFPACK_STATUS] == UMFPACK_OK) B = X; umfpack_di_free_numeric(&numeric); return info[UMFPACK_STATUS] == UMFPACK_OK; #else std::cerr <<"SparseMatrix::solve: UMFPACK solver not available"<< std::endl; return false; #endif }
/*---------------------------------------------------------------------------*/ void sparse_solve(sparse_t *A, double *b, double *x) /*---------------------------------------------------------------------------*/ { assert (A->m == A->n); if (sparse_is_triangular(A)) { sparse_solve_triangular(A, b, x); return; } int n = A->m; /* UMFPACK expect compressed-sparse-column format. */ sparse_t *B = NULL; sparse_copy(&B, A); B = sparse_transpose(B); double *null = (double *) NULL ; void *Symbolic, *Numeric ; umfpack_di_symbolic (n, n, B->ia, B->ja, B->a, &Symbolic, null, null) ; umfpack_di_numeric (B->ia, B->ja, B->a, Symbolic, &Numeric, null, null) ; umfpack_di_free_symbolic (&Symbolic); umfpack_di_solve (UMFPACK_A, B->ia, B->ja, B->a, x, b, Numeric, null, null) ; umfpack_di_free_numeric (&Numeric); sparse_free(B); }
void SolveRealByLU(int numberOfRows, int numberOfColumn, int nnz, int *Ti, int *Tj, double *Tx, double *X, double *b) { //创建 Compressed Row Storage 存储结构 int *Ai = (int*)malloc(sizeof(int)*(nnz)); int *Ap = (int*)malloc(sizeof(int)*(numberOfRows + 1)); double *Ax = (double*)malloc(sizeof(double)*(nnz)); //转换 triplet 到 CRS int staus = umfpack_di_triplet_to_col(numberOfRows, numberOfColumn, nnz, Ti, Tj, Tx, Ap, Ai, Ax, NULL); if (staus != UMFPACK_OK){ return; } //因子化 void *Symbolic, *Numeric; umfpack_di_symbolic(numberOfRows, numberOfColumn, Ap, Ai, Ax, &Symbolic, NULL, NULL); umfpack_di_numeric(Ap, Ai, Ax, Symbolic, &Numeric, NULL, NULL); umfpack_di_solve(UMFPACK_A, Ap, Ai, Ax, X, b, Numeric, NULL, NULL); umfpack_di_free_symbolic(&Symbolic); umfpack_di_free_numeric(&Numeric); if (Ai != NULL) free(Ai); if (Ap != NULL) free(Ap); if (Ax != NULL) free(Ax); }
inline int solve (int sys, int, int const* Ap, int const* Ai, double const* Ax, double* X, double const* B, void *Numeric, double const* Control, double* Info) { return umfpack_di_solve (sys, Ap, Ai, Ax, X, B, Numeric, Control, Info); }
bool CommonSolverUmfpack::solve(Matrix *mat, double *res) { printf("UMFPACK solver\n"); CSCMatrix *Acsc = NULL; if (CooMatrix *mcoo = dynamic_cast<CooMatrix*>(mat)) Acsc = new CSCMatrix(mcoo); else if (CSCMatrix *mcsc = dynamic_cast<CSCMatrix*>(mat)) Acsc = mcsc; else if (CSRMatrix *mcsr = dynamic_cast<CSRMatrix*>(mat)) Acsc = new CSCMatrix(mcsr); else _error("Matrix type not supported."); int nnz = Acsc->get_nnz(); int size = Acsc->get_size(); // solve umfpack_di_defaults(control_array); /* symbolic analysis */ void *symbolic, *numeric; int status_symbolic = umfpack_di_symbolic(size, size, Acsc->get_Ap(), Acsc->get_Ai(), NULL, &symbolic, control_array, info_array); print_status(status_symbolic); /* LU factorization */ int status_numeric = umfpack_di_numeric(Acsc->get_Ap(), Acsc->get_Ai(), Acsc->get_Ax(), symbolic, &numeric, control_array, info_array); print_status(status_numeric); umfpack_di_free_symbolic(&symbolic); double *x = new double[size]; /* solve system */ int status_solve = umfpack_di_solve(UMFPACK_A, Acsc->get_Ap(), Acsc->get_Ai(), Acsc->get_Ax(), x, res, numeric, control_array, info_array); print_status(status_solve); umfpack_di_free_numeric(&numeric); if (symbolic) umfpack_di_free_symbolic(&symbolic); if (numeric) umfpack_di_free_numeric(&numeric); memcpy(res, x, size*sizeof(double)); delete[] x; if (!dynamic_cast<CSCMatrix*>(mat)) delete Acsc; }
/* Transform the target model like source_ref==>source_deformed, trans->target is modified to deformed model. */ void Transform2TargetMeshModel( const dtMeshModel *source_deformed, dtTransformer *trans) { __dt_BuildRhsConstantVector(source_deformed, &(trans->target), &(trans->sinvlist), &(trans->tcdict), trans->C); __dt_CHOLMOD_Axc(trans->At, trans->C, trans->c); umfpack_di_solve(UMFPACK_A, (const int*)(trans->AtA->p), (const int*)(trans->AtA->i), (const double*)(trans->AtA->x), (double*)(trans->x->x), (const double*)(trans->c->x), trans->numeric_obj, NULL, NULL); __apply_deformation_to_model(&(trans->target), trans->x); }
int main(int argc, char *argv[]) { if (argc < 3) { printf("Not enough parameters.\n"); return -1; } if (readFromBinaryFile(argv[1]) < 0) { return -1; } printf("symbolic analysis\n"); void *symbolic, *numeric; if (umfpack_di_symbolic(ndofs, ndofs, Ap, Ai, Ax, &symbolic, NULL, NULL) < 0) { printf("umfpack_di_symbolic failed\n"); return -1; } if (symbolic == NULL) { printf("umfpack_di_symbolic error: symbolic == NULL\n"); return -1; } printf("numeric analysis\n"); if (umfpack_di_numeric(Ap, Ai, Ax, symbolic, &numeric, NULL, NULL) < 0) { printf("umfpack_di_numeric failed\n"); return -1; } if (numeric == NULL) { printf("umfpack_di_numeric error: numeric == NULL\n"); return -1; } printf("solving\n"); sln = new double [ndofs]; if (umfpack_di_solve(UMFPACK_A, Ap, Ai, Ax, sln, rhs, numeric, NULL, NULL) < 0) { printf("umfpack_di_solve failed\n"); return -1; } umfpack_di_free_symbolic(&symbolic); umfpack_di_free_numeric(&numeric); dump_rhs(argv[2]); printf("done\n"); return 0; }
void UMFPACK(int n, int *Ap, int *Ai, double *Ax, double *b, double *x) { void *Symbolic, *Numeric; int i; /* symbolic analysis */ umfpack_di_symbolic(n, n, Ap, Ai, Ax, &Symbolic, NULL, NULL); /* LU factorization */ umfpack_di_numeric(Ap, Ai, Ax, Symbolic, &Numeric, NULL, NULL); umfpack_di_free_symbolic(&Symbolic); /* solve system */ umfpack_di_solve(UMFPACK_A, Ap, Ai, Ax, x, b, Numeric, NULL, NULL); umfpack_di_free_numeric(&Numeric); }
int UMF::Solve(double *rhs, double *x) { int status; if (!_is_factored) status = Factor(); int NEQN = _dim; double Info[UMFPACK_INFO], Control[UMFPACK_CONTROL]; /* load the rhs only (matrix already there) */ if (x != rhs) memcpy( x, rhs, NEQN*sizeof(double) ); /* deal with transpose later */ status = umfpack_di_solve (UMFPACK_A, &_Ap[0], &_Ai[0], &_Ax[0], x, rhs, _Numeric, Control, Info); return (status); }
int main (void) { double **Y = new_square_matrix(n); Y[0][0] = 1; Y[0][1] = 0; Y[0][2] = 0; Y[1][0] = 0; Y[1][1] = 0.2; Y[1][2] = 1; Y[2][0] = 0; Y[2][1] = 1; Y[2][2] = 0; int nz = count_entry(Y,n); int Ti[nz]; int Tj[nz]; double Tx[nz]; matrix_to_triplet(Ti,Tj,Tx,nz,Y,n); int n_row = n; int n_col = n; int * Ap = new int [n_col+1]; int * Ai = new int [nz]; double * Ax = new double [nz]; int status; double Control [UMFPACK_CONTROL]; umfpack_di_defaults (Control) ; status = umfpack_di_triplet_to_col(n_row, n_col, nz, Ti, Tj, Tx, Ap, Ai, Ax, (int *) NULL); if( status < 0 ) { umfpack_di_report_status (Control, status) ; report_exit("umfpack_zi_triplet_to_col failed\n") ; } double *null = (double *) NULL ; int i ; void *Symbolic, *Numeric ; (void) umfpack_di_symbolic (n, n, Ap, Ai, Ax, &Symbolic, null, null) ; (void) umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, null, null) ; umfpack_di_free_symbolic (&Symbolic) ; (void) umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, v, J, Numeric, null, null) ; umfpack_di_free_numeric (&Numeric) ; for (i = 0 ; i < n ; i++) printf ("v [%d] = %lf\n", i, v[i]) ; delete [] Ap; delete [] Ai; delete [] Ax; return (0) ; }
DllExport int SolveLUUMFPACK(void * sp, double *x, double *b) { UmfpackSolver *umfSolver = (UmfpackSolver*)sp; if (umfSolver->Ai == NULL || umfSolver->Ap == NULL || umfSolver->Ax == NULL) return -1; int *Ap = umfSolver->Ap; int *Ai = umfSolver->Ai; double *Ax = umfSolver->Ax; int n = umfSolver->n; int m = umfSolver->m; double *null = (double *)NULL; //解方程 Ax = b void *Numeric = umfSolver->Numeric; (void)umfpack_di_solve(UMFPACK_A, Ap, Ai, Ax, x, b, Numeric, null, null); return 0; }
void SolveRealByLU_CCS(int numberOfRow, int numberOfColumn, int nnz, int *rowIndices, int *colPtr, double *values, double *X, double *b) { int *Ai = (int*)malloc(sizeof(int)*(nnz)); int *Ap = (int*)malloc(sizeof(int)*(numberOfColumn + 1)); double *Ax = (double*)malloc(sizeof(double)*(nnz)); memcpy(Ax, values, sizeof(double)*nnz); memcpy(Ap, colPtr, sizeof(int)*(numberOfColumn + 1)); memcpy(Ai, rowIndices, sizeof(int)*nnz); void *Symbolic, *Numeric; (void)umfpack_di_symbolic(numberOfRow, numberOfColumn, Ap, Ai, Ax, &Symbolic, NULL, NULL); (void)umfpack_di_numeric(Ap, Ai, Ax, Symbolic, &Numeric, NULL, NULL); umfpack_di_solve(UMFPACK_A, Ap, Ai, Ax, X, b, Numeric, NULL, NULL); umfpack_di_free_numeric(&Numeric); umfpack_di_free_symbolic(&Symbolic); free(Ai); free(Ap); free(Ax); }
//============================================================================= int Amesos_Umfpack::Solve() { // if necessary, perform numeric factorization. // This may call SymbolicFactorization() as well. if (!IsNumericFactorizationOK_) AMESOS_CHK_ERR(NumericFactorization()); ResetTimer(1); Epetra_MultiVector* vecX = Problem_->GetLHS(); Epetra_MultiVector* vecB = Problem_->GetRHS(); if ((vecX == 0) || (vecB == 0)) AMESOS_CHK_ERR(-1); int NumVectors = vecX->NumVectors(); if (NumVectors != vecB->NumVectors()) AMESOS_CHK_ERR(-1); Epetra_MultiVector *SerialB, *SerialX; // Extract Serial versions of X and B // double *SerialXvalues ; double *SerialBvalues ; Epetra_MultiVector* SerialXextract = 0; Epetra_MultiVector* SerialBextract = 0; // Copy B to the serial version of B // ResetTimer(0); if (IsLocal_ == 1) { SerialB = vecB ; SerialX = vecX ; } else { assert (IsLocal_ == 0); SerialXextract = new Epetra_MultiVector(SerialMap(),NumVectors); SerialBextract = new Epetra_MultiVector(SerialMap(),NumVectors); SerialBextract->Import(*vecB,Importer(),Insert); SerialB = SerialBextract; SerialX = SerialXextract; } VecRedistTime_ = AddTime("Total vector redistribution time", VecRedistTime_, 0); // Call UMFPACK to perform the solve // Note: UMFPACK uses a Compressed Column Storage instead of compressed row storage, // Hence to compute A X = B, we ask UMFPACK to perform A^T X = B and vice versa OverheadTime_ = AddTime("Total Amesos overhead time", OverheadTime_, 1); ResetTimer(0); int SerialBlda, SerialXlda ; int UmfpackRequest = UseTranspose()?UMFPACK_A:UMFPACK_At ; int status = 0; if ( MyPID_ == 0 ) { int ierr; ierr = SerialB->ExtractView(&SerialBvalues, &SerialBlda); assert (ierr == 0); ierr = SerialX->ExtractView(&SerialXvalues, &SerialXlda); assert (ierr == 0); assert( SerialBlda == NumGlobalElements_ ) ; assert( SerialXlda == NumGlobalElements_ ) ; for ( int j =0 ; j < NumVectors; j++ ) { double *Control = (double *) NULL, *Info = (double *) NULL ; status = umfpack_di_solve (UmfpackRequest, &Ap[0], &Ai[0], &Aval[0], &SerialXvalues[j*SerialXlda], &SerialBvalues[j*SerialBlda], Numeric, Control, Info) ; } } if (status) AMESOS_CHK_ERR(status); SolveTime_ = AddTime("Total solve time", SolveTime_, 0); // Copy X back to the original vector ResetTimer(0); ResetTimer(1); if ( IsLocal_ == 0 ) { vecX->Export(*SerialX, Importer(), Insert ) ; if (SerialBextract) delete SerialBextract ; if (SerialXextract) delete SerialXextract ; } VecRedistTime_ = AddTime("Total vector redistribution time", VecRedistTime_, 0); if (ComputeTrueResidual_) { Epetra_RowMatrix* Matrix = dynamic_cast<Epetra_RowMatrix*>(Problem_->GetOperator()); ComputeTrueResidual(*Matrix, *vecX, *vecB, UseTranspose(), "Amesos_Umfpack"); } if (ComputeVectorNorms_) { ComputeVectorNorms(*vecX, *vecB, "Amesos_Umfpack"); } NumSolve_++; OverheadTime_ = AddTime("Total Amesos overhead time", OverheadTime_, 1); // Amesos overhead return(0); }
int main ( ) /******************************************************************************/ /* Purpose: MAIN is the main program for UMFPACK_WEST. Discussion: This program uses UMFPACK to solve a linear system A*X=B for which the matrix is stored, in compressed column (CC) format, in three files. Licensing: This code is distributed under the GNU LGPL license. Modified: 16 July 2014 Author: John Burkardt Reference: Timothy Davis, UMFPACK User Guide, Version 5.6.2, 25 April 2013 http://suitesparse.com */ { double *acc; double *b; int *ccc; int i; int *icc; int m; int n; int ncc; double *null = ( double * ) NULL; void *Numeric; char prefix[] = "west"; double r; int seed; int status; void *Symbolic; double *x1; double *x2; timestamp ( ); printf ( "\n" ); printf ( "UMFPACK_WEST:\n" ); printf ( " C version\n" ); printf ( " Use UMFPACK to solve the sparse linear system A*x=b.\n" ); printf ( " The matrix A is stored, in CC format, in 3 files.\n" ); /* Get the matrix size. */ cc_header_read ( prefix, &ncc, &n ); printf ( "\n" ); printf ( " Number of rows and columns = %d\n", n ); printf ( " Number of nonzeros NCC = %d\n", ncc ); /* Allocate space. */ acc = ( double * ) malloc ( ncc * sizeof ( double ) ); ccc = ( int * ) malloc ( ( n + 1 ) * sizeof ( int ) ); icc = ( int * ) malloc ( ncc * sizeof ( int ) ); /* Read the matrix data. */ cc_data_read ( prefix, ncc, n, icc, ccc, acc ); /* Print the matrix. */ m = n; cc_print ( m, n, ncc, icc, ccc, acc, " The CC matrix:" ); /* Set up the solution. */ seed = 123456789; x1 = r8vec_uniform_01_new ( n, &seed ); /* Set the right hand side. */ b = cc_mv ( m, n, ncc, icc, ccc, acc, x1 ); /* From the matrix data, create the symbolic factorization information. */ status = umfpack_di_symbolic ( n, n, ccc, icc, acc, &Symbolic, null, null ); /* From the symbolic factorization information, carry out the numeric factorization. */ status = umfpack_di_numeric ( ccc, icc, acc, Symbolic, &Numeric, null, null ); /* Free the symbolic factorization memory. */ umfpack_di_free_symbolic ( &Symbolic ); /* Using the numeric factorization, solve the linear system. */ x2 = ( double * ) malloc ( n * sizeof ( double ) ); status = umfpack_di_solve ( UMFPACK_A, ccc, icc, acc, x2, b, Numeric, null, null ); /* Free the numeric factorization. */ umfpack_di_free_numeric ( &Numeric ); /* Compute the error: */ r = r8vec_diff_norm ( n, x1, x2 ); printf ( "\n" ); printf ( " Residual: ||A*x-b|| = %g\n", r ); /* Free memory. */ free ( acc ); free ( b ); free ( ccc ); free ( icc ); free ( x1 ); free ( x2 ); /* Terminate. */ printf ( "\n" ); printf ( "UMFPACK_WEST:\n" ); printf ( " Normal end of execution.\n" ); printf ( "\n" ); timestamp ( ); return 0; }
/* This returns an integer identifier that should be unique to your * system. There were problems with UMF mixing up systems becuase it * would identify unique systems just by its size. * * This unique identifier is passed in as system_id. If you're * creating the matrix for the first time, then you should pass in a * -1, otherwise you should pass in the returned value from SL_UMF * when you created your system. * * Note that we don't do this very intelligently. We simply use * indices sequentially. There is no mechanism to allow re-use. */ int SL_UMF ( int system_id, int *first, int *fact_optn, int *matr_form, int *nj, int *nnz_j, int *row, int *col, double *a, double *b, double *x ) { /* Static struct holds all linear systems also keep track of number * of systems we have set up */ static struct UMF_Linear_Solver_System ums_a[UMF_MAX_SYSTEMS]; static int number_systems = 0; double Control[UMFPACK_CONTROL], Info[UMFPACK_INFO]; struct UMF_Linear_Solver_System *ums = 0; /* pointer to current system */ int i, j, k, umf_option = 0; int hit_diag, err; for (i = 0; i < UMFPACK_CONTROL; i++) { Control[i] = 0; } for (i = 0; i < UMFPACK_INFO; i++) { Info[i] = 0; } #ifdef DEBUG_SL_UMF fprintf(stderr, "SL_UMF: system_id = %d, *first = %d, *fact_optn = %d\n", system_id, *first, *fact_optn); #endif /* MEMORY */ switch (*first) { case 1: /* If *first == 1, then we're creating a new matrix. */ /* If system_id isn't -1, then we're probably making some sort of mistake... */ if(system_id != -1) EH(-1, "Entered SL_UMF with *first == 1, but system_id != -1"); /* If we've already gone through all of our slots, get out. */ if(number_systems == UMF_MAX_SYSTEMS) EH(-1, "Already created UMF_MAX_SYSTEMS systems"); system_id = number_systems; ums = &ums_a[number_systems++]; ums->n = *nj; ums->nnz = *nnz_j; /* MATRIX VECTORS */ ums->ap = Ivector_birth(ums->n + 1); ums->ai = Ivector_birth(ums->nnz); ums->ax = Dvector_birth(ums->nnz); /* MSR needs extra allocation for A-transpose */ ums->atp = NULL; ums->ati = NULL; ums->atx = NULL; if ( *matr_form == 1 ) { ums->atp = Ivector_birth(ums->n + 1); ums->ati = Ivector_birth(ums->nnz); ums->atx = Dvector_birth(ums->nnz); } break; case 0: /* If *first == 0, then we want to just reuse a previously created * system. */ /* system_id should have the appropriate identifier. */ if(system_id == -1) EH(-1, "Conflicting orders: system_id == -1 and *first != 1"); if(system_id < 0 || system_id >= UMF_MAX_SYSTEMS) EH(-1, "Index out of range: system_id"); /* Grab the hopeful system. */ ums = &ums_a[system_id]; /* Run through some sanity checks to help ensure we're dealing * with the correct system. */ if(ums->n != *nj || ums->nnz != *nnz_j) EH(-1, "Tried to access a bad system"); break; case -1: /* If *first == -1, then we want to free space. */ /* system_id should have the appropriate identifier. */ if(system_id == -1) EH(-1, "Conflicting orders: system_id == -1 and *first != 1"); if(system_id < 0 || system_id >= UMF_MAX_SYSTEMS) EH(-1, "Index out of range: system_id"); ums = &ums_a[system_id]; /* Run through some sanity checks to help ensure we're dealing * with the correct system. */ if(ums->n != *nj || ums->nnz != *nnz_j) EH(-1, "Tried to free a bad system"); umfpack_di_free_symbolic(&ums->symbolic); ums->symbolic = NULL; umfpack_di_free_numeric(&ums->numeric); ums->numeric = NULL; Ivector_death(ums->ap, ums->n + 1); Ivector_death(ums->ai, ums->nnz); Dvector_death(ums->ax, ums->nnz); if ( ums->atp != NULL ) { Ivector_death(ums->atp, ums->n + 1); Ivector_death(ums->ati, ums->nnz); Dvector_death(ums->atx, ums->nnz); } /* MMH: The fix that changed the world... */ ums->n = 0; ums->nnz = 0; /* So things break later in case we actually use the return value * after deallocating space. */ system_id = -1; break; } /* CONVERT MSR FORMAT TO MATLAB FORMAT IF NEEDED */ if (abs(*fact_optn) < 3) { switch (*matr_form) { case 0: /* COORDINATE FORMAT */ umfpack_di_triplet_to_col( ums->n, ums->n, ums->nnz, row, col, a, ums->ap, ums->ai, ums->ax, NULL ); break; case 1: /* MSR FORMAT */ /* Note: MSR is row-oriented and UMF wants column-oriented data. So, assemble A-transpose in UMF format, and use umf utility to get back A in UMF format. Note also that UMF can operate directly on A-transpose. This can save having to make another copy of the matrix, but it limited experiments, I found it to be slower. -DRN To form A-transpose in UMF format, merge the diagonal entries back into the rows. */ k = 0; for (i=0;i<ums->n;i++) { /* loop over rows */ ums->atp[i] = k; hit_diag = FALSE; for (j=col[i];j<col[i+1];j++) { /* loop over colums within row */ /* if we get to the spot where the diagonal term belongs, merge it in */ if (!hit_diag && col[j] > i ) { ums->ati[k] = i; ums->atx[k] = a[i]; k++; hit_diag = TRUE; } ums->ati[k] = col[j]; ums->atx[k] = a[j]; k++; } /* if we never got to the diagonal, merge it in now */ if (!hit_diag) { ums->ati[k] = i; ums->atx[k] = a[i]; k++; hit_diag = TRUE; } } ums->atp[ums->n] = ums->nnz; if (ums->nnz != k) { DPRINTF(stderr, "E: NNZ=%12d CT=%12d\n", ums->nnz, k); exit(0); } /* transpose matrix */ err = umfpack_di_transpose (ums->n, ums->n, ums->atp, ums->ati, ums->atx, (int *) NULL, (int *) NULL, ums->ap, ums->ai, ums->ax); if ( err != UMFPACK_OK ) { fprintf(stderr,"UMFPACK error = %d\n",err); EH(-1,"Error computing matrix transpose using umfpack_di_transpose\n"); } break; case 2: /* CSR FORMAT - NOT DONE YET */ EH(-1, "Sorry, cannot convert CSR systems"); break; } /* SET OPTIONS */ switch (*fact_optn) { case -2: /* FULL ANALYSIS AND FACTORIZATION */ umf_option = 1; break; case -1: /* FACTORIZATION WITH PAST ANALYSIS */ umf_option = 0; break; case 0: /* FULL ANALYSIS AND FACTORIZATION */ umf_option = 1; break; case 1: /* FACTORIZATION WITH PAST ANALYSIS */ umf_option = 0; break; case 3: umf_option = 0; break; default: EH(-1, "Bad *fact_optn"); } /* load default control parameters for UMF */ umfpack_di_defaults( Control ); /* optionally can ask for feedback from routines by uncommenting below */ /*Control[UMFPACK_PRL] = 2.;*/ /* optionally force solution strategy */ Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_UNSYMMETRIC; if ( umf_option == 1 ) { /* analysis */ if ( ums->symbolic != NULL ) { umfpack_di_free_symbolic(&ums->symbolic); ums->symbolic = NULL; } err = umfpack_di_symbolic( ums->n, ums->n, ums->ap, ums->ai, ums->ax, &ums->symbolic, Control, Info ); umfpack_di_report_status(Control, err); umfpack_di_report_info(Control, Info); } /* factorization */ if ( ums->numeric != NULL ) { umfpack_di_free_numeric(&ums->numeric); ums->numeric = NULL; } err = umfpack_di_numeric( ums->ap, ums->ai, ums->ax, ums->symbolic, &ums->numeric, Control, Info ); umfpack_di_report_status(Control, err); umfpack_di_report_info(Control, Info); } /* solve */ if ( *fact_optn >= 0 ) { err = umfpack_di_solve( UMFPACK_A, ums->ap, ums->ai, ums->ax, x, b, ums->numeric, Control, Info ); umfpack_di_report_status(Control, err); umfpack_di_report_info(Control, Info); } return system_id; } /* END of routine SL_UMF */
std::vector<double> solveQ(std::vector<std::vector<double>> const &cols, std::vector<Vertex> const & fixed_cells, std::vector<Vertex> const * virtual_cells) { //assert N x N dim of cols matrix assert(cols.size() == cols.at(0).size()); int m_dim = cols.size(); std::vector<double> retval; retval.resize(2*m_dim); double * X = new double[m_dim](); double * Y = new double[m_dim](); double * Bx = new double[m_dim](); double * By = new double[m_dim](); //construct rhs vectors - Bx, By for (unsigned int i=0; i < fixed_cells.size(); ++i) { std::list<Edge> const & adj_cells = fixed_cells.at(i).adj_list; for(auto it = adj_cells.begin(); it != adj_cells.end(); ++it) { if ((*it).tgt->fixed) continue; int idx = Vertex::v_map_table.at((*it).tgt->v_id - 1); assert(idx < m_dim && idx >= 0); Bx[idx] += (*it).weight * (double)fixed_cells.at(i).x_pos; By[idx] += (*it).weight * (double)fixed_cells.at(i).y_pos; } } //add weight contributions from virtual pins if (virtual_cells != nullptr) { for (unsigned int i=0; i < (*virtual_cells).size(); ++i) { std::list<Edge> const & adj_cells = (*virtual_cells).at(i).adj_list; for(auto it = adj_cells.begin(); it != adj_cells.end(); ++it) { if ((*it).tgt->fixed) continue; int idx = Vertex::v_map_table.at((*it).tgt->v_id - 1); assert(idx < m_dim && idx >= 0); Bx[idx] += (*it).weight * (double)(*virtual_cells).at(i).x_pos; By[idx] += (*it).weight * (double)(*virtual_cells).at(i).y_pos; } } } //UMFPACK sparse matrix solver arguments int * Ap = new int[m_dim+1]; int * Ai; double * Ax; Ap[0] = 0; int nz_cnt = 0; for (int c=0; c<m_dim; ++c) { for(int r=0; r<m_dim; ++r) { if (cols[c][r] != 0) ++nz_cnt; } Ap[c+1] = nz_cnt; } Ai = new int[nz_cnt]; Ax = new double[nz_cnt]; int idx = 0; for (int c=0; c<m_dim; ++c) { for(int r=0; r<m_dim; ++r) { if (cols[c][r] != 0) { Ai[idx] = r; Ax[idx] = cols[c][r]; ++idx; } } } #ifdef _DEBUG_ std::cout << "Bx: "; for(int i =0; i<m_dim; ++i) { std::cout << Bx[i] << " "; } std::cout << "\n"; std::cout << "By: "; for(int i =0; i<m_dim; ++i) { std::cout << Bx[i] << " "; } std::cout << "\n"; std::cout << "Ap: "; for(int i =0; i<m_dim+1; ++i) { std::cout << Ap[i] << " "; } std::cout << "\n"; std::cout << "Ai: "; for(int i =0; i<nz_cnt; ++i) { std::cout << Ai[i] << " "; } std::cout << "\n"; std::cout << "Ax: "; for(int i =0; i<nz_cnt; ++i) { std::cout << Ax[i] << " "; } std::cout << "\n"; #endif double *null = (double *) NULL; void *Symbolic, *Numeric; (void) umfpack_di_symbolic (m_dim, m_dim, Ap, Ai, Ax, &Symbolic, null, null); (void) umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, null, null); umfpack_di_free_symbolic(&Symbolic); (void) umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, X, Bx, Numeric, null, null); (void) umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, Y, By, Numeric, null, null); umfpack_di_free_numeric(&Numeric); //push X, Y into return vector for(int i=0; i<m_dim; ++i) { retval[i] = X[i]; retval[i+m_dim] = Y[i]; } delete [] X; delete [] Y; delete [] Bx; delete [] By; delete [] Ap; delete [] Ai; delete [] Ax; return retval; }
int main (int argc, char **argv) { int i, j, k, n, nz, *Ap, *Ai, *Ti, *Tj, status, *Pamd, nrow, ncol, rhs ; double *Ax, *b, *x, Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], aij, *Tx, *r, amd_Control [AMD_CONTROL], amd_Info [AMD_INFO], tamd [2], stats [2], droptol ; void *Symbolic, *Numeric ; FILE *f, *f2 ; char s [SMAX] ; /* ---------------------------------------------------------------------- */ /* set controls */ /* ---------------------------------------------------------------------- */ printf ("\n===========================================================\n" "=== UMFPACK v%d.%d.%d ========================================\n" "===========================================================\n", UMFPACK_MAIN_VERSION, UMFPACK_SUB_VERSION, UMFPACK_SUBSUB_VERSION) ; umfpack_di_defaults (Control) ; Control [UMFPACK_PRL] = 3 ; Control [UMFPACK_BLOCK_SIZE] = 32 ; f = fopen ("tmp/control.umf4", "r") ; if (f != (FILE *) NULL) { printf ("Reading control file tmp/control.umf4\n") ; for (i = 0 ; i < UMFPACK_CONTROL ; i++) { fscanf (f, "%lg\n", & Control [i]) ; } fclose (f) ; } if (argc > 1) { char *t = argv [1] ; /* get the strategy */ if (t [0] == 'u') { Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_UNSYMMETRIC ; } else if (t [0] == 'a') { Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_AUTO ; } else if (t [0] == 's') { Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_SYMMETRIC ; } else if (t [0] == '2') { printf ("unrecognized strategy: %s\n", argv [1]) ; } else if (t [0] == 'U') { Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_UNSYMMETRIC ; Control [UMFPACK_SCALE] = UMFPACK_SCALE_MAX ; } else if (t [0] == 'A') { Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_AUTO ; Control [UMFPACK_SCALE] = UMFPACK_SCALE_MAX ; } else if (t [0] == 'S') { Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_SYMMETRIC ; Control [UMFPACK_SCALE] = UMFPACK_SCALE_MAX ; } else if (t [0] == 'T') { printf ("unrecognized strategy: %s\n", argv [1]) ; } else { printf ("unrecognized strategy: %s\n", argv [1]) ; } if (t [1] == 'n') { /* no aggressive absorption */ Control [UMFPACK_AGGRESSIVE] = FALSE ; } } if (argc > 2) { /* get the drop tolerance */ sscanf (argv [2], "%lg", &droptol) ; printf ("droptol %g\n", droptol) ; Control [UMFPACK_DROPTOL] = droptol ; } umfpack_di_report_control (Control) ; /* ---------------------------------------------------------------------- */ /* open the matrix file (tmp/A) */ /* ---------------------------------------------------------------------- */ printf ("File: tmp/A\n") ; f = fopen ("tmp/A", "r") ; if (!f) { printf ("Unable to open file\n") ; exit (1) ; } /* ---------------------------------------------------------------------- */ /* get n and nz */ /* ---------------------------------------------------------------------- */ printf ("File: tmp/Asize\n") ; f2 = fopen ("tmp/Asize", "r") ; if (f2) { fscanf (f2, "%d %d %d\n", &nrow, &ncol, &nz) ; fclose (f2) ; } else { nrow = 1 ; ncol = 1 ; } nz = 0 ; while (fgets (s, SMAX, f) != (char *) NULL) { sscanf (s, "%d %d %lg", &i, &j, &aij) ; #ifdef ZERO_BASED /* matrix is zero based */ i++ ; j++ ; #endif nrow = MAX (nrow, i) ; ncol = MAX (ncol, j) ; nz++ ; } fclose (f) ; n = MAX (nrow, ncol) ; printf ("n %d nrow %d ncol %d nz %d\n", n, nrow, ncol, nz) ; /* ---------------------------------------------------------------------- */ /* allocate space for the input triplet form */ /* ---------------------------------------------------------------------- */ Ti = (int *) malloc (nz * sizeof (int)) ; Tj = (int *) malloc (nz * sizeof (int)) ; Tx = (double *) malloc (nz * sizeof (double)) ; if (!Ti || !Tj || !Tx) { printf ("out of memory for input matrix\n") ; exit (1) ; } /* ---------------------------------------------------------------------- */ /* read in the triplet form */ /* ---------------------------------------------------------------------- */ f2 = fopen ("tmp/A", "r") ; if (!f2) { printf ("Unable to open file\n") ; exit (1) ; } k = 0 ; while (fgets (s, SMAX, f2) != (char *) NULL) { sscanf (s, "%d %d %lg", &i, &j, &aij) ; #ifndef ZERO_BASED i-- ; /* convert to 0-based */ j-- ; #endif if (k >= nz) { printf ("Error! Matrix size is wrong\n") ; exit (1) ; } Ti [k] = i ; Tj [k] = j ; Tx [k] = aij ; k++ ; } fclose (f2) ; (void) umfpack_di_report_triplet (nrow, ncol, nz, Ti, Tj, Tx, Control) ; /* ---------------------------------------------------------------------- */ /* convert to column form */ /* ---------------------------------------------------------------------- */ /* convert to column form */ Ap = (int *) malloc ((n+1) * sizeof (int)) ; Ai = (int *) malloc (nz * sizeof (int)) ; Ax = (double *) malloc (nz * sizeof (double)) ; b = (double *) malloc (n * sizeof (double)) ; r = (double *) malloc (n * sizeof (double)) ; x = (double *) malloc (n * sizeof (double)) ; if (!Ap || !Ai || !Ax || !b || !r) { printf ("out of memory") ; exit (1) ; } umfpack_tic (stats) ; status = umfpack_di_triplet_to_col (nrow, ncol, nz, Ti, Tj, Tx, Ap, Ai, Ax, (int *) NULL) ; umfpack_toc (stats) ; printf ("triplet-to-col time: wall %g cpu %g\n", stats [0], stats [1]) ; if (status != UMFPACK_OK) { umfpack_di_report_status (Control, status) ; printf ("umfpack_di_triplet_to_col failed") ; exit (1) ; } /* print the column-form of A */ (void) umfpack_di_report_matrix (nrow, ncol, Ap, Ai, Ax, 1, Control) ; /* b = A * xtrue */ rhs = FALSE ; if (nrow == ncol) { f = fopen ("tmp/b", "r") ; if (f != (FILE *) NULL) { printf ("Reading tmp/b\n") ; rhs = TRUE ; for (i = 0 ; i < n ; i++) { fscanf (f, "%lg\n", &b [i]) ; } fclose (f) ; } else { Atimesx (n, Ap, Ai, Ax, b, FALSE) ; } } /* ---------------------------------------------------------------------- */ /* free the triplet form */ /* ---------------------------------------------------------------------- */ free (Ti) ; free (Tj) ; free (Tx) ; /* ---------------------------------------------------------------------- */ /* symbolic factorization */ /* ---------------------------------------------------------------------- */ status = umfpack_di_symbolic (nrow, ncol, Ap, Ai, Ax, &Symbolic, Control, Info) ; umfpack_di_report_info (Control, Info) ; if (status != UMFPACK_OK) { umfpack_di_report_status (Control, status) ; printf ("umfpack_di_symbolic failed") ; exit (1) ; } /* print the symbolic factorization */ (void) umfpack_di_report_symbolic (Symbolic, Control) ; /* ---------------------------------------------------------------------- */ /* numeric factorization */ /* ---------------------------------------------------------------------- */ status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, Control, Info); if (status < UMFPACK_OK) { umfpack_di_report_info (Control, Info) ; umfpack_di_report_status (Control, status) ; fprintf (stderr, "umfpack_di_numeric failed: %d\n", status) ; printf ("umfpack_di_numeric failed\n") ; exit (1) ; } /* print the numeric factorization */ (void) umfpack_di_report_numeric (Numeric, Control) ; /* ---------------------------------------------------------------------- */ /* solve Ax=b */ /* ---------------------------------------------------------------------- */ if (nrow == ncol && status == UMFPACK_OK) { status = umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, x, b, Numeric, Control, Info) ; umfpack_di_report_info (Control, Info) ; umfpack_di_report_status (Control, status) ; if (status < UMFPACK_OK) { printf ("umfpack_di_solve failed\n") ; exit (1) ; } (void) umfpack_di_report_vector (n, x, Control) ; printf ("relative maxnorm of residual, ||Ax-b||/||b||: %g\n", resid (n, Ap, Ai, Ax, x, r, b, FALSE)) ; if (!rhs) { printf ("relative maxnorm of error, ||x-xtrue||/||xtrue||: %g\n\n", err (n, x)) ; } f = fopen ("tmp/x", "w") ; if (f != (FILE *) NULL) { printf ("Writing tmp/x\n") ; for (i = 0 ; i < n ; i++) { fprintf (f, "%30.20e\n", x [i]) ; } fclose (f) ; } else { printf ("Unable to write output x!\n") ; exit (1) ; } f = fopen ("tmp/info.umf4", "w") ; if (f != (FILE *) NULL) { printf ("Writing tmp/info.umf4\n") ; for (i = 0 ; i < UMFPACK_INFO ; i++) { fprintf (f, "%30.20e\n", Info [i]) ; } fclose (f) ; } else { printf ("Unable to write output info!\n") ; exit (1) ; } } else { /* don't solve, just report the results */ umfpack_di_report_info (Control, Info) ; umfpack_di_report_status (Control, status) ; } /* ---------------------------------------------------------------------- */ /* free the Symbolic and Numeric factorization */ /* ---------------------------------------------------------------------- */ umfpack_di_free_symbolic (&Symbolic) ; umfpack_di_free_numeric (&Numeric) ; printf ("umf4 done, strategy: %g\n", Control [UMFPACK_STRATEGY]) ; /* ---------------------------------------------------------------------- */ /* test just AMD ordering (not part of UMFPACK, but a separate test) */ /* ---------------------------------------------------------------------- */ /* first make the matrix square */ if (ncol < n) { for (j = ncol+1 ; j <= n ; j++) { Ap [j] = Ap [ncol] ; } } printf ( "\n\n===========================================================\n" "=== AMD ===================================================\n" "===========================================================\n") ; printf ("\n\n------- Now trying the AMD ordering. This not part of\n" "the UMFPACK analysis or factorization, above, but a separate\n" "test of just the AMD ordering routine.\n") ; Pamd = (int *) malloc (n * sizeof (int)) ; if (!Pamd) { printf ("out of memory\n") ; exit (1) ; } amd_defaults (amd_Control) ; amd_control (amd_Control) ; umfpack_tic (tamd) ; status = amd_order (n, Ap, Ai, Pamd, amd_Control, amd_Info) ; umfpack_toc (tamd) ; printf ("AMD ordering time: cpu %10.2f wall %10.2f\n", tamd [1], tamd [0]) ; if (status != AMD_OK) { printf ("amd failed: %d\n", status) ; exit (1) ; } amd_info (amd_Info) ; free (Pamd) ; printf ("AMD test done\n") ; free (Ap) ; free (Ai) ; free (Ax) ; free (b) ; free (r) ; free (x) ; return (0) ; }
/*! \fn solve linear system with UmfPack method * * \param [in] [data] * [sysNumber] index of the corresponding linear system * * * author: kbalzereit, wbraun */ int solveUmfPack(DATA *data, int sysNumber) { LINEAR_SYSTEM_DATA* systemData = &(data->simulationInfo.linearSystemData[sysNumber]); DATA_UMFPACK* solverData = (DATA_UMFPACK*)systemData->solverData; int i, j, status = UMFPACK_OK, success = 0, ni=0, n = systemData->size, eqSystemNumber = systemData->equationIndex, indexes[2] = {1,eqSystemNumber}; infoStreamPrintWithEquationIndexes(LOG_LS, 0, indexes, "Start solving Linear System %d (size %d) at time %g with UMFPACK Solver", eqSystemNumber, (int) systemData->size, data->localData[0]->timeValue); rt_ext_tp_tick(&(solverData->timeClock)); if (0 == systemData->method) { /* set A matrix */ solverData->Ap[0] = 0; systemData->setA(data, systemData); solverData->Ap[solverData->n_row] = solverData->nnz; if (ACTIVE_STREAM(LOG_LS_V)) { infoStreamPrint(LOG_LS_V, 1, "Matrix A"); printMatrixCSR(solverData->Ap, solverData->Ai, solverData->Ax, n); messageClose(LOG_LS_V); } /* set b vector */ systemData->setb(data, systemData); } else { solverData->Ap[0] = 0; /* calculate jacobian -> matrix A*/ if(systemData->jacobianIndex != -1) { getAnalyticalJacobianUmfPack(data, sysNumber); } else { assertStreamPrint(data->threadData, 1, "jacobian function pointer is invalid" ); } solverData->Ap[solverData->n_row] = solverData->nnz; /* calculate vector b (rhs) */ memcpy(solverData->work, systemData->x, sizeof(double)*solverData->n_row); wrapper_fvec_umfpack(solverData->work, systemData->b, data, sysNumber); } infoStreamPrint(LOG_LS, 0, "### %f time to set Matrix A and vector b.", rt_ext_tp_tock(&(solverData->timeClock))); if (ACTIVE_STREAM(LOG_LS_V)) { if (ACTIVE_STREAM(LOG_LS_V)) { infoStreamPrint(LOG_LS_V, 1, "Old solution x:"); for(i = 0; i < solverData->n_row; ++i) infoStreamPrint(LOG_LS_V, 0, "[%d] %s = %g", i+1, modelInfoGetEquation(&data->modelData.modelDataXml,eqSystemNumber).vars[i], systemData->x[i]); messageClose(LOG_LS_V); } infoStreamPrint(LOG_LS_V, 1, "Matrix A n_rows = %d", solverData->n_row); for (i=0; i<solverData->n_row; i++) { infoStreamPrint(LOG_LS_V, 0, "%d. Ap => %d -> %d", i, solverData->Ap[i], solverData->Ap[i+1]); for (j=solverData->Ap[i]; j<solverData->Ap[i+1]; j++) { infoStreamPrint(LOG_LS_V, 0, "A[%d,%d] = %f", i, solverData->Ai[j], solverData->Ax[j]); } } messageClose(LOG_LS_V); for (i=0; i<solverData->n_row; i++) infoStreamPrint(LOG_LS_V, 0, "b[%d] = %e", i, systemData->b[i]); } rt_ext_tp_tick(&(solverData->timeClock)); /* symbolic pre-ordering of A to reduce fill-in of L and U */ if (0 == solverData->numberSolving) { status = umfpack_di_symbolic(solverData->n_col, solverData->n_row, solverData->Ap, solverData->Ai, solverData->Ax, &(solverData->symbolic), solverData->control, solverData->info); } /* compute the LU factorization of A */ if (0 == status) { status = umfpack_di_numeric(solverData->Ap, solverData->Ai, solverData->Ax, solverData->symbolic, &(solverData->numeric), solverData->control, solverData->info); } if (0 == status) { if (1 == systemData->method) { status = umfpack_di_solve(UMFPACK_A, solverData->Ap, solverData->Ai, solverData->Ax, systemData->x, systemData->b, solverData->numeric, solverData->control, solverData->info); } else { status = umfpack_di_solve(UMFPACK_Aat, solverData->Ap, solverData->Ai, solverData->Ax, systemData->x, systemData->b, solverData->numeric, solverData->control, solverData->info); } } if (status == UMFPACK_OK) { success = 1; } else if (status == UMFPACK_WARNING_singular_matrix) { if (!solveSingularSystem(systemData)) { success = 1; } } infoStreamPrint(LOG_LS, 0, "Solve System: %f", rt_ext_tp_tock(&(solverData->timeClock))); /* print solution */ if (1 == success) { if (1 == systemData->method) { /* take the solution */ for(i = 0; i < solverData->n_row; ++i) systemData->x[i] += solverData->work[i]; /* update inner equations */ wrapper_fvec_umfpack(systemData->x, solverData->work, data, sysNumber); } else { /* the solution is automatically in x */ } if (ACTIVE_STREAM(LOG_LS_V)) { infoStreamPrint(LOG_LS_V, 1, "Solution x:"); infoStreamPrint(LOG_LS_V, 0, "System %d numVars %d.", eqSystemNumber, modelInfoGetEquation(&data->modelData.modelDataXml,eqSystemNumber).numVar); for(i = 0; i < systemData->size; ++i) infoStreamPrint(LOG_LS_V, 0, "[%d] %s = %g", i+1, modelInfoGetEquation(&data->modelData.modelDataXml,eqSystemNumber).vars[i], systemData->x[i]); messageClose(LOG_LS_V); } } else { warningStreamPrint(LOG_STDOUT, 0, "Failed to solve linear system of equations (no. %d) at time %f, system status %d.", (int)systemData->equationIndex, data->localData[0]->timeValue, status); } solverData->numberSolving += 1; return success; }
int umfpack_solver(struct simulation *sim,int col,int nz,int *Ti,int *Tj, long double *lTx,long double *lb) { int i; void *Symbolic, *Numeric; int status; double *dtemp; int *itemp; if ((sim->last_col!=col)||(sim->last_nz!=nz)) { dtemp = realloc(sim->x,col*sizeof(double)); if (dtemp==NULL) { ewe(sim,"realloc failed\n"); }else { sim->x=dtemp; } dtemp = realloc(sim->b,col*sizeof(double)); if (dtemp==NULL) { ewe(sim,"realloc failed\n"); }else { sim->b=dtemp; } itemp = realloc(sim->Ap,(col+1)*sizeof(int)); if (itemp==NULL) { ewe(sim,"realloc failed\n"); }else { sim->Ap=itemp; } itemp = realloc(sim->Ai,(nz)*sizeof(int)); if (itemp==NULL) { ewe(sim,"realloc failed\n"); }else { sim->Ai=itemp; } dtemp = realloc(sim->Ax,(nz)*sizeof(double)); if (dtemp==NULL) { ewe(sim,"realloc failed\n"); }else { sim->Ax=dtemp; } dtemp = realloc(sim->Tx,(nz)*sizeof(double)); if (dtemp==NULL) { ewe(sim,"realloc failed\n"); }else { sim->Tx=dtemp; } sim->last_col=col; sim->last_nz=nz; } for (i=0;i<col;i++) { sim->b[i]=(double)lb[i]; } for (i=0;i<nz;i++) { sim->Tx[i]=(double)lTx[i]; } double Control [UMFPACK_CONTROL],Info [UMFPACK_INFO]; umfpack_di_defaults (Control) ; Control[UMFPACK_BLOCK_SIZE]=20; //Control [UMFPACK_STRATEGY]=UMFPACK_STRATEGY_SYMMETRIC;//UMFPACK_STRATEGY_UNSYMMETRIC; //Control [UMFPACK_ORDERING]=UMFPACK_ORDERING_BEST;//UMFPACK_ORDERING_AMD;//UMFPACK_ORDERING_BEST;// //printf("%lf\n",Control[UMFPACK_BLOCK_SIZE]); //Control [UMFPACK_PIVOT_TOLERANCE]=0.0001; //Control[UMFPACK_SINGLETONS]=1; //Control[UMFPACK_SCALE]=3; status = umfpack_di_triplet_to_col(col, col, nz, Ti, Tj, sim->Tx, sim->Ap, sim->Ai, sim->Ax, NULL); //printf("rod1\n"); //getchar(); if (status != UMFPACK_OK) { error_report(status, __FILE__, __func__, __LINE__); return EXIT_FAILURE; } // symbolic analysis //printf("here2 %d\n",col); status = umfpack_di_symbolic(col, col, sim->Ap, sim->Ai, sim->Ax, &Symbolic, Control, Info); //printf("rod2\n"); //getchar(); //printf("here3\n"); if (status != UMFPACK_OK) { error_report(status, __FILE__, __func__, __LINE__); return EXIT_FAILURE; } // LU factorization umfpack_di_numeric(sim->Ap, sim->Ai, sim->Ax, Symbolic, &Numeric, Control, Info); //printf("rod5\n"); //getchar(); if (status != UMFPACK_OK) { error_report(status, __FILE__, __func__, __LINE__); return EXIT_FAILURE; } // solve system umfpack_di_free_symbolic(&Symbolic); //printf("rod a\n"); //getchar(); umfpack_di_solve(UMFPACK_A, sim->Ap, sim->Ai, sim->Ax, sim->x, sim->b, Numeric, Control, Info); //printf("rod b\n"); //getchar(); //printf("%lf\n",Info [UMFPACK_ORDERING_USED]); if (status != UMFPACK_OK) { error_report(status, __FILE__, __func__, __LINE__); return EXIT_FAILURE; } umfpack_di_free_numeric(&Numeric); //printf("rod\n"); //getchar(); for (i=0;i<col;i++) { lb[i]=(long double)sim->x[i]; } //memcpy(b, x, col*sizeof(double)); //umfpack_toc(stats); return 0; }
void solve_linear_system(const int_vector& lhs_row_index, const int_vector& lhs_col_index, const dbl_vector& lhs_values, dbl_vector rhs, dbl_vector& out_solution, void* numeric) { // Assume lhs is square. unsigned long num_nonzero = lhs_values.size(); unsigned long num_rows = rhs.size(); // Convert lhs matrix into the format used in UMFPACK. int* ti; int* tj; double* tx; int* ap; int* ai; double* ax; double* x; double* b; ti = new int[num_nonzero]; ELOG("ti memory allocated..."); tj = new int[num_nonzero]; ELOG("tj memory allocated..."); tx = new double[num_nonzero]; ELOG("tx memory allocated..."); // Copy to input data. for(unsigned long i = 0; i < num_nonzero; i++) { ti[i] = lhs_row_index(i); tj[i] = lhs_col_index(i); tx[i] = lhs_values(i); ELOG("ti, tj, tx (", i, ") = ", ti[i], ", ", tj[i], ", ", tx[i], ", "); } ap = new int[num_rows + 1]; ELOG("ap memory allocated..."); ai = new int[num_rows * num_rows]; ELOG("ai memory allocated..."); ax = new double[num_rows * num_rows]; ELOG("ax memory allocated..."); umfpack_di_triplet_to_col(num_rows, num_rows, num_nonzero, ti, tj, tx, ap, ai, ax, null_int); delete [] ti; delete [] tj; delete [] tx; x = new double[num_rows]; ELOG("x memory allocated..."); b = new double[num_rows]; ELOG("b memory allocated..."); ELOG("Define right hand side..."); // Set right hand side equal to portfolio. for(unsigned long i = 0; i < num_rows; ++i) b[i] = rhs(i); ELOG("Rhs to solve = ", rhs); #ifdef DEBUG for(unsigned long i = 0; i < num_rows + 1; ++i) ELOG("ap[", i, "] = ", ap[i]); for(unsigned long i_row = 0; i_row < num_rows; ++i_row) { for(unsigned long i_col = 0; i_col < num_rows; ++i_col) { ELOG("A(", i_row, ",", i_col, ") = ", ax[ap[i_col] + i_row]); } ELOG("b(", i_row, ") = ", b[i_row]); } #endif // Sovle system by LU factorization. void *symbolic; // If the numeric pointer is void then we need to perform the // factorization. if(numeric == null_void) { umfpack_di_symbolic(num_rows, num_rows, ap, ai, ax, &symbolic, null_double, null_double); umfpack_di_numeric(ap, ai, ax, symbolic, &numeric, null_double, null_double); umfpack_di_free_symbolic(&symbolic); } umfpack_di_solve(UMFPACK_A, ap, ai, ax, x, b, numeric, null_double, null_double); #ifdef DEBUG // Calculate determinant for diagnostics. double *det = new double[2]; umfpack_di_get_determinant(det, null_double, numeric, null_double); ELOG("Determinant of second moment = ", det[0]); delete[] det; #endif // Do not free the numeric pointer because this function does not own it. // Store the solution in the output argument. for(unsigned long i = 0; i < num_rows; ++i) out_solution(i) = x[i]; // Free memory. delete[] ap; delete[] ai; delete[] ax; delete[] x; delete[] b; }
/*! \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; }
dbl_vector solve_linear_system(dbl_matrix lhs, dbl_vector rhs) { // Assume lhs is square. unsigned long num_rows = lhs.size1(); // Convert lhs matrix into the format used in UMFPACK. int* ap; int* ai; double* ax; double* x; double* b; ap = new int[num_rows + 1]; ELOG("ap memory allocated..."); ai = new int[num_rows * num_rows]; ELOG("ai memory allocated..."); ax = new double[num_rows * num_rows]; ELOG("ax memory allocated..."); x = new double[num_rows]; ELOG("x memory allocated..."); b = new double[num_rows]; ELOG("b memory allocated..."); ap[0] = 0; for(unsigned long i_col = 1; i_col < num_rows + 1; ++i_col) { ap[i_col] = num_rows * i_col; ELOG("ap[", i_col, "] = ", ap[i_col]); for(unsigned long i_row = 0; i_row < num_rows; ++i_row) { ai[ap[i_col-1] + i_row] = i_row; ax[ap[i_col-1] + i_row] = lhs(i_row, i_col - 1); } } ELOG("Define right hand side..."); // Set right hand side equal to portfolio. for(unsigned long i = 0; i < num_rows; ++i) b[i] = rhs(i); ELOG("Rhs to solve = ", rhs); #ifdef DEBUG for(unsigned long i = 0; i < num_rows + 1; ++i) ELOG("ap[", i, "] = ", ap[i]); for(unsigned long i_row = 0; i_row < num_rows; ++i_row) { for(unsigned long i_col = 0; i_col < num_rows; ++i_col) { ELOG("A(", i_row, ",", i_col, ") = ", ax[ap[i_col] + i_row]); } ELOG("b(", i_row, ") = ", b[i_row]); } #endif // Multiply inverted matrix and the transformed first_moment via lu // factorization and substitution. void *symbolic, *numeric; umfpack_di_symbolic(num_rows, num_rows, ap, ai, ax, &symbolic, null_double, null_double); umfpack_di_numeric(ap, ai, ax, symbolic, &numeric, null_double, null_double); umfpack_di_free_symbolic(&symbolic); umfpack_di_solve(UMFPACK_A, ap, ai, ax, x, b, numeric, null_double, null_double); #ifdef DEBUG // Calculate determinant for diagnostics. double *det = new double[2]; umfpack_di_get_determinant(det, null_double, numeric, null_double); ELOG("Determinant of second moment = ", det[0]); delete[] det; #endif umfpack_di_free_numeric(&numeric); // Store solution in rhs. for(unsigned long i = 0; i < num_rows; ++i) rhs(i) = x[i]; // Free memory. delete[] ap; delete[] ai; delete[] ax; delete[] x; delete[] b; return rhs; }