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; }
bool UMFPackLinearMatrixSolver<double>::setup_factorization() { // Perform both factorization phases for the first time. if(reuse_scheme != HERMES_CREATE_STRUCTURE_FROM_SCRATCH && symbolic == nullptr && numeric == nullptr) reuse_scheme = HERMES_CREATE_STRUCTURE_FROM_SCRATCH; else reuse_scheme = reuse_scheme; int status; switch(reuse_scheme) { case HERMES_CREATE_STRUCTURE_FROM_SCRATCH: if(symbolic != nullptr) { umfpack_di_free_symbolic(&symbolic); memset(Info, 0, 90 * sizeof(double)); } // Factorizing symbolically. status = umfpack_real_symbolic(m->get_size(), m->get_size(), m->get_Ap(), m->get_Ai(), m->get_Ax(), &symbolic, Control, Info); if(status != UMFPACK_OK) { if(symbolic) umfpack_di_free_symbolic(&symbolic); throw Exceptions::LinearMatrixSolverException(check_status("UMFPACK symbolic factorization", status)); } case HERMES_REUSE_MATRIX_REORDERING: case HERMES_REUSE_MATRIX_REORDERING_AND_SCALING: if(numeric != nullptr) { umfpack_di_free_numeric(&numeric); memset(Info + 0, 0, 90 * sizeof(double)); } // Factorizing numerically. status = umfpack_real_numeric(m->get_Ap(), m->get_Ai(), m->get_Ax(), symbolic, &numeric, Control, Info); if(status != UMFPACK_OK) { if(numeric) umfpack_di_free_numeric(&numeric); throw Exceptions::LinearMatrixSolverException(check_status("UMFPACK numeric factorization", status)); } else umfpack_di_report_info (Control, Info); } return true; }
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); }
DllExport void* CreateSolverLUUMFPACK(int numberOfRows, int numberOfNoneZero, int *Ti, int *Tj, double *Tx) { //创建 Compressed Row Storage 存储结构 int *Ai = (int*)malloc(sizeof(int)*(numberOfNoneZero)); int *Ap = (int*)malloc(sizeof(int)*(numberOfRows + 1)); double *Ax = (double*)malloc(sizeof(double)*(numberOfNoneZero)); //转换 triplet 到 CRS int staus = umfpack_di_triplet_to_col(numberOfRows, numberOfRows, numberOfNoneZero, Ti, Tj, Tx, Ap, Ai, Ax, NULL); if (staus != UMFPACK_OK){ return NULL; } //创建 solver UmfpackSolver *umpsolver = (UmfpackSolver*)malloc(sizeof(UmfpackSolver)); //设置 solver umpsolver->Ai = Ai; umpsolver->Ap = Ap; umpsolver->Ax = Ax; umpsolver->AiSize = umpsolver->AxSize = numberOfNoneZero; umpsolver->ApSize = numberOfRows + 1; umpsolver->n = numberOfRows; umpsolver->m = numberOfRows; //因子化 void *Symbolic, *Numeric; (void)umfpack_di_symbolic(numberOfRows, numberOfRows, Ap, Ai, Ax, &Symbolic, NULL, NULL); (void)umfpack_di_numeric(Ap, Ai, Ax, Symbolic, &Numeric, NULL, NULL); umfpack_di_free_symbolic(&Symbolic); umpsolver->Numeric = Numeric; return umpsolver; };
void UMFPackLinearMatrixSolver<double>::free_factorization_data() { if(symbolic != nullptr) umfpack_di_free_symbolic(&symbolic); symbolic = nullptr; if(numeric != nullptr) umfpack_di_free_numeric(&numeric); numeric = nullptr; }
void SparseMatrix::resize (size_t r, size_t c, bool forceEditable) { factored = false; if (r == nrow && c == ncol && !forceEditable) { // Clear the matrix content but retain its sparsity pattern for (ValueMap::iterator it = elem.begin(); it != elem.end(); ++it) it->second = Real(0); std::fill(A.begin(),A.end(),Real(0)); return; } // Clear the matrix completely, including its sparsity pattern editable = 'P'; elem.clear(); IA.clear(); JA.clear(); A.clear(); nrow = r; ncol = c > 0 ? c : r; if (slu) delete slu; slu = 0; #ifdef HAS_UMFPACK if (umfSymbolic) { umfpack_di_free_symbolic(&umfSymbolic); umfSymbolic = nullptr; } #endif }
/* * *************************************************************************** * Routine: Slu_factor * * Purpose: Sparse LU factor the system. * * Author: Michael Holst and Stephen Bond * *************************************************************************** */ VPUBLIC int Slu_factor(Slu *thee) { int status; int n = thee->n, m = thee->m; int *Ap = thee->ia, *Ai = thee->ja; double *Ax = thee->a; void *Symbolic, *Numeric; VASSERT( thee != VNULL ); if( thee->statLU == 1 ) { umfpack_di_free_numeric( thee->work ); thee->statLU = 0; } status = umfpack_di_symbolic(n, m, Ap, Ai, Ax, &Symbolic, VNULL, VNULL); if (UMFPACK_OK != status) { return 0; } status = umfpack_di_numeric(Ap, Ai, Ax, Symbolic, &Numeric, VNULL, VNULL); umfpack_di_free_symbolic(&Symbolic); if (UMFPACK_OK != status) { return 0; } thee->work = Numeric; thee->statLU = 1; return 1; }
/*---------------------------------------------------------------------------*/ 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); }
SparseMatrix::~SparseMatrix () { if (slu) delete slu; #ifdef HAS_UMFPACK if (umfSymbolic) umfpack_di_free_symbolic(&umfSymbolic); #endif }
//============================================================================= Amesos_Umfpack::~Amesos_Umfpack(void) { if (Symbolic) umfpack_di_free_symbolic (&Symbolic); if (Numeric) umfpack_di_free_numeric (&Numeric); // print out some information if required by the user if ((verbose_ && PrintTiming_) || verbose_ == 2) PrintTiming(); if ((verbose_ && PrintStatus_) || verbose_ == 2) PrintStatus(); }
/* Create a deformation transfer object, once created, this object can help deforming the target mesh like the source mesh deformation quicky and faithfully. */ void CreateDeformationTransformer( const char *source_ref_name, const char *target_ref_name, const char *tricorrs_name, dt_size_type n_maxcorrs, dtTransformer *trans) { __dt_TriangleCorrsList tclist; cholmod_sparse *A; __dt_SparseMatrix A_tri; void *symbolic_obj; /* for umfpack's symbolic analysis */ /* Load data */ __dt_ReadObjFile_commit_or_crash(source_ref_name, &(trans->source_ref)); __dt_ReadObjFile_commit_or_crash(target_ref_name, &(trans->target)); if (__dt_LoadTriangleCorrsList( tricorrs_name, &tclist) == -1) { perror("Loading triangle correspondence failed"); exit(1); } /* Initialize triangle correspondence dictionary */ __dt_StripTriangleCorrsList(&tclist, n_maxcorrs); __dt_CreateTriangleCorrsDict(&(trans->target), &tclist, &(trans->tcdict)); /* Precalculate inverse of surface matrices of source reference model*/ __dt_InitializeSurfaceInvVList(&(trans->source_ref), &(trans->sinvlist)); /* Allocate for linear system */ __dt_AllocDeformationEquation(&(trans->target), &(trans->tcdict), &A_tri, &(trans->C)); trans->c = __dt_CHOLMOD_dense_zeros(A_tri->ncol, 1); /* rhs vector: ncol*1 */ trans->x = __dt_CHOLMOD_dense_zeros(A_tri->ncol, 1); /* solution vector: ncol*1 */ /* Building coefficient matrix: A_tri(triplet) ==> A(sparse) ==> At ==> AtA */ printf("building equation...\n"); __dt_BuildCoefficientMatrix(&(trans->target), &(trans->tcdict), A_tri); A = __dt_CHOLMOD_triplet_to_sparse(A_tri); __dt_CHOLMOD_free_triplet(&A_tri); trans->At = __dt_CHOLMOD_transpose(A); __dt_CHOLMOD_free_sparse(&A); trans->AtA = __dt_CHOLMOD_AxAt(trans->At); printf("factorizing...\n"); /* factorize AtA */ umfpack_di_symbolic( (int)trans->AtA->nrow, (int)trans->AtA->ncol, (const int*)trans->AtA->p, (const int*)trans->AtA->i, (const double*)trans->AtA->x, &symbolic_obj, NULL, NULL); umfpack_di_numeric( (const int*)trans->AtA->p, (const int*)trans->AtA->i, (const double*)trans->AtA->x, symbolic_obj, &(trans->numeric_obj), NULL, NULL); umfpack_di_free_symbolic(&symbolic_obj); }
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 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 Amesos_Umfpack::PerformSymbolicFactorization() { // MS // no overhead time in this method ResetTimer(0); double *Control = (double *) NULL, *Info = (double *) NULL; if (Symbolic) umfpack_di_free_symbolic (&Symbolic) ; if (MyPID_== 0) { (void) umfpack_di_symbolic (NumGlobalElements_, NumGlobalElements_, &Ap[0], &Ai[0], &Aval[0], &Symbolic, Control, Info) ; } SymFactTime_ = AddTime("Total symbolic factorization time", SymFactTime_, 0); return 0; }
/*! \fn free memory for linear system solver UmfPack * */ int freeUmfPackData(void **voiddata) { TRACE_PUSH DATA_UMFPACK* data = (DATA_UMFPACK*) *voiddata; free(data->Ap); free(data->Ai); free(data->Ax); free(data->work); if(data->symbolic) umfpack_di_free_symbolic (&data->symbolic); if(data->numeric) umfpack_di_free_numeric (&data->numeric); TRACE_POP 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); }
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; }
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; }
int sci_umf_lufact(char* fname, void* pvApiCtx) { SciErr sciErr; int stat = 0; SciSparse AA; CcsSparse A; int mA = 0; // rows int nA = 0; // cols int iNbItem = 0; int* piNbItemRow = NULL; int* piColPos = NULL; double* pdblSpReal = NULL; double* pdblSpImg = NULL; /* umfpack stuff */ double* Control = NULL; double* Info = NULL; void* Symbolic = NULL; void* Numeric = NULL; int* piAddr1 = NULL; int iComplex = 0; int iType1 = 0; /* Check numbers of input/output arguments */ CheckInputArgument(pvApiCtx, 1, 1); CheckOutputArgument(pvApiCtx, 1, 1); /* get A the sparse matrix to factorize */ sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr1); if (sciErr.iErr) { printError(&sciErr, 0); return 1; } /* check if the first argument is a sparse matrix */ sciErr = getVarType(pvApiCtx, piAddr1, &iType1); if (sciErr.iErr || iType1 != sci_sparse) { printError(&sciErr, 0); Scierror(999, _("%s: Wrong type for input argument #%d: A sparse matrix expected.\n"), fname, 1); return 1; } if (isVarComplex(pvApiCtx, piAddr1)) { iComplex = 1; sciErr = getComplexSparseMatrix(pvApiCtx, piAddr1, &mA, &nA, &iNbItem, &piNbItemRow, &piColPos, &pdblSpReal, &pdblSpImg); } else { sciErr = getSparseMatrix(pvApiCtx, piAddr1, &mA, &nA, &iNbItem, &piNbItemRow, &piColPos, &pdblSpReal); } if (sciErr.iErr) { FREE(piNbItemRow); FREE(piColPos); FREE(pdblSpReal); if (pdblSpImg) { FREE(pdblSpImg); } printError(&sciErr, 0); return 1; } // fill struct sparse AA.m = mA; AA.n = nA; AA.it = iComplex; AA.nel = iNbItem; AA.mnel = piNbItemRow; AA.icol = piColPos; AA.R = pdblSpReal; AA.I = pdblSpImg; if (nA <= 0 || mA <= 0) { FREE(piNbItemRow); FREE(piColPos); FREE(pdblSpReal); if (pdblSpImg) { FREE(pdblSpImg); } Scierror(999, _("%s: Wrong size for input argument #%d.\n"), fname, 1); return 1; } SciSparseToCcsSparse(&AA, &A); FREE(piNbItemRow); FREE(piColPos); FREE(pdblSpReal); if (pdblSpImg) { FREE(pdblSpImg); } /* symbolic factorization */ if (A.it == 1) { stat = umfpack_zi_symbolic(nA, mA, A.p, A.irow, A.R, A.I, &Symbolic, Control, Info); } else { stat = umfpack_di_symbolic(nA, mA, A.p, A.irow, A.R, &Symbolic, Control, Info); } if (stat != UMFPACK_OK) { freeCcsSparse(A); Scierror(999, _("%s: An error occurred: %s: %s\n"), fname, _("symbolic factorization"), UmfErrorMes(stat)); return 1; } /* numeric factorization */ if (A.it == 1) { stat = umfpack_zi_numeric(A.p, A.irow, A.R, A.I, Symbolic, &Numeric, Control, Info); } else { stat = umfpack_di_numeric(A.p, A.irow, A.R, Symbolic, &Numeric, Control, Info); } if (A.it == 1) { umfpack_zi_free_symbolic(&Symbolic); } else { umfpack_di_free_symbolic(&Symbolic); } if ( stat != UMFPACK_OK && stat != UMFPACK_WARNING_singular_matrix ) { freeCcsSparse(A); Scierror(999, _("%s: An error occurred: %s: %s\n"), fname, _("symbolic factorization"), UmfErrorMes(stat)); return 1; } if ( stat == UMFPACK_WARNING_singular_matrix && mA == nA ) { if (getWarningMode()) { Sciwarning("\n%s:%s\n", _("Warning"), _("The (square) matrix appears to be singular.")); } } /* add the pointer in the list ListNumeric */ if (! AddAdrToList(Numeric, A.it, &ListNumeric)) { /* AddAdrToList return 0 if malloc have failed : as it is just for storing 2 pointers this is unlikely to occurs but ... */ if (A.it == 1) { umfpack_zi_free_numeric(&Numeric); } else { umfpack_di_free_numeric(&Numeric); } freeCcsSparse(A); Scierror(999, _("%s: An error occurred: %s\n"), fname, _("no place to store the LU pointer in ListNumeric.")); return 1; } freeCcsSparse(A); /* create the scilab object to store the pointer onto the LU factors */ sciErr = createPointer(pvApiCtx, 2, Numeric); if (sciErr.iErr) { printError(&sciErr, 0); return 1; } /* return the pointer */ AssignOutputVariable(pvApiCtx, 1) = 2; ReturnArguments(pvApiCtx); return 0; }
inline void free_symbolic (double, int, void **Symbolic) { umfpack_di_free_symbolic (Symbolic); }
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; }
static int cs_fact_init_umfpack( cs_fact_t *umfd, const cs *A ) { #ifdef USE_UMFPACK int ret; void *symbolic; cs *T; /* Create matrix and sort. */ /* Non-symmetric case. */ if (0) { T = cs_transpose( A, 1 ); umfd->A = cs_transpose( T, 1 ); cs_spfree( T ); } /* Symmetric case. */ else { umfd->A = cs_transpose( A, 1 ); } cs_dupl( umfd->A ); /* Generate symbolic. */ ret = umfpack_di_symbolic( umfd->n, umfd->n, umfd->A->p, umfd->A->i, umfd->A->x, &symbolic, NULL, NULL ); if (ret < UMFPACK_OK) goto err_sym; /* Generate numeric. */ ret = umfpack_di_numeric( umfd->A->p, umfd->A->i, umfd->A->x, symbolic, &umfd->numeric, NULL, NULL ); if (ret < UMFPACK_OK) goto err_num; else if (ret > UMFPACK_OK) { switch (ret) { case UMFPACK_WARNING_singular_matrix: fprintf( stderr, "UMFPACK: Matrix is singular.\n" ); break; case UMFPACK_WARNING_determinant_underflow: fprintf( stderr, "UMFPACK: Determinant underflow.\n" ); break; case UMFPACK_WARNING_determinant_overflow: fprintf( stderr, "UMFPACK: Determinant overflow.\n" ); break; } } /* Clean up symbolic. */ umfpack_di_free_symbolic( &symbolic ); /* Allocate buffers. */ umfd->wi = malloc( umfd->n * sizeof(int) ); if (umfd->wi == NULL) goto err_wi; umfd->w = malloc( umfd->n*5 * sizeof(double) ); /* We consider iteration refinement. */ if (umfd->w == NULL) goto err_w; umfd->x = calloc( umfd->n, sizeof(double) ); if (umfd->x == NULL) goto err_x; umfd->type = CS_FACT_UMFPACK; return 0; err_x: free( umfd->w ); err_w: free( umfd->wi ); err_wi: umfpack_di_free_numeric( &umfd->numeric ); err_num: umfpack_di_free_symbolic( &symbolic ); err_sym: cs_spfree( umfd->A ); return -1; #else /* USE_UMFPACK */ (void) umfd; (void) A; return -1; #endif /* USE_UMFPACK */ }
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; }
bool CommonSolverUmfpack::solve(Matrix *mat, cplx *res) { printf("UMFPACK solver - cplx\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(); // complex components double *Axr = new double[nnz]; double *Axi = new double[nnz]; cplx *Ax = Acsc->get_Ax_cplx(); for (int i = 0; i < nnz; i++) { Axr[i] = Ax[i].real(); Axi[i] = Ax[i].imag(); } umfpack_zi_defaults(control_array); /* symbolic analysis */ void *symbolic, *numeric; int status_symbolic = umfpack_zi_symbolic(size, size, Acsc->get_Ap(), Acsc->get_Ai(), NULL, NULL, &symbolic, control_array, info_array); print_status(status_symbolic); /* LU factorization */ int status_numeric = umfpack_zi_numeric(Acsc->get_Ap(), Acsc->get_Ai(), Axr, Axi, symbolic, &numeric, control_array, info_array); print_status(status_numeric); umfpack_zi_free_symbolic(&symbolic); double *xr = new double[size]; double *xi = new double[size]; double *resr = new double[size]; double *resi = new double[size]; for (int i = 0; i < size; i++) { resr[i] = res[i].real(); resi[i] = res[i].imag(); } /* solve system */ int status_solve = umfpack_zi_solve(UMFPACK_A, Acsc->get_Ap(), Acsc->get_Ai(), Axr, Axi, xr, xi, resr, resi, numeric, control_array, info_array); print_status(status_solve); umfpack_zi_free_numeric(&numeric); delete[] resr; delete[] resi; delete[] Axr; delete[] Axi; if (symbolic) umfpack_di_free_symbolic(&symbolic); if (numeric) umfpack_di_free_numeric(&numeric); for (int i = 0; i < Acsc->get_size(); i++) res[i] = cplx(xr[i], xi[i]); delete[] xr; delete[] xi; if (!dynamic_cast<CSCMatrix*>(mat)) delete Acsc; }
int sci_umfpack(char* fname, void* pvApiCtx) { SciErr sciErr; int mb = 0; int nb = 0; int i = 0; int num_A = 0; int num_b = 0; int mW = 0; int Case = 0; int stat = 0; SciSparse AA; CcsSparse A; int* piAddrA = NULL; int* piAddr2 = NULL; int* piAddrB = NULL; double* pdblBR = NULL; double* pdblBI = NULL; double* pdblXR = NULL; double* pdblXI = NULL; int iComplex = 0; int freepdblBI = 0; int mA = 0; // rows int nA = 0; // cols int iNbItem = 0; int* piNbItemRow = NULL; int* piColPos = NULL; double* pdblSpReal = NULL; double* pdblSpImg = NULL; /* umfpack stuff */ double Info[UMFPACK_INFO]; double* Control = NULL; void* Symbolic = NULL; void* Numeric = NULL; int* Wi = NULL; double* W = NULL; char* pStr = NULL; int iType2 = 0; int iTypeA = 0; int iTypeB = 0; /* Check numbers of input/output arguments */ CheckInputArgument(pvApiCtx, 3, 3); CheckOutputArgument(pvApiCtx, 1, 1); /* First get arg #2 : a string of length 1 */ sciErr = getVarAddressFromPosition(pvApiCtx, 2, &piAddr2); if (sciErr.iErr) { printError(&sciErr, 0); return 1; } sciErr = getVarType(pvApiCtx, piAddr2, &iType2); if (sciErr.iErr || iType2 != sci_strings) { printError(&sciErr, 0); Scierror(999, _("%s: Wrong type for input argument #%d: string expected.\n"), fname, 2); return 1; } if (getAllocatedSingleString(pvApiCtx, piAddr2, &pStr)) { return 1; } /* select Case 1 or 2 depending (of the first char of) the string ... */ if (pStr[0] == '\\') // compare pStr[0] with '\' { Case = 1; num_A = 1; num_b = 3; } else if (pStr[0] == '/') { Case = 2; num_A = 3; num_b = 1; } else { Scierror(999, _("%s: Wrong input argument #%d: '%s' or '%s' expected.\n"), fname, 2, "\\", "/"); FREE(pStr); return 1; } FREE(pStr); /* get A */ sciErr = getVarAddressFromPosition(pvApiCtx, num_A, &piAddrA); if (sciErr.iErr) { printError(&sciErr, 0); return 1; } sciErr = getVarType(pvApiCtx, piAddrA, &iTypeA); if (sciErr.iErr || iTypeA != sci_sparse) { printError(&sciErr, 0); Scierror(999, _("%s: Wrong type for input argument #%d: A sparse matrix expected.\n"), fname, 1); return 1; } if (isVarComplex(pvApiCtx, piAddrA)) { AA.it = 1; iComplex = 1; sciErr = getComplexSparseMatrix(pvApiCtx, piAddrA, &mA, &nA, &iNbItem, &piNbItemRow, &piColPos, &pdblSpReal, &pdblSpImg); } else { AA.it = 0; sciErr = getSparseMatrix(pvApiCtx, piAddrA, &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; if ( mA != nA || mA < 1 ) { Scierror(999, _("%s: Wrong size for input argument #%d.\n"), fname, num_A); return 1; } /* get B*/ sciErr = getVarAddressFromPosition(pvApiCtx, num_b, &piAddrB); if (sciErr.iErr) { printError(&sciErr, 0); return 1; } sciErr = getVarType(pvApiCtx, piAddrB, &iTypeB); if (sciErr.iErr || iTypeB != sci_matrix) { printError(&sciErr, 0); Scierror(999, _("%s: Wrong type for input argument #%d: A matrix expected.\n"), fname, 3); return 1; } if (isVarComplex(pvApiCtx, piAddrB)) { iComplex = 1; sciErr = getComplexMatrixOfDouble(pvApiCtx, piAddrB, &mb, &nb, &pdblBR, &pdblBI); } else { sciErr = getMatrixOfDouble(pvApiCtx, piAddrB, &mb, &nb, &pdblBR); } if (sciErr.iErr) { printError(&sciErr, 0); return 1; } if ( (Case == 1 && ( mb != mA || nb < 1 )) || (Case == 2 && ( nb != mA || mb < 1 )) ) { Scierror(999, _("%s: Wrong size for input argument #%d.\n"), fname, num_b); return 1; } SciSparseToCcsSparse(&AA, &A); /* allocate memory for the solution x */ if (iComplex) { sciErr = allocComplexMatrixOfDouble(pvApiCtx, 4, mb, nb, &pdblXR, &pdblXI); } else { sciErr = allocMatrixOfDouble(pvApiCtx, 4, mb, nb, &pdblXR); } if (sciErr.iErr) { printError(&sciErr, 0); freeCcsSparse(A); return 1; } if (A.it == 1) { mW = 10 * mA; } else { mW = 5 * mA; } if (A.it == 1 && pdblBI == NULL) { int iSize = mb * nb * sizeof(double); pdblBI = (double*)MALLOC(iSize); memset(pdblBI, 0x00, iSize); freepdblBI = 1; } /* Now calling umfpack routines */ if (A.it == 1) { stat = umfpack_zi_symbolic(mA, nA, A.p, A.irow, A.R, A.I, &Symbolic, Control, Info); } else { stat = umfpack_di_symbolic(mA, nA, A.p, A.irow, A.R, &Symbolic, Control, Info); } if ( stat != UMFPACK_OK ) { Scierror(999, _("%s: An error occurred: %s: %s\n"), fname, _("symbolic factorization"), UmfErrorMes(stat)); freeCcsSparse(A); if (freepdblBI) { FREE(pdblBI); } return 1; } if (A.it == 1) { stat = umfpack_zi_numeric(A.p, A.irow, A.R, A.I, Symbolic, &Numeric, Control, Info); } else { stat = umfpack_di_numeric(A.p, A.irow, A.R, Symbolic, &Numeric, Control, Info); } if (A.it == 1) { umfpack_zi_free_symbolic(&Symbolic); } else { umfpack_di_free_symbolic(&Symbolic); } if ( stat != UMFPACK_OK ) { Scierror(999, _("%s: An error occurred: %s: %s\n"), fname, _("numeric factorization"), UmfErrorMes(stat)); if (A.it == 1) { umfpack_zi_free_numeric(&Numeric); } else { umfpack_di_free_numeric(&Numeric); } freeCcsSparse(A); if (freepdblBI) { FREE(pdblBI); } return 1; } /* allocate memory for umfpack_di_wsolve usage or umfpack_zi_wsolve usage*/ Wi = (int*)MALLOC(mA * sizeof(int)); W = (double*)MALLOC(mW * sizeof(double)); if ( Case == 1 ) /* x = A\b <=> Ax = b */ { if (A.it == 0) { for ( i = 0 ; i < nb ; i++ ) { umfpack_di_wsolve(UMFPACK_A, A.p, A.irow, A.R, &pdblXR[i * mb], &pdblBR[i * mb], Numeric, Control, Info, Wi, W); } if (isVarComplex(pvApiCtx, piAddrB)) { for ( i = 0 ; i < nb ; i++ ) { umfpack_di_wsolve(UMFPACK_A, A.p, A.irow, A.R, &pdblXI[i * mb], &pdblBI[i * mb], Numeric, Control, Info, Wi, W); } } } else /* A.it == 1 */ { for ( i = 0 ; i < nb ; i++ ) { umfpack_zi_wsolve(UMFPACK_A, A.p, A.irow, A.R, A.I, &pdblXR[i * mb], &pdblXI[i * mb], &pdblBR[i * mb], &pdblBI[i * mb], Numeric, Control, Info, Wi, W); } } } else /* Case == 2, x = b/A <=> x A = b <=> A.'x.' = b.' */ { if (A.it == 0) { TransposeMatrix(pdblBR, mb, nb, pdblXR); /* put b in x (with transposition) */ for ( i = 0 ; i < mb ; i++ ) { umfpack_di_wsolve(UMFPACK_At, A.p, A.irow, A.R, &pdblBR[i * nb], &pdblXR[i * nb], Numeric, Control, Info, Wi, W); /* the solutions are in br */ } TransposeMatrix(pdblBR, nb, mb, pdblXR); /* put now br in xr with transposition */ if (isVarComplex(pvApiCtx, piAddrB)) { TransposeMatrix(pdblBI, mb, nb, pdblXI); /* put b in x (with transposition) */ for ( i = 0 ; i < mb ; i++ ) { umfpack_di_wsolve(UMFPACK_At, A.p, A.irow, A.R, &pdblBI[i * nb], &pdblXI[i * nb], Numeric, Control, Info, Wi, W); /* the solutions are in bi */ } TransposeMatrix(pdblBI, nb, mb, pdblXI); /* put now bi in xi with transposition */ } } else /* A.it==1 */ { TransposeMatrix(pdblBR, mb, nb, pdblXR); TransposeMatrix(pdblBI, mb, nb, pdblXI); for ( i = 0 ; i < mb ; i++ ) { umfpack_zi_wsolve(UMFPACK_Aat, A.p, A.irow, A.R, A.I, &pdblBR[i * nb], &pdblBI[i * nb], &pdblXR[i * nb], &pdblXI[i * nb], Numeric, Control, Info, Wi, W); } TransposeMatrix(pdblBR, nb, mb, pdblXR); TransposeMatrix(pdblBI, nb, mb, pdblXI); } } if (A.it == 1) { umfpack_zi_free_numeric(&Numeric); } else { umfpack_di_free_numeric(&Numeric); } if (piNbItemRow != NULL) { FREE(piNbItemRow); } if (piColPos != NULL) { FREE(piColPos); } if (pdblSpReal != NULL) { FREE(pdblSpReal); } if (pdblSpImg != NULL) { FREE(pdblSpImg); } FREE(W); FREE(Wi); if (freepdblBI) { FREE(pdblBI); } freeCcsSparse(A); AssignOutputVariable(pvApiCtx, 1) = 4; ReturnArguments(pvApiCtx); return 0; }
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) ; }
/* 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; }