/*! \fn allocate memory for linear system solver UmfPack * */ int allocateUmfPackData(int n_row, int n_col, int nz, void** voiddata) { DATA_UMFPACK* data = (DATA_UMFPACK*) malloc(sizeof(DATA_UMFPACK)); assertStreamPrint(NULL, 0 != data, "Could not allocate data for linear solver UmfPack."); data->symbolic = NULL; data->numeric = NULL; data->n_col = n_col; data->n_row = n_row; data->nnz = nz; data->Ap = (int*) calloc((n_row+1),sizeof(int)); data->Ai = (int*) calloc(nz,sizeof(int)); data->Ax = (double*) calloc(nz,sizeof(double)); data->work = (double*) calloc(n_col,sizeof(double)); data->numberSolving=0; umfpack_di_defaults(data->control); data->control[UMFPACK_PIVOT_TOLERANCE] = 0.1; data->control[UMFPACK_IRSTEP] = 2; data->control[UMFPACK_SCALE] = 1; data->control[UMFPACK_STRATEGY] = 5; *voiddata = (void*)data; return 0; }
int UMF::Factor() { int status; double Info[UMFPACK_INFO]; // UMF internal communcation array double Control[UMFPACK_CONTROL]; memcpy(&_rows[0], _rows_ptr, _nnz*sizeof(int)); memcpy(&_cols[0], _cols_ptr, _nnz*sizeof(int)); memcpy(&_vals[0], _vals_ptr, _nnz*sizeof(double)); _Ap.size(_dim+1); _Ai.size(_nnz); _Ax.size(_nnz); _NRC = _nnz; /* get the default control parameters */ umfpack_di_defaults (Control) ; /* convert to column form */ status = umfpack_di_triplet_to_col(_dim, _dim, _NRC, &_rows[0], &_cols[0], &_vals[0], &_Ap[0], &_Ai[0], &_Ax[0], (int*)NULL) ; if (status < 0 ) { umfpack_di_report_status (Control, status) ; fprintf(stderr,"umfpack_di_triplet_to_col failed\n"); return (-1); } /* ---------------------------------------------------------------------- */ /* symbolic factorization */ /* ---------------------------------------------------------------------- */ if ( _Symbolic == NULL ) { // skip the symbolic factorization steps except the very first one status = umfpack_di_symbolic (_dim, _dim, &_Ap[0], &_Ai[0], &_Ax[0], &_Symbolic, Control, Info) ; if (status < 0 ) { umfpack_di_report_info (Control, Info) ; umfpack_di_report_status (Control, status) ; fprintf(stderr,"umfpack_di_symbolic failed\n"); return (-1); } } /* ---------------------------------------------------------------------- */ /* numeric factorization */ /* ---------------------------------------------------------------------- */ if ( _Numeric ) umfpack_di_free_numeric (&_Numeric); status = umfpack_di_numeric (&_Ap[0], &_Ai[0], &_Ax[0], _Symbolic, &_Numeric, Control, Info) ; if (status < 0 ) { umfpack_di_report_info (Control, Info) ; umfpack_di_report_status (Control, status) ; fprintf(stderr,"umfpack_di_numeric failed\n") ; return (-1); } _is_factored = 1; return 0; }
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; }
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) ; }
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; }
UMFPackLinearMatrixSolver<Scalar>::UMFPackLinearMatrixSolver(CSCMatrix<Scalar> *m, SimpleVector<Scalar> *rhs) : DirectSolver<Scalar>(m, rhs), m(m), rhs(rhs), symbolic(nullptr), numeric(nullptr) { umfpack_di_defaults(Control); }
//============================================================================= 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; }
/* 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 */
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) ; }
inline void defaults (double, int, double* Control) { umfpack_di_defaults (Control); }
int sci_umf_lusolve(char* fname, unsigned long l) { SciErr sciErr; int mb = 0; int nb = 0; int it_flag = 0; int i = 0; int j = 0; int NoTranspose = 0; int NoRaffinement = 0; SciSparse AA; CcsSparse A; /* umfpack stuff */ double Info[UMFPACK_INFO]; // double *Info = (double *) NULL; double Control[UMFPACK_CONTROL]; void* Numeric = NULL; int lnz = 0, unz = 0, n = 0, n_col = 0, nz_udiag = 0, umf_flag = 0; int* Wi = NULL; int mW = 0; double *W = NULL; int iComplex = 0; int* piAddr1 = NULL; int* piAddr2 = NULL; int* piAddr3 = NULL; int* piAddr4 = NULL; double* pdblBR = NULL; double* pdblBI = NULL; double* pdblXR = NULL; double* pdblXI = NULL; int mA = 0; // rows int nA = 0; // cols int iNbItem = 0; int* piNbItemRow = NULL; int* piColPos = NULL; double* pdblSpReal = NULL; double* pdblSpImg = NULL; /* Check numbers of input/output arguments */ CheckInputArgument(pvApiCtx, 2, 4); CheckOutputArgument(pvApiCtx, 1, 1); /* First get arg #1 : the pointer to the LU factors */ sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr1); if (sciErr.iErr) { printError(&sciErr, 0); return 1; } sciErr = getPointer(pvApiCtx, piAddr1, &Numeric); if (sciErr.iErr) { printError(&sciErr, 0); return 1; } /* Check if this pointer is a valid ref to a umfpack LU numeric object */ if ( ! IsAdrInList(Numeric, ListNumeric, &it_flag) ) { Scierror(999, _("%s: Wrong value for input argument #%d: Must be a valid reference to (umf) LU factors.\n"), fname, 1); return 1; } /* get some parameters of the factorization (for some checking) */ if ( it_flag == 0 ) { umfpack_di_get_lunz(&lnz, &unz, &n, &n_col, &nz_udiag, Numeric); } else { iComplex = 1; umfpack_zi_get_lunz(&lnz, &unz, &n, &n_col, &nz_udiag, Numeric); } if ( n != n_col ) { Scierror(999, _("%s: An error occurred: %s.\n"), fname, _("This is not a factorization of a square matrix")); return 1; } if ( nz_udiag < n ) { Scierror(999, _("%s: An error occurred: %s.\n"), fname, _("This is a factorization of a singular matrix")); return 1; } /* Get now arg #2 : the vector b */ sciErr = getVarAddressFromPosition(pvApiCtx, 2, &piAddr2); if (sciErr.iErr) { printError(&sciErr, 0); return 1; } if (isVarComplex(pvApiCtx, piAddr2)) { iComplex = 1; sciErr = getComplexMatrixOfDouble(pvApiCtx, piAddr2, &mb, &nb, &pdblBR, &pdblBI); } else { sciErr = getMatrixOfDouble(pvApiCtx, piAddr2, &mb, &nb, &pdblBR); } if (sciErr.iErr) { printError(&sciErr, 0); return 1; } if (mb != n || nb < 1) /* test if the right hand side is compatible */ { Scierror(999, _("%s: Wrong size for input argument #%d.\n"), fname, 2); return 1; } /* allocate memory for the solution x */ if (iComplex) { sciErr = allocComplexMatrixOfDouble(pvApiCtx, nbInputArgument(pvApiCtx) + 1, mb, nb, &pdblXR, &pdblXI); } else { sciErr = allocMatrixOfDouble(pvApiCtx, nbInputArgument(pvApiCtx) + 1, mb, nb, &pdblXR); } if (sciErr.iErr) { printError(&sciErr, 0); return 1; } /* selection between the different options : * -- solving Ax=b or A'x=b (Note: we could add A.'x=b) * -- with or without raffinement */ if (nbInputArgument(pvApiCtx) == 2) { NoTranspose = 1; NoRaffinement = 1; } else /* 3 or 4 input arguments but the third must be a string */ { char* pStr = NULL; sciErr = getVarAddressFromPosition(pvApiCtx, 3, &piAddr3); if (sciErr.iErr) { printError(&sciErr, 0); return 1; } getAllocatedSingleString(pvApiCtx, piAddr3, &pStr); if (strcmp(pStr, "Ax=b") == 0) { NoTranspose = 1; } else if ( strcmp(pStr, "A'x=b") == 0 ) { NoTranspose = 0; } else { Scierror(999, _("%s: Wrong input argument #%d: '%s' or '%s' expected.\n"), fname, 3, "Ax=b", "A'x=b"); return 1; } if (nbInputArgument(pvApiCtx) == 4) { sciErr = getVarAddressFromPosition(pvApiCtx, 4, &piAddr4); if (sciErr.iErr) { printError(&sciErr, 0); return 1; } if (isVarComplex(pvApiCtx, piAddr4)) { AA.it = 1; sciErr = getComplexSparseMatrix(pvApiCtx, piAddr4, &mA, &nA, &iNbItem, &piNbItemRow, &piColPos, &pdblSpReal, &pdblSpImg); } else { AA.it = 0; sciErr = getSparseMatrix(pvApiCtx, piAddr4, &mA, &nA, &iNbItem, &piNbItemRow, &piColPos, &pdblSpReal); } if (sciErr.iErr) { printError(&sciErr, 0); return 1; } // fill struct sparse AA.m = mA; AA.n = nA; AA.nel = iNbItem; AA.mnel = piNbItemRow; AA.icol = piColPos; AA.R = pdblSpReal; AA.I = pdblSpImg; /* some check... but we can't be sure that the matrix corresponds to the LU factors */ if ( mA != nA || mA != n || AA.it != it_flag ) { Scierror(999, _("%s: Wrong size for input argument #%d: %s.\n"), fname, 4, _("Matrix is not compatible with the given LU factors")); return 1; } NoRaffinement = 0; } else { NoRaffinement = 1; /* only 3 input var => no raffinement */ } } /* allocate memory for umfpack_di_wsolve usage or umfpack_zi_wsolve usage*/ Wi = (int*)MALLOC(n * sizeof(int)); if (it_flag == 1) { if (NoRaffinement) { mW = 4 * n; } else { mW = 10 * n; } } else { if (NoRaffinement) { mW = n; } else { mW = 5 * n; } } W = (double*)MALLOC(mW * sizeof(double)); if (NoRaffinement == 0) { SciSparseToCcsSparse(&AA, &A); } else { A.p = NULL; A.irow = NULL; A.R = NULL; A.I = NULL; } /* get the pointer for b */ if (it_flag == 1 && pdblBI == NULL) { int iSize = mb * nb * sizeof(double); pdblBI = (double*)MALLOC(iSize); memset(pdblBI, 0x00, iSize); } /* init Control */ if (it_flag == 0) { umfpack_di_defaults(Control); } else { umfpack_zi_defaults(Control); } if (NoRaffinement) { Control[UMFPACK_IRSTEP] = 0; } if (NoTranspose) { umf_flag = UMFPACK_A; } else { umf_flag = UMFPACK_At; } if (it_flag == 0) { for (j = 0; j < nb ; j++) { umfpack_di_wsolve(umf_flag, A.p, A.irow, A.R, &pdblXR[j * mb], &pdblBR[j * mb], Numeric, Control, Info, Wi, W); } if (iComplex == 1) { for (j = 0; j < nb ; j++) { umfpack_di_wsolve(umf_flag, A.p, A.irow, A.R, &pdblXI[j * mb], &pdblBI[j * mb], Numeric, Control, Info, Wi, W); } } } else { for (j = 0; j < nb ; j++) { umfpack_zi_wsolve(umf_flag, A.p, A.irow, A.R, A.I, &pdblXR[j * mb], &pdblXI[j * mb], &pdblBR[j * mb], &pdblBI[j * mb], Numeric, Control, Info, Wi, W); } } if (isVarComplex(pvApiCtx, piAddr2) == 0) { FREE(pdblBI); } freeCcsSparse(A); FREE(W); FREE(Wi); AssignOutputVariable(pvApiCtx, 1) = nbInputArgument(pvApiCtx) + 1; ReturnArguments(pvApiCtx); return 0; }